/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2008-05-29 19:46:01 UTC
  • mfrom: (3456 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3459.
  • Revision ID: john@arbash-meinel.com-20080529194601-r2gpmk536xin9c4a
merge bzr.dev, put the NEWS entry in the right place

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
45
46
import time
46
47
import unittest
47
48
import warnings
73
74
from bzrlib.merge import merge_inner
74
75
import bzrlib.merge3
75
76
import bzrlib.plugin
76
 
from bzrlib.revision import common_ancestor
77
77
import bzrlib.store
78
78
from bzrlib import symbol_versioning
79
79
from bzrlib.symbol_versioning import (
81
81
    deprecated_function,
82
82
    deprecated_method,
83
83
    deprecated_passed,
84
 
    zero_ninetyone,
85
 
    zero_ninetytwo,
86
 
    one_zero,
87
84
    )
88
85
import bzrlib.trace
89
86
from bzrlib.transport import get_transport
109
106
 
110
107
default_transport = LocalURLServer
111
108
 
112
 
MODULES_TO_TEST = []
113
 
MODULES_TO_DOCTEST = [
114
 
        bzrlib,
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
 
 
167
109
 
168
110
class ExtendedTestResult(unittest._TextTestResult):
169
111
    """Accepts, reports and accumulates the results of running tests.
315
257
        self.report_success(test)
316
258
        self._cleanupLogFile(test)
317
259
        unittest.TestResult.addSuccess(self, test)
 
260
        test._log_contents = ''
318
261
 
319
262
    def _testConcluded(self, test):
320
263
        """Common code when a test has finished.
357
300
            # seems best to treat this as success from point-of-view of unittest
358
301
            # -- it actually does nothing so it barely matters :)
359
302
            unittest.TestResult.addSuccess(self, test)
 
303
            test._log_contents = ''
360
304
 
361
305
    def printErrorList(self, flavour, errors):
362
306
        for test, err in errors:
417
361
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
418
362
 
419
363
    def _progress_prefix_text(self):
420
 
        a = '[%d' % self.count
 
364
        # the longer this text, the less space we have to show the test
 
365
        # name...
 
366
        a = '[%d' % self.count              # total that have been run
 
367
        # tests skipped as known not to be relevant are not important enough
 
368
        # to show here
 
369
        ## if self.skip_count:
 
370
        ##     a += ', %d skip' % self.skip_count
 
371
        ## if self.known_failure_count:
 
372
        ##     a += '+%dX' % self.known_failure_count
421
373
        if self.num_tests is not None:
422
374
            a +='/%d' % self.num_tests
423
 
        a += ' in %ds' % (time.time() - self._overall_start_time)
 
375
        a += ' in '
 
376
        runtime = time.time() - self._overall_start_time
 
377
        if runtime >= 60:
 
378
            a += '%dm%ds' % (runtime / 60, runtime % 60)
 
379
        else:
 
380
            a += '%ds' % runtime
424
381
        if self.error_count:
425
 
            a += ', %d errors' % self.error_count
 
382
            a += ', %d err' % self.error_count
426
383
        if self.failure_count:
427
 
            a += ', %d failed' % self.failure_count
428
 
        if self.known_failure_count:
429
 
            a += ', %d known failures' % self.known_failure_count
430
 
        if self.skip_count:
431
 
            a += ', %d skipped' % self.skip_count
 
384
            a += ', %d fail' % self.failure_count
432
385
        if self.unsupported:
433
 
            a += ', %d missing features' % len(self.unsupported)
 
386
            a += ', %d missing' % len(self.unsupported)
434
387
        a += ']'
435
388
        return a
436
389
 
764
717
        return password
765
718
 
766
719
 
 
720
def _report_leaked_threads():
 
721
    bzrlib.trace.warning('%s is leaking threads among %d leaking tests',
 
722
                         TestCase._first_thread_leaker_id,
 
723
                         TestCase._leaking_threads_tests)
 
724
 
 
725
 
767
726
class TestCase(unittest.TestCase):
768
727
    """Base class for bzr unit tests.
769
728
    
785
744
    accidentally overlooked.
786
745
    """
787
746
 
 
747
    _active_threads = None
 
748
    _leaking_threads_tests = 0
 
749
    _first_thread_leaker_id = None
788
750
    _log_file_name = None
789
751
    _log_contents = ''
790
752
    _keep_log_file = False
791
753
    # record lsprof data when performing benchmark calls.
792
754
    _gather_lsprof_in_benchmarks = False
 
755
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
 
756
                     '_log_contents', '_log_file_name', '_benchtime',
 
757
                     '_TestCase__testMethodName')
793
758
 
794
759
    def __init__(self, methodName='testMethod'):
795
760
        super(TestCase, self).__init__(methodName)
804
769
        self._benchtime = None
805
770
        self._clear_hooks()
806
771
        self._clear_debug_flags()
 
772
        TestCase._active_threads = threading.activeCount()
 
773
        self.addCleanup(self._check_leaked_threads)
 
774
 
 
775
    def _check_leaked_threads(self):
 
776
        active = threading.activeCount()
 
777
        leaked_threads = active - TestCase._active_threads
 
778
        TestCase._active_threads = active
 
779
        if leaked_threads:
 
780
            TestCase._leaking_threads_tests += 1
 
781
            if TestCase._first_thread_leaker_id is None:
 
782
                TestCase._first_thread_leaker_id = self.id()
 
783
                # we're not specifically told when all tests are finished.
 
784
                # This will do. We use a function to avoid keeping a reference
 
785
                # to a TestCase object.
 
786
                atexit.register(_report_leaked_threads)
807
787
 
808
788
    def _clear_debug_flags(self):
809
789
        """Prevent externally set debug flags affecting tests.
811
791
        Tests that want to use debug flags can just set them in the
812
792
        debug_flags set during setup/teardown.
813
793
        """
814
 
        self._preserved_debug_flags = set(debug.debug_flags)
815
 
        debug.debug_flags.clear()
816
 
        self.addCleanup(self._restore_debug_flags)
 
794
        if 'allow_debug' not in selftest_debug_flags:
 
795
            self._preserved_debug_flags = set(debug.debug_flags)
 
796
            debug.debug_flags.clear()
 
797
            self.addCleanup(self._restore_debug_flags)
817
798
 
818
799
    def _clear_hooks(self):
819
800
        # prevent hooks affecting tests
821
802
        import bzrlib.smart.server
822
803
        self._preserved_hooks = {
823
804
            bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
 
805
            bzrlib.mutabletree.MutableTree: bzrlib.mutabletree.MutableTree.hooks,
824
806
            bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
825
807
            }
826
808
        self.addCleanup(self._restoreHooks)
1099
1081
        To test that a deprecated method raises an error, do something like
1100
1082
        this::
1101
1083
 
1102
 
        self.assertRaises(errors.ReservedId,
1103
 
            self.applyDeprecated, zero_ninetyone,
1104
 
                br.append_revision, 'current:')
 
1084
            self.assertRaises(errors.ReservedId,
 
1085
                self.applyDeprecated,
 
1086
                deprecated_in((1, 5, 0)),
 
1087
                br.append_revision,
 
1088
                'current:')
1105
1089
 
1106
1090
        :param deprecation_format: The deprecation format that the callable
1107
1091
            should have been deprecated with. This is the same type as the
1283
1267
                    result.addSuccess(self)
1284
1268
                result.stopTest(self)
1285
1269
                return
1286
 
        return unittest.TestCase.run(self, result)
 
1270
        try:
 
1271
            return unittest.TestCase.run(self, result)
 
1272
        finally:
 
1273
            saved_attrs = {}
 
1274
            absent_attr = object()
 
1275
            for attr_name in self.attrs_to_keep:
 
1276
                attr = getattr(self, attr_name, absent_attr)
 
1277
                if attr is not absent_attr:
 
1278
                    saved_attrs[attr_name] = attr
 
1279
            self.__dict__ = saved_attrs
1287
1280
 
1288
1281
    def tearDown(self):
1289
1282
        self._runCleanups()
1531
1524
            elif isinstance(args[0], basestring):
1532
1525
                args = list(shlex.split(args[0]))
1533
1526
        else:
1534
 
            symbol_versioning.warn(zero_ninetyone %
1535
 
                                   "passing varargs to run_bzr_subprocess",
1536
 
                                   DeprecationWarning, stacklevel=3)
 
1527
            raise ValueError("passing varargs to run_bzr_subprocess")
1537
1528
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
1538
1529
                                            working_dir=working_dir,
1539
1530
                                            allow_plugins=allow_plugins)
