~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Martin Pool
  • Date: 2009-09-14 01:48:28 UTC
  • mfrom: (4685 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4688.
  • Revision ID: mbp@sourcefrog.net-20090914014828-ydr9rlkdfq2sv57z
Merge news

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
import atexit
30
30
import codecs
 
31
from copy import copy
31
32
from cStringIO import StringIO
32
33
import difflib
33
34
import doctest
102
103
                          TestLoader,
103
104
                          )
104
105
from bzrlib.tests.treeshape import build_tree_contents
 
106
from bzrlib.ui import NullProgressView
105
107
from bzrlib.ui.text import TextUIFactory
106
108
import bzrlib.version_info_formats.format_custom
107
109
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
113
115
 
114
116
default_transport = LocalURLServer
115
117
 
 
118
# Subunit result codes, defined here to prevent a hard dependency on subunit.
 
119
SUBUNIT_SEEK_SET = 0
 
120
SUBUNIT_SEEK_CUR = 1
 
121
 
116
122
 
117
123
class ExtendedTestResult(unittest._TextTestResult):
118
124
    """Accepts, reports and accumulates the results of running tests.
134
140
 
135
141
    def __init__(self, stream, descriptions, verbosity,
136
142
                 bench_history=None,
137
 
                 num_tests=None,
138
143
                 strict=False,
139
144
                 ):
140
145
        """Construct new TestResult.
159
164
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
160
165
        self._bench_history = bench_history
161
166
        self.ui = ui.ui_factory
162
 
        self.num_tests = num_tests
 
167
        self.num_tests = 0
163
168
        self.error_count = 0
164
169
        self.failure_count = 0
165
170
        self.known_failure_count = 0
170
175
        self._overall_start_time = time.time()
171
176
        self._strict = strict
172
177
 
173
 
    def done(self):
 
178
    def stopTestRun(self):
 
179
        run = self.testsRun
 
180
        actionTaken = "Ran"
 
181
        stopTime = time.time()
 
182
        timeTaken = stopTime - self.startTime
 
183
        self.printErrors()
 
184
        self.stream.writeln(self.separator2)
 
185
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
 
186
                            run, run != 1 and "s" or "", timeTaken))
 
187
        self.stream.writeln()
 
188
        if not self.wasSuccessful():
 
189
            self.stream.write("FAILED (")
 
190
            failed, errored = map(len, (self.failures, self.errors))
 
191
            if failed:
 
192
                self.stream.write("failures=%d" % failed)
 
193
            if errored:
 
194
                if failed: self.stream.write(", ")
 
195
                self.stream.write("errors=%d" % errored)
 
196
            if self.known_failure_count:
 
197
                if failed or errored: self.stream.write(", ")
 
198
                self.stream.write("known_failure_count=%d" %
 
199
                    self.known_failure_count)
 
200
            self.stream.writeln(")")
 
201
        else:
 
202
            if self.known_failure_count:
 
203
                self.stream.writeln("OK (known_failures=%d)" %
 
204
                    self.known_failure_count)
 
205
            else:
 
206
                self.stream.writeln("OK")
 
207
        if self.skip_count > 0:
 
208
            skipped = self.skip_count
 
209
            self.stream.writeln('%d test%s skipped' %
 
210
                                (skipped, skipped != 1 and "s" or ""))
 
211
        if self.unsupported:
 
212
            for feature, count in sorted(self.unsupported.items()):
 
213
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
 
214
                    (feature, count))
174
215
        if self._strict:
175
216
            ok = self.wasStrictlySuccessful()
176
217
        else:
177
218
            ok = self.wasSuccessful()
178
 
        if ok:
179
 
            self.stream.write('tests passed\n')
180
 
        else:
181
 
            self.stream.write('tests failed\n')
182
219
        if TestCase._first_thread_leaker_id:
