~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Aaron Bentley
  • Date: 2008-03-03 16:52:41 UTC
  • mfrom: (3144.3.11 fix-conflict-handling)
  • mto: This revision was merged to the branch mainline in revision 3250.
  • Revision ID: aaron@aaronbentley.com-20080303165241-0k2c7ggs6kr9q6hf
Merge with fix-conflict-handling

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
from subprocess import Popen, PIPE
43
43
import sys
44
44
import tempfile
45
 
import threading
46
45
import time
47
46
import unittest
48
47
import warnings
49
48
 
50
49
 
51
50
from bzrlib import (
52
 
    branchbuilder,
53
51
    bzrdir,
54
52
    debug,
55
53
    errors,
58
56
    progress,
59
57
    ui,
60
58
    urlutils,
61
 
    registry,
62
59
    workingtree,
63
60
    )
64
61
import bzrlib.branch
76
73
from bzrlib.merge import merge_inner
77
74
import bzrlib.merge3
78
75
import bzrlib.plugin
 
76
from bzrlib.revision import common_ancestor
79
77
import bzrlib.store
80
78
from bzrlib import symbol_versioning
81
79
from bzrlib.symbol_versioning import (
83
81
    deprecated_function,
84
82
    deprecated_method,
85
83
    deprecated_passed,
 
84
    zero_ninetyone,
 
85
    zero_ninetytwo,
 
86
    one_zero,
86
87
    )
87
88
import bzrlib.trace
88
89
from bzrlib.transport import get_transport
108
109
 
109
110
default_transport = LocalURLServer
110
111
 
 
112
MODULES_TO_TEST = []
 
113
MODULES_TO_DOCTEST = [
 
114
        bzrlib.timestamp,
 
115
        bzrlib.errors,
 
116
        bzrlib.export,
 
117
        bzrlib.inventory,
 
118
        bzrlib.iterablefile,
 
119
        bzrlib.lockdir,
 
120
        bzrlib.merge3,
 
121
        bzrlib.option,
 
122
        bzrlib.store,
 
123
        bzrlib.version_info_formats.format_custom,
 
124
        # quoted to avoid module-loading circularity
 
125
        'bzrlib.tests',
 
126
        ]
 
127
 
 
128
 
 
129
def packages_to_test():
 
130
    """Return a list of packages to test.
 
131
 
 
132
    The packages are not globally imported so that import failures are
 
133
    triggered when running selftest, not when importing the command.
 
134
    """
 
135
    import bzrlib.doc
 
136
    import bzrlib.tests.blackbox
 
137
    import bzrlib.tests.branch_implementations
 
138
    import bzrlib.tests.bzrdir_implementations
 
139
    import bzrlib.tests.commands
 
140
    import bzrlib.tests.interrepository_implementations
 
141
    import bzrlib.tests.interversionedfile_implementations
 
142
    import bzrlib.tests.intertree_implementations
 
143
    import bzrlib.tests.inventory_implementations
 
144
    import bzrlib.tests.per_lock
 
145
    import bzrlib.tests.repository_implementations
 
146
    import bzrlib.tests.revisionstore_implementations
 
147
    import bzrlib.tests.tree_implementations
 
148
    import bzrlib.tests.workingtree_implementations
 
149
    return [
 
150
            bzrlib.doc,
 
151
            bzrlib.tests.blackbox,
 
152
            bzrlib.tests.branch_implementations,
 
153
            bzrlib.tests.bzrdir_implementations,
 
154
            bzrlib.tests.commands,
 
155
            bzrlib.tests.interrepository_implementations,
 
156
            bzrlib.tests.interversionedfile_implementations,
 
157
            bzrlib.tests.intertree_implementations,
 
158
            bzrlib.tests.inventory_implementations,
 
159
            bzrlib.tests.per_lock,
 
160
            bzrlib.tests.repository_implementations,
 
161
            bzrlib.tests.revisionstore_implementations,
 
162
            bzrlib.tests.tree_implementations,
 
163
            bzrlib.tests.workingtree_implementations,
 
164
            ]
 
165
 
111
166
 
112
167
class ExtendedTestResult(unittest._TextTestResult):
113
168
    """Accepts, reports and accumulates the results of running tests.
220
275
        elif isinstance(err[1], UnavailableFeature):
221
276
            return self.addNotSupported(test, err[1].args[0])
222
277
        else:
 
278
            self._cleanupLogFile(test)
223
279
            unittest.TestResult.addError(self, test, err)
224
280
            self.error_count += 1
225
281
            self.report_error(test, err)
226
282
            if self.stop_early:
227
283
                self.stop()
228
 
            self._cleanupLogFile(test)
229
284
 
230
285
    def addFailure(self, test, err):
231
286
        """Tell result that test failed.
237
292
        if isinstance(err[1], KnownFailure):
238
293
            return self._addKnownFailure(test, err)
239
294
        else:
 
295
            self._cleanupLogFile(test)
240
296
            unittest.TestResult.addFailure(self, test, err)
241
297
            self.failure_count += 1
242
298
            self.report_failure(test, err)
243
299
            if self.stop_early:
244
300
                self.stop()
245
 
            self._cleanupLogFile(test)
246
301
 
247
302
    def addSuccess(self, test):
248
303
        """Tell result that test completed successfully.
259
314
        self.report_success(test)
260
315
        self._cleanupLogFile(test)
261
316
        unittest.TestResult.addSuccess(self, test)
262
 
        test._log_contents = ''
263
317
 
264
318
    def _testConcluded(self, test):
265
319
        """Common code when a test has finished.
302
356
            # seems best to treat this as success from point-of-view of unittest
303
357
            # -- it actually does nothing so it barely matters :)
304
358
            unittest.TestResult.addSuccess(self, test)
305
 
            test._log_contents = ''
306
359
 
307
360
    def printErrorList(self, flavour, errors):
308
361
        for test, err in errors:
363
416
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
364
417
 
365
418
    def _progress_prefix_text(self):
366
 
        # the longer this text, the less space we have to show the test
367
 
        # name...
368
 
        a = '[%d' % self.count              # total that have been run
369
 
        # tests skipped as known not to be relevant are not important enough
370
 
        # to show here
371
 
        ## if self.skip_count:
372
 
        ##     a += ', %d skip' % self.skip_count
373
 
        ## if self.known_failure_count:
374
 
        ##     a += '+%dX' % self.known_failure_count
 
419
        a = '[%d' % self.count
375
420
        if self.num_tests is not None:
376
421
            a +='/%d' % self.num_tests
377
 
        a += ' in '
378
 
        runtime = time.time() - self._overall_start_time
379
 
        if runtime >= 60:
380
 
            a += '%dm%ds' % (runtime / 60, runtime % 60)
381
 
        else:
382
 
            a += '%ds' % runtime
 
422
        a += ' in %ds' % (time.time() - self._overall_start_time)
383
423
        if self.error_count:
384
 
            a += ', %d err' % self.error_count
 
424
            a += ', %d errors' % self.error_count
385
425
        if self.failure_count:
386
 
            a += ', %d fail' % self.failure_count
 
426
            a += ', %d failed' % self.failure_count
 
427
        if self.known_failure_count:
 
428
            a += ', %d known failures' % self.known_failure_count
 
429
        if self.skip_count:
 
430
            a += ', %d skipped' % self.skip_count
387
431
        if self.unsupported:
388
 
            a += ', %d missing' % len(self.unsupported)
 
432
            a += ', %d missing features' % len(self.unsupported)
389
433
        a += ']'
390
434
        return a
391
435
 
719
763
        return password
720
764
 
721
765
 
722
 
def _report_leaked_threads():
723
 
    bzrlib.trace.warning('%s is leaking threads among %d leaking tests',
724
 
                         TestCase._first_thread_leaker_id,
725
 
                         TestCase._leaking_threads_tests)