2269
2260
def condition_id_in_list(id_list):
2270
2261
    """Create a condition filter which verify that test's id in a list.
2271
2262
    
2272
 
    :param name: A TestIdList object.
 
2263
    :param id_list: A TestIdList object.
2273
2264
    :return: A callable that returns True if the test's id appears in the list.
2274
2265
    """
2275
2266
    def condition(test):
2276
 
        return id_list.test_in(test.id())
 
2267
        return id_list.includes(test.id())
 
2268
    return condition
 
2269
 
 
2270
 
 
2271
def condition_id_startswith(start):
 
2272
    """Create a condition filter verifying that test's id starts with a string.
 
2273
    
 
2274
    :param start: A string.
 
2275
    :return: A callable that returns True if the test's id starts with the
 
2276
        given string.
 
2277
    """
 
2278
    def condition(test):
 
2279
        return test.id().startswith(start)
2277
2280
    return condition
2278
2281
 
2279
2282
 
2309
2312
    return TestUtil.TestSuite(result)
2310
2313
 
2311
2314
 
2312
 
def filter_suite_by_re(suite, pattern, exclude_pattern=DEPRECATED_PARAMETER,
2313
 
                       random_order=DEPRECATED_PARAMETER):
 
2315
def filter_suite_by_re(suite, pattern):
2314
2316
    """Create a test suite by filtering another one.
2315
2317
    
2316
2318
    :param suite:           the source suite
2317
2319
    :param pattern:         pattern that names must match
2318
 
    :param exclude_pattern: A pattern that names must not match. This parameter
2319
 
        is deprecated as of bzrlib 1.0. Please use the separate function
2320
 
        exclude_tests_by_re instead.
2321
 
    :param random_order:    If True, tests in the new suite will be put in
2322
 
        random order. This parameter is deprecated as of bzrlib 1.0. Please
2323
 
        use the separate function randomize_suite instead.
2324
2320
    :returns: the newly created suite
2325
2321
    """ 