183
220
            self.stream.write(
184
221
                '%s is leaking threads among %d leaking tests.\n' % (
220
257
        self._recordTestStartTime()
221
258
 
222
259
    def startTests(self):
223
 
        self.stream.write(
224
 
            'testing: %s\n' % (osutils.realpath(sys.argv[0]),))
225
 
        self.stream.write(
226
 
            '   %s (%s python%s)\n' % (
227
 
                    bzrlib.__path__[0],
 
260
        import platform
 
261
        if getattr(sys, 'frozen', None) is None:
 
262
            bzr_path = osutils.realpath(sys.argv[0])
 
263
        else:
 
264
            bzr_path = sys.executable
 
265
        self.stream.write(
 
266
            'testing: %s\n' % (bzr_path,))
 
267
        self.stream.write(
 
268
            '   %s\n' % (
 
269
                    bzrlib.__path__[0],))
 
270
        self.stream.write(
 
271
            '   bzr-%s python-%s %s\n' % (
228
272
                    bzrlib.version_string,
229
273
                    bzrlib._format_version_tuple(sys.version_info),
 
274
                    platform.platform(aliased=1),
230
275
                    ))
231
276
        self.stream.write('\n')
232
277
 
359
404
            self.stream.writeln(self.separator2)
360
405
            self.stream.writeln("%s" % err)
361
406
 
362
 
    def finished(self):
363
 
        pass
 
407
    def progress(self, offset, whence):
 
408
        """The test is adjusting the count of tests to run."""
 
409
        if whence == SUBUNIT_SEEK_SET:
 
410
            self.num_tests = offset
 
411
        elif whence == SUBUNIT_SEEK_CUR:
 
412
            self.num_tests += offset
 
413
        else:
 
414
            raise errors.BzrError("Unknown whence %r" % whence)
364
415
 
365
416
    def report_cleaning_up(self):
366
417
        pass
367
418
 
 
419
    def startTestRun(self):
 
420
        self.startTime = time.time()
 
421
 
368
422
    def report_success(self, test):
369
423
        pass
370
424
 
379
433
 
380
434
    def __init__(self, stream, descriptions, verbosity,
381
435
                 bench_history=None,
382
 
                 num_tests=None,
383
436
                 pb=None,
384
437
                 strict=None,
385
438
                 ):
386
439
        ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
387
 
            bench_history, num_tests, strict)
388
 
        if pb is None:
389
 
            self.pb = self.ui.nested_progress_bar()
390
 
            self._supplied_pb = False
391
 
        else:
392
 
            self.pb = pb
393
 
            self._supplied_pb = True
 
440
            bench_history, strict)
 
441
        # We no longer pass them around, but just rely on the UIFactory stack
 
442
        # for state
 
443
        if pb is not None:
 
444
            warnings.warn("Passing pb to TextTestResult is deprecated")
 
445
        self.pb = self.ui.nested_progress_bar()
394
446
        self.pb.show_pct = False
395
447
        self.pb.show_spinner = False
396
448
        self.pb.show_eta = False,
397
449
        self.pb.show_count = False
398
450
        self.pb.show_bar = False
399
 
 
400
 
    def report_starting(self):
 
451
        self.pb.update_latency = 0
 
452
        self.pb.show_transport_activity = False
 
453
 
 
454
    def stopTestRun(self):
 
455
        # called when the tests that are going to run have run
 
456
        self.pb.clear()
 
457
        self.pb.finished()
 
458
        super(TextTestResult, self).stopTestRun()
 
459
 
 
460
    def startTestRun(self):
 
461
        super(TextTestResult, self).startTestRun()
401
462
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
402
463
 
 
464
    def printErrors(self):
 
465
        # clear the pb to make room for the error listing
 
466
        self.pb.clear()
 
467
        super(TextTestResult, self).printErrors()
 
468
 
403
469
    def _progress_prefix_text(self):
404
470
        # the longer this text, the less space we have to show the test
405
471
        # name...
410
476
        ##     a += ', %d skip' % self.skip_count
411
477
        ## if self.known_failure_count:
412
478
        ##     a += '+%dX' % self.known_failure_count
413
 
        if self.num_tests is not None:
 
479
        if self.num_tests:
414
480
            a +='/%d' % self.num_tests
415
481
        a += ' in '
416
482
        runtime = time.time() - self._overall_start_time
465
531
    def report_cleaning_up(self):
466
532
        self.pb.update('Cleaning up')
467
533
 
468
 
    def finished(self):
469
 
        if not self._supplied_pb:
470
 
            self.pb.finished()
471
 
 
472
534
 
473
535
class VerboseTestResult(ExtendedTestResult):
474
536
    """Produce long output, with one line per test run plus times"""
481
543
            result = a_string
482
544
        return result.ljust(final_width)
483
545
 
484
 
    def report_starting(self):
 
546
    def startTestRun(self):
 
547
        super(VerboseTestResult, self).startTestRun()
485
548
        self.stream.write('running %d tests...\n' % self.num_tests)
486
549
 
487
550
    def report_test_start(self, test):
545
608
                 descriptions=0,
546
609
                 verbosity=1,
547
610
                 bench_history=None,
548
 
                 list_only=False,
549
611
                 strict=False,
 
612
                 result_decorators=None,
550
613
                 ):
 
614
        """Create a TextTestRunner.
 
615
 
 
616
        :param result_decorators: An optional list of decorators to apply
 
617
            to the result object being used by the runner. Decorators are
 
618
            applied left to right - the first element in the list is the 
 
619
            innermost decorator.
 
620
        """
551
621
        self.stream = unittest._WritelnDecorator(stream)
552
622
        self.descriptions = descriptions
553
623
        self.verbosity = verbosity
554
624
        self._bench_history = bench_history
555
 
        self.list_only = list_only
556
625
        self._strict = strict
 
626
        self._result_decorators = result_decorators or []
557
627
 
558
628
    def run(self, test):
559
629
        "Run the given test case or test suite."
560
 
        startTime = time.time()
561
630
        if self.verbosity == 1:
562
631
            result_class = TextTestResult
563
632
        elif self.verbosity >= 2:
564
633
            result_class = VerboseTestResult
565
 
        result = result_class(self.stream,
 
634
        original_result = result_class(self.stream,
566
635
                              self.descriptions,
567
636
                              self.verbosity,
568
637
                              bench_history=self._bench_history,
569
 
                              num_tests=test.countTestCases(),
570
638
                              strict=self._strict,
571
639
                              )
572
 
        result.stop_early = self.stop_on_failure
573
 
        result.report_starting()
574
 
        if self.list_only:
575
 
            if self.verbosity >= 2:
576
 
                self.stream.writeln("Listing tests only ...\n")
577
 
            run = 0
578
 
            for t in iter_suite_tests(test):
579
 
                self.stream.writeln("%s" % (t.id()))
580
 
                run += 1
581
 
            return None
582
 
        else:
583
 
            try:
584
 
                import testtools
585
 
            except ImportError:
586
 
                test.run(result)
587
 
            else:
588
 
                if isinstance(test, testtools.ConcurrentTestSuite):
589
 
                    # We need to catch bzr specific behaviors
590
 
                    test.run(BZRTransformingResult(result))
591
 
                else:
592
 
                    test.run(result)
593
 
            run = result.testsRun
594
 
            actionTaken = "Ran"
595
 
        stopTime = time.time()
596
 
        timeTaken = stopTime - startTime
597
 
        result.printErrors()
598
 
        self.stream.writeln(result.separator2)
599
 
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
600
 
                            run, run != 1 and "s" or "", timeTaken))
601
 
        self.stream.writeln()
602
 
        if not result.wasSuccessful():
603
 
            self.stream.write("FAILED (")
604
 
            failed, errored = map(len, (result.failures, result.errors))
605
 
            if failed:
606
 
                self.stream.write("failures=%d" % failed)
607
 
            if errored:
608
 
                if failed: self.stream.write(", ")
609
 
                self.stream.write("errors=%d" % errored)
610
 
            if result.known_failure_count:
611
 
                if failed or errored: self.stream.write(", ")
612
 
                self.stream.write("known_failure_count=%d" %
613
 
                    result.known_failure_count)
614
 
            self.stream.writeln(")")
615
 
        else:
616
 
            if result.known_failure_count:
617
 
                self.stream.writeln("OK (known_failures=%d)" %
618
 
                    result.known_failure_count)
619
 
            else:
620
 
                self.stream.writeln("OK")
621
 
        if result.skip_count > 0:
622
 
            skipped = result.skip_count
623
 
            self.stream.writeln('%d test%s skipped' %
624
 
                                (skipped, skipped != 1 and "s" or ""))
625
 
        if result.unsupported:
626
 
            for feature, count in sorted(result.unsupported.items()):
627
 
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
628
 
                    (feature, count))
629
 
        result.finished()
630
 
        return result
 
640
        # Signal to result objects that look at stop early policy to stop,
 
641
        original_result.stop_early = self.stop_on_failure
 
642
        result = original_result
 
643
        for decorator in self._result_decorators:
 
644
            result = decorator(result)
 
645
            result.stop_early = self.stop_on_failure
 
646
        try:
 
647
            import testtools
 
648
        except ImportError:
 
649
            pass
 
650
        else:
 
651
            if isinstance(test, testtools.ConcurrentTestSuite):
 
652
                # We need to catch bzr specific behaviors
 
653
                result = BZRTransformingResult(result)
 
654
        result.startTestRun()
 
655
        try:
 
656
            test.run(result)
 
657
        finally:
 
658
            result.stopTestRun()
 
659
        # higher level code uses our extended protocol to determine
 
660
        # what exit code to give.
 
661
        return original_result
631
662
 
632
663
 
633
664
def iter_suite_tests(suite):
709
740
    Hide the progress bar but emit note()s.
710
741
    Redirect stdin.
711
742
    Allows get_password to be tested without real tty attached.
 
743
 
 
744
    See also CannedInputUIFactory which lets you provide programmatic input in
 
745
    a structured way.