726
 
 
727
 
 
728
766
class TestCase(unittest.TestCase):
729
767
    """Base class for bzr unit tests.
730
768
    
746
784
    accidentally overlooked.
747
785
    """
748
786
 
749
 
    _active_threads = None
750
 
    _leaking_threads_tests = 0
751
 
    _first_thread_leaker_id = None
752
787
    _log_file_name = None
753
788
    _log_contents = ''
754
789
    _keep_log_file = False
755
790
    # record lsprof data when performing benchmark calls.
756
791
    _gather_lsprof_in_benchmarks = False
757
 
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
758
 
                     '_log_contents', '_log_file_name', '_benchtime',
759
 
                     '_TestCase__testMethodName')
760
792
 
761
793
    def __init__(self, methodName='testMethod'):
762
794
        super(TestCase, self).__init__(methodName)
771
803
        self._benchtime = None
772
804
        self._clear_hooks()
773
805
        self._clear_debug_flags()
774
 
        TestCase._active_threads = threading.activeCount()
775
 
        self.addCleanup(self._check_leaked_threads)
776
 
 
777
 
    def _check_leaked_threads(self):
778
 
        active = threading.activeCount()
779
 
        leaked_threads = active - TestCase._active_threads
780
 
        TestCase._active_threads = active
781
 
        if leaked_threads:
782
 
            TestCase._leaking_threads_tests += 1
783
 
            if TestCase._first_thread_leaker_id is None:
784
 
                TestCase._first_thread_leaker_id = self.id()
785
 
                # we're not specifically told when all tests are finished.
786
 
                # This will do. We use a function to avoid keeping a reference
787
 
                # to a TestCase object.
788
 
                atexit.register(_report_leaked_threads)
789
806
 
790
807
    def _clear_debug_flags(self):
791
808
        """Prevent externally set debug flags affecting tests.
792
 
 
 
809
        
793
810
        Tests that want to use debug flags can just set them in the
794
811
        debug_flags set during setup/teardown.
795
812
        """
796
813
        self._preserved_debug_flags = set(debug.debug_flags)
797
 
        if 'allow_debug' not in selftest_debug_flags:
798
 
            debug.debug_flags.clear()
 
814
        debug.debug_flags.clear()
799
815
        self.addCleanup(self._restore_debug_flags)
800
816
 
801
817
    def _clear_hooks(self):
802
818
        # prevent hooks affecting tests
803
819
        import bzrlib.branch
804
 
        import bzrlib.smart.client
805
820
        import bzrlib.smart.server
806
821
        self._preserved_hooks = {
807
822
            bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
808
 
            bzrlib.mutabletree.MutableTree: bzrlib.mutabletree.MutableTree.hooks,
809
 
            bzrlib.smart.client._SmartClient: bzrlib.smart.client._SmartClient.hooks,
810
823
            bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
811
 
            bzrlib.commands.Command: bzrlib.commands.Command.hooks,
812
824
            }
813
825
        self.addCleanup(self._restoreHooks)
814
826
        # reset all hooks to an empty instance of the appropriate type
815
827
        bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
816
 
        bzrlib.smart.client._SmartClient.hooks = bzrlib.smart.client.SmartClientHooks()
817
828
        bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
818
 
        bzrlib.commands.Command.hooks = bzrlib.commands.CommandHooks()
819
829
 
820
830
    def _silenceUI(self):
821
831
        """Turn off UI for duration of test"""
868
878
            return
869
879
        if message is None:
870
880
            message = "texts not equal:\n"
871
 
        if a == b + '\n':
872
 
            message = 'first string is missing a final newline.\n'
873
 
        if a + '\n' == b:
874
 
            message = 'second string is missing a final newline.\n'
875
881
        raise AssertionError(message +
876
882
                             self._ndiff_strings(a, b))
877
883
        
879
885
        self.assertEqual(mode, mode_test,
880
886
                         'mode mismatch %o != %o' % (mode, mode_test))
881
887
 
882
 
    def assertEqualStat(self, expected, actual):
883
 
        """assert that expected and actual are the same stat result.
884
 
 
885
 
        :param expected: A stat result.
886
 
        :param actual: A stat result.
887
 
        :raises AssertionError: If the expected and actual stat values differ
888
 
            other than by atime.
889
 
        """
890
 
        self.assertEqual(expected.st_size, actual.st_size)
891
 
        self.assertEqual(expected.st_mtime, actual.st_mtime)
892
 
        self.assertEqual(expected.st_ctime, actual.st_ctime)
893
 
        self.assertEqual(expected.st_dev, actual.st_dev)
894
 
        self.assertEqual(expected.st_ino, actual.st_ino)
895
 
        self.assertEqual(expected.st_mode, actual.st_mode)
896
 
 
897
888
    def assertPositive(self, val):
898
889
        """Assert that val is greater than 0."""
899
890
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
911
902
        if not s.endswith(suffix):
912
903
            raise AssertionError('string %r does not end with %r' % (s, suffix))
913
904
 
914
 
    def assertContainsRe(self, haystack, needle_re, flags=0):
 
905
    def assertContainsRe(self, haystack, needle_re):
915
906
        """Assert that a contains something matching a regular expression."""
916
 
        if not re.search(needle_re, haystack, flags):
 
907
        if not re.search(needle_re, haystack):
917
908
            if '\n' in haystack or len(haystack) > 60:
918
909
                # a long string, format it in a more readable way