2326
 
    if deprecated_passed(exclude_pattern):
2327
 
        symbol_versioning.warn(
2328
 
            one_zero % "passing exclude_pattern to filter_suite_by_re",
2329
 
                DeprecationWarning, stacklevel=2)
2330
 
        if exclude_pattern is not None:
2331
 
            suite = exclude_tests_by_re(suite, exclude_pattern)
2332
2322
    condition = condition_id_re(pattern)
2333
2323
    result_suite = filter_suite_by_condition(suite, condition)
2334
 
    if deprecated_passed(random_order):
2335
 
        symbol_versioning.warn(
2336
 
            one_zero % "passing random_order to filter_suite_by_re",
2337
 
                DeprecationWarning, stacklevel=2)
2338
 
        if random_order:
2339
 
            result_suite = randomize_suite(result_suite)
2340
2324
    return result_suite
2341
2325
 
2342
2326
 
2352
2336
    return result_suite
2353
2337
 
2354
2338
 
 
2339
def filter_suite_by_id_startswith(suite, start):
 
2340
    """Create a test suite by filtering another one.
 
2341
 
 
2342
    :param suite: The source suite.
 
2343
    :param start: A string the test id must start with.
 
2344
    :returns: the newly created suite
 
2345
    """
 
2346
    condition = condition_id_startswith(start)
 
2347
    result_suite = filter_suite_by_condition(suite, condition)
 
2348
    return result_suite
 
2349
 
 
2350
 