712
746
    """
 
747
    # TODO: Capture progress events at the model level and allow them to be
 
748
    # observed by tests that care.
 
749
    #
 
750
    # XXX: Should probably unify more with CannedInputUIFactory or a
 
751
    # particular configuration of TextUIFactory, or otherwise have a clearer
 
752
    # idea of how they're supposed to be different.
 
753
    # See https://bugs.edge.launchpad.net/bzr/+bug/408213
713
754
 
714
755
    def __init__(self, stdout=None, stderr=None, stdin=None):
715
756
        if stdin is not None:
720
761
            stdin = StringIOWrapper(stdin)
721
762
        super(TestUIFactory, self).__init__(stdin, stdout, stderr)
722
763
 
723
 
    def clear(self):
724
 
        """See progress.ProgressBar.clear()."""
725
 
 
726
 
    def clear_term(self):
727
 
        """See progress.ProgressBar.clear_term()."""
728
 
 
729
 
    def finished(self):
730
 
        """See progress.ProgressBar.finished()."""
731
 
 
732
 
    def note(self, fmt_string, *args):
733
 
        """See progress.ProgressBar.note()."""
734
 
        if args:
735
 
            fmt_string = fmt_string % args
736
 
        self.stdout.write(fmt_string + "\n")
737
 
 
738
 
    def progress_bar(self):
739
 
        return self
740
 
 
741
 
    def nested_progress_bar(self):
742
 
        return self
743
 
 
744
 
    def update(self, message, count=None, total=None):
745
 
        """See progress.ProgressBar.update()."""
746
 
 
747
764
    def get_non_echoed_password(self):
748
765
        """Get password from stdin without trying to handle the echo mode"""
749
766
        password = self.stdin.readline()
753
770
            password = password[:-1]
754
771
        return password
755
772
 
 
773
    def make_progress_view(self):
 
774
        return NullProgressView()
 
775
 
756
776
 
757
777
class TestCase(unittest.TestCase):
758
778
    """Base class for bzr unit tests.
802
822
        self._benchcalls = []
803
823
        self._benchtime = None
804
824
        self._clear_hooks()
805
 
        # Track locks - needs to be called before _clear_debug_flags.
806
825
        self._track_locks()
807
826
        self._clear_debug_flags()
808
827
        TestCase._active_threads = threading.activeCount()
831
850
        self._preserved_debug_flags = set(debug.debug_flags)
832
851
        if 'allow_debug' not in selftest_debug_flags:
833
852
            debug.debug_flags.clear()
 
853
        if 'disable_lock_checks' not in selftest_debug_flags:
 
854
            debug.debug_flags.add('strict_locks')
834
855
        self.addCleanup(self._restore_debug_flags)
835
856
 
836
857
    def _clear_hooks(self):
858
879
 
859
880
    def _check_locks(self):
860
881
        """Check that all lock take/release actions have been paired."""
861
 
        # once we have fixed all the current lock problems, we can change the
862
 
        # following code to always check for mismatched locks, but only do
863
 
        # traceback showing with -Dlock (self._lock_check_thorough is True).
864
 
        # For now, because the test suite will fail, we only assert that lock
865
 
        # matching has occured with -Dlock.
 
882
        # We always check for mismatched locks. If a mismatch is found, we
 
883
        # fail unless -Edisable_lock_checks is supplied to selftest, in which
 
884
        # case we just print a warning.
866
885
        # unhook:
867
886
        acquired_locks = [lock for action, lock in self._lock_actions
868
887
                          if action == 'acquired']
887
906
    def _track_locks(self):
888
907
        """Track lock activity during tests."""
889
908
        self._lock_actions = []
890
 
        self._lock_check_thorough = 'lock' not in debug.debug_flags
 
909
        if 'disable_lock_checks' in selftest_debug_flags:
 
910
            self._lock_check_thorough = False
 
911
        else:
 
912
            self._lock_check_thorough = True
 
913
            
891
914
        self.addCleanup(self._check_locks)
892
915
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
893
916
                                                self._lock_acquired, None)
905
928
    def _lock_broken(self, result):
906
929
        self._lock_actions.append(('broken', result))
907
930
 
 
931
    def start_server(self, transport_server, backing_server=None):
 
932
        """Start transport_server for this test.
 
933
 
 
934
        This starts the server, registers a cleanup for it and permits the
 
935
        server's urls to be used.
 
936
        """
 
937
        if backing_server is None:
 
938
            transport_server.setUp()
 
939
        else:
 
940
            transport_server.setUp(backing_server)
 
941
        self.addCleanup(transport_server.tearDown)
 
942
 
908
943
    def _ndiff_strings(self, a, b):
909
944
        """Return ndiff between two strings containing lines.
910
945
 
947
982
            return
948
983
        if message is None:
949
984
            message = "texts not equal:\n"
 
985
        if a + '\n' == b:
 
986
            message = 'first string is missing a final newline.\n'
950
987
        if a == b + '\n':
951
 
            message = 'first string is missing a final newline.\n'
952
 
        if a + '\n' == b:
953
988
            message = 'second string is missing a final newline.\n'
954
989
        raise AssertionError(message +
955
990
                             self._ndiff_strings(a, b))
1309
1344
        """Make the logfile not be deleted when _finishLogFile is called."""
1310
1345
        self._keep_log_file = True
1311
1346
 
 
1347
    def thisFailsStrictLockCheck(self):
 
1348
        """It is known that this test would fail with -Dstrict_locks.
 
1349
 
 
1350
        By default, all tests are run with strict lock checking unless
 
1351
        -Edisable_lock_checks is supplied. However there are some tests which
 
1352
        we know fail strict locks at this point that have not been fixed.
 
1353
        They should call this function to disable the strict checking.
 
1354
 
 
1355
        This should be used sparingly, it is much better to fix the locking
 
1356
        issues rather than papering over the problem by calling this function.
 
1357
        """
 
1358
        debug.debug_flags.discard('strict_locks')
 
1359
 
1312
1360
    def addCleanup(self, callable, *args, **kwargs):
1313
1361
        """Arrange to run a callable when this case is torn down.
1314
1362
 
1926
1974
        sio.encoding = output_encoding
1927
1975
        return sio
1928
1976
 
 
1977
    def disable_verb(self, verb):
 
1978
        """Disable a smart server verb for one test."""
 
1979
        from bzrlib.smart import request
 
1980
        request_handlers = request.request_handlers
 
1981
        orig_method = request_handlers.get(verb)
 
1982
        request_handlers.remove(verb)
 
1983
        def restoreVerb():
 
1984
            request_handlers.register(verb, orig_method)
 
1985
        self.addCleanup(restoreVerb)
 
1986
 
1929
1987
 
1930
1988
class CapturedCall(object):
1931
1989
    """A helper for capturing smart server calls for easy debug analysis."""
2021
2079
        if self.__readonly_server is None:
2022
2080
            if self.transport_readonly_server is None:
2023
2081
                # readonly decorator requested
2024
 
                # bring up the server
2025
2082
                self.__readonly_server = ReadonlyServer()
2026
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
2027
2083
            else:
 
2084
                # explicit readonly transport.
2028
2085
                self.__readonly_server = self.create_transport_readonly_server()
2029
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
2030
 
            self.addCleanup(self.__readonly_server.tearDown)
 
2086
            self.start_server(self.__readonly_server,
 
2087
                self.get_vfs_only_server())
2031
2088
        return self.__readonly_server
2032
2089
 
2033
2090
    def get_readonly_url(self, relpath=None):
2052
2109
        """
2053
2110
        if self.__vfs_server is None:
2054
2111
            self.__vfs_server = MemoryServer()
2055
 
            self.__vfs_server.setUp()
2056
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2112
            self.start_server(self.__vfs_server)
2057
2113
        return self.__vfs_server
2058
2114
 
2059
2115
    def get_server(self):
2066
2122
        then the self.get_vfs_server is returned.
2067
2123
        """
2068
2124
        if self.__server is None:
2069
 
            if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
2070
 
                return self.get_vfs_only_server()
 