919
910
                raise AssertionError(
923
914
                raise AssertionError('pattern "%s" not found in "%s"'
924
915
                        % (needle_re, haystack))
925
916
 
926
 
    def assertNotContainsRe(self, haystack, needle_re, flags=0):
 
917
    def assertNotContainsRe(self, haystack, needle_re):
927
918
        """Assert that a does not match a regular expression"""
928
 
        if re.search(needle_re, haystack, flags):
 
919
        if re.search(needle_re, haystack):
929
920
            raise AssertionError('pattern "%s" found in "%s"'
930
921
                    % (needle_re, haystack))
931
922
 
945
936
        """
946
937
        try:
947
938
            list(func(*args, **kwargs))
948
 
        except excClass, e:
949
 
            return e
 
939
        except excClass:
 
940
            return
950
941
        else:
951
942
            if getattr(excClass,'__name__', None) is not None:
952
943
                excName = excClass.__name__
1107
1098
        To test that a deprecated method raises an error, do something like
1108
1099
        this::
1109
1100
 
1110
 
            self.assertRaises(errors.ReservedId,
1111
 
                self.applyDeprecated,
1112
 
                deprecated_in((1, 5, 0)),
1113
 
                br.append_revision,
1114
 
                'current:')
 
1101
        self.assertRaises(errors.ReservedId,
 
1102
            self.applyDeprecated, zero_ninetyone,
 
1103
                br.append_revision, 'current:')
1115
1104
 
1116
1105
        :param deprecation_format: The deprecation format that the callable
1117
1106
            should have been deprecated with. This is the same type as the
1151
1140
        # warnings.  It's the easiest way to insulate ourselves from -Werror,
1152
1141
        # though.  -- Andrew, 20071062
1153
1142
        wlist = []
1154
 
        def _catcher(message, category, filename, lineno, file=None, line=None):
 
1143
        def _catcher(message, category, filename, lineno, file=None):
1155
1144
            # despite the name, 'message' is normally(?) a Warning subclass
1156
1145
            # instance
1157
1146
            wlist.append(message)
1217
1206
        """Make the logfile not be deleted when _finishLogFile is called."""
1218
1207
        self._keep_log_file = True
1219
1208
 
1220
 
    def addCleanup(self, callable, *args, **kwargs):
 
1209
    def addCleanup(self, callable):
1221
1210
        """Arrange to run a callable when this case is torn down.
1222
1211
 
1223
1212
        Callables are run in the reverse of the order they are registered, 
1224
1213
        ie last-in first-out.
1225
1214
        """
1226
 
        self._cleanups.append((callable, args, kwargs))
 
1215
        if callable in self._cleanups:
 
1216
            raise ValueError("cleanup function %r already registered on %s" 
 
1217
                    % (callable, self))
 
1218
        self._cleanups.append(callable)
1227
1219
 
1228
1220
    def _cleanEnvironment(self):
1229
1221
        new_env = {
1230
1222
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1231
1223
            'HOME': os.getcwd(),
1232
 
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
1233
 
            # tests do check our impls match APPDATA
 
1224
            'APPDATA': None,  # bzr now use Win32 API and don't rely on APPDATA
1234
1225
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
1235
1226
            'BZR_EMAIL': None,
1236
1227
            'BZREMAIL': None, # may still be present in the environment
1237
1228
            'EMAIL': None,
1238
1229
            'BZR_PROGRESS_BAR': None,
1239
1230
            'BZR_LOG': None,
1240
 
            'BZR_PLUGIN_PATH': None,
1241
1231
            # SSH Agent
1242
1232
            'SSH_AUTH_SOCK': None,
1243
1233
            # Proxies
1292
1282
                    result.addSuccess(self)
1293
1283
                result.stopTest(self)
1294
1284
                return
1295
 
        try:
1296
 
            return unittest.TestCase.run(self, result)
1297
 
        finally:
1298
 
            saved_attrs = {}
1299
 
            absent_attr = object()
1300
 
            for attr_name in self.attrs_to_keep:
1301
 
                attr = getattr(self, attr_name, absent_attr)
1302
 
                if attr is not absent_attr:
1303
 
                    saved_attrs[attr_name] = attr
1304
 
            self.__dict__ = saved_attrs
 
1285
        return unittest.TestCase.run(self, result)
1305
1286
 
1306
1287
    def tearDown(self):
1307
1288
        self._runCleanups()
1340
1321
        # Actually pop the cleanups from the list so tearDown running
1341
1322
        # twice is safe (this happens for skipped tests).
1342
1323
        while self._cleanups:
1343
 
            cleanup, args, kwargs = self._cleanups.pop()
1344
 
            cleanup(*args, **kwargs)
 
1324
            self._cleanups.pop()()
1345
1325
 
1346
1326
    def log(self, *args):
1347
1327
        mutter(*args)
1357
1337
        """
1358
1338
        # flush the log file, to get all content
1359
1339
        import bzrlib.trace
1360
 
        if bzrlib.trace._trace_file:
1361
 
            bzrlib.trace._trace_file.flush()
 
1340
        bzrlib.trace._trace_file.flush()
1362
1341
        if self._log_contents:
1363
1342
            # XXX: this can hardly contain the content flushed above --vila
1364
1343
            # 20080128
1405
1384
    def _run_bzr_core(self, args, retcode, encoding, stdin,
1406
1385
            working_dir):
1407
1386
        if encoding is None:
1408
 
            encoding = osutils.get_user_encoding()
 
1387
            encoding = bzrlib.user_encoding
1409
1388
        stdout = StringIOWrapper()
1410
1389
        stderr = StringIOWrapper()
1411
1390
        stdout.encoding = encoding
1551
1530
            elif isinstance(args[0], basestring):
1552
1531
                args = list(shlex.split(args[0]))
1553
1532
        else:
1554
 
            raise ValueError("passing varargs to run_bzr_subprocess")
 
1533
            symbol_versioning.warn(zero_ninetyone %
 
1534
                                   "passing varargs to run_bzr_subprocess",
 
1535
                                   DeprecationWarning, stacklevel=3)
1555
1536
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
1556
1537
                                            working_dir=working_dir,
1557
1538
                                            allow_plugins=allow_plugins)
1613
1594
            # so we will avoid using it on all platforms, just to
1614
1595
            # make sure the code path is used, and we don't break on win32
1615
1596
            cleanup_environment()
1616
 
            command = [sys.executable]
1617
 
            # frozen executables don't need the path to bzr
1618
 
            if getattr(sys, "frozen", None) is None:
1619
 
                command.append(bzr_path)
 
1597
            command = [sys.executable, bzr_path]
1620
1598
            if not allow_plugins:
1621
1599
                command.append('--no-plugins')
1622
1600
            command.extend(process_args)
2019
1997
        b = self.make_branch(relpath, format=format)
2020
1998
        return memorytree.MemoryTree.create_on_branch(b)
2021
1999
 
2022
 
    def make_branch_builder(self, relpath, format=None):
2023
 
        url = self.get_url(relpath)
2024
 
        tran = get_transport(url)
2025
 
        return branchbuilder.BranchBuilder(get_transport(url), format=format)
2026
 
 
2027
2000
    def overrideEnvironmentForTesting(self):
2028
2001
        os.environ['HOME'] = self.test_home_dir
2029
2002
        os.environ['BZR_HOME'] = self.test_home_dir
2072
2045
            self.log("actually: %r" % contents)
2073
2046
            self.fail("contents of %s not as expected" % filename)
2074
2047
 
2075
 
    def _getTestDirPrefix(self):
2076
 
        # create a directory within the top level test directory
2077
 
        if sys.platform == 'win32':
2078
 
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
2079
 
            # windows is likely to have path-length limits so use a short name
2080
 
            name_prefix = name_prefix[-30:]
2081
 
        else:
2082
 
            name_prefix = re.sub('[/]', '_', self.id())
2083
 
        return name_prefix
2084
 
 
2085
2048
    def makeAndChdirToTestDir(self):
2086
2049
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
2087
2050
        
2088
2051
        For TestCaseInTempDir we create a temporary directory based on the test
2089
2052
        name and then create two subdirs - test and home under it.
2090
2053
        """
2091
 
        name_prefix = osutils.pathjoin(self.TEST_ROOT, self._getTestDirPrefix())
2092
 
        name = name_prefix
2093
 
        for i in range(100):
2094
 
            if os.path.exists(name):
2095
 
                name = name_prefix + '_' + str(i)
2096
 
            else:
2097
 
                os.mkdir(name)
2098
 
                break
 
2054
        # create a directory within the top level test directory
 
2055
        candidate_dir = osutils.mkdtemp(dir=self.TEST_ROOT)
2099
2056
        # now create test and home directories within this dir
2100
 
        self.test_base_dir = name
 
2057
        self.test_base_dir = candidate_dir
2101
2058
        self.test_home_dir = self.test_base_dir + '/home'
2102
2059
        os.mkdir(self.test_home_dir)
2103
2060
        self.test_dir = self.test_base_dir + '/work'
2140
2097
        if transport is None or transport.is_readonly():
2141
2098
            transport = get_transport(".")
2142
2099
        for name in shape:
2143
 
            self.assertIsInstance(name, basestring)
 
2100
            self.assert_(isinstance(name, basestring))
2144
2101
            if name[-1] == '/':
2145
2102
                transport.mkdir(urlutils.escape(name[:-1]))
2146
2103
            else:
2163
2120
            tree = workingtree.WorkingTree.open(root_path)
2164
2121
        if not isinstance(path, basestring):
2165
2122
            for p in path:
2166
 
                self.assertInWorkingTree(p, tree=tree)
 
2123
                self.assertInWorkingTree(p,tree=tree)
2167
2124
        else:
2168
2125
            self.assertIsNot(tree.path2id(path), None,
2169
2126
                path+' not in working tree.')
2233
2190
                # the branch is colocated on disk, we cannot create a checkout.
2234
2191
                # hopefully callers will expect this.
2235
2192
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2236
 
                wt = local_controldir.create_workingtree()
2237
 
                if wt.branch._format != b._format:
2238
 
                    wt._branch = b
2239
 
                    # Make sure that assigning to wt._branch fixes wt.branch,
2240
 
                    # in case the implementation details of workingtree objects
2241
 
                    # change.
2242
 
                    self.assertIs(b, wt.branch)
2243
 
                return wt
 
2193
                return local_controldir.create_workingtree()
2244
2194
            else:
2245
2195
                return b.create_checkout(relpath, lightweight=True)
2246
2196
 
2318
2268
def condition_id_in_list(id_list):
2319
2269
    """Create a condition filter which verify that test's id in a list.