2355
2351
def exclude_tests_by_re(suite, pattern):
2356
2352
    """Create a test suite which excludes some tests from suite.
2357
2353
 
2386
2382
    return TestUtil.TestSuite(tests)
2387
2383
 
2388
2384
 
2389
 
@deprecated_function(one_zero)
2390
 
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
2391
 
                     random_order=False, append_rest=True):
2392
 
    """DEPRECATED: Create a test suite by sorting another one.
2393
 
 
2394
 
    This method has been decomposed into separate helper methods that should be
2395
 
    called directly:
2396
 
     - filter_suite_by_re
2397
 
     - exclude_tests_by_re
2398
 
     - randomize_suite
2399
 
     - split_suite_by_re
 
2385
def split_suite_by_condition(suite, condition):
 
2386
    """Split a test suite into two by a condition.
2400
2387
    
2401
 
    :param suite:           the source suite
2402
 
    :param pattern:         pattern that names must match in order to go
2403
 
                            first in the new suite
2404
 
    :param exclude_pattern: pattern that names must not match, if any
2405
 
    :param random_order:    if True, tests in the new suite will be put in
2406
 
                            random order (with all tests matching pattern
2407
 
                            first).
2408
 
    :param append_rest:     if False, pattern is a strict filter and not
2409
 
                            just an ordering directive
2410
 
    :returns: the newly created suite
 
2388
    :param suite: The suite to split.
 
2389
    :param condition: The condition to match on. Tests that match this
 
2390
        condition are returned in the first test suite, ones that do not match
 
2391
        are in the second suite.
 
2392
    :return: A tuple of two test suites, where the first contains tests from
 
2393
        suite matching the condition, and the second contains the remainder
 
2394
        from suite. The order within each output suite is the same as it was in
 
2395
        suite.
2411
2396
    """ 
2412
 
    if exclude_pattern is not None:
2413
 
        suite = exclude_tests_by_re(suite, exclude_pattern)
2414
 
    if random_order:
2415
 
        order_changer = randomize_suite
2416
 
    else:
2417
 
        order_changer = preserve_input
2418
 
    if append_rest:
2419
 
        suites = map(order_changer, split_suite_by_re(suite, pattern))
2420
 
        return TestUtil.TestSuite(suites)
2421
 
    else:
2422
 
        return order_changer(filter_suite_by_re(suite, pattern))
 
2397
    matched = []
 
2398
    did_not_match = []
 
2399
    for test in iter_suite_tests(suite):
 
2400
        if condition(test):
 
2401
            matched.append(test)
 
2402
        else:
 
2403
            did_not_match.append(test)
 
2404
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
2423
2405
 
2424
2406
 
2425
2407
def split_suite_by_re(suite, pattern):
2434
2416
        suite. The order within each output suite is the same as it was in
2435
2417
        suite.
2436
2418
    """ 
2437
 
    matched = []
2438
 
    did_not_match = []
2439
 
    filter_re = re.compile(pattern)
2440
 
    for test in iter_suite_tests(suite):
2441
 
        test_id = test.id()
2442
 
        if filter_re.search(test_id):
2443
 
            matched.append(test)
2444
 
        else:
2445
 
            did_not_match.append(test)
2446
 
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
 
2419
    return split_suite_by_condition(suite, condition_id_re(pattern))
2447
2420
 
2448
2421
 
2449
2422
def run_suite(suite, name='test', verbose=False, pattern=".*",
2504
2477
    return result.wasSuccessful()
2505
2478
 
2506
2479
 
 
2480
# Controlled by "bzr selftest -E=..." option
 
2481
selftest_debug_flags = set()
 
2482
 
 
2483
 
2507
2484
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
2508
2485
             transport=None,
2509
2486
             test_suite_factory=None,
2515
2492
             exclude_pattern=None,
2516
2493
             strict=False,
2517
2494
             load_list=None,
 
2495
             debug_flags=None,
 
2496
             starting_with=None,
2518
2497
             ):
2519
2498
    """Run the whole test suite under the enhanced runner"""
2520
2499
    # XXX: Very ugly way to do this...
2528
2507
        transport = default_transport
2529
2508
    old_transport = default_transport
2530
2509
    default_transport = transport
 
2510
    global selftest_debug_flags
 
2511
    old_debug_flags = selftest_debug_flags
 
2512
    if debug_flags is not None:
 
2513
        selftest_debug_flags = set(debug_flags)
2531
2514
    try:
2532
2515
        if load_list is None:
2533
2516
            keep_only = None
2534
2517
        else:
2535
2518
            keep_only = load_test_id_list(load_list)
2536
2519
        if test_suite_factory is None:
2537
 
            suite = test_suite(keep_only)
 
2520
            suite = test_suite(keep_only, starting_with)
2538
2521
        else:
2539
2522
            suite = test_suite_factory()
2540
2523
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2549
2532
                     strict=strict)
2550
2533
    finally:
2551
2534
        default_transport = old_transport
 
2535
        selftest_debug_flags = old_debug_flags
2552
2536
 
2553
2537
 
2554
2538
def load_test_id_list(file_name):
2574
2558
    return test_list
2575
2559
 
2576
2560
 
 
2561
def suite_matches_id_list(test_suite, id_list):
 
2562
    """Warns about tests not appearing or appearing more than once.
 