2125
            if (self.transport_server is None or self.transport_server is
 
2126
                self.vfs_transport_factory):
 
2127
                self.__server = self.get_vfs_only_server()
2071
2128
            else:
2072
2129
                # bring up a decorated means of access to the vfs only server.
2073
2130
                self.__server = self.transport_server()
2074
 
                try:
2075
 
                    self.__server.setUp(self.get_vfs_only_server())
2076
 
                except TypeError, e:
2077
 
                    # This should never happen; the try:Except here is to assist
2078
 
                    # developers having to update code rather than seeing an
2079
 
                    # uninformative TypeError.
2080
 
                    raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
2081
 
            self.addCleanup(self.__server.tearDown)
 
2131
                self.start_server(self.__server, self.get_vfs_only_server())
2082
2132
        return self.__server
2083
2133
 
2084
2134
    def _adjust_url(self, base, relpath):
2217
2267
 
2218
2268
    def make_smart_server(self, path):
2219
2269
        smart_server = server.SmartTCPServer_for_testing()
2220
 
        smart_server.setUp(self.get_server())
 
2270
        self.start_server(smart_server, self.get_server())
2221
2271
        remote_transport = get_transport(smart_server.get_url()).clone(path)
2222
 
        self.addCleanup(smart_server.tearDown)
2223
2272
        return remote_transport
2224
2273
 
2225
2274
    def make_branch_and_memory_tree(self, relpath, format=None):
2298
2347
 
2299
2348
    def _getTestDirPrefix(self):
2300
2349
        # create a directory within the top level test directory
2301
 
        if sys.platform == 'win32':
 
2350
        if sys.platform in ('win32', 'cygwin'):
2302
2351
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
2303
2352
            # windows is likely to have path-length limits so use a short name
2304
2353
            name_prefix = name_prefix[-30:]
2426
2475
        """
2427
2476
        if self.__vfs_server is None:
2428
2477
            self.__vfs_server = self.vfs_transport_factory()
2429
 
            self.__vfs_server.setUp()
2430
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2478
            self.start_server(self.__vfs_server)
2431
2479
        return self.__vfs_server
2432
2480
 
2433
2481
    def make_branch_and_tree(self, relpath, format=None):
2440
2488
        repository will also be accessed locally. Otherwise a lightweight
2441
2489
        checkout is created and returned.
2442
2490
 
 
2491
        We do this because we can't physically create a tree in the local
 
2492
        path, with a branch reference to the transport_factory url, and
 
2493
        a branch + repository in the vfs_transport, unless the vfs_transport
 
2494
        namespace is distinct from the local disk - the two branch objects
 
2495
        would collide. While we could construct a tree with its branch object
 
2496
        pointing at the transport_factory transport in memory, reopening it
 
2497
        would behaving unexpectedly, and has in the past caused testing bugs
 
2498
        when we tried to do it that way.
 
2499
 
2443
2500
        :param format: The BzrDirFormat.
2444
2501
        :returns: the WorkingTree.
2445
2502
        """
2716
2773
              strict=False,
2717
2774
              runner_class=None,
2718
2775
              suite_decorators=None,
2719
 
              stream=None):
 
2776
              stream=None,
 
2777
              result_decorators=None,
 
2778
              ):
2720
2779
    """Run a test suite for bzr selftest.
2721
2780
 
2722
2781
    :param runner_class: The class of runner to use. Must support the
2737
2796
                            descriptions=0,
2738
2797
                            verbosity=verbosity,
2739
2798
                            bench_history=bench_history,
2740
 
                            list_only=list_only,
2741
2799
                            strict=strict,
 
2800
                            result_decorators=result_decorators,
2742
2801
                            )
2743
2802
    runner.stop_on_failure=stop_on_failure
2744
2803
    # built in decorator factories:
2752
2811
        decorators.append(filter_tests(pattern))
2753
2812
    if suite_decorators:
2754
2813
        decorators.extend(suite_decorators)
 
2814
    # tell the result object how many tests will be running: (except if
 
2815
    # --parallel=fork is being used. Robert said he will provide a better
 
2816
    # progress design later -- vila 20090817)
 
2817
    if fork_decorator not in decorators:
 
2818
        decorators.append(CountingDecorator)
2755
2819
    for decorator in decorators:
2756
2820
        suite = decorator(suite)
2757
 
    result = runner.run(suite)
2758
2821
    if list_only:
 
2822
        # Done after test suite decoration to allow randomisation etc
 
2823
        # to take effect, though that is of marginal benefit.
 
2824
        if verbosity >= 2:
 
2825
            stream.write("Listing tests only ...\n")
 
2826
        for t in iter_suite_tests(suite):
 
2827
            stream.write("%s\n" % (t.id()))
2759
2828
        return True
2760
 
    result.done()
 
2829
    result = runner.run(suite)
2761
2830
    if strict:
2762
2831
        return result.wasStrictlySuccessful()
2763
2832
    else:
2861
2930
        return result
2862
2931
 
2863
2932
 
 
2933
class CountingDecorator(TestDecorator):
 
2934
    """A decorator which calls result.progress(self.countTestCases)."""
 
2935
 
 
2936
    def run(self, result):
 
2937
        progress_method = getattr(result, 'progress', None)
 
2938
        if callable(progress_method):
 
2939
            progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
 
2940
        return super(CountingDecorator, self).run(result)
 
2941
 
 
2942
 
2864
2943
class ExcludeDecorator(TestDecorator):
2865
2944
    """A decorator which excludes test matching an exclude pattern."""
2866
2945
 
3070
3149
    return result
3071
3150
 
3072
3151
 
3073
 
class BZRTransformingResult(unittest.TestResult):
 
3152
class ForwardingResult(unittest.TestResult):
3074
3153
 
3075
3154
    def __init__(self, target):
3076
3155
        unittest.TestResult.__init__(self)
3082
3161
    def stopTest(self, test):
3083
3162
        self.result.stopTest(test)
3084
3163
 
 
3164
    def startTestRun(self):
 
3165
        self.result.startTestRun()
 
3166
 
 
3167
    def stopTestRun(self):
 
3168
        self.result.stopTestRun()
 
3169
 
 
3170
    def addSkip(self, test, reason):
 
3171
        self.result.addSkip(test, reason)
 
3172
 
 
3173
    def addSuccess(self, test):
 
3174
        self.result.addSuccess(test)
 
3175
 
 
3176
    def addError(self, test, err):
 
3177
        self.result.addError(test, err)
 
3178
 
 
3179
    def addFailure(self, test, err):
 
3180
        self.result.addFailure(test, err)
 
3181
 
 
3182
 
 
3183
class BZRTransformingResult(ForwardingResult):
 
3184
 
3085
3185
    def addError(self, test, err):
3086
3186
        feature = self._error_looks_like('UnavailableFeature: ', err)
3087
3187
        if feature is not None:
3097
3197
        else:
3098
3198
            self.result.addFailure(test, err)
3099
3199
 
3100
 
    def addSkip(self, test, reason):
3101
 
        self.result.addSkip(test, reason)
3102
 
 
3103
 
    def addSuccess(self, test):
3104
 
        self.result.addSuccess(test)
3105
 
 
3106
3200
    def _error_looks_like(self, prefix, err):
3107
3201
        """Deserialize exception and returns the stringify value."""
3108
3202
        import subunit
3120
3214
        return value
3121
3215
 
3122
3216
 
 
3217
class ProfileResult(ForwardingResult):
 
3218
    """Generate profiling data for all activity between start and success.
 