2320
2270
    
2321
 
    :param id_list: A TestIdList object.
 
2271
    :param name: A TestIdList object.
2322
2272
    :return: A callable that returns True if the test's id appears in the list.
2323
2273
    """
2324
2274
    def condition(test):
2325
 
        return id_list.includes(test.id())
2326
 
    return condition
2327
 
 
2328
 
 
2329
 
def condition_id_startswith(starts):
2330
 
    """Create a condition filter verifying that test's id starts with a string.
2331
 
    
2332
 
    :param starts: A list of string.
2333
 
    :return: A callable that returns True if the test's id starts with one of 
2334
 
        the given strings.
2335
 
    """
2336
 
    def condition(test):
2337
 
        for start in starts:
2338
 
            if test.id().startswith(start):
2339
 
                return True
2340
 
        return False
 
2275
        return id_list.test_in(test.id())
2341
2276
    return condition
2342
2277
 
2343
2278
 
2365
2300
        test case which should be included in the result.
2366
2301
    :return: A suite which contains the tests found in suite that pass
2367
2302
        condition.
2368
 
    """
 
2303
    """ 
2369
2304
    result = []
2370
2305
    for test in iter_suite_tests(suite):
2371
2306
        if condition(test):
2373
2308
    return TestUtil.TestSuite(result)
2374
2309
 
2375
2310
 
2376
 
def filter_suite_by_re(suite, pattern):
 
2311
def filter_suite_by_re(suite, pattern, exclude_pattern=DEPRECATED_PARAMETER,
 
2312
                       random_order=DEPRECATED_PARAMETER):
2377
2313
    """Create a test suite by filtering another one.
2378
2314
    
2379
2315
    :param suite:           the source suite
2380
2316
    :param pattern:         pattern that names must match
 
2317
    :param exclude_pattern: A pattern that names must not match. This parameter
 
2318
        is deprecated as of bzrlib 1.0. Please use the separate function
 
2319
        exclude_tests_by_re instead.
 
2320
    :param random_order:    If True, tests in the new suite will be put in
 
2321
        random order. This parameter is deprecated as of bzrlib 1.0. Please
 
2322
        use the separate function randomize_suite instead.
2381
2323
    :returns: the newly created suite
2382
 
    """
 
2324
    """ 
 
2325
    if deprecated_passed(exclude_pattern):
 
2326
        symbol_versioning.warn(
 
2327
            one_zero % "passing exclude_pattern to filter_suite_by_re",
 
2328
                DeprecationWarning, stacklevel=2)
 
2329
        if exclude_pattern is not None:
 
2330
            suite = exclude_tests_by_re(suite, exclude_pattern)
2383
2331
    condition = condition_id_re(pattern)
2384
2332
    result_suite = filter_suite_by_condition(suite, condition)
 
2333
    if deprecated_passed(random_order):
 
2334
        symbol_versioning.warn(
 
2335
            one_zero % "passing random_order to filter_suite_by_re",
 
2336
                DeprecationWarning, stacklevel=2)
 
2337
        if random_order:
 
2338
            result_suite = randomize_suite(result_suite)
2385
2339
    return result_suite
2386
2340
 
2387
2341
 
2397
2351
    return result_suite
2398
2352
 
2399
2353
 
2400
 
def filter_suite_by_id_startswith(suite, start):
2401
 
    """Create a test suite by filtering another one.
2402
 
 
2403
 
    :param suite: The source suite.
2404
 
    :param start: A list of string the test id must start with one of.
2405
 
    :returns: the newly created suite
2406
 
    """
2407
 
    condition = condition_id_startswith(start)
2408
 
    result_suite = filter_suite_by_condition(suite, condition)
2409
 
    return result_suite
2410
 
 
2411
 
 
2412
2354
def exclude_tests_by_re(suite, pattern):
2413
2355
    """Create a test suite which excludes some tests from suite.
2414
2356
 
2443
2385
    return TestUtil.TestSuite(tests)
2444
2386
 
2445
2387
 
2446
 
def split_suite_by_condition(suite, condition):
2447
 
    """Split a test suite into two by a condition.
 
2388
@deprecated_function(one_zero)
 
2389
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
 
2390
                     random_order=False, append_rest=True):
 
2391
    """DEPRECATED: Create a test suite by sorting another one.
 
2392
 
 
2393
    This method has been decomposed into separate helper methods that should be
 
2394
    called directly:
 
2395
     - filter_suite_by_re
 
2396
     - exclude_tests_by_re
 
2397
     - randomize_suite
 
2398
     - split_suite_by_re
2448
2399
    
2449
 
    :param suite: The suite to split.
2450
 
    :param condition: The condition to match on. Tests that match this
2451
 
        condition are returned in the first test suite, ones that do not match
2452
 
        are in the second suite.
2453
 
    :return: A tuple of two test suites, where the first contains tests from
2454
 
        suite matching the condition, and the second contains the remainder
2455
 
        from suite. The order within each output suite is the same as it was in
2456
 
        suite.
2457
 
    """
2458
 
    matched = []
2459
 
    did_not_match = []
2460
 
    for test in iter_suite_tests(suite):
2461
 
        if condition(test):
2462
 
            matched.append(test)
2463
 
        else:
2464
 
            did_not_match.append(test)
2465
 
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
 
2400
    :param suite:           the source suite
 
2401
    :param pattern:         pattern that names must match in order to go
 
2402
                            first in the new suite
 
2403
    :param exclude_pattern: pattern that names must not match, if any
 
2404
    :param random_order:    if True, tests in the new suite will be put in
 
2405
                            random order (with all tests matching pattern
 
2406
                            first).
 
2407
    :param append_rest:     if False, pattern is a strict filter and not
 
2408
                            just an ordering directive
 
2409
    :returns: the newly created suite
 
2410
    """ 
 
2411
    if exclude_pattern is not None:
 
2412
        suite = exclude_tests_by_re(suite, exclude_pattern)
 
2413
    if random_order:
 
2414
        order_changer = randomize_suite
 
2415
    else:
 
2416
        order_changer = preserve_input
 
2417
    if append_rest:
 
2418
        suites = map(order_changer, split_suite_by_re(suite, pattern))
 
2419
        return TestUtil.TestSuite(suites)
 
2420
    else:
 
2421
        return order_changer(filter_suite_by_re(suite, pattern))
2466
2422
 
2467
2423
 
2468
2424
def split_suite_by_re(suite, pattern):
2476
2432
        suite matching pattern, and the second contains the remainder from
2477
2433
        suite. The order within each output suite is the same as it was in
2478
2434
        suite.
2479
 
    """
2480
 
    return split_suite_by_condition(suite, condition_id_re(pattern))
 
2435
    """ 
 
2436
    matched = []
 
2437
    did_not_match = []
 
2438
    filter_re = re.compile(pattern)
 
2439
    for test in iter_suite_tests(suite):
 
2440
        test_id = test.id()
 
2441
        if filter_re.search(test_id):
 
2442
            matched.append(test)
 
2443
        else:
 
2444
            did_not_match.append(test)
 
2445
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
2481
2446
 
2482
2447
 
2483
2448
def run_suite(suite, name='test', verbose=False, pattern=".*",
2487
2452
              list_only=False,
2488
2453
              random_seed=None,
2489
2454
              exclude_pattern=None,
2490
 
              strict=False,
2491
 
              runner_class=None):
2492
 
    """Run a test suite for bzr selftest.