2563
 
 
2564
    :param test_suite: A TestSuite object.
 
2565
    :param test_id_list: The list of test ids that should be found in 
 
2566
         test_suite.
 
2567
 
 
2568
    :return: (absents, duplicates) absents is a list containing the test found
 
2569
        in id_list but not in test_suite, duplicates is a list containing the
 
2570
        test found multiple times in test_suite.
 
2571
 
 
2572
    When using a prefined test id list, it may occurs that some tests do not
 
2573
    exist anymore or that some tests use the same id. This function warns the
 
2574
    tester about potential problems in his workflow (test lists are volatile)
 
2575
    or in the test suite itself (using the same id for several tests does not
 
2576
    help to localize defects).
 
2577
    """
 
2578
    # Build a dict counting id occurrences
 
2579
    tests = dict()
 
2580
    for test in iter_suite_tests(test_suite):
 
2581
        id = test.id()
 
2582
        tests[id] = tests.get(id, 0) + 1
 
2583
 
 
2584
    not_found = []
 
2585
    duplicates = []
 
2586
    for id in id_list:
 
2587
        occurs = tests.get(id, 0)
 
2588
        if not occurs:
 
2589
            not_found.append(id)
 
2590
        elif occurs > 1:
 
2591
            duplicates.append(id)
 
2592
 
 
2593
    return not_found, duplicates
 
2594
 
 
2595
 
2577
2596
class TestIdList(object):
2578
2597
    """Test id list to filter a test suite.
2579
2598
 
2610
2629
                modules[mod_name] = True
2611
2630
        self.modules = modules
2612
2631
 
2613
 
    def is_module_name_used(self, module_name):
 
2632
    def refers_to(self, module_name):
2614
2633
        """Is there tests for the module or one of its sub modules."""
2615
2634
        return self.modules.has_key(module_name)
2616
2635
 
2617
 
    def test_in(self, test_id):
 
2636
    def includes(self, test_id):
2618
2637
        return self.tests.has_key(test_id)
2619
2638
 
2620
2639
 
2621
 
def test_suite(keep_only=None):
 
2640
def test_suite(keep_only=None, starting_with=None):
2622
2641
    """Build and return TestSuite for the whole of bzrlib.
2623
2642
 
2624
2643
    :param keep_only: A list of test ids limiting the suite returned.
2625
2644
 
 
2645
    :param starting_with: An id limiting the suite returned to the tests
 
2646
         starting with it.
 
2647
 
2626
2648
    This function can be replaced if you need to change the default test
2627
2649
    suite on a global basis, but it is not encouraged.
2628
2650
    """