3219
    
 
3220
    The profile data is appended to the test's _benchcalls attribute and can
 
3221
    be accessed by the forwarded-to TestResult.
 
3222
 
 
3223
    While it might be cleaner do accumulate this in stopTest, addSuccess is
 
3224
    where our existing output support for lsprof is, and this class aims to
 
3225
    fit in with that: while it could be moved it's not necessary to accomplish
 
3226
    test profiling, nor would it be dramatically cleaner.
 
3227
    """
 
3228
 
 
3229
    def startTest(self, test):
 
3230
        self.profiler = bzrlib.lsprof.BzrProfiler()
 
3231
        self.profiler.start()
 
3232
        ForwardingResult.startTest(self, test)
 
3233
 
 
3234
    def addSuccess(self, test):
 
3235
        stats = self.profiler.stop()
 
3236
        try:
 
3237
            calls = test._benchcalls
 
3238
        except AttributeError:
 
3239
            test._benchcalls = []
 
3240
            calls = test._benchcalls
 
3241
        calls.append(((test.id(), "", ""), stats))
 
3242
        ForwardingResult.addSuccess(self, test)
 
3243
 
 
3244
    def stopTest(self, test):
 
3245
        ForwardingResult.stopTest(self, test)
 
3246
        self.profiler = None
 
3247
 
 
3248
 
3123
3249
# Controlled by "bzr selftest -E=..." option
 
3250
# Currently supported:
 
3251
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
 
3252
#                           preserves any flags supplied at the command line.
 
3253
#   -Edisable_lock_checks   Turns errors in mismatched locks into simple prints
 
3254
#                           rather than failing tests. And no longer raise
 
3255
#                           LockContention when fctnl locks are not being used
 
3256
#                           with proper exclusion rules.
3124
3257
selftest_debug_flags = set()
3125
3258
 
3126
3259
 
3139
3272
             starting_with=None,
3140
3273
             runner_class=None,
3141
3274
             suite_decorators=None,
 
3275
             stream=None,
 
3276
             lsprof_tests=False,
3142
3277
             ):
3143
3278
    """Run the whole test suite under the enhanced runner"""
3144
3279
    # XXX: Very ugly way to do this...
3161
3296
            keep_only = None
3162
3297
        else:
3163
3298
            keep_only = load_test_id_list(load_list)
 
3299
        if starting_with:
 
3300
            starting_with = [test_prefix_alias_registry.resolve_alias(start)
 
3301
                             for start in starting_with]
3164
3302
        if test_suite_factory is None:
 
3303
            # Reduce loading time by loading modules based on the starting_with
 
3304
            # patterns.
3165
3305
            suite = test_suite(keep_only, starting_with)
3166
3306
        else:
3167
3307
            suite = test_suite_factory()
 
3308
        if starting_with:
 
3309
            # But always filter as requested.
 
3310
            suite = filter_suite_by_id_startswith(suite, starting_with)
 
3311
        result_decorators = []
 
3312
        if lsprof_tests:
 
3313
            result_decorators.append(ProfileResult)
3168
3314
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
3169
3315
                     stop_on_failure=stop_on_failure,
3170
3316
                     transport=transport,
3177
3323
                     strict=strict,
3178
3324
                     runner_class=runner_class,
3179
3325
                     suite_decorators=suite_decorators,
 
3326
                     stream=stream,
 
3327
                     result_decorators=result_decorators,
3180
3328
                     )
3181
3329
    finally:
3182
3330
        default_transport = old_transport
3338
3486
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3339
3487
 
3340
3488
 
 
3489
def _test_suite_testmod_names():
 
3490
    """Return the standard list of test module names to test."""
 
3491
    return [
 
3492
        'bzrlib.doc',
 
3493
        'bzrlib.tests.blackbox',
 
3494
        'bzrlib.tests.commands',
 
3495
        'bzrlib.tests.per_branch',
 
3496
        'bzrlib.tests.per_bzrdir',
 
3497
        'bzrlib.tests.per_interrepository',
 
3498
        'bzrlib.tests.per_intertree',
 
3499
        'bzrlib.tests.per_inventory',
 
3500
        'bzrlib.tests.per_interbranch',
 
3501
        'bzrlib.tests.per_lock',
 
3502
        'bzrlib.tests.per_transport',
 
3503
        'bzrlib.tests.per_tree',
 
3504
        'bzrlib.tests.per_pack_repository',
 
3505
        'bzrlib.tests.per_repository',
 
3506
        'bzrlib.tests.per_repository_chk',
 
3507
        'bzrlib.tests.per_repository_reference',
 
3508
        'bzrlib.tests.per_versionedfile',
 
3509
        'bzrlib.tests.per_workingtree',
 
3510
        'bzrlib.tests.test__annotator',
 
3511
        'bzrlib.tests.test__chk_map',
 
3512
        'bzrlib.tests.test__dirstate_helpers',
 
3513
        'bzrlib.tests.test__groupcompress',
 
3514
        'bzrlib.tests.test__known_graph',
 
3515
        'bzrlib.tests.test__rio',
 
3516
        'bzrlib.tests.test__walkdirs_win32',
 
3517
        'bzrlib.tests.test_ancestry',
 
3518
        'bzrlib.tests.test_annotate',
 
3519
        'bzrlib.tests.test_api',
 
3520
        'bzrlib.tests.test_atomicfile',
 
3521
        'bzrlib.tests.test_bad_files',
 
3522
        'bzrlib.tests.test_bencode',
 
3523
        'bzrlib.tests.test_bisect_multi',
 
3524
        'bzrlib.tests.test_branch',
 
3525
        'bzrlib.tests.test_branchbuilder',
 
3526
        'bzrlib.tests.test_btree_index',
 
3527
        'bzrlib.tests.test_bugtracker',
 
3528
        'bzrlib.tests.test_bundle',
 
3529
        'bzrlib.tests.test_bzrdir',
 
3530
        'bzrlib.tests.test__chunks_to_lines',
 
3531
        'bzrlib.tests.test_cache_utf8',
 
3532
        'bzrlib.tests.test_chk_map',
 
3533
        'bzrlib.tests.test_chk_serializer',
 
3534
        'bzrlib.tests.test_chunk_writer',
 
3535
        'bzrlib.tests.test_clean_tree',
 
3536
        'bzrlib.tests.test_commands',
 
3537
        'bzrlib.tests.test_commit',
 
3538
        'bzrlib.tests.test_commit_merge',
 
3539
        'bzrlib.tests.test_config',
 
3540
        'bzrlib.tests.test_conflicts',
 
3541
        'bzrlib.tests.test_counted_lock',
 
3542
        'bzrlib.tests.test_crash',
 
3543
        'bzrlib.tests.test_decorators',
 
3544
        'bzrlib.tests.test_delta',
 
3545
        'bzrlib.tests.test_debug',
 
3546
        'bzrlib.tests.test_deprecated_graph',
 
3547
        'bzrlib.tests.test_diff',
 
3548
        'bzrlib.tests.test_directory_service',
 
3549
        'bzrlib.tests.test_dirstate',
 
3550
        'bzrlib.tests.test_email_message',
 
3551
        'bzrlib.tests.test_eol_filters',
 
3552
        'bzrlib.tests.test_errors',
 
3553
        'bzrlib.tests.test_export',
 
3554
        'bzrlib.tests.test_extract',
 
3555
        'bzrlib.tests.test_fetch',
 
3556
        'bzrlib.tests.test_fifo_cache',
 
3557
        'bzrlib.tests.test_filters',
 
3558
        'bzrlib.tests.test_ftp_transport',
 
3559
        'bzrlib.tests.test_foreign',
 
3560
        'bzrlib.tests.test_generate_docs',
 
3561
        'bzrlib.tests.test_generate_ids',
 
3562
        'bzrlib.tests.test_globbing',
 
3563
        'bzrlib.tests.test_gpg',
 
3564
        'bzrlib.tests.test_graph',
 
3565
        'bzrlib.tests.test_groupcompress',
 
3566
        'bzrlib.tests.test_hashcache',
 
3567
        'bzrlib.tests.test_help',
 
3568
        'bzrlib.tests.test_hooks',
 
3569
        'bzrlib.tests.test_http',
 
3570
        'bzrlib.tests.test_http_response',
 
3571
        'bzrlib.tests.test_https_ca_bundle',
 
3572
        'bzrlib.tests.test_identitymap',
 
3573
        'bzrlib.tests.test_ignores',
 
3574
        'bzrlib.tests.test_index',
 
3575
        'bzrlib.tests.test_info',
 
3576
        'bzrlib.tests.test_inv',
 
3577
        'bzrlib.tests.test_inventory_delta',
 
3578
        'bzrlib.tests.test_knit',
 
3579
        'bzrlib.tests.test_lazy_import',
 
3580
        'bzrlib.tests.test_lazy_regex',
 
3581
        'bzrlib.tests.test_lock',
 
3582
        'bzrlib.tests.test_lockable_files',
 
3583
        'bzrlib.tests.test_lockdir',
 
3584
        'bzrlib.tests.test_log',
 
3585
        'bzrlib.tests.test_lru_cache',
 
3586
        'bzrlib.tests.test_lsprof',
 
3587
        'bzrlib.tests.test_mail_client',
 
3588
        'bzrlib.tests.test_memorytree',
 
3589
        'bzrlib.tests.test_merge',
 
3590
        'bzrlib.tests.test_merge3',
 
3591
        'bzrlib.tests.test_merge_core',
 
3592
        'bzrlib.tests.test_merge_directive',
 
3593
        'bzrlib.tests.test_missing',
 
3594
        'bzrlib.tests.test_msgeditor',
 
3595
        'bzrlib.tests.test_multiparent',
 
3596
        'bzrlib.tests.test_mutabletree',
 
3597
        'bzrlib.tests.test_nonascii',
 
3598
        'bzrlib.tests.test_options',
 
3599
        'bzrlib.tests.test_osutils',
 
3600
        'bzrlib.tests.test_osutils_encodings',
 
3601
        'bzrlib.tests.test_pack',
 
3602
        'bzrlib.tests.test_patch',
 
3603
        'bzrlib.tests.test_patches',
 
3604
        'bzrlib.tests.test_permissions',
 
3605
        'bzrlib.tests.test_plugins',
 
3606
        'bzrlib.tests.test_progress',
 
3607
        'bzrlib.tests.test_read_bundle',
 
3608
        'bzrlib.tests.test_reconcile',
 
3609
        'bzrlib.tests.test_reconfigure',
 
3610
        'bzrlib.tests.test_registry',
 
3611
        'bzrlib.tests.test_remote',
 
3612
        'bzrlib.tests.test_rename_map',
 
3613
        'bzrlib.tests.test_repository',
 
3614
        'bzrlib.tests.test_revert',
 
3615
        'bzrlib.tests.test_revision',
 
3616
        'bzrlib.tests.test_revisionspec',
 
3617
        'bzrlib.tests.test_revisiontree',
 
3618
        'bzrlib.tests.test_rio',
 
3619
        'bzrlib.tests.test_rules',
 
3620
        'bzrlib.tests.test_sampler',
 
3621
        'bzrlib.tests.test_selftest',
 
3622
        'bzrlib.tests.test_serializer',
 
3623
        'bzrlib.tests.test_setup',
 
3624
        'bzrlib.tests.test_sftp_transport',
 
3625
        'bzrlib.tests.test_shelf',
 
3626
        'bzrlib.tests.test_shelf_ui',
 
3627
        'bzrlib.tests.test_smart',
 
3628
        'bzrlib.tests.test_smart_add',
 
3629
        'bzrlib.tests.test_smart_request',
 
3630
        'bzrlib.tests.test_smart_transport',
 
3631
        'bzrlib.tests.test_smtp_connection',
 
3632
        'bzrlib.tests.test_source',
 
3633
        'bzrlib.tests.test_ssh_transport',
 
3634
        'bzrlib.tests.test_status',
 
3635
        'bzrlib.tests.test_store',
 
3636
        'bzrlib.tests.test_strace',
 
3637
        'bzrlib.tests.test_subsume',
 
3638
        'bzrlib.tests.test_switch',
 
3639
        'bzrlib.tests.test_symbol_versioning',
 
3640
        'bzrlib.tests.test_tag',
 
3641
        'bzrlib.tests.test_testament',
 
3642
        'bzrlib.tests.test_textfile',
 
3643
        'bzrlib.tests.test_textmerge',
 
3644
        'bzrlib.tests.test_timestamp',
 
3645
        'bzrlib.tests.test_trace',
 
3646
        'bzrlib.tests.test_transactions',
 
3647
        'bzrlib.tests.test_transform',
 
3648
        'bzrlib.tests.test_transport',
 
3649
        'bzrlib.tests.test_transport_log',
 
3650
        'bzrlib.tests.test_tree',
 
3651
        'bzrlib.tests.test_treebuilder',
 
3652
        'bzrlib.tests.test_tsort',
 
3653
        'bzrlib.tests.test_tuned_gzip',
 
3654
        'bzrlib.tests.test_ui',
 
3655
        'bzrlib.tests.test_uncommit',
 
3656
        'bzrlib.tests.test_upgrade',
 
3657
        'bzrlib.tests.test_upgrade_stacked',
 
3658
        'bzrlib.tests.test_urlutils',
 
3659
        'bzrlib.tests.test_version',
 
3660
        'bzrlib.tests.test_version_info',
 
3661
        'bzrlib.tests.test_weave',
 
3662
        'bzrlib.tests.test_whitebox',
 
3663
        'bzrlib.tests.test_win32utils',
 
3664
        'bzrlib.tests.test_workingtree',
 
3665
        'bzrlib.tests.test_workingtree_4',
 
3666
        'bzrlib.tests.test_wsgi',
 
3667
        'bzrlib.tests.test_xml',
 
3668
        ]
 
3669
 
 
3670
 
 
3671
def _test_suite_modules_to_doctest():
 
3672
    """Return the list of modules to doctest."""   
 
3673
    return [
 
3674
        'bzrlib',
 
3675
        'bzrlib.branchbuilder',
 
3676
        'bzrlib.export',
 
3677
        'bzrlib.inventory',
 
3678
        'bzrlib.iterablefile',
 
3679
        'bzrlib.lockdir',
 
3680
        'bzrlib.merge3',
 
3681
        'bzrlib.option',
 
3682
        'bzrlib.symbol_versioning',
 
3683
        'bzrlib.tests',
 
3684
        'bzrlib.timestamp',
 
3685
        'bzrlib.version_info_formats.format_custom',
 
3686
        ]
 
3687
 
 
3688
 
3341
3689
def test_suite(keep_only=None, starting_with=None):
3342
3690
    """Build and return TestSuite for the whole of bzrlib.