2493
 
 
2494
 
    :param runner_class: The class of runner to use. Must support the
2495
 
        constructor arguments passed by run_suite which are more than standard
2496
 
        python uses.
2497
 
    :return: A boolean indicating success.
2498
 
    """
 
2455
              strict=False):
2499
2456
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2500
2457
    if verbose:
2501
2458
        verbosity = 2
2502
2459
    else:
2503
2460
        verbosity = 1
2504
 
    if runner_class is None:
2505
 
        runner_class = TextTestRunner
2506
 
    runner = runner_class(stream=sys.stdout,
 
2461
    runner = TextTestRunner(stream=sys.stdout,
2507
2462
                            descriptions=0,
2508
2463
                            verbosity=verbosity,
2509
2464
                            bench_history=bench_history,
2548
2503
    return result.wasSuccessful()
2549
2504
 
2550
2505
 
2551
 
# Controlled by "bzr selftest -E=..." option
2552
 
selftest_debug_flags = set()
2553
 
 
2554
 
 
2555
2506
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
2556
2507
             transport=None,
2557
2508
             test_suite_factory=None,
2563
2514
             exclude_pattern=None,
2564
2515
             strict=False,
2565
2516
             load_list=None,
2566
 
             debug_flags=None,
2567
 
             starting_with=None,
2568
 
             runner_class=None,
2569
2517
             ):
2570
2518
    """Run the whole test suite under the enhanced runner"""
2571
2519
    # XXX: Very ugly way to do this...
2579
2527
        transport = default_transport
2580
2528
    old_transport = default_transport
2581
2529
    default_transport = transport
2582
 
    global selftest_debug_flags
2583
 
    old_debug_flags = selftest_debug_flags
2584
 
    if debug_flags is not None:
2585
 
        selftest_debug_flags = set(debug_flags)
2586
2530
    try:
2587
2531
        if load_list is None:
2588
2532
            keep_only = None
2589
2533
        else:
2590
2534
            keep_only = load_test_id_list(load_list)
2591
2535
        if test_suite_factory is None:
2592
 
            suite = test_suite(keep_only, starting_with)
 
2536
            suite = test_suite(keep_only)
2593
2537
        else:
2594
2538
            suite = test_suite_factory()
2595
2539
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2601
2545
                     list_only=list_only,
2602
2546
                     random_seed=random_seed,
2603
2547
                     exclude_pattern=exclude_pattern,
2604
 
                     strict=strict,
2605
 
                     runner_class=runner_class,
2606
 
                     )
 
2548
                     strict=strict)
2607
2549
    finally:
2608
2550
        default_transport = old_transport
2609
 
        selftest_debug_flags = old_debug_flags
2610
2551
 
2611
2552
 
2612
2553
def load_test_id_list(file_name):
2632
2573
    return test_list
2633
2574
 
2634
2575
 
2635
 
def suite_matches_id_list(test_suite, id_list):
2636
 
    """Warns about tests not appearing or appearing more than once.
2637
 
 
2638
 
    :param test_suite: A TestSuite object.
2639
 
    :param test_id_list: The list of test ids that should be found in 
2640
 
         test_suite.
2641
 
 
2642
 
    :return: (absents, duplicates) absents is a list containing the test found
2643
 
        in id_list but not in test_suite, duplicates is a list containing the
2644
 
        test found multiple times in test_suite.
2645
 
 
2646
 
    When using a prefined test id list, it may occurs that some tests do not
2647
 
    exist anymore or that some tests use the same id. This function warns the
2648
 
    tester about potential problems in his workflow (test lists are volatile)
2649
 
    or in the test suite itself (using the same id for several tests does not
2650
 
    help to localize defects).
2651
 
    """
2652
 
    # Build a dict counting id occurrences
2653
 
    tests = dict()
2654
 
    for test in iter_suite_tests(test_suite):
2655
 
        id = test.id()
2656
 
        tests[id] = tests.get(id, 0) + 1
2657
 
 
2658
 
    not_found = []
2659
 
    duplicates = []
2660
 
    for id in id_list:
2661
 
        occurs = tests.get(id, 0)
2662
 
        if not occurs:
2663
 
            not_found.append(id)
2664
 
        elif occurs > 1:
2665
 
            duplicates.append(id)
2666
 
 
2667
 
    return not_found, duplicates
2668
 
 
2669
 
 
2670
2576
class TestIdList(object):
2671
2577
    """Test id list to filter a test suite.
2672
2578
 
2703
2609
                modules[mod_name] = True
2704
2610
        self.modules = modules
2705
2611
 
2706
 
    def refers_to(self, module_name):
 
2612
    def is_module_name_used(self, module_name):
2707
2613
        """Is there tests for the module or one of its sub modules."""
2708
2614
        return self.modules.has_key(module_name)
2709
2615
 
2710
 
    def includes(self, test_id):
 
2616
    def test_in(self, test_id):
2711
2617
        return self.tests.has_key(test_id)
2712
2618
 
2713
2619
 
2714
 
class TestPrefixAliasRegistry(registry.Registry):
2715
 
    """A registry for test prefix aliases.
2716
 
 
2717
 
    This helps implement shorcuts for the --starting-with selftest
2718
 
    option. Overriding existing prefixes is not allowed but not fatal (a
2719
 
    warning will be emitted).
2720
 
    """
2721
 
 
2722
 
    def register(self, key, obj, help=None, info=None,
2723
 
                 override_existing=False):
2724
 
        """See Registry.register.
2725
 
 
2726
 
        Trying to override an existing alias causes a warning to be emitted,
2727
 
        not a fatal execption.
2728
 
        """
2729
 
        try:
2730
 
            super(TestPrefixAliasRegistry, self).register(
2731
 
                key, obj, help=help, info=info, override_existing=False)
2732
 
        except KeyError:
2733
 
            actual = self.get(key)
2734
 
            note('Test prefix alias %s is already used for %s, ignoring %s'
2735
 
                 % (key, actual, obj))
2736
 
 
2737
 
    def resolve_alias(self, id_start):
2738
 
        """Replace the alias by the prefix in the given string.
2739
 
 
2740
 
        Using an unknown prefix is an error to help catching typos.
2741
 
        """
2742
 
        parts = id_start.split('.')
2743
 
        try:
2744
 
            parts[0] = self.get(parts[0])
2745
 
        except KeyError:
2746
 
            raise errors.BzrCommandError(
2747
 
                '%s is not a known test prefix alias' % parts[0])
2748
 
        return '.'.join(parts)
2749
 
 
2750
 
 
2751
 
test_prefix_alias_registry = TestPrefixAliasRegistry()
2752
 
"""Registry of test prefix aliases."""
2753
 
 
2754
 
 
2755
 
# This alias allows to detect typos ('bzrlin.') by making all valid test ids
2756
 
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
2757
 
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
2758
 
 
2759
 
# Obvious higest levels prefixes, feel free to add your own via a plugin
2760
 
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
2761
 
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
2762
 
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
2763
 
test_prefix_alias_registry.register('bb', 'bzrlib.tests.blackbox')
2764
 
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
2765
 
 
2766
 
 
2767
 
def test_suite(keep_only=None, starting_with=None):
 
2620
def test_suite(keep_only=None):
2768
2621
    """Build and return TestSuite for the whole of bzrlib.
2769
2622
 
2770
2623
    :param keep_only: A list of test ids limiting the suite returned.
2771
2624
 
2772
 
    :param starting_with: An id limiting the suite returned to the tests
2773
 
         starting with it.
2774
 
 
2775
2625
    This function can be replaced if you need to change the default test
2776
2626
    suite on a global basis, but it is not encouraged.
2777
2627
    """