2629
2651
    testmod_names = [
 
2652
                   'bzrlib.doc',
2630
2653
                   'bzrlib.util.tests.test_bencode',
 
2654
                   'bzrlib.tests.blackbox',
 
2655
                   'bzrlib.tests.branch_implementations',
 
2656
                   'bzrlib.tests.bzrdir_implementations',
 
2657
                   'bzrlib.tests.commands',
 
2658
                   'bzrlib.tests.inventory_implementations',
 
2659
                   'bzrlib.tests.interrepository_implementations',
 
2660
                   'bzrlib.tests.intertree_implementations',
 
2661
                   'bzrlib.tests.interversionedfile_implementations',
 
2662
                   'bzrlib.tests.per_lock',
 
2663
                   'bzrlib.tests.repository_implementations',
 
2664
                   'bzrlib.tests.revisionstore_implementations',
2631
2665
                   'bzrlib.tests.test__dirstate_helpers',
2632
2666
                   'bzrlib.tests.test_ancestry',
2633
2667
                   'bzrlib.tests.test_annotate',
2693
2727
                   'bzrlib.tests.test_missing',
2694
2728
                   'bzrlib.tests.test_msgeditor',
2695
2729
                   'bzrlib.tests.test_multiparent',
 
2730
                   'bzrlib.tests.test_mutabletree',
2696
2731
                   'bzrlib.tests.test_nonascii',
2697
2732
                   'bzrlib.tests.test_options',
2698
2733
                   'bzrlib.tests.test_osutils',
2703
2738
                   'bzrlib.tests.test_permissions',
2704
2739
                   'bzrlib.tests.test_plugins',
2705
2740
                   'bzrlib.tests.test_progress',
 
2741
                   'bzrlib.tests.test_read_bundle',
2706
2742
                   'bzrlib.tests.test_reconfigure',
2707
2743
                   'bzrlib.tests.test_reconcile',
2708
2744
                   'bzrlib.tests.test_registry',
2710
2746
                   'bzrlib.tests.test_repository',
2711
2747
                   'bzrlib.tests.test_revert',
2712
2748
                   'bzrlib.tests.test_revision',
2713
 
                   'bzrlib.tests.test_revisionnamespaces',
 
2749
                   'bzrlib.tests.test_revisionspec',
2714
2750
                   'bzrlib.tests.test_revisiontree',
2715
2751
                   'bzrlib.tests.test_rio',
2716
2752
                   'bzrlib.tests.test_sampler',
2738
2774
                   'bzrlib.tests.test_transactions',
2739
2775
                   'bzrlib.tests.test_transform',
2740
2776
                   'bzrlib.tests.test_transport',
 
2777
                   'bzrlib.tests.test_transport_implementations',
2741
2778
                   'bzrlib.tests.test_tree',
2742
2779
                   'bzrlib.tests.test_treebuilder',
2743
2780
                   'bzrlib.tests.test_tsort',
2744
2781
                   'bzrlib.tests.test_tuned_gzip',
2745
2782
                   'bzrlib.tests.test_ui',
 
2783
                   'bzrlib.tests.test_uncommit',
2746
2784
                   'bzrlib.tests.test_upgrade',
2747
2785
                   'bzrlib.tests.test_urlutils',
2748
2786
                   'bzrlib.tests.test_versionedfile',
2755
2793
                   'bzrlib.tests.test_workingtree_4',
2756
2794
                   'bzrlib.tests.test_wsgi',
2757
2795
                   'bzrlib.tests.test_xml',
 
2796
                   'bzrlib.tests.tree_implementations',
 
2797
                   'bzrlib.tests.workingtree_implementations',
2758
2798
                   ]
2759
 
    test_transport_implementations = [
2760
 
        'bzrlib.tests.test_transport_implementations',
2761
 
        'bzrlib.tests.test_read_bundle',
2762
 
        ]
2763
 
    suite = TestUtil.TestSuite()
 
2799
 
2764
2800
    loader = TestUtil.TestLoader()
2765
2801
 
2766
 
    if keep_only is not None:
 
2802
    if starting_with is not None:
 
2803
        # We take precedence over keep_only because *at loading time* using
 
2804
        # both options means we will load less tests for the same final result.
 
2805
        def interesting_module(name):
 