3343
3691
 
3349
3697
    This function can be replaced if you need to change the default test
3350
3698
    suite on a global basis, but it is not encouraged.
3351
3699
    """
3352
 
    testmod_names = [
3353
 
                   'bzrlib.doc',
3354
 
                   'bzrlib.tests.blackbox',
3355
 
                   'bzrlib.tests.commands',
3356
 
                   'bzrlib.tests.per_branch',
3357
 
                   'bzrlib.tests.per_bzrdir',
3358
 
                   'bzrlib.tests.per_interrepository',
3359
 
                   'bzrlib.tests.per_intertree',
3360
 
                   'bzrlib.tests.per_inventory',
3361
 
                   'bzrlib.tests.per_interbranch',
3362
 
                   'bzrlib.tests.per_lock',
3363
 
                   'bzrlib.tests.per_transport',
3364
 
                   'bzrlib.tests.per_tree',
3365
 
                   'bzrlib.tests.per_repository',
3366
 
                   'bzrlib.tests.per_repository_chk',
3367
 
                   'bzrlib.tests.per_repository_reference',
3368
 
                   'bzrlib.tests.per_workingtree',
3369
 
                   'bzrlib.tests.test__annotator',
3370
 
                   'bzrlib.tests.test__chk_map',
3371
 
                   'bzrlib.tests.test__dirstate_helpers',
3372
 
                   'bzrlib.tests.test__groupcompress',
3373
 
                   'bzrlib.tests.test__known_graph',
3374
 
                   'bzrlib.tests.test__rio',
3375
 
                   'bzrlib.tests.test__walkdirs_win32',
3376
 
                   'bzrlib.tests.test_ancestry',
3377
 
                   'bzrlib.tests.test_annotate',
3378
 
                   'bzrlib.tests.test_api',
3379
 
                   'bzrlib.tests.test_atomicfile',
3380
 
                   'bzrlib.tests.test_bad_files',
3381
 
                   'bzrlib.tests.test_bencode',
3382
 
                   'bzrlib.tests.test_bisect_multi',
3383
 
                   'bzrlib.tests.test_branch',
3384
 
                   'bzrlib.tests.test_branchbuilder',
3385
 
                   'bzrlib.tests.test_btree_index',
3386
 
                   'bzrlib.tests.test_bugtracker',
3387
 
                   'bzrlib.tests.test_bundle',
3388
 
                   'bzrlib.tests.test_bzrdir',
3389
 
                   'bzrlib.tests.test__chunks_to_lines',
3390
 
                   'bzrlib.tests.test_cache_utf8',
3391
 
                   'bzrlib.tests.test_chk_map',
3392
 
                   'bzrlib.tests.test_chk_serializer',
3393
 
                   'bzrlib.tests.test_chunk_writer',
3394
 
                   'bzrlib.tests.test_clean_tree',
3395
 
                   'bzrlib.tests.test_commands',
3396
 
                   'bzrlib.tests.test_commit',
3397
 
                   'bzrlib.tests.test_commit_merge',
3398
 
                   'bzrlib.tests.test_config',
3399
 
                   'bzrlib.tests.test_conflicts',
3400
 
                   'bzrlib.tests.test_counted_lock',
3401
 
                   'bzrlib.tests.test_decorators',
3402
 
                   'bzrlib.tests.test_delta',
3403
 
                   'bzrlib.tests.test_debug',
3404
 
                   'bzrlib.tests.test_deprecated_graph',
3405
 
                   'bzrlib.tests.test_diff',
3406
 
                   'bzrlib.tests.test_directory_service',
3407
 
                   'bzrlib.tests.test_dirstate',
3408
 
                   'bzrlib.tests.test_email_message',
3409
 
                   'bzrlib.tests.test_eol_filters',
3410
 
                   'bzrlib.tests.test_errors',
3411
 
                   'bzrlib.tests.test_export',
3412
 
                   'bzrlib.tests.test_extract',
3413
 
                   'bzrlib.tests.test_fetch',
3414
 
                   'bzrlib.tests.test_fifo_cache',
3415
 
                   'bzrlib.tests.test_filters',
3416
 
                   'bzrlib.tests.test_ftp_transport',
3417
 
                   'bzrlib.tests.test_foreign',
3418
 
                   'bzrlib.tests.test_generate_docs',
3419
 
                   'bzrlib.tests.test_generate_ids',
3420
 
                   'bzrlib.tests.test_globbing',
3421
 
                   'bzrlib.tests.test_gpg',
3422
 
                   'bzrlib.tests.test_graph',
3423
 
                   'bzrlib.tests.test_groupcompress',
3424
 
                   'bzrlib.tests.test_hashcache',
3425
 
                   'bzrlib.tests.test_help',
3426
 
                   'bzrlib.tests.test_hooks',
3427
 
                   'bzrlib.tests.test_http',
3428
 
                   'bzrlib.tests.test_http_response',
3429
 
                   'bzrlib.tests.test_https_ca_bundle',
3430
 
                   'bzrlib.tests.test_identitymap',
3431
 
                   'bzrlib.tests.test_ignores',
3432
 
                   'bzrlib.tests.test_index',
3433
 
                   'bzrlib.tests.test_info',
3434
 
                   'bzrlib.tests.test_inv',
3435
 
                   'bzrlib.tests.test_inventory_delta',
3436
 
                   'bzrlib.tests.test_knit',
3437
 
                   'bzrlib.tests.test_lazy_import',
3438
 
                   'bzrlib.tests.test_lazy_regex',
3439
 
                   'bzrlib.tests.test_lockable_files',
3440
 
                   'bzrlib.tests.test_lockdir',
3441
 
                   'bzrlib.tests.test_log',
3442
 
                   'bzrlib.tests.test_lru_cache',
3443
 
                   'bzrlib.tests.test_lsprof',
3444
 
                   'bzrlib.tests.test_mail_client',
3445
 
                   'bzrlib.tests.test_memorytree',
3446
 
                   'bzrlib.tests.test_merge',
3447
 
                   'bzrlib.tests.test_merge3',
3448
 
                   'bzrlib.tests.test_merge_core',
3449
 
                   'bzrlib.tests.test_merge_directive',
3450
 
                   'bzrlib.tests.test_missing',
3451
 
                   'bzrlib.tests.test_msgeditor',
3452
 
                   'bzrlib.tests.test_multiparent',
3453
 
                   'bzrlib.tests.test_mutabletree',
3454
 
                   'bzrlib.tests.test_nonascii',
3455
 
                   'bzrlib.tests.test_options',
3456
 
                   'bzrlib.tests.test_osutils',
3457
 
                   'bzrlib.tests.test_osutils_encodings',
3458
 
                   'bzrlib.tests.test_pack',
3459
 
                   'bzrlib.tests.test_pack_repository',
3460
 
                   'bzrlib.tests.test_patch',
3461
 
                   'bzrlib.tests.test_patches',
3462
 
                   'bzrlib.tests.test_permissions',
3463
 
                   'bzrlib.tests.test_plugins',
3464
 
                   'bzrlib.tests.test_progress',
3465
 
                   'bzrlib.tests.test_read_bundle',
3466
 
                   'bzrlib.tests.test_reconcile',
3467
 
                   'bzrlib.tests.test_reconfigure',
3468
 
                   'bzrlib.tests.test_registry',
3469
 
                   'bzrlib.tests.test_remote',
3470
 
                   'bzrlib.tests.test_rename_map',
3471
 
                   'bzrlib.tests.test_repository',
3472
 
                   'bzrlib.tests.test_revert',
3473
 
                   'bzrlib.tests.test_revision',
3474
 
                   'bzrlib.tests.test_revisionspec',
3475
 
                   'bzrlib.tests.test_revisiontree',
3476
 
                   'bzrlib.tests.test_rio',
3477
 
                   'bzrlib.tests.test_rules',
3478
 
                   'bzrlib.tests.test_sampler',
3479
 
                   'bzrlib.tests.test_selftest',
3480
 
                   'bzrlib.tests.test_serializer',
3481
 
                   'bzrlib.tests.test_setup',
3482
 
                   'bzrlib.tests.test_sftp_transport',
3483
 
                   'bzrlib.tests.test_shelf',
3484
 
                   'bzrlib.tests.test_shelf_ui',
3485
 
                   'bzrlib.tests.test_smart',
3486
 
                   'bzrlib.tests.test_smart_add',
3487
 
                   'bzrlib.tests.test_smart_request',
3488
 
                   'bzrlib.tests.test_smart_transport',
3489
 
                   'bzrlib.tests.test_smtp_connection',
3490
 
                   'bzrlib.tests.test_source',
3491
 
                   'bzrlib.tests.test_ssh_transport',
3492
 
                   'bzrlib.tests.test_status',
3493
 
                   'bzrlib.tests.test_store',
3494
 
                   'bzrlib.tests.test_strace',
3495
 
                   'bzrlib.tests.test_subsume',
3496
 
                   'bzrlib.tests.test_switch',
3497
 
                   'bzrlib.tests.test_symbol_versioning',
3498
 
                   'bzrlib.tests.test_tag',
3499
 
                   'bzrlib.tests.test_testament',
3500
 
                   'bzrlib.tests.test_textfile',
3501
 
                   'bzrlib.tests.test_textmerge',
3502
 
                   'bzrlib.tests.test_timestamp',
3503
 
                   'bzrlib.tests.test_trace',
3504
 
                   'bzrlib.tests.test_transactions',
3505
 
                   'bzrlib.tests.test_transform',
3506
 
                   'bzrlib.tests.test_transport',
3507
 
                   'bzrlib.tests.test_transport_log',
3508
 
                   'bzrlib.tests.test_tree',
3509
 
                   'bzrlib.tests.test_treebuilder',
3510
 
                   'bzrlib.tests.test_tsort',
3511
 
                   'bzrlib.tests.test_tuned_gzip',
3512
 
                   'bzrlib.tests.test_ui',
3513
 
                   'bzrlib.tests.test_uncommit',
3514
 
                   'bzrlib.tests.test_upgrade',
3515
 
                   'bzrlib.tests.test_upgrade_stacked',
3516
 
                   'bzrlib.tests.test_urlutils',
3517
 
                   'bzrlib.tests.test_version',
3518
 
                   'bzrlib.tests.test_version_info',
3519
 
                   'bzrlib.tests.test_versionedfile',
3520
 
                   'bzrlib.tests.test_weave',
3521
 
                   'bzrlib.tests.test_whitebox',
3522
 
                   'bzrlib.tests.test_win32utils',
3523
 
                   'bzrlib.tests.test_workingtree',
3524
 
                   'bzrlib.tests.test_workingtree_4',
3525
 
                   'bzrlib.tests.test_wsgi',
3526
 
                   'bzrlib.tests.test_xml',
3527
 
                   ]
3528
3700
 
3529
3701
    loader = TestUtil.TestLoader()
3530
3702
 
3531
3703
    if keep_only is not None:
3532
3704
        id_filter = TestIdList(keep_only)
3533
3705
    if starting_with:
3534
 
        starting_with = [test_prefix_alias_registry.resolve_alias(start)
3535
 
                         for start in starting_with]
3536
3706
        # We take precedence over keep_only because *at loading time* using
3537
3707
        # both options means we will load less tests for the same final result.
3538
3708
        def interesting_module(name):
3561
3731
    suite = loader.suiteClass()
3562
3732
 
3563
3733
    # modules building their suite with loadTestsFromModuleNames
3564
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
3565
 
 
3566
 
    modules_to_doctest = [
3567
 
        'bzrlib',
3568
 
        'bzrlib.branchbuilder',
3569
 
        'bzrlib.export',
3570
 
        'bzrlib.inventory',
3571
 
        'bzrlib.iterablefile',
3572
 
        'bzrlib.lockdir',
3573
 
        'bzrlib.merge3',
3574
 
        'bzrlib.option',
3575
 
        'bzrlib.symbol_versioning',
3576
 
        'bzrlib.tests',
3577
 
        'bzrlib.timestamp',
3578
 
        'bzrlib.version_info_formats.format_custom',
3579
 
        ]
3580
 
 
3581
 
    for mod in modules_to_doctest:
 
3734
    suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
 
3735
 
 
3736
    for mod in _test_suite_modules_to_doctest():
3582
3737
        if not interesting_module(mod):
3583
3738
            # No tests to keep here, move along
3584
3739
            continue
3613
3768
            reload(sys)
3614
3769
            sys.setdefaultencoding(default_encoding)
3615
3770
 
3616
 
    if starting_with:
3617
 
        suite = filter_suite_by_id_startswith(suite, starting_with)
3618
 
 
3619
3771
    if keep_only is not None:
3620
3772
        # Now that the referred modules have loaded their tests, keep only the
3621
3773
        # requested ones.
3728
3880
    :param new_id: The id to assign to it.
3729
3881
    :return: The new test.
3730
3882
    """
3731
 
    from copy import deepcopy
3732
 
    new_test = deepcopy(test)
 
3883
    new_test = copy(test)
3733
3884
    new_test.id = lambda: new_id
3734
3885
    return new_test
3735
3886
 
3749
3900
    try:
3750
3901
        osutils.rmtree(dirname)
3751
3902
    except OSError, e:
3752
 
        if sys.platform == 'win32' and e.errno == errno.EACCES:
3753
 
            sys.stderr.write('Permission denied: '
3754
 
                             'unable to remove testing dir '
3755
 
                             '%s\n%s'
3756
 
                             % (os.path.basename(dirname), e))
3757
 
        else:
3758
 
            raise
 
3903
        # We don't want to fail here because some useful display will be lost
 
3904
        # otherwise. Polluting the tmp dir is bad, but not giving all the
 
3905
        # possible info to the test runner is even worse.
 
3906
        sys.stderr.write('Unable to remove testing dir %s\n%s'
 
3907
                         % (os.path.basename(dirname), e))
3759
3908
 
3760
3909
 
3761
3910
class Feature(object):