2778
2628
    testmod_names = [
2779
 
                   'bzrlib.doc',
2780
 
                   'bzrlib.tests.blackbox',
2781
 
                   'bzrlib.tests.branch_implementations',
2782
 
                   'bzrlib.tests.bzrdir_implementations',
2783
 
                   'bzrlib.tests.commands',
2784
 
                   'bzrlib.tests.interrepository_implementations',
2785
 
                   'bzrlib.tests.intertree_implementations',
2786
 
                   'bzrlib.tests.inventory_implementations',
2787
 
                   'bzrlib.tests.per_lock',
2788
 
                   'bzrlib.tests.per_repository',
2789
 
                   'bzrlib.tests.per_repository_reference',
 
2629
                   'bzrlib.util.tests.test_bencode',
2790
2630
                   'bzrlib.tests.test__dirstate_helpers',
2791
 
                   'bzrlib.tests.test__walkdirs_win32',
2792
2631
                   'bzrlib.tests.test_ancestry',
2793
2632
                   'bzrlib.tests.test_annotate',
2794
2633
                   'bzrlib.tests.test_api',
2797
2636
                   'bzrlib.tests.test_bisect_multi',
2798
2637
                   'bzrlib.tests.test_branch',
2799
2638
                   'bzrlib.tests.test_branchbuilder',
2800
 
                   'bzrlib.tests.test_btree_index',
2801
2639
                   'bzrlib.tests.test_bugtracker',
2802
2640
                   'bzrlib.tests.test_bundle',
2803
2641
                   'bzrlib.tests.test_bzrdir',
2804
2642
                   'bzrlib.tests.test_cache_utf8',
2805
 
                   'bzrlib.tests.test_chunk_writer',
2806
 
                   'bzrlib.tests.test__chunks_to_lines',
2807
2643
                   'bzrlib.tests.test_commands',
2808
2644
                   'bzrlib.tests.test_commit',
2809
2645
                   'bzrlib.tests.test_commit_merge',
2814
2650
                   'bzrlib.tests.test_delta',
2815
2651
                   'bzrlib.tests.test_deprecated_graph',
2816
2652
                   'bzrlib.tests.test_diff',
2817
 
                   'bzrlib.tests.test_directory_service',
2818
2653
                   'bzrlib.tests.test_dirstate',
2819
2654
                   'bzrlib.tests.test_email_message',
2820
2655
                   'bzrlib.tests.test_errors',
 
2656
                   'bzrlib.tests.test_escaped_store',
2821
2657
                   'bzrlib.tests.test_extract',
2822
2658
                   'bzrlib.tests.test_fetch',
2823
 
                   'bzrlib.tests.test_fifo_cache',
2824
2659
                   'bzrlib.tests.test_ftp_transport',
2825
 
                   'bzrlib.tests.test_foreign',
2826
2660
                   'bzrlib.tests.test_generate_docs',
2827
2661
                   'bzrlib.tests.test_generate_ids',
2828
2662
                   'bzrlib.tests.test_globbing',
2843
2677
                   'bzrlib.tests.test_knit',
2844
2678
                   'bzrlib.tests.test_lazy_import',
2845
2679
                   'bzrlib.tests.test_lazy_regex',
 
2680
                   'bzrlib.tests.test_lockdir',
2846
2681
                   'bzrlib.tests.test_lockable_files',
2847
 
                   'bzrlib.tests.test_lockdir',
2848
2682
                   'bzrlib.tests.test_log',
 
2683
                   'bzrlib.tests.test_lsprof',
2849
2684
                   'bzrlib.tests.test_lru_cache',
2850
 
                   'bzrlib.tests.test_lsprof',
2851
2685
                   'bzrlib.tests.test_mail_client',
2852
2686
                   'bzrlib.tests.test_memorytree',
2853
2687
                   'bzrlib.tests.test_merge',
2857
2691
                   'bzrlib.tests.test_missing',
2858
2692
                   'bzrlib.tests.test_msgeditor',
2859
2693
                   'bzrlib.tests.test_multiparent',
2860
 
                   'bzrlib.tests.test_mutabletree',
2861
2694
                   'bzrlib.tests.test_nonascii',
2862
2695
                   'bzrlib.tests.test_options',
2863
2696
                   'bzrlib.tests.test_osutils',
2864
2697
                   'bzrlib.tests.test_osutils_encodings',
2865
2698
                   'bzrlib.tests.test_pack',
2866
 
                   'bzrlib.tests.test_pack_repository',
2867
2699
                   'bzrlib.tests.test_patch',
2868
2700
                   'bzrlib.tests.test_patches',
2869
2701
                   'bzrlib.tests.test_permissions',
2870
2702
                   'bzrlib.tests.test_plugins',
2871
2703
                   'bzrlib.tests.test_progress',
2872
 
                   'bzrlib.tests.test_read_bundle',
 
2704
                   'bzrlib.tests.test_reconfigure',
2873
2705
                   'bzrlib.tests.test_reconcile',
2874
 
                   'bzrlib.tests.test_reconfigure',
2875
2706
                   'bzrlib.tests.test_registry',
2876
2707
                   'bzrlib.tests.test_remote',
2877
2708
                   'bzrlib.tests.test_repository',
2878
2709
                   'bzrlib.tests.test_revert',
2879
2710
                   'bzrlib.tests.test_revision',
2880
 
                   'bzrlib.tests.test_revisionspec',
 
2711
                   'bzrlib.tests.test_revisionnamespaces',
2881
2712
                   'bzrlib.tests.test_revisiontree',
2882
2713
                   'bzrlib.tests.test_rio',
2883
 
                   'bzrlib.tests.test_rules',
2884
2714
                   'bzrlib.tests.test_sampler',
2885
2715
                   'bzrlib.tests.test_selftest',
2886
2716
                   'bzrlib.tests.test_setup',
2887
2717
                   'bzrlib.tests.test_sftp_transport',
2888
 
                   'bzrlib.tests.test_shelf',
2889
 
                   'bzrlib.tests.test_shelf_ui',
2890
2718
                   'bzrlib.tests.test_smart',
2891
2719
                   'bzrlib.tests.test_smart_add',
2892
 
                   'bzrlib.tests.test_smart_request',
2893
2720
                   'bzrlib.tests.test_smart_transport',
2894
2721
                   'bzrlib.tests.test_smtp_connection',
2895
2722
                   'bzrlib.tests.test_source',
2909
2736
                   'bzrlib.tests.test_transactions',
2910
2737
                   'bzrlib.tests.test_transform',
2911
2738
                   'bzrlib.tests.test_transport',
2912
 
                   'bzrlib.tests.test_transport_implementations',
2913
 
                   'bzrlib.tests.test_transport_log',
2914
2739
                   'bzrlib.tests.test_tree',
2915
2740
                   'bzrlib.tests.test_treebuilder',
2916
2741
                   'bzrlib.tests.test_tsort',
2917
2742
                   'bzrlib.tests.test_tuned_gzip',
2918
2743
                   'bzrlib.tests.test_ui',
2919
 
                   'bzrlib.tests.test_uncommit',
2920
2744
                   'bzrlib.tests.test_upgrade',
2921
 
                   'bzrlib.tests.test_upgrade_stacked',
2922
2745
                   'bzrlib.tests.test_urlutils',
 
2746
                   'bzrlib.tests.test_versionedfile',
2923
2747
                   'bzrlib.tests.test_version',
2924
2748
                   'bzrlib.tests.test_version_info',
2925
 
                   'bzrlib.tests.test_versionedfile',
2926
2749
                   'bzrlib.tests.test_weave',
2927
2750
                   'bzrlib.tests.test_whitebox',
2928
2751
                   'bzrlib.tests.test_win32utils',
2930
2753
                   'bzrlib.tests.test_workingtree_4',
2931
2754
                   'bzrlib.tests.test_wsgi',
2932
2755
                   'bzrlib.tests.test_xml',
2933
 
                   'bzrlib.tests.tree_implementations',
2934
 
                   'bzrlib.tests.workingtree_implementations',
2935
 
                   'bzrlib.util.tests.test_bencode',
2936
2756
                   ]