2806
            return (
 
2807
                # Either the module name starts with the specified string
 
2808
                name.startswith(starting_with)
 
2809
                # or it may contain tests starting with the specified string
 
2810
                or starting_with.startswith(name)
 
2811
                )
 
2812
        loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
 
2813
 
 
2814
    elif keep_only is not None:
2767
2815
        id_filter = TestIdList(keep_only)
 
2816
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
 
2817
        def interesting_module(name):
 
2818
            return id_filter.refers_to(name)
 
2819
 
 
2820
    else:
 
2821
        loader = TestUtil.TestLoader()
 
2822
        def interesting_module(name):
 
2823
            # No filtering, all modules are interesting
 
2824
            return True
 
2825
 
 
2826
    suite = loader.suiteClass()
2768
2827
 
2769
2828
    # modules building their suite with loadTestsFromModuleNames
2770
 
    if keep_only is None:
2771
 
        suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2772
 
    else:
2773
 
        for mod in [m for m in testmod_names
2774
 
                    if id_filter.is_module_name_used(m)]:
2775
 
            mod_suite = loader.loadTestsFromModuleNames([mod])
2776
 
            mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
2777
 
            suite.addTest(mod_suite)
2778
 
 
2779
 
    # modules adapted for transport implementations
2780
 
    from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
2781
 
    adapter = TransportTestProviderAdapter()
2782
 
    if keep_only is None:
2783
 
        adapt_modules(test_transport_implementations, adapter, loader, suite)
2784
 
    else:
2785
 
        for mod in [m for m in test_transport_implementations
2786
 
                    if id_filter.is_module_name_used(m)]:
2787
 
            mod_suite = TestUtil.TestSuite()
2788
 
            adapt_modules([mod], adapter, loader, mod_suite)
2789
 
            mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
2790
 
            suite.addTest(mod_suite)
2791
 
 
2792
 
    # modules defining their own test_suite()
2793
 
    for package in [p for p in packages_to_test()
2794
 
                    if (keep_only is None
2795
 
                        or id_filter.is_module_name_used(p.__name__))]:
2796
 
        pack_suite = package.test_suite()
2797
 
        if keep_only is not None:
2798
 
            pack_suite = filter_suite_by_id_list(pack_suite, id_filter)
2799
 
        suite.addTest(pack_suite)
2800
 
 
2801
 
    # XXX: MODULES_TO_TEST should be obsoleted ?
2802
 
    for mod in [m for m in MODULES_TO_TEST
2803
 
                if keep_only is None or id_filter.is_module_name_used(m)]:
2804
 
        mod_suite = loader.loadTestsFromModule(mod)
2805
 
        if keep_only is not None:
2806
 
            mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
2807
 
        suite.addTest(mod_suite)
2808
 
 
2809
 
    for mod in MODULES_TO_DOCTEST:
 
2829
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
 
2830
 
 
2831
    modules_to_doctest = [
 
2832
        'bzrlib',
 
2833
        'bzrlib.errors',
 
2834
        'bzrlib.export',
 
2835
        'bzrlib.inventory',
 
2836
        'bzrlib.iterablefile',
 
2837
        'bzrlib.lockdir',
 
2838
        'bzrlib.merge3',
 
2839
        'bzrlib.option',
 
2840
        'bzrlib.store',
 
2841
        'bzrlib.symbol_versioning',
 
2842
        'bzrlib.tests',
 
2843
        'bzrlib.timestamp',
 
2844
        'bzrlib.version_info_formats.format_custom',
 
2845
        ]
 
2846
 
 
2847
    for mod in modules_to_doctest:
 
2848
        if not interesting_module(mod):
 
2849
            # No tests to keep here, move along
 
2850
            continue
2810
2851
        try:
2811
2852
            doc_suite = doctest.DocTestSuite(mod)
2812
2853
        except ValueError, e:
2813
2854
            print '**failed to get doctest for: %s\n%s' % (mod, e)
2814
2855
            raise
2815
 
        if keep_only is not None:
2816
 
            # DocTests may use ids which doesn't contain the module name
