~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Aaron Bentley
  • Date: 2007-12-25 04:17:50 UTC
  • mto: This revision was merged to the branch mainline in revision 3160.
  • Revision ID: aaron.bentley@utoronto.ca-20071225041750-t6chr3pmgnebvqcz
Handle non-directory parent conflicts (abentley, #177390)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
42
42
from subprocess import Popen, PIPE
43
43
import sys
44
44
import tempfile
45
 
import threading
46
45
import time
 
46
import trace
47
47
import unittest
48
48
import warnings
49
49
 
50
50
 
51
51
from bzrlib import (
52
 
    branchbuilder,
53
52
    bzrdir,
54
53
    debug,
55
54
    errors,
75
74
from bzrlib.merge import merge_inner
76
75
import bzrlib.merge3
77
76
import bzrlib.plugin
 
77
from bzrlib.revision import common_ancestor
78
78
import bzrlib.store
79
79
from bzrlib import symbol_versioning
80
80
from bzrlib.symbol_versioning import (
82
82
    deprecated_function,
83
83
    deprecated_method,
84
84
    deprecated_passed,
 
85
    zero_ninetyone,
 
86
    zero_ninetytwo,
 
87
    one_zero,
85
88
    )
86
89
import bzrlib.trace
87
90
from bzrlib.transport import get_transport
91
94
from bzrlib.transport.readonly import ReadonlyServer
92
95
from bzrlib.trace import mutter, note
93
96
from bzrlib.tests import TestUtil
94
 
from bzrlib.tests.http_server import HttpServer
 
97
from bzrlib.tests.HttpServer import HttpServer
95
98
from bzrlib.tests.TestUtil import (
96
99
                          TestSuite,
97
100
                          TestLoader,
107
110
 
108
111
default_transport = LocalURLServer
109
112
 
 
113
MODULES_TO_TEST = []
 
114
MODULES_TO_DOCTEST = [
 
115
        bzrlib.timestamp,
 
116
        bzrlib.errors,
 
117
        bzrlib.export,
 
118
        bzrlib.inventory,
 
119
        bzrlib.iterablefile,
 
120
        bzrlib.lockdir,
 
121
        bzrlib.merge3,
 
122
        bzrlib.option,
 
123
        bzrlib.store,
 
124
        bzrlib.version_info_formats.format_custom,
 
125
        # quoted to avoid module-loading circularity
 
126
        'bzrlib.tests',
 
127
        ]
 
128
 
 
129
 
 
130
def packages_to_test():
 
131
    """Return a list of packages to test.
 
132
 
 
133
    The packages are not globally imported so that import failures are
 
134
    triggered when running selftest, not when importing the command.
 
135
    """
 
136
    import bzrlib.doc
 
137
    import bzrlib.tests.blackbox
 
138
    import bzrlib.tests.branch_implementations
 
139
    import bzrlib.tests.bzrdir_implementations
 
140
    import bzrlib.tests.commands
 
141
    import bzrlib.tests.interrepository_implementations
 
142
    import bzrlib.tests.interversionedfile_implementations
 
143
    import bzrlib.tests.intertree_implementations
 
144
    import bzrlib.tests.inventory_implementations
 
145
    import bzrlib.tests.per_lock
 
146
    import bzrlib.tests.repository_implementations
 
147
    import bzrlib.tests.revisionstore_implementations
 
148
    import bzrlib.tests.tree_implementations
 
149
    import bzrlib.tests.workingtree_implementations
 
150
    return [
 
151
            bzrlib.doc,
 
152
            bzrlib.tests.blackbox,
 
153
            bzrlib.tests.branch_implementations,
 
154
            bzrlib.tests.bzrdir_implementations,
 
155
            bzrlib.tests.commands,
 
156
            bzrlib.tests.interrepository_implementations,
 
157
            bzrlib.tests.interversionedfile_implementations,
 
158
            bzrlib.tests.intertree_implementations,
 
159
            bzrlib.tests.inventory_implementations,
 
160
            bzrlib.tests.per_lock,
 
161
            bzrlib.tests.repository_implementations,
 
162
            bzrlib.tests.revisionstore_implementations,
 
163
            bzrlib.tests.tree_implementations,
 
164
            bzrlib.tests.workingtree_implementations,
 
165
            ]
 
166
 
110
167
 
111
168
class ExtendedTestResult(unittest._TextTestResult):
112
169
    """Accepts, reports and accumulates the results of running tests.
224
281
            self.report_error(test, err)
225
282
            if self.stop_early:
226
283
                self.stop()
227
 
            self._cleanupLogFile(test)
228
284
 
229
285
    def addFailure(self, test, err):
230
286
        """Tell result that test failed.
241
297
            self.report_failure(test, err)
242
298
            if self.stop_early:
243
299
                self.stop()
244
 
            self._cleanupLogFile(test)
245
300
 
246
301
    def addSuccess(self, test):
247
302
        """Tell result that test completed successfully.
256
311
                    self._formatTime(benchmark_time),
257
312
                    test.id()))
258
313
        self.report_success(test)
259
 
        self._cleanupLogFile(test)
260
314
        unittest.TestResult.addSuccess(self, test)
261
 
        test._log_contents = ''
262
315
 
263
316
    def _testConcluded(self, test):
264
317
        """Common code when a test has finished.
265
318
 
266
319
        Called regardless of whether it succeded, failed, etc.
267
320
        """
268
 
        pass
 
321
        self._cleanupLogFile(test)
269
322
 
270
323
    def _addKnownFailure(self, test, err):
271
324
        self.known_failure_count += 1
301
354
            # seems best to treat this as success from point-of-view of unittest
302
355
            # -- it actually does nothing so it barely matters :)
303
356
            unittest.TestResult.addSuccess(self, test)
304
 
            test._log_contents = ''
305
357
 
306
358
    def printErrorList(self, flavour, errors):
307
359
        for test, err in errors:
362
414
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
363
415
 
364
416
    def _progress_prefix_text(self):
365
 
        # the longer this text, the less space we have to show the test
366
 
        # name...
367
 
        a = '[%d' % self.count              # total that have been run
368
 
        # tests skipped as known not to be relevant are not important enough
369
 
        # to show here
370
 
        ## if self.skip_count:
371
 
        ##     a += ', %d skip' % self.skip_count
372
 
        ## if self.known_failure_count:
373
 
        ##     a += '+%dX' % self.known_failure_count
 
417
        a = '[%d' % self.count
374
418
        if self.num_tests is not None:
375
419
            a +='/%d' % self.num_tests
376
 
        a += ' in '
377
 
        runtime = time.time() - self._overall_start_time
378
 
        if runtime >= 60:
379
 
            a += '%dm%ds' % (runtime / 60, runtime % 60)
380
 
        else:
381
 
            a += '%ds' % runtime
 
420
        a += ' in %ds' % (time.time() - self._overall_start_time)
382
421
        if self.error_count:
383
 
            a += ', %d err' % self.error_count
 
422
            a += ', %d errors' % self.error_count
384
423
        if self.failure_count:
385
 
            a += ', %d fail' % self.failure_count
 
424
            a += ', %d failed' % self.failure_count
 
425
        if self.known_failure_count:
 
426
            a += ', %d known failures' % self.known_failure_count
 
427
        if self.skip_count:
 
428
            a += ', %d skipped' % self.skip_count
386
429
        if self.unsupported:
387
 
            a += ', %d missing' % len(self.unsupported)
 
430
            a += ', %d missing features' % len(self.unsupported)
388
431
        a += ']'
389
432
        return a
390
433
 
718
761
        return password
719
762
 
720
763
 
721
 
def _report_leaked_threads():
722
 
    bzrlib.trace.warning('%s is leaking threads among %d leaking tests',
723
 
                         TestCase._first_thread_leaker_id,
724
 
                         TestCase._leaking_threads_tests)
725
 
 
726
 
 
727
764
class TestCase(unittest.TestCase):
728
765
    """Base class for bzr unit tests.
729
766
    
745
782
    accidentally overlooked.
746
783
    """
747
784
 
748
 
    _active_threads = None
749
 
    _leaking_threads_tests = 0
750
 
    _first_thread_leaker_id = None
751
785
    _log_file_name = None
752
786
    _log_contents = ''
753
787
    _keep_log_file = False
754
788
    # record lsprof data when performing benchmark calls.
755
789
    _gather_lsprof_in_benchmarks = False
756
 
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
757
 
                     '_log_contents', '_log_file_name', '_benchtime',
758
 
                     '_TestCase__testMethodName')
759
790
 
760
791
    def __init__(self, methodName='testMethod'):
761
792
        super(TestCase, self).__init__(methodName)
764
795
    def setUp(self):
765
796
        unittest.TestCase.setUp(self)
766
797
        self._cleanEnvironment()
 
798
        bzrlib.trace.disable_default_logging()
767
799
        self._silenceUI()
768
800
        self._startLogFile()
769
801
        self._benchcalls = []
770
802
        self._benchtime = None
771
803
        self._clear_hooks()
772
804
        self._clear_debug_flags()
773
 
        TestCase._active_threads = threading.activeCount()
774
 
        self.addCleanup(self._check_leaked_threads)
775
 
 
776
 
    def _check_leaked_threads(self):
777
 
        active = threading.activeCount()
778
 
        leaked_threads = active - TestCase._active_threads
779
 
        TestCase._active_threads = active
780
 
        if leaked_threads:
781
 
            TestCase._leaking_threads_tests += 1
782
 
            if TestCase._first_thread_leaker_id is None:
783
 
                TestCase._first_thread_leaker_id = self.id()
784
 
                # we're not specifically told when all tests are finished.
785
 
                # This will do. We use a function to avoid keeping a reference
786
 
                # to a TestCase object.
787
 
                atexit.register(_report_leaked_threads)
788
805
 
789
806
    def _clear_debug_flags(self):
790
807
        """Prevent externally set debug flags affecting tests.
792
809
        Tests that want to use debug flags can just set them in the
793
810
        debug_flags set during setup/teardown.
794
811
        """
795
 
        if 'allow_debug' not in selftest_debug_flags:
796
 
            self._preserved_debug_flags = set(debug.debug_flags)
797
 
            debug.debug_flags.clear()
798
 
            self.addCleanup(self._restore_debug_flags)
 
812
        self._preserved_debug_flags = set(debug.debug_flags)
 
813
        debug.debug_flags.clear()
 
814
        self.addCleanup(self._restore_debug_flags)
799
815
 
800
816
    def _clear_hooks(self):
801
817
        # prevent hooks affecting tests
803
819
        import bzrlib.smart.server
804
820
        self._preserved_hooks = {
805
821
            bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
806
 
            bzrlib.mutabletree.MutableTree: bzrlib.mutabletree.MutableTree.hooks,
807
822
            bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
808
823
            }
809
824
        self.addCleanup(self._restoreHooks)
862
877
            return
863
878
        if message is None:
864
879
            message = "texts not equal:\n"
865
 
        if a == b + '\n':
866
 
            message = 'first string is missing a final newline.\n'
867
 
        if a + '\n' == b:
868
 
            message = 'second string is missing a final newline.\n'
869
880
        raise AssertionError(message +
870
881
                             self._ndiff_strings(a, b))
871
882
        
924
935
        """
925
936
        try:
926
937
            list(func(*args, **kwargs))
927
 
        except excClass, e:
928
 
            return e
 
938
        except excClass:
 
939
            return
929
940
        else:
930
941
            if getattr(excClass,'__name__', None) is not None:
931
942
                excName = excClass.__name__
1028
1039
        else:
1029
1040
            self.fail('Unexpected success.  Should have failed: %s' % reason)
1030
1041
 
1031
 
    def assertFileEqual(self, content, path):
1032
 
        """Fail if path does not contain 'content'."""
1033
 
        self.failUnlessExists(path)
1034
 
        f = file(path, 'rb')
1035
 
        try:
1036
 
            s = f.read()
1037
 
        finally:
1038
 
            f.close()
1039
 
        self.assertEqualDiff(content, s)
1040
 
 
1041
 
    def failUnlessExists(self, path):
1042
 
        """Fail unless path or paths, which may be abs or relative, exist."""
1043
 
        if not isinstance(path, basestring):
1044
 
            for p in path:
1045
 
                self.failUnlessExists(p)
1046
 
        else:
1047
 
            self.failUnless(osutils.lexists(path),path+" does not exist")
1048
 
 
1049
 
    def failIfExists(self, path):
1050
 
        """Fail if path or paths, which may be abs or relative, exist."""
1051
 
        if not isinstance(path, basestring):
1052
 
            for p in path:
1053
 
                self.failIfExists(p)
1054
 
        else:
1055
 
            self.failIf(osutils.lexists(path),path+" exists")
1056
 
 
1057
1042
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1058
1043
        """A helper for callDeprecated and applyDeprecated.
1059
1044
 
1086
1071
        To test that a deprecated method raises an error, do something like
1087
1072
        this::
1088
1073
 
1089
 
            self.assertRaises(errors.ReservedId,
1090
 
                self.applyDeprecated,
1091
 
                deprecated_in((1, 5, 0)),
1092
 
                br.append_revision,
1093
 
                'current:')
 
1074
        self.assertRaises(errors.ReservedId,
 
1075
            self.applyDeprecated, zero_ninetyone,
 
1076
                br.append_revision, 'current:')
1094
1077
 
1095
1078
        :param deprecation_format: The deprecation format that the callable
1096
1079
            should have been deprecated with. This is the same type as the
1174
1157
        """
1175
1158
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1176
1159
        self._log_file = os.fdopen(fileno, 'w+')
1177
 
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
 
1160
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
1178
1161
        self._log_file_name = name
1179
1162
        self.addCleanup(self._finishLogFile)
1180
1163
 
1185
1168
        """
1186
1169
        if self._log_file is None:
1187
1170
            return
1188
 
        bzrlib.trace.pop_log_file(self._log_memento)
 
1171
        bzrlib.trace.disable_test_log(self._log_nonce)
1189
1172
        self._log_file.close()
1190
1173
        self._log_file = None
1191
1174
        if not self._keep_log_file:
1196
1179
        """Make the logfile not be deleted when _finishLogFile is called."""
1197
1180
        self._keep_log_file = True
1198
1181
 
1199
 
    def addCleanup(self, callable, *args, **kwargs):
 
1182
    def addCleanup(self, callable):
1200
1183
        """Arrange to run a callable when this case is torn down.
1201
1184
 
1202
1185
        Callables are run in the reverse of the order they are registered, 
1203
1186
        ie last-in first-out.
1204
1187
        """
1205
 
        self._cleanups.append((callable, args, kwargs))
 
1188
        if callable in self._cleanups:
 
1189
            raise ValueError("cleanup function %r already registered on %s" 
 
1190
                    % (callable, self))
 
1191
        self._cleanups.append(callable)
1206
1192
 
1207
1193
    def _cleanEnvironment(self):
1208
1194
        new_env = {
1214
1200
            'BZREMAIL': None, # may still be present in the environment
1215
1201
            'EMAIL': None,
1216
1202
            'BZR_PROGRESS_BAR': None,
1217
 
            'BZR_LOG': None,
1218
1203
            # SSH Agent
1219
1204
            'SSH_AUTH_SOCK': None,
1220
1205
            # Proxies
1269
1254
                    result.addSuccess(self)
1270
1255
                result.stopTest(self)
1271
1256
                return
1272
 
        try:
1273
 
            return unittest.TestCase.run(self, result)
1274
 
        finally:
1275
 
            saved_attrs = {}
1276
 
            absent_attr = object()
1277
 
            for attr_name in self.attrs_to_keep:
1278
 
                attr = getattr(self, attr_name, absent_attr)
1279
 
                if attr is not absent_attr:
1280
 
                    saved_attrs[attr_name] = attr
1281
 
            self.__dict__ = saved_attrs
 
1257
        return unittest.TestCase.run(self, result)
1282
1258
 
1283
1259
    def tearDown(self):
1284
1260
        self._runCleanups()
1317
1293
        # Actually pop the cleanups from the list so tearDown running
1318
1294
        # twice is safe (this happens for skipped tests).
1319
1295
        while self._cleanups:
1320
 
            cleanup, args, kwargs = self._cleanups.pop()
1321
 
            cleanup(*args, **kwargs)
 
1296
            self._cleanups.pop()()
1322
1297
 
1323
1298
    def log(self, *args):
1324
1299
        mutter(*args)
1336
1311
        import bzrlib.trace
1337
1312
        bzrlib.trace._trace_file.flush()
1338
1313
        if self._log_contents:
1339
 
            # XXX: this can hardly contain the content flushed above --vila
1340
 
            # 20080128
1341
1314
            return self._log_contents
1342
1315
        if self._log_file_name is not None:
1343
1316
            logfile = open(self._log_file_name)
1527
1500
            elif isinstance(args[0], basestring):
1528
1501
                args = list(shlex.split(args[0]))
1529
1502
        else:
1530
 
            raise ValueError("passing varargs to run_bzr_subprocess")
 
1503
            symbol_versioning.warn(zero_ninetyone %
 
1504
                                   "passing varargs to run_bzr_subprocess",
 
1505
                                   DeprecationWarning, stacklevel=3)
1531
1506
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
1532
1507
                                            working_dir=working_dir,
1533
1508
                                            allow_plugins=allow_plugins)
1589
1564
            # so we will avoid using it on all platforms, just to
1590
1565
            # make sure the code path is used, and we don't break on win32
1591
1566
            cleanup_environment()
1592
 
            command = [sys.executable]
1593
 
            # frozen executables don't need the path to bzr
1594
 
            if getattr(sys, "frozen", None) is None:
1595
 
                command.append(bzr_path)
 
1567
            command = [sys.executable, bzr_path]
1596
1568
            if not allow_plugins:
1597
1569
                command.append('--no-plugins')
1598
1570
            command.extend(process_args)
1995
1967
        b = self.make_branch(relpath, format=format)
1996
1968
        return memorytree.MemoryTree.create_on_branch(b)
1997
1969
 
1998
 
    def make_branch_builder(self, relpath, format=None):
1999
 
        url = self.get_url(relpath)
2000
 
        tran = get_transport(url)
2001
 
        return branchbuilder.BranchBuilder(get_transport(url), format=format)
2002
 
 
2003
1970
    def overrideEnvironmentForTesting(self):
2004
1971
        os.environ['HOME'] = self.test_home_dir
2005
1972
        os.environ['BZR_HOME'] = self.test_home_dir
2048
2015
            self.log("actually: %r" % contents)
2049
2016
            self.fail("contents of %s not as expected" % filename)
2050
2017
 
2051
 
    def _getTestDirPrefix(self):
2052
 
        # create a directory within the top level test directory
2053
 
        if sys.platform == 'win32':
2054
 
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
2055
 
            # windows is likely to have path-length limits so use a short name
2056
 
            name_prefix = name_prefix[-30:]
2057
 
        else:
2058
 
            name_prefix = re.sub('[/]', '_', self.id())
2059
 
        return name_prefix
2060
 
 
2061
2018
    def makeAndChdirToTestDir(self):
2062
2019
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
2063
2020
        
2064
2021
        For TestCaseInTempDir we create a temporary directory based on the test
2065
2022
        name and then create two subdirs - test and home under it.
2066
2023
        """
2067
 
        name_prefix = osutils.pathjoin(self.TEST_ROOT, self._getTestDirPrefix())
2068
 
        name = name_prefix
2069
 
        for i in range(100):
2070
 
            if os.path.exists(name):
2071
 
                name = name_prefix + '_' + str(i)
2072
 
            else:
2073
 
                os.mkdir(name)
2074
 
                break
 
2024
        # create a directory within the top level test directory
 
2025
        candidate_dir = osutils.mkdtemp(dir=self.TEST_ROOT)
2075
2026
        # now create test and home directories within this dir
2076
 
        self.test_base_dir = name
 
2027
        self.test_base_dir = candidate_dir
2077
2028
        self.test_home_dir = self.test_base_dir + '/home'
2078
2029
        os.mkdir(self.test_home_dir)
2079
2030
        self.test_dir = self.test_base_dir + '/work'
2133
2084
    def build_tree_contents(self, shape):
2134
2085
        build_tree_contents(shape)
2135
2086
 
 
2087
    def assertFileEqual(self, content, path):
 
2088
        """Fail if path does not contain 'content'."""
 
2089
        self.failUnlessExists(path)
 
2090
        f = file(path, 'rb')
 
2091
        try:
 
2092
            s = f.read()
 
2093
        finally:
 
2094
            f.close()
 
2095
        self.assertEqualDiff(content, s)
 
2096
 
 
2097
    def failUnlessExists(self, path):
 
2098
        """Fail unless path or paths, which may be abs or relative, exist."""
 
2099
        if not isinstance(path, basestring):
 
2100
            for p in path:
 
2101
                self.failUnlessExists(p)
 
2102
        else:
 
2103
            self.failUnless(osutils.lexists(path),path+" does not exist")
 
2104
 
 
2105
    def failIfExists(self, path):
 
2106
        """Fail if path or paths, which may be abs or relative, exist."""
 
2107
        if not isinstance(path, basestring):
 
2108
            for p in path:
 
2109
                self.failIfExists(p)
 
2110
        else:
 
2111
            self.failIf(osutils.lexists(path),path+" exists")
 
2112
 
2136
2113
    def assertInWorkingTree(self, path, root_path='.', tree=None):
2137
2114
        """Assert whether path or paths are in the WorkingTree"""
2138
2115
        if tree is None:
2139
2116
            tree = workingtree.WorkingTree.open(root_path)
2140
2117
        if not isinstance(path, basestring):
2141
2118
            for p in path:
2142
 
                self.assertInWorkingTree(p, tree=tree)
 
2119
                self.assertInWorkingTree(p,tree=tree)
2143
2120
        else:
2144
2121
            self.assertIsNot(tree.path2id(path), None,
2145
2122
                path+' not in working tree.')
2209
2186
                # the branch is colocated on disk, we cannot create a checkout.
2210
2187
                # hopefully callers will expect this.
2211
2188
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2212
 
                wt = local_controldir.create_workingtree()
2213
 
                if wt.branch._format != b._format:
2214
 
                    wt._branch = b
2215
 
                    # Make sure that assigning to wt._branch fixes wt.branch,
2216
 
                    # in case the implementation details of workingtree objects
2217
 
                    # change.
2218
 
                    self.assertIs(b, wt.branch)
2219
 
                return wt
 
2189
                return local_controldir.create_workingtree()
2220
2190
            else:
2221
2191
                return b.create_checkout(relpath, lightweight=True)
2222
2192
 
2291
2261
    return condition
2292
2262
 
2293
2263
 
2294
 
def condition_id_in_list(id_list):
2295
 
    """Create a condition filter which verify that test's id in a list.
2296
 
    
2297
 
    :param id_list: A TestIdList object.
2298
 
    :return: A callable that returns True if the test's id appears in the list.
2299
 
    """
2300
 
    def condition(test):
2301
 
        return id_list.includes(test.id())
2302
 
    return condition
2303
 
 
2304
 
 
2305
 
def condition_id_startswith(start):
2306
 
    """Create a condition filter verifying that test's id starts with a string.
2307
 
    
2308
 
    :param start: A string.
2309
 
    :return: A callable that returns True if the test's id starts with the
2310
 
        given string.
2311
 
    """
2312
 
    def condition(test):
2313
 
        return test.id().startswith(start)
2314
 
    return condition
2315
 
 
2316
 
 
2317
2264
def exclude_tests_by_condition(suite, condition):
2318
2265
    """Create a test suite which excludes some tests from suite.
2319
2266
 
2346
2293
    return TestUtil.TestSuite(result)
2347
2294
 
2348
2295
 
2349
 
def filter_suite_by_re(suite, pattern):
 
2296
def filter_suite_by_re(suite, pattern, exclude_pattern=DEPRECATED_PARAMETER,
 
2297
                       random_order=DEPRECATED_PARAMETER):
2350
2298
    """Create a test suite by filtering another one.
2351
2299
    
2352
2300
    :param suite:           the source suite
2353
2301
    :param pattern:         pattern that names must match
 
2302
    :param exclude_pattern: A pattern that names must not match. This parameter
 
2303
        is deprecated as of bzrlib 1.0. Please use the separate function
 
2304
        exclude_tests_by_re instead.
 
2305
    :param random_order:    If True, tests in the new suite will be put in
 
2306
        random order. This parameter is deprecated as of bzrlib 1.0. Please
 
2307
        use the separate function randomize_suite instead.
2354
2308
    :returns: the newly created suite
2355
2309
    """ 
 
2310
    if deprecated_passed(exclude_pattern):
 
2311
        symbol_versioning.warn(
 
2312
            one_zero % "passing exclude_pattern to filter_suite_by_re",
 
2313
                DeprecationWarning, stacklevel=2)
 
2314
        if exclude_pattern is not None:
 
2315
            suite = exclude_tests_by_re(suite, exclude_pattern)
2356
2316
    condition = condition_id_re(pattern)
2357
2317
    result_suite = filter_suite_by_condition(suite, condition)
2358
 
    return result_suite
2359
 
 
2360
 
 
2361
 
def filter_suite_by_id_list(suite, test_id_list):
2362
 
    """Create a test suite by filtering another one.
2363
 
 
2364
 
    :param suite: The source suite.
2365
 
    :param test_id_list: A list of the test ids to keep as strings.
2366
 
    :returns: the newly created suite
2367
 
    """
2368
 
    condition = condition_id_in_list(test_id_list)
2369
 
    result_suite = filter_suite_by_condition(suite, condition)
2370
 
    return result_suite
2371
 
 
2372
 
 
2373
 
def filter_suite_by_id_startswith(suite, start):
2374
 
    """Create a test suite by filtering another one.
2375
 
 
2376
 
    :param suite: The source suite.
2377
 
    :param start: A string the test id must start with.
2378
 
    :returns: the newly created suite
2379
 
    """
2380
 
    condition = condition_id_startswith(start)
2381
 
    result_suite = filter_suite_by_condition(suite, condition)
 
2318
    if deprecated_passed(random_order):
 
2319
        symbol_versioning.warn(
 
2320
            one_zero % "passing random_order to filter_suite_by_re",
 
2321
                DeprecationWarning, stacklevel=2)
 
2322
        if random_order:
 
2323
            result_suite = randomize_suite(result_suite)
2382
2324
    return result_suite
2383
2325
 
2384
2326
 
2416
2358
    return TestUtil.TestSuite(tests)
2417
2359
 
2418
2360
 
2419
 
def split_suite_by_condition(suite, condition):
2420
 
    """Split a test suite into two by a condition.
 
2361
@deprecated_function(one_zero)
 
2362
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
 
2363
                     random_order=False, append_rest=True):
 
2364
    """DEPRECATED: Create a test suite by sorting another one.
 
2365
 
 
2366
    This method has been decomposed into separate helper methods that should be
 
2367
    called directly:
 
2368
     - filter_suite_by_re
 
2369
     - exclude_tests_by_re
 
2370
     - randomize_suite
 
2371
     - split_suite_by_re
2421
2372
    
2422
 
    :param suite: The suite to split.
2423
 
    :param condition: The condition to match on. Tests that match this
2424
 
        condition are returned in the first test suite, ones that do not match
2425
 
        are in the second suite.
2426
 
    :return: A tuple of two test suites, where the first contains tests from
2427
 
        suite matching the condition, and the second contains the remainder
2428
 
        from suite. The order within each output suite is the same as it was in
2429
 
        suite.
 
2373
    :param suite:           the source suite
 
2374
    :param pattern:         pattern that names must match in order to go
 
2375
                            first in the new suite
 
2376
    :param exclude_pattern: pattern that names must not match, if any
 
2377
    :param random_order:    if True, tests in the new suite will be put in
 
2378
                            random order (with all tests matching pattern
 
2379
                            first).
 
2380
    :param append_rest:     if False, pattern is a strict filter and not
 
2381
                            just an ordering directive
 
2382
    :returns: the newly created suite
2430
2383
    """ 
2431
 
    matched = []
2432
 
    did_not_match = []
2433
 
    for test in iter_suite_tests(suite):
2434
 
        if condition(test):
2435
 
            matched.append(test)
2436
 
        else:
2437
 
            did_not_match.append(test)
2438
 
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
 
2384
    if exclude_pattern is not None:
 
2385
        suite = exclude_tests_by_re(suite, exclude_pattern)
 
2386
    if random_order:
 
2387
        order_changer = randomize_suite
 
2388
    else:
 
2389
        order_changer = preserve_input
 
2390
    if append_rest:
 
2391
        suites = map(order_changer, split_suite_by_re(suite, pattern))
 
2392
        return TestUtil.TestSuite(suites)
 
2393
    else:
 
2394
        return order_changer(filter_suite_by_re(suite, pattern))
2439
2395
 
2440
2396
 
2441
2397
def split_suite_by_re(suite, pattern):
2450
2406
        suite. The order within each output suite is the same as it was in
2451
2407
        suite.
2452
2408
    """ 
2453
 
    return split_suite_by_condition(suite, condition_id_re(pattern))
 
2409
    matched = []
 
2410
    did_not_match = []
 
2411
    filter_re = re.compile(pattern)
 
2412
    for test in iter_suite_tests(suite):
 
2413
        test_id = test.id()
 
2414
        if filter_re.search(test_id):
 
2415
            matched.append(test)
 
2416
        else:
 
2417
            did_not_match.append(test)
 
2418
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
2454
2419
 
2455
2420
 
2456
2421
def run_suite(suite, name='test', verbose=False, pattern=".*",
2460
2425
              list_only=False,
2461
2426
              random_seed=None,
2462
2427
              exclude_pattern=None,
2463
 
              strict=False):
 
2428
              strict=False,
 
2429
              coverage_dir=None,
 
2430
              ):
2464
2431
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2465
2432
    if verbose:
2466
2433
        verbosity = 2
2503
2470
        else:
2504
2471
            suite = order_changer(filter_suite_by_re(suite, pattern))
2505
2472
 
 
2473
    # Activate code coverage.
 
2474
    if coverage_dir is not None:
 
2475
        tracer = trace.Trace(count=1, trace=0)
 
2476
        sys.settrace(tracer.globaltrace)
 
2477
 
2506
2478
    result = runner.run(suite)
2507
2479
 
 
2480
    if coverage_dir is not None:
 
2481
        sys.settrace(None)
 
2482
        results = tracer.results()
 
2483
        results.write_results(show_missing=1, summary=False,
 
2484
                              coverdir=coverage_dir)
 
2485
 
2508
2486
    if strict:
2509
2487
        return result.wasStrictlySuccessful()
2510
2488
 
2511
2489
    return result.wasSuccessful()
2512
2490
 
2513
2491
 
2514
 
# Controlled by "bzr selftest -E=..." option
2515
 
selftest_debug_flags = set()
2516
 
 
2517
 
 
2518
2492
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
2519
2493
             transport=None,
2520
2494
             test_suite_factory=None,
2525
2499
             random_seed=None,
2526
2500
             exclude_pattern=None,
2527
2501
             strict=False,
2528
 
             load_list=None,
2529
 
             debug_flags=None,
2530
 
             starting_with=None,
 
2502
             coverage_dir=None,
2531
2503
             ):
2532
2504
    """Run the whole test suite under the enhanced runner"""
2533
2505
    # XXX: Very ugly way to do this...
2541
2513
        transport = default_transport
2542
2514
    old_transport = default_transport
2543
2515
    default_transport = transport
2544
 
    global selftest_debug_flags
2545
 
    old_debug_flags = selftest_debug_flags
2546
 
    if debug_flags is not None:
2547
 
        selftest_debug_flags = set(debug_flags)
2548
2516
    try:
2549
 
        if load_list is None:
2550
 
            keep_only = None
2551
 
        else:
2552
 
            keep_only = load_test_id_list(load_list)
2553
2517
        if test_suite_factory is None:
2554
 
            suite = test_suite(keep_only, starting_with)
 
2518
            suite = test_suite()
2555
2519
        else:
2556
2520
            suite = test_suite_factory()
2557
2521
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2563
2527
                     list_only=list_only,
2564
2528
                     random_seed=random_seed,
2565
2529
                     exclude_pattern=exclude_pattern,
2566
 
                     strict=strict)
 
2530
                     strict=strict,
 
2531
                     coverage_dir=coverage_dir)
2567
2532
    finally:
2568
2533
        default_transport = old_transport
2569
 
        selftest_debug_flags = old_debug_flags
2570
 
 
2571
 
 
2572
 
def load_test_id_list(file_name):
2573
 
    """Load a test id list from a text file.
2574
 
 
2575
 
    The format is one test id by line.  No special care is taken to impose
2576
 
    strict rules, these test ids are used to filter the test suite so a test id
2577
 
    that do not match an existing test will do no harm. This allows user to add
2578
 
    comments, leave blank lines, etc.
2579
 
    """
2580
 
    test_list = []
2581
 
    try:
2582
 
        ftest = open(file_name, 'rt')
2583
 
    except IOError, e:
2584
 
        if e.errno != errno.ENOENT:
2585
 
            raise
2586
 
        else:
2587
 
            raise errors.NoSuchFile(file_name)
2588
 
 
2589
 
    for test_name in ftest.readlines():
2590
 
        test_list.append(test_name.strip())
2591
 
    ftest.close()
2592
 
    return test_list
2593
 
 
2594
 
 
2595
 
def suite_matches_id_list(test_suite, id_list):
2596
 
    """Warns about tests not appearing or appearing more than once.
2597
 
 
2598
 
    :param test_suite: A TestSuite object.
2599
 
    :param test_id_list: The list of test ids that should be found in 
2600
 
         test_suite.
2601
 
 
2602
 
    :return: (absents, duplicates) absents is a list containing the test found
2603
 
        in id_list but not in test_suite, duplicates is a list containing the
2604
 
        test found multiple times in test_suite.
2605
 
 
2606
 
    When using a prefined test id list, it may occurs that some tests do not
2607
 
    exist anymore or that some tests use the same id. This function warns the
2608
 
    tester about potential problems in his workflow (test lists are volatile)
2609
 
    or in the test suite itself (using the same id for several tests does not
2610
 
    help to localize defects).
2611
 
    """
2612
 
    # Build a dict counting id occurrences
2613
 
    tests = dict()
2614
 
    for test in iter_suite_tests(test_suite):
2615
 
        id = test.id()
2616
 
        tests[id] = tests.get(id, 0) + 1
2617
 
 
2618
 
    not_found = []
2619
 
    duplicates = []
2620
 
    for id in id_list:
2621
 
        occurs = tests.get(id, 0)
2622
 
        if not occurs:
2623
 
            not_found.append(id)
2624
 
        elif occurs > 1:
2625
 
            duplicates.append(id)
2626
 
 
2627
 
    return not_found, duplicates
2628
 
 
2629
 
 
2630
 
class TestIdList(object):
2631
 
    """Test id list to filter a test suite.
2632
 
 
2633
 
    Relying on the assumption that test ids are built as:
2634
 
    <module>[.<class>.<method>][(<param>+)], <module> being in python dotted
2635
 
    notation, this class offers methods to :
2636
 
    - avoid building a test suite for modules not refered to in the test list,
2637
 
    - keep only the tests listed from the module test suite.
2638
 
    """
2639
 
 
2640
 
    def __init__(self, test_id_list):
2641
 
        # When a test suite needs to be filtered against us we compare test ids
2642
 
        # for equality, so a simple dict offers a quick and simple solution.
2643
 
        self.tests = dict().fromkeys(test_id_list, True)
2644
 
 
2645
 
        # While unittest.TestCase have ids like:
2646
 
        # <module>.<class>.<method>[(<param+)],
2647
 
        # doctest.DocTestCase can have ids like:
2648
 
        # <module>
2649
 
        # <module>.<class>
2650
 
        # <module>.<function>
2651
 
        # <module>.<class>.<method>
2652
 
 
2653
 
        # Since we can't predict a test class from its name only, we settle on
2654
 
        # a simple constraint: a test id always begins with its module name.
2655
 
 
2656
 
        modules = {}
2657
 
        for test_id in test_id_list:
2658
 
            parts = test_id.split('.')
2659
 
            mod_name = parts.pop(0)
2660
 
            modules[mod_name] = True
2661
 
            for part in parts:
2662
 
                mod_name += '.' + part
2663
 
                modules[mod_name] = True
2664
 
        self.modules = modules
2665
 
 
2666
 
    def refers_to(self, module_name):
2667
 
        """Is there tests for the module or one of its sub modules."""
2668
 
        return self.modules.has_key(module_name)
2669
 
 
2670
 
    def includes(self, test_id):
2671
 
        return self.tests.has_key(test_id)
2672
 
 
2673
 
 
2674
 
def test_suite(keep_only=None, starting_with=None):
 
2534
 
 
2535
 
 
2536
def test_suite():
2675
2537
    """Build and return TestSuite for the whole of bzrlib.
2676
 
 
2677
 
    :param keep_only: A list of test ids limiting the suite returned.
2678
 
 
2679
 
    :param starting_with: An id limiting the suite returned to the tests
2680
 
         starting with it.
2681
 
 
 
2538
    
2682
2539
    This function can be replaced if you need to change the default test
2683
2540
    suite on a global basis, but it is not encouraged.
2684
2541
    """
2685
2542
    testmod_names = [
2686
 
                   'bzrlib.doc',
2687
2543
                   'bzrlib.util.tests.test_bencode',
2688
 
                   'bzrlib.tests.blackbox',
2689
 
                   'bzrlib.tests.branch_implementations',
2690
 
                   'bzrlib.tests.bzrdir_implementations',
2691
 
                   'bzrlib.tests.commands',
2692
 
                   'bzrlib.tests.inventory_implementations',
2693
 
                   'bzrlib.tests.interrepository_implementations',
2694
 
                   'bzrlib.tests.intertree_implementations',
2695
 
                   'bzrlib.tests.per_lock',
2696
 
                   'bzrlib.tests.repository_implementations',
2697
2544
                   'bzrlib.tests.test__dirstate_helpers',
2698
2545
                   'bzrlib.tests.test_ancestry',
2699
2546
                   'bzrlib.tests.test_annotate',
2703
2550
                   'bzrlib.tests.test_bisect_multi',
2704
2551
                   'bzrlib.tests.test_branch',
2705
2552
                   'bzrlib.tests.test_branchbuilder',
2706
 
                   'bzrlib.tests.test_btree_index',
2707
2553
                   'bzrlib.tests.test_bugtracker',
2708
2554
                   'bzrlib.tests.test_bundle',
2709
2555
                   'bzrlib.tests.test_bzrdir',
2710
2556
                   'bzrlib.tests.test_cache_utf8',
2711
 
                   'bzrlib.tests.test_chunk_writer',
2712
2557
                   'bzrlib.tests.test_commands',
2713
2558
                   'bzrlib.tests.test_commit',
2714
2559
                   'bzrlib.tests.test_commit_merge',
2720
2565
                   'bzrlib.tests.test_deprecated_graph',
2721
2566
                   'bzrlib.tests.test_diff',
2722
2567
                   'bzrlib.tests.test_dirstate',
2723
 
                   'bzrlib.tests.test_directory_service',
2724
2568
                   'bzrlib.tests.test_email_message',
2725
2569
                   'bzrlib.tests.test_errors',
 
2570
                   'bzrlib.tests.test_escaped_store',
2726
2571
                   'bzrlib.tests.test_extract',
2727
2572
                   'bzrlib.tests.test_fetch',
2728
2573
                   'bzrlib.tests.test_ftp_transport',
2735
2580
                   'bzrlib.tests.test_help',
2736
2581
                   'bzrlib.tests.test_hooks',
2737
2582
                   'bzrlib.tests.test_http',
2738
 
                   'bzrlib.tests.test_http_implementations',
2739
2583
                   'bzrlib.tests.test_http_response',
2740
2584
                   'bzrlib.tests.test_https_ca_bundle',
2741
2585
                   'bzrlib.tests.test_identitymap',
2760
2604
                   'bzrlib.tests.test_missing',
2761
2605
                   'bzrlib.tests.test_msgeditor',
2762
2606
                   'bzrlib.tests.test_multiparent',
2763
 
                   'bzrlib.tests.test_mutabletree',
2764
2607
                   'bzrlib.tests.test_nonascii',
2765
2608
                   'bzrlib.tests.test_options',
2766
2609
                   'bzrlib.tests.test_osutils',
2767
2610
                   'bzrlib.tests.test_osutils_encodings',
2768
2611
                   'bzrlib.tests.test_pack',
2769
 
                   'bzrlib.tests.test_pack_repository',
2770
2612
                   'bzrlib.tests.test_patch',
2771
2613
                   'bzrlib.tests.test_patches',
2772
2614
                   'bzrlib.tests.test_permissions',
2773
2615
                   'bzrlib.tests.test_plugins',
2774
2616
                   'bzrlib.tests.test_progress',
2775
 
                   'bzrlib.tests.test_read_bundle',
2776
2617
                   'bzrlib.tests.test_reconfigure',
2777
2618
                   'bzrlib.tests.test_reconcile',
2778
2619
                   'bzrlib.tests.test_registry',
2779
2620
                   'bzrlib.tests.test_remote',
2780
2621
                   'bzrlib.tests.test_repository',
2781
 
                   'bzrlib.tests.per_repository_reference',
2782
2622
                   'bzrlib.tests.test_revert',
2783
2623
                   'bzrlib.tests.test_revision',
2784
 
                   'bzrlib.tests.test_revisionspec',
 
2624
                   'bzrlib.tests.test_revisionnamespaces',
2785
2625
                   'bzrlib.tests.test_revisiontree',
2786
2626
                   'bzrlib.tests.test_rio',
2787
 
                   'bzrlib.tests.test_rules',
2788
2627
                   'bzrlib.tests.test_sampler',
2789
2628
                   'bzrlib.tests.test_selftest',
2790
2629
                   'bzrlib.tests.test_setup',
2810
2649
                   'bzrlib.tests.test_transactions',
2811
2650
                   'bzrlib.tests.test_transform',
2812
2651
                   'bzrlib.tests.test_transport',
2813
 
                   'bzrlib.tests.test_transport_implementations',
2814
2652
                   'bzrlib.tests.test_tree',
2815
2653
                   'bzrlib.tests.test_treebuilder',
2816
2654
                   'bzrlib.tests.test_tsort',
2817
2655
                   'bzrlib.tests.test_tuned_gzip',
2818
2656
                   'bzrlib.tests.test_ui',
2819
 
                   'bzrlib.tests.test_uncommit',
2820
2657
                   'bzrlib.tests.test_upgrade',
2821
 
                   'bzrlib.tests.test_upgrade_stacked',
2822
2658
                   'bzrlib.tests.test_urlutils',
2823
2659
                   'bzrlib.tests.test_versionedfile',
2824
2660
                   'bzrlib.tests.test_version',
2825
2661
                   'bzrlib.tests.test_version_info',
2826
 
                   'bzrlib.tests.test__walkdirs_win32',
2827
2662
                   'bzrlib.tests.test_weave',
2828
2663
                   'bzrlib.tests.test_whitebox',
2829
2664
                   'bzrlib.tests.test_win32utils',
2831
2666
                   'bzrlib.tests.test_workingtree_4',
2832
2667
                   'bzrlib.tests.test_wsgi',
2833
2668
                   'bzrlib.tests.test_xml',
2834
 
                   'bzrlib.tests.tree_implementations',
2835
 
                   'bzrlib.tests.workingtree_implementations',
2836
2669
                   ]
2837
 
 
 
2670
    test_transport_implementations = [
 
2671
        'bzrlib.tests.test_transport_implementations',
 
2672
        'bzrlib.tests.test_read_bundle',
 
2673
        ]
 
2674
    suite = TestUtil.TestSuite()
2838
2675
    loader = TestUtil.TestLoader()
2839
 
 
2840
 
    if starting_with is not None:
2841
 
        # We take precedence over keep_only because *at loading time* using
2842
 
        # both options means we will load less tests for the same final result.
2843
 
        def interesting_module(name):
2844
 
            return (
2845
 
                # Either the module name starts with the specified string
2846
 
                name.startswith(starting_with)
2847
 
                # or it may contain tests starting with the specified string
2848
 
                or starting_with.startswith(name)
2849
 
                )
2850
 
        loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
2851
 
 
2852
 
    elif keep_only is not None:
2853
 
        id_filter = TestIdList(keep_only)
2854
 
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
2855
 
        def interesting_module(name):
2856
 
            return id_filter.refers_to(name)
2857
 
 
2858
 
    else:
2859
 
        loader = TestUtil.TestLoader()
2860
 
        def interesting_module(name):
2861
 
            # No filtering, all modules are interesting
2862
 
            return True
2863
 
 
2864
 
    suite = loader.suiteClass()
2865
 
 
2866
 
    # modules building their suite with loadTestsFromModuleNames
2867
2676
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2868
 
 
2869
 
    modules_to_doctest = [
2870
 
        'bzrlib',
2871
 
        'bzrlib.errors',
2872
 
        'bzrlib.export',
2873
 
        'bzrlib.inventory',
2874
 
        'bzrlib.iterablefile',
2875
 
        'bzrlib.lockdir',
2876
 
        'bzrlib.merge3',
2877
 
        'bzrlib.option',
2878
 
        'bzrlib.store',
2879
 
        'bzrlib.symbol_versioning',
2880
 
        'bzrlib.tests',
2881
 
        'bzrlib.timestamp',
2882
 
        'bzrlib.version_info_formats.format_custom',
2883
 
        ]
2884
 
 
2885
 
    for mod in modules_to_doctest:
2886
 
        if not interesting_module(mod):
2887
 
            # No tests to keep here, move along
2888
 
            continue
 
2677
    from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
 
2678
    adapter = TransportTestProviderAdapter()
 
2679
    adapt_modules(test_transport_implementations, adapter, loader, suite)
 
2680
    for package in packages_to_test():
 
2681
        suite.addTest(package.test_suite())
 
2682
    for m in MODULES_TO_TEST:
 
2683
        suite.addTest(loader.loadTestsFromModule(m))
 
2684
    for m in MODULES_TO_DOCTEST:
2889
2685
        try:
2890
 
            doc_suite = doctest.DocTestSuite(mod)
 
2686
            suite.addTest(doctest.DocTestSuite(m))
2891
2687
        except ValueError, e:
2892
 
            print '**failed to get doctest for: %s\n%s' % (mod, e)
 
2688
            print '**failed to get doctest for: %s\n%s' %(m,e)
2893
2689
            raise
2894
 
        suite.addTest(doc_suite)
2895
 
 
2896
2690
    default_encoding = sys.getdefaultencoding()
2897
2691
    for name, plugin in bzrlib.plugin.plugins().items():
2898
 
        if not interesting_module(plugin.module.__name__):
2899
 
            continue
2900
 
        plugin_suite = plugin.test_suite()
2901
 
        # We used to catch ImportError here and turn it into just a warning,
2902
 
        # but really if you don't have --no-plugins this should be a failure.
2903
 
        # mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
2904
 
        if plugin_suite is None:
2905
 
            plugin_suite = plugin.load_plugin_tests(loader)
2906
 
        if plugin_suite is not None:
2907
 
            suite.addTest(plugin_suite)
 
2692
        try:
 
2693
            plugin_suite = plugin.test_suite()
 
2694
        except ImportError, e:
 
2695
            bzrlib.trace.warning(
 
2696
                'Unable to test plugin "%s": %s', name, e)
 
2697
        else:
 
2698
            if plugin_suite is not None:
 
2699
                suite.addTest(plugin_suite)
2908
2700
        if default_encoding != sys.getdefaultencoding():
2909
2701
            bzrlib.trace.warning(
2910
2702
                'Plugin "%s" tried to reset default encoding to: %s', name,
2911
2703
                sys.getdefaultencoding())
2912
2704
            reload(sys)
2913
2705
            sys.setdefaultencoding(default_encoding)
2914
 
 
2915
 
    if starting_with is not None:
2916
 
        suite = filter_suite_by_id_startswith(suite, starting_with)
2917
 
 
2918
 
    if keep_only is not None:
2919
 
        # Now that the referred modules have loaded their tests, keep only the
2920
 
        # requested ones.
2921
 
        suite = filter_suite_by_id_list(suite, id_filter)
2922
 
        # Do some sanity checks on the id_list filtering
2923
 
        not_found, duplicates = suite_matches_id_list(suite, keep_only)
2924
 
        if starting_with is not None:
2925
 
            # The tester has used both keep_only and starting_with, so he is
2926
 
            # already aware that some tests are excluded from the list, there
2927
 
            # is no need to tell him which.
2928
 
            pass
2929
 
        else:
2930
 
            # Some tests mentioned in the list are not in the test suite. The
2931
 
            # list may be out of date, report to the tester.
2932
 
            for id in not_found:
2933
 
                bzrlib.trace.warning('"%s" not found in the test suite', id)
2934
 
        for id in duplicates:
2935
 
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
2936
 
 
2937
2706
    return suite
2938
2707
 
2939
2708
 
2940
 
def multiply_tests_from_modules(module_name_list, scenario_iter, loader=None):
 
2709
def multiply_tests_from_modules(module_name_list, scenario_iter):
2941
2710
    """Adapt all tests in some given modules to given scenarios.
2942
2711
 
2943
2712
    This is the recommended public interface for test parameterization.
2949
2718
        modules.
2950
2719
    :param scenario_iter: Iterable of pairs of (scenario_name, 
2951
2720
        scenario_param_dict).
2952
 
    :param loader: If provided, will be used instead of a new 
2953
 
        bzrlib.tests.TestLoader() instance.
2954
2721
 
2955
2722
    This returns a new TestSuite containing the cross product of
2956
2723
    all the tests in all the modules, each repeated for each scenario.
2972
2739
    >>> tests[1].param
2973
2740
    2
2974
2741
    """
2975
 
    # XXX: Isn't load_tests() a better way to provide the same functionality
2976
 
    # without forcing a predefined TestScenarioApplier ? --vila 080215
2977
 
    if loader is None:
2978
 
        loader = TestUtil.TestLoader()
2979
 
 
2980
 
    suite = loader.suiteClass()
2981
 
 
 
2742
    loader = TestLoader()
 
2743
    suite = TestSuite()
2982
2744
    adapter = TestScenarioApplier()
2983
2745
    adapter.scenarios = list(scenario_iter)
2984
2746
    adapt_modules(module_name_list, adapter, loader, suite)
3002
2764
 
3003
2765
def adapt_modules(mods_list, adapter, loader, suite):
3004
2766
    """Adapt the modules in mods_list using adapter and add to suite."""
3005
 
    tests = loader.loadTestsFromModuleNames(mods_list)
3006
 
    adapt_tests(tests, adapter, suite)
3007
 
 
3008
 
 
3009
 
def adapt_tests(tests_list, adapter, suite):
 
2767
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
 
2768
        suite.addTests(adapter.adapt(test))
 
2769
 
 
2770
 
 
2771
def adapt_tests(tests_list, adapter, loader, suite):
3010
2772
    """Adapt the tests in tests_list using adapter and add to suite."""
3011
 
    for test in iter_suite_tests(tests_list):
3012
 
        suite.addTests(adapter.adapt(test))
 
2773
    for test in tests_list:
 
2774
        suite.addTests(adapter.adapt(loader.loadTestsFromName(test)))
3013
2775
 
3014
2776
 
3015
2777
def _rmtree_temp_dir(dirname):
3074
2836
SymlinkFeature = _SymlinkFeature()
3075
2837
 
3076
2838
 
3077
 
class _HardlinkFeature(Feature):
3078
 
 
3079
 
    def _probe(self):
3080
 
        return osutils.has_hardlinks()
3081
 
 
3082
 
    def feature_name(self):
3083
 
        return 'hardlinks'
3084
 
 
3085
 
HardlinkFeature = _HardlinkFeature()
3086
 
 
3087
 
 
3088
2839
class _OsFifoFeature(Feature):
3089
2840
 
3090
2841
    def _probe(self):
3096
2847
OsFifoFeature = _OsFifoFeature()
3097
2848
 
3098
2849
 
3099
 
class _UnicodeFilenameFeature(Feature):
3100
 
    """Does the filesystem support Unicode filenames?"""
3101
 
 
3102
 
    def _probe(self):
3103
 
        try:
3104
 
            # Check for character combinations unlikely to be covered by any
3105
 
            # single non-unicode encoding. We use the characters
3106
 
            # - greek small letter alpha (U+03B1) and
3107
 
            # - braille pattern dots-123456 (U+283F).
3108
 
            os.stat(u'\u03b1\u283f')
3109
 
        except UnicodeEncodeError:
3110
 
            return False
3111
 
        except (IOError, OSError):
3112
 
            # The filesystem allows the Unicode filename but the file doesn't
3113
 
            # exist.
3114
 
            return True
3115
 
        else:
3116
 
            # The filesystem allows the Unicode filename and the file exists,
3117
 
            # for some reason.
3118
 
            return True
3119
 
 
3120
 
UnicodeFilenameFeature = _UnicodeFilenameFeature()
3121
 
 
3122
 
 
3123
2850
class TestScenarioApplier(object):
3124
2851
    """A tool to apply scenarios to tests."""
3125
2852
 
3202
2929
FTPServerFeature = _FTPServerFeature()
3203
2930
 
3204
2931
 
3205
 
class _UnicodeFilename(Feature):
3206
 
    """Does the filesystem support Unicode filenames?"""
3207
 
 
3208
 
    def _probe(self):
3209
 
        try:
3210
 
            os.stat(u'\u03b1')
3211
 
        except UnicodeEncodeError:
3212
 
            return False
3213
 
        except (IOError, OSError):
3214
 
            # The filesystem allows the Unicode filename but the file doesn't
3215
 
            # exist.
3216
 
            return True
3217
 
        else:
3218
 
            # The filesystem allows the Unicode filename and the file exists,
3219
 
            # for some reason.
3220
 
            return True
3221
 
 
3222
 
UnicodeFilename = _UnicodeFilename()
3223
 
 
3224
 
 
3225
 
class _UTF8Filesystem(Feature):
3226
 
    """Is the filesystem UTF-8?"""
3227
 
 
3228
 
    def _probe(self):
3229
 
        if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
3230
 
            return True
3231
 
        return False
3232
 
 
3233
 
UTF8Filesystem = _UTF8Filesystem()
3234
 
 
3235
 
 
3236
2932
class _CaseInsensitiveFilesystemFeature(Feature):
3237
2933
    """Check if underlined filesystem is case-insensitive
3238
2934
    (e.g. on Windows, Cygwin, MacOS)