2937
 
 
 
2757
    test_transport_implementations = [
 
2758
        'bzrlib.tests.test_transport_implementations',
 
2759
        'bzrlib.tests.test_read_bundle',
 
2760
        ]
 
2761
    suite = TestUtil.TestSuite()
2938
2762
    loader = TestUtil.TestLoader()
2939
2763
 
2940
 
    if starting_with:
2941
 
        starting_with = [test_prefix_alias_registry.resolve_alias(start)
2942
 
                         for start in starting_with]
2943
 
        # We take precedence over keep_only because *at loading time* using
2944
 
        # both options means we will load less tests for the same final result.
2945
 
        def interesting_module(name):
2946
 
            for start in starting_with:
2947
 
                if (
2948
 
                    # Either the module name starts with the specified string
2949
 
                    name.startswith(start)
2950
 
                    # or it may contain tests starting with the specified string
2951
 
                    or start.startswith(name)
2952
 
                    ):
2953
 
                    return True
2954
 
            return False
2955
 
        loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
2956
 
 
2957
 
    elif keep_only is not None:
 
2764
    if keep_only is not None:
2958
2765
        id_filter = TestIdList(keep_only)
2959
 
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
2960
 
        def interesting_module(name):
2961
 
            return id_filter.refers_to(name)
2962
 
 
2963
 
    else:
2964
 
        loader = TestUtil.TestLoader()
2965
 
        def interesting_module(name):
2966
 
            # No filtering, all modules are interesting
2967
 
            return True
2968
 
 
2969
 
    suite = loader.suiteClass()
2970
2766
 
2971
2767
    # modules building their suite with loadTestsFromModuleNames
2972
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2973
 
 
2974
 
    modules_to_doctest = [
2975
 
        'bzrlib',
2976
 
        'bzrlib.branchbuilder',
2977
 
        'bzrlib.export',
2978
 
        'bzrlib.inventory',
2979
 
        'bzrlib.iterablefile',
2980
 
        'bzrlib.lockdir',
2981
 
        'bzrlib.merge3',
2982
 
        'bzrlib.option',
2983
 
        'bzrlib.symbol_versioning',
2984
 
        'bzrlib.tests',
2985
 
        'bzrlib.timestamp',
2986
 
        'bzrlib.version_info_formats.format_custom',
2987
 
        ]
2988
 
 
2989
 
    for mod in modules_to_doctest:
2990
 
        if not interesting_module(mod):
2991
 
            # No tests to keep here, move along
2992
 
            continue
 
2768
    if keep_only is None:
 
2769
        suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
 
2770
    else:
 
2771
        for mod in [m for m in testmod_names
 
2772
                    if id_filter.is_module_name_used(m)]:
 
2773
            mod_suite = loader.loadTestsFromModuleNames([mod])
 
2774
            mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
 
2775
            suite.addTest(mod_suite)
 
2776
 
 
2777
    # modules adapted for transport implementations
 
2778
    from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
 
2779
    adapter = TransportTestProviderAdapter()
 
2780
    if keep_only is None:
 
2781
        adapt_modules(test_transport_implementations, adapter, loader, suite)
 
2782
    else:
 
2783
        for mod in [m for m in test_transport_implementations
 
2784
                    if id_filter.is_module_name_used(m)]:
 
2785
            mod_suite = TestUtil.TestSuite()
 
2786
            adapt_modules([mod], adapter, loader, mod_suite)
 
2787
            mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
 
2788
            suite.addTest(mod_suite)
 
2789
 
 
2790
    # modules defining their own test_suite()
 
2791
    for package in [p for p in packages_to_test()
 
2792
                    if (keep_only is None
 
2793
                        or id_filter.is_module_name_used(p.__name__))]:
 
2794
        pack_suite = package.test_suite()
 
2795
        if keep_only is not None:
 
2796
            pack_suite = filter_suite_by_id_list(pack_suite, id_filter)
 
2797
        suite.addTest(pack_suite)
 
2798
 
 
2799
    # XXX: MODULES_TO_TEST should be obsoleted ?
 
2800
    for mod in [m for m in MODULES_TO_TEST
 
2801
                if keep_only is None or id_filter.is_module_name_used(m)]:
 
2802
        mod_suite = loader.loadTestsFromModule(mod)
 
2803
        if keep_only is not None:
 
2804
            mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
 
2805
        suite.addTest(mod_suite)
 
2806
 
 
2807
    for mod in MODULES_TO_DOCTEST:
2993
2808
        try:
2994
 
            # note that this really does mean "report only" -- doctest 
2995
 
            # still runs the rest of the examples