2817
 
            doc_suite = filter_suite_by_id_list(doc_suite, id_filter)
2818
2856
        suite.addTest(doc_suite)
2819
2857
 
2820
2858
    default_encoding = sys.getdefaultencoding()
2821
2859
    for name, plugin in bzrlib.plugin.plugins().items():
2822
 
        if keep_only is not None:
2823
 
            if not id_filter.is_module_name_used(plugin.module.__name__):
2824
 
                continue
 
2860
        if not interesting_module(plugin.module.__name__):
 
2861
            continue
2825
2862
        plugin_suite = plugin.test_suite()
2826
2863
        # We used to catch ImportError here and turn it into just a warning,
2827
2864
        # but really if you don't have --no-plugins this should be a failure.
2828
2865
        # mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
 
2866
        if plugin_suite is None:
 
2867
            plugin_suite = plugin.load_plugin_tests(loader)
2829
2868
        if plugin_suite is not None:
2830
 
            if keep_only is not None:
2831
 
                plugin_suite = filter_suite_by_id_list(plugin_suite,
2832
 
                                                       id_filter)
2833
2869
            suite.addTest(plugin_suite)
2834
2870
        if default_encoding != sys.getdefaultencoding():
2835
2871
            bzrlib.trace.warning(
2837
2873
                sys.getdefaultencoding())
2838
2874
            reload(sys)
2839
2875
            sys.setdefaultencoding(default_encoding)
 
2876
 
 
2877
    if starting_with is not None:
 
2878
        suite = filter_suite_by_id_startswith(suite, starting_with)
 
2879
 
 
2880
    if keep_only is not None:
 
2881
        # Now that the referred modules have loaded their tests, keep only the
 
2882
        # requested ones.
 
2883
        suite = filter_suite_by_id_list(suite, id_filter)
 
2884
        # Do some sanity checks on the id_list filtering
 
2885
        not_found, duplicates = suite_matches_id_list(suite, keep_only)
 
2886
        if starting_with is not None:
 
2887
            # The tester has used both keep_only and starting_with, so he is
 
2888
            # already aware that some tests are excluded from the list, there
 
2889
            # is no need to tell him which.
 
2890
            pass
 
2891
        else:
 
2892
            # Some tests mentioned in the list are not in the test suite. The
 
2893
            # list may be out of date, report to the tester.
 
2894
            for id in not_found:
 
2895
                bzrlib.trace.warning('"%s" not found in the test suite', id)
 
2896
        for id in duplicates:
 
2897
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
 
2898
 
2840
2899
    return suite
2841
2900
 
2842
2901
 
2843
 
def multiply_tests_from_modules(module_name_list, scenario_iter):
 
2902
def multiply_tests_from_modules(module_name_list, scenario_iter, loader=None):
2844
2903
    """Adapt all tests in some given modules to given scenarios.
2845
2904
 
2846
2905
    This is the recommended public interface for test parameterization.
2852
2911
        modules.
2853
2912
    :param scenario_iter: Iterable of pairs of (scenario_name, 
2854
2913
        scenario_param_dict).
 
2914
    :param loader: If provided, will be used instead of a new 
 
2915
        bzrlib.tests.TestLoader() instance.
2855
2916
 
2856
2917
    This returns a new TestSuite containing the cross product of
2857
2918
    all the tests in all the modules, each repeated for each scenario.
2873
2934
    >>> tests[1].param
2874
2935
    2
2875
2936
    """
2876
 
    loader = TestLoader()
2877
 
    suite = TestSuite()
 
2937
    # XXX: Isn't load_tests() a better way to provide the same functionality
 
2938
    # without forcing a predefined TestScenarioApplier ? --vila 080215
 
2939
    if loader is None:
 
2940
        loader = TestUtil.TestLoader()
 
2941
 
 
2942
    suite = loader.suiteClass()
 
2943
 
2878
2944
    adapter = TestScenarioApplier()
2879
2945
    adapter.scenarios = list(scenario_iter)
2880
2946
    adapt_modules(module_name_list, adapter, loader, suite)