2996
 
            doc_suite = doctest.DocTestSuite(mod,
2997
 
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
2809
            doc_suite = doctest.DocTestSuite(mod)
2998
2810
        except ValueError, e:
2999
2811
            print '**failed to get doctest for: %s\n%s' % (mod, e)
3000
2812
            raise
3001
 
        if len(doc_suite._tests) == 0:
3002
 
            raise errors.BzrError("no doctests found in %s" % (mod,))
 
2813
        if keep_only is not None:
 
2814
            # DocTests may use ids which doesn't contain the module name
 
2815
            doc_suite = filter_suite_by_id_list(doc_suite, id_filter)
3003
2816
        suite.addTest(doc_suite)
3004
2817
 
3005
2818
    default_encoding = sys.getdefaultencoding()
3006
2819
    for name, plugin in bzrlib.plugin.plugins().items():
3007
 
        if not interesting_module(plugin.module.__name__):
3008
 
            continue
 
2820
        if keep_only is not None:
 
2821
            if not id_filter.is_module_name_used(plugin.module.__name__):
 
2822
                continue
3009
2823
        plugin_suite = plugin.test_suite()
3010
2824
        # We used to catch ImportError here and turn it into just a warning,
3011
2825
        # but really if you don't have --no-plugins this should be a failure.
3012
2826
        # mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
3013
 
        if plugin_suite is None:
3014
 
            plugin_suite = plugin.load_plugin_tests(loader)
3015
2827
        if plugin_suite is not None:
 
2828
            if keep_only is not None:
 
2829
                plugin_suite = filter_suite_by_id_list(plugin_suite,
 
2830
                                                       id_filter)
3016
2831
            suite.addTest(plugin_suite)
3017
2832
        if default_encoding != sys.getdefaultencoding():
3018
2833
            bzrlib.trace.warning(
3020
2835
                sys.getdefaultencoding())
3021
2836
            reload(sys)
3022
2837
            sys.setdefaultencoding(default_encoding)
3023
 
 
3024
 
    if starting_with:
3025
 
        suite = filter_suite_by_id_startswith(suite, starting_with)
3026
 
 
3027
 
    if keep_only is not None:
3028
 
        # Now that the referred modules have loaded their tests, keep only the
3029
 
        # requested ones.
3030
 
        suite = filter_suite_by_id_list(suite, id_filter)
3031
 
        # Do some sanity checks on the id_list filtering
3032
 
        not_found, duplicates = suite_matches_id_list(suite, keep_only)
3033
 
        if starting_with:
3034
 
            # The tester has used both keep_only and starting_with, so he is
3035
 
            # already aware that some tests are excluded from the list, there
3036
 
            # is no need to tell him which.
3037
 
            pass
3038
 
        else:
3039
 
            # Some tests mentioned in the list are not in the test suite. The
3040
 
            # list may be out of date, report to the tester.
3041
 
            for id in not_found:
3042
 
                bzrlib.trace.warning('"%s" not found in the test suite', id)
3043
 
        for id in duplicates:
3044
 
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
3045
 
 
3046
2838
    return suite
3047
2839
 
3048
2840
 
3049
 
def multiply_tests_from_modules(module_name_list, scenario_iter, loader=None):
 
2841
def multiply_tests_from_modules(module_name_list, scenario_iter):
3050
2842
    """Adapt all tests in some given modules to given scenarios.
3051
2843
 
3052
2844
    This is the recommended public interface for test parameterization.
3058
2850
        modules.
3059
2851
    :param scenario_iter: Iterable of pairs of (scenario_name, 
3060
2852
        scenario_param_dict).
3061
 
    :param loader: If provided, will be used instead of a new 
3062
 
        bzrlib.tests.TestLoader() instance.
3063
2853
 
3064
2854
    This returns a new TestSuite containing the cross product of
3065
2855
    all the tests in all the modules, each repeated for each scenario.
3081
2871
    >>> tests[1].param
3082
2872
    2
3083
2873
    """
3084
 
    # XXX: Isn't load_tests() a better way to provide the same functionality
3085
 
    # without forcing a predefined TestScenarioApplier ? --vila 080215
3086
 
    if loader is None:
3087
 
        loader = TestUtil.TestLoader()
3088
 
 
3089
 
    suite = loader.suiteClass()
3090
 
 
 
2874
    loader = TestLoader()
 
2875
    suite = TestSuite()
3091
2876
    adapter = TestScenarioApplier()
3092
2877
    adapter.scenarios = list(scenario_iter)
3093
2878
    adapt_modules(module_name_list, adapter, loader, suite)
3111
2896
 
3112
2897
def adapt_modules(mods_list, adapter, loader, suite):
3113
2898
    """Adapt the modules in mods_list using adapter and add to suite."""
3114
 
    tests = loader.loadTestsFromModuleNames(mods_list)
3115
 
    adapt_tests(tests, adapter, suite)
3116
 
 
3117
 
 
3118
 
def adapt_tests(tests_list, adapter, suite):
 
2899
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
 
2900
        suite.addTests(adapter.adapt(test))
 
2901
 
 
2902
 
 
2903
def adapt_tests(tests_list, adapter, loader, suite):
3119
2904
    """Adapt the tests in tests_list using adapter and add to suite."""
3120
 
    for test in iter_suite_tests(tests_list):
3121
 
        suite.addTests(adapter.adapt(test))
 
2905
    for test in tests_list:
 
2906
        suite.addTests(adapter.adapt(loader.loadTestsFromName(test)))
3122
2907
 
3123
2908
 
3124
2909
def _rmtree_temp_dir(dirname):
3205
2990
OsFifoFeature = _OsFifoFeature()
3206
2991
 
3207
2992
 
3208
 
class _UnicodeFilenameFeature(Feature):
3209
 
    """Does the filesystem support Unicode filenames?"""
3210
 
 
3211
 
    def _probe(self):
3212
 
        try:
3213
 
            # Check for character combinations unlikely to be covered by any
3214
 
            # single non-unicode encoding. We use the characters
3215
 
            # - greek small letter alpha (U+03B1) and
3216
 
            # - braille pattern dots-123456 (U+283F).
3217
 
            os.stat(u'\u03b1\u283f')
3218
 
        except UnicodeEncodeError:
3219
 
            return False
3220
 
        except (IOError, OSError):
3221
 
            # The filesystem allows the Unicode filename but the file doesn't
3222
 
            # exist.
3223
 
            return True
3224
 
        else:
3225
 
            # The filesystem allows the Unicode filename and the file exists,
3226
 
            # for some reason.
3227
 
            return True
3228
 
 
3229
 
UnicodeFilenameFeature = _UnicodeFilenameFeature()
3230
 
 
3231
 
 
3232
2993
class TestScenarioApplier(object):
3233
2994
    """A tool to apply scenarios to tests."""
3234
2995
 
3267
3028
    possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
3268
3029
    for uni_val in possible_vals:
3269
3030
        try:
3270
 
            str_val = uni_val.encode(osutils.get_user_encoding())
 
3031
            str_val = uni_val.encode(bzrlib.user_encoding)
3271
3032
        except UnicodeEncodeError:
3272
3033
            # Try a different character
3273
3034
            pass
3308
3069
    def feature_name(self):
3309
3070
        return 'FTPServer'
3310
3071
 
3311
 
 
3312
3072
FTPServerFeature = _FTPServerFeature()
3313
3073
 
3314
3074
 
3315
 
class _HTTPSServerFeature(Feature):
3316
 
    """Some tests want an https Server, check if one is available.
3317
 
 
3318
 
    Right now, the only way this is available is under python2.6 which provides
3319
 
    an ssl module.
3320
 
    """
3321
 
 
3322
 
    def _probe(self):
3323
 
        try:
3324
 
            import ssl
3325
 
            return True
3326
 
        except ImportError:
3327
 
            return False
3328
 
 
3329
 
    def feature_name(self):
3330
 
        return 'HTTPSServer'
3331
 
 
3332
 
 
3333
 
HTTPSServerFeature = _HTTPSServerFeature()
3334
 
 
3335
 
 
3336
 
class _UnicodeFilename(Feature):
3337
 
    """Does the filesystem support Unicode filenames?"""
3338
 
 
3339
 
    def _probe(self):
3340
 
        try:
3341
 
            os.stat(u'\u03b1')
3342
 
        except UnicodeEncodeError:
3343
 
            return False
3344
 
        except (IOError, OSError):
3345
 
            # The filesystem allows the Unicode filename but the file doesn't
3346
 
            # exist.
3347
 
            return True
3348
 
        else:
3349
 
            # The filesystem allows the Unicode filename and the file exists,
3350
 
            # for some reason.
3351
 
            return True
3352
 
 
3353
 
UnicodeFilename = _UnicodeFilename()
3354
 
 
3355
 
 
3356
 
class _UTF8Filesystem(Feature):
3357
 
    """Is the filesystem UTF-8?"""
3358
 
 
3359
 
    def _probe(self):
3360
 
        if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
3361
 
            return True
3362
 
        return False
3363
 
 
3364
 
UTF8Filesystem = _UTF8Filesystem()
3365
 
 
3366
 
 
3367
 
class _CaseInsCasePresFilenameFeature(Feature):
3368
 
    """Is the file-system case insensitive, but case-preserving?"""
3369
 
 
3370
 
    def _probe(self):
3371
 
        fileno, name = tempfile.mkstemp(prefix='MixedCase')
3372
 
        try:
3373
 
            # first check truly case-preserving for created files, then check
3374
 
            # case insensitive when opening existing files.
3375
 
            name = osutils.normpath(name)
3376
 
            base, rel = osutils.split(name)
3377
 
            found_rel = osutils.canonical_relpath(base, name)
3378
 
            return (found_rel == rel
3379
 
                    and os.path.isfile(name.upper())
3380
 
                    and os.path.isfile(name.lower()))
3381
 
        finally:
3382
 
            os.close(fileno)
3383
 
            os.remove(name)
3384
 
 
3385
 
    def feature_name(self):
3386
 
        return "case-insensitive case-preserving filesystem"
3387
 
 
3388
 
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
3389
 
 
3390
 
 
3391
3075
class _CaseInsensitiveFilesystemFeature(Feature):
3392
 
    """Check if underlying filesystem is case-insensitive but *not* case
3393
 
    preserving.
 
3076
    """Check if underlined filesystem is case-insensitive
 
3077
    (e.g. on Windows, Cygwin, MacOS)
3394
3078
    """
3395
 
    # Note that on Windows, Cygwin, MacOS etc, the file-systems are far
3396
 
    # more likely to be case preserving, so this case is rare.
3397
3079
 
3398
3080
    def _probe(self):
3399
 
        if CaseInsCasePresFilenameFeature.available():
3400
 
            return False
3401
 
 
3402
3081
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
3403
3082
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
3404
3083
            TestCaseWithMemoryTransport.TEST_ROOT = root