~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: wang
  • Date: 2006-10-29 13:41:32 UTC
  • mto: (2104.4.1 wang_65714)
  • mto: This revision was merged to the branch mainline in revision 2109.
  • Revision ID: wang@ubuntu-20061029134132-3d7f4216f20c4aef
Replace python's difflib by patiencediff because the worst case 
performance is cubic for difflib and people commiting large data 
files are often hurt by this. The worst case performance of patience is 
quadratic. Fix bug 65714.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 by Canonical Ltd
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
43
43
import time
44
44
 
45
45
 
 
46
from bzrlib import memorytree
46
47
import bzrlib.branch
47
48
import bzrlib.bzrdir as bzrdir
48
49
import bzrlib.commands
49
50
import bzrlib.bundle.serializer
50
51
import bzrlib.errors as errors
 
52
import bzrlib.export
51
53
import bzrlib.inventory
52
54
import bzrlib.iterablefile
53
55
import bzrlib.lockdir
64
66
import bzrlib.progress as progress
65
67
from bzrlib.revision import common_ancestor
66
68
import bzrlib.store
 
69
from bzrlib import symbol_versioning
67
70
import bzrlib.trace
68
71
from bzrlib.transport import get_transport
69
72
import bzrlib.transport
70
 
from bzrlib.transport.local import LocalRelpathServer
 
73
from bzrlib.transport.local import LocalURLServer
 
74
from bzrlib.transport.memory import MemoryServer
71
75
from bzrlib.transport.readonly import ReadonlyServer
72
76
from bzrlib.trace import mutter
73
77
from bzrlib.tests import TestUtil
79
83
import bzrlib.urlutils as urlutils
80
84
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
81
85
 
82
 
default_transport = LocalRelpathServer
 
86
default_transport = LocalURLServer
83
87
 
84
88
MODULES_TO_TEST = []
85
89
MODULES_TO_DOCTEST = [
86
 
                      bzrlib.branch,
87
90
                      bzrlib.bundle.serializer,
88
 
                      bzrlib.commands,
89
91
                      bzrlib.errors,
 
92
                      bzrlib.export,
90
93
                      bzrlib.inventory,
91
94
                      bzrlib.iterablefile,
92
95
                      bzrlib.lockdir,
93
96
                      bzrlib.merge3,
94
97
                      bzrlib.option,
95
 
                      bzrlib.osutils,
96
 
                      bzrlib.store
 
98
                      bzrlib.store,
97
99
                      ]
98
100
 
99
101
 
136
138
    """
137
139
    stop_early = False
138
140
    
139
 
    def __init__(self, stream, descriptions, verbosity, pb=None):
 
141
    def __init__(self, stream, descriptions, verbosity, pb=None,
 
142
                 bench_history=None):
 
143
        """Construct new TestResult.
 
144
 
 
145
        :param bench_history: Optionally, a writable file object to accumulate
 
146
            benchmark results.
 
147
        """
140
148
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
141
149
        self.pb = pb
 
150
        if bench_history is not None:
 
151
            from bzrlib.version import _get_bzr_source_tree
 
152
            src_tree = _get_bzr_source_tree()
 
153
            if src_tree:
 
154
                try:
 
155
                    revision_id = src_tree.get_parent_ids()[0]
 
156
                except IndexError:
 
157
                    # XXX: if this is a brand new tree, do the same as if there
 
158
                    # is no branch.
 
159
                    revision_id = ''
 
160
            else:
 
161
                # XXX: If there's no branch, what should we do?
 
162
                revision_id = ''
 
163
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
 
164
        self._bench_history = bench_history
142
165
    
143
166
    def extractBenchmarkTime(self, testCase):
144
167
        """Add a benchmark time for the current test case."""
216
239
        if isinstance(err[1], TestSkipped):
217
240
            return self.addSkipped(test, err)    
218
241
        unittest.TestResult.addError(self, test, err)
 
242
        # We can only do this if we have one of our TestCases, not if
 
243
        # we have a doctest.
 
244
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
245
        if setKeepLogfile is not None:
 
246
            setKeepLogfile()
219
247
        self.extractBenchmarkTime(test)
220
248
        if self.showAll:
221
249
            self.stream.writeln("ERROR %s" % self._testTimeString())
232
260
 
233
261
    def addFailure(self, test, err):
234
262
        unittest.TestResult.addFailure(self, test, err)
 
263
        # We can only do this if we have one of our TestCases, not if
 
264
        # we have a doctest.
 
265
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
266
        if setKeepLogfile is not None:
 
267
            setKeepLogfile()
235
268
        self.extractBenchmarkTime(test)
236
269
        if self.showAll:
237
270
            self.stream.writeln(" FAIL %s" % self._testTimeString())
248
281
 
249
282
    def addSuccess(self, test):
250
283
        self.extractBenchmarkTime(test)
 
284
        if self._bench_history is not None:
 
285
            if self._benchmarkTime is not None:
 
286
                self._bench_history.write("%s %s\n" % (
 
287
                    self._formatTime(self._benchmarkTime),
 
288
                    test.id()))
251
289
        if self.showAll:
252
290
            self.stream.writeln('   OK %s' % self._testTimeString())
253
291
            for bench_called, stats in getattr(test, '_benchcalls', []):
304
342
                 descriptions=0,
305
343
                 verbosity=1,
306
344
                 keep_output=False,
307
 
                 pb=None):
 
345
                 pb=None,
 
346
                 bench_history=None):
308
347
        self.stream = unittest._WritelnDecorator(stream)
309
348
        self.descriptions = descriptions
310
349
        self.verbosity = verbosity
311
350
        self.keep_output = keep_output
312
351
        self.pb = pb
 
352
        self._bench_history = bench_history
313
353
 
314
354
    def _makeResult(self):
315
355
        result = _MyResult(self.stream,
316
356
                           self.descriptions,
317
357
                           self.verbosity,
318
 
                           pb=self.pb)
 
358
                           pb=self.pb,
 
359
                           bench_history=self._bench_history)
319
360
        result.stop_early = self.stop_on_failure
320
361
        return result
321
362
 
350
391
        # This is still a little bogus, 
351
392
        # but only a little. Folk not using our testrunner will
352
393
        # have to delete their temp directories themselves.
353
 
        test_root = TestCaseInTempDir.TEST_ROOT
 
394
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
354
395
        if result.wasSuccessful() or not self.keep_output:
355
396
            if test_root is not None:
356
397
                # If LANG=C we probably have created some bogus paths
374
415
                self.stream.writeln(
375
416
                    "Failed tests working directories are in '%s'\n" %
376
417
                    test_root)
377
 
        TestCaseInTempDir.TEST_ROOT = None
 
418
        TestCaseWithMemoryTransport.TEST_ROOT = None
378
419
        if self.pb is not None:
379
420
            self.pb.clear()
380
421
        return result
395
436
 
396
437
class TestSkipped(Exception):
397
438
    """Indicates that a test was intentionally skipped, rather than failing."""
398
 
    # XXX: Not used yet
399
439
 
400
440
 
401
441
class CommandFailed(Exception):
451
491
 
452
492
    _log_file_name = None
453
493
    _log_contents = ''
 
494
    _keep_log_file = False
454
495
    # record lsprof data when performing benchmark calls.
455
496
    _gather_lsprof_in_benchmarks = False
456
497
 
552
593
            self.fail("%r is an instance of %s rather than %s" % (
553
594
                obj, obj.__class__, kls))
554
595
 
 
596
    def _capture_warnings(self, a_callable, *args, **kwargs):
 
597
        """A helper for callDeprecated and applyDeprecated.
 
598
 
 
599
        :param a_callable: A callable to call.
 
600
        :param args: The positional arguments for the callable
 
601
        :param kwargs: The keyword arguments for the callable
 
602
        :return: A tuple (warnings, result). result is the result of calling
 
603
            a_callable(*args, **kwargs).
 
604
        """
 
605
        local_warnings = []
 
606
        def capture_warnings(msg, cls, stacklevel=None):
 
607
            # we've hooked into a deprecation specific callpath,
 
608
            # only deprecations should getting sent via it.
 
609
            self.assertEqual(cls, DeprecationWarning)
 
610
            local_warnings.append(msg)
 
611
        original_warning_method = symbol_versioning.warn
 
612
        symbol_versioning.set_warning_method(capture_warnings)
 
613
        try:
 
614
            result = a_callable(*args, **kwargs)
 
615
        finally:
 
616
            symbol_versioning.set_warning_method(original_warning_method)
 
617
        return (local_warnings, result)
 
618
 
 
619
    def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
 
620
        """Call a deprecated callable without warning the user.
 
621
 
 
622
        :param deprecation_format: The deprecation format that the callable
 
623
            should have been deprecated with. This is the same type as the 
 
624
            parameter to deprecated_method/deprecated_function. If the 
 
625
            callable is not deprecated with this format, an assertion error
 
626
            will be raised.
 
627
        :param a_callable: A callable to call. This may be a bound method or
 
628
            a regular function. It will be called with *args and **kwargs.
 
629
        :param args: The positional arguments for the callable
 
630
        :param kwargs: The keyword arguments for the callable
 
631
        :return: The result of a_callable(*args, **kwargs)
 
632
        """
 
633
        call_warnings, result = self._capture_warnings(a_callable,
 
634
            *args, **kwargs)
 
635
        expected_first_warning = symbol_versioning.deprecation_string(
 
636
            a_callable, deprecation_format)
 
637
        if len(call_warnings) == 0:
 
638
            self.fail("No assertion generated by call to %s" %
 
639
                a_callable)
 
640
        self.assertEqual(expected_first_warning, call_warnings[0])
 
641
        return result
 
642
 
 
643
    def callDeprecated(self, expected, callable, *args, **kwargs):
 
644
        """Assert that a callable is deprecated in a particular way.
 
645
 
 
646
        This is a very precise test for unusual requirements. The 
 
647
        applyDeprecated helper function is probably more suited for most tests
 
648
        as it allows you to simply specify the deprecation format being used
 
649
        and will ensure that that is issued for the function being called.
 
650
 
 
651
        :param expected: a list of the deprecation warnings expected, in order
 
652
        :param callable: The callable to call
 
653
        :param args: The positional arguments for the callable
 
654
        :param kwargs: The keyword arguments for the callable
 
655
        """
 
656
        call_warnings, result = self._capture_warnings(callable,
 
657
            *args, **kwargs)
 
658
        self.assertEqual(expected, call_warnings)
 
659
        return result
 
660
 
555
661
    def _startLogFile(self):
556
662
        """Send bzr and test log messages to a temporary file.
557
663
 
558
664
        The file is removed as the test is torn down.
559
665
        """
560
666
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
561
 
        encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
562
 
        self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
 
667
        self._log_file = os.fdopen(fileno, 'w+')
563
668
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
564
669
        self._log_file_name = name
565
670
        self.addCleanup(self._finishLogFile)
567
672
    def _finishLogFile(self):
568
673
        """Finished with the log file.
569
674
 
570
 
        Read contents into memory, close, and delete.
 
675
        Close the file and delete it, unless setKeepLogfile was called.
571
676
        """
572
677
        if self._log_file is None:
573
678
            return
574
679
        bzrlib.trace.disable_test_log(self._log_nonce)
575
 
        self._log_file.seek(0)
576
 
        self._log_contents = self._log_file.read()
577
680
        self._log_file.close()
578
 
        os.remove(self._log_file_name)
579
 
        self._log_file = self._log_file_name = None
 
681
        self._log_file = None
 
682
        if not self._keep_log_file:
 
683
            os.remove(self._log_file_name)
 
684
            self._log_file_name = None
 
685
 
 
686
    def setKeepLogfile(self):
 
687
        """Make the logfile not be deleted when _finishLogFile is called."""
 
688
        self._keep_log_file = True
580
689
 
581
690
    def addCleanup(self, callable):
582
691
        """Arrange to run a callable when this case is torn down.
591
700
 
592
701
    def _cleanEnvironment(self):
593
702
        new_env = {
 
703
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
594
704
            'HOME': os.getcwd(),
595
705
            'APPDATA': os.getcwd(),
596
706
            'BZR_EMAIL': None,
597
707
            'BZREMAIL': None, # may still be present in the environment
598
708
            'EMAIL': None,
 
709
            'BZR_PROGRESS_BAR': None,
599
710
        }
600
711
        self.__old_env = {}
601
712
        self.addCleanup(self._restoreEnvironment)
602
713
        for name, value in new_env.iteritems():
603
714
            self._captureVar(name, value)
604
715
 
605
 
 
606
716
    def _captureVar(self, name, newvalue):
607
 
        """Set an environment variable, preparing it to be reset when finished."""
608
 
        self.__old_env[name] = os.environ.get(name, None)
609
 
        if newvalue is None:
610
 
            if name in os.environ:
611
 
                del os.environ[name]
612
 
        else:
613
 
            os.environ[name] = newvalue
614
 
 
615
 
    @staticmethod
616
 
    def _restoreVar(name, value):
617
 
        if value is None:
618
 
            if name in os.environ:
619
 
                del os.environ[name]
620
 
        else:
621
 
            os.environ[name] = value
 
717
        """Set an environment variable, and reset it when finished."""
 
718
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
622
719
 
623
720
    def _restoreEnvironment(self):
624
721
        for name, value in self.__old_env.iteritems():
625
 
            self._restoreVar(name, value)
 
722
            osutils.set_or_unset_env(name, value)
626
723
 
627
724
    def tearDown(self):
628
725
        self._runCleanups()
663
760
    def log(self, *args):
664
761
        mutter(*args)
665
762
 
666
 
    def _get_log(self):
667
 
        """Return as a string the log for this test"""
668
 
        if self._log_file_name:
669
 
            return open(self._log_file_name).read()
670
 
        else:
 
763
    def _get_log(self, keep_log_file=False):
 
764
        """Return as a string the log for this test. If the file is still
 
765
        on disk and keep_log_file=False, delete the log file and store the
 
766
        content in self._log_contents."""
 
767
        # flush the log file, to get all content
 
768
        import bzrlib.trace
 
769
        bzrlib.trace._trace_file.flush()
 
770
        if self._log_contents:
671
771
            return self._log_contents
672
 
        # TODO: Delete the log after it's been read in
 
772
        if self._log_file_name is not None:
 
773
            logfile = open(self._log_file_name)
 
774
            try:
 
775
                log_contents = logfile.read()
 
776
            finally:
 
777
                logfile.close()
 
778
            if not keep_log_file:
 
779
                self._log_contents = log_contents
 
780
                os.remove(self._log_file_name)
 
781
            return log_contents
 
782
        else:
 
783
            return "DELETED log file to reduce memory footprint"
673
784
 
674
785
    def capture(self, cmd, retcode=0):
675
786
        """Shortcut that splits cmd into words, runs, and returns stdout"""
676
787
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
677
788
 
678
 
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None):
 
789
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
 
790
                         working_dir=None):
679
791
        """Invoke bzr and return (stdout, stderr).
680
792
 
681
793
        Useful for code that wants to check the contents of the
696
808
        :param retcode: expected return code, or None for don't-care.
697
809
        :param encoding: encoding for sys.stdout and sys.stderr
698
810
        :param stdin: A string to be used as stdin for the command.
 
811
        :param working_dir: Change to this directory before running
699
812
        """
700
813
        if encoding is None:
701
814
            encoding = bzrlib.user_encoding
717
830
            stdout=stdout,
718
831
            stderr=stderr)
719
832
        bzrlib.ui.ui_factory.stdin = stdin
 
833
 
 
834
        cwd = None
 
835
        if working_dir is not None:
 
836
            cwd = osutils.getcwd()
 
837
            os.chdir(working_dir)
 
838
 
720
839
        try:
721
840
            result = self.apply_redirected(stdin, stdout, stderr,
722
841
                                           bzrlib.commands.run_bzr_catch_errors,
724
843
        finally:
725
844
            logger.removeHandler(handler)
726
845
            bzrlib.ui.ui_factory = old_ui_factory
 
846
            if cwd is not None:
 
847
                os.chdir(cwd)
727
848
 
728
849
        out = stdout.getvalue()
729
850
        err = stderr.getvalue()
750
871
        retcode = kwargs.pop('retcode', 0)
751
872
        encoding = kwargs.pop('encoding', None)
752
873
        stdin = kwargs.pop('stdin', None)
753
 
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding, stdin=stdin)
 
874
        working_dir = kwargs.pop('working_dir', None)
 
875
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
 
876
                                     stdin=stdin, working_dir=working_dir)
754
877
 
755
878
    def run_bzr_decode(self, *args, **kwargs):
756
 
        if kwargs.has_key('encoding'):
 
879
        if 'encoding' in kwargs:
757
880
            encoding = kwargs['encoding']
758
881
        else:
759
882
            encoding = bzrlib.user_encoding
798
921
        profiled or debugged so easily.
799
922
 
800
923
        :param retcode: The status code that is expected.  Defaults to 0.  If
801
 
        None is supplied, the status code is not checked.
802
 
        """
 
924
            None is supplied, the status code is not checked.
 
925
        :param env_changes: A dictionary which lists changes to environment
 
926
            variables. A value of None will unset the env variable.
 
927
            The values must be strings. The change will only occur in the
 
928
            child, so you don't need to fix the environment after running.
 
929
        :param universal_newlines: Convert CRLF => LF
 
930
        :param allow_plugins: By default the subprocess is run with
 
931
            --no-plugins to ensure test reproducibility. Also, it is possible
 
932
            for system-wide plugins to create unexpected output on stderr,
 
933
            which can cause unnecessary test failures.
 
934
        """
 
935
        env_changes = kwargs.get('env_changes', {})
 
936
        working_dir = kwargs.get('working_dir', None)
 
937
        allow_plugins = kwargs.get('allow_plugins', False)
 
938
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
 
939
                                            working_dir=working_dir,
 
940
                                            allow_plugins=allow_plugins)
 
941
        # We distinguish between retcode=None and retcode not passed.
 
942
        supplied_retcode = kwargs.get('retcode', 0)
 
943
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
 
944
            universal_newlines=kwargs.get('universal_newlines', False),
 
945
            process_args=args)
 
946
 
 
947
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
948
                             skip_if_plan_to_signal=False,
 
949
                             working_dir=None,
 
950
                             allow_plugins=False):
 
951
        """Start bzr in a subprocess for testing.
 
952
 
 
953
        This starts a new Python interpreter and runs bzr in there.
 
954
        This should only be used for tests that have a justifiable need for
 
955
        this isolation: e.g. they are testing startup time, or signal
 
956
        handling, or early startup code, etc.  Subprocess code can't be
 
957
        profiled or debugged so easily.
 
958
 
 
959
        :param process_args: a list of arguments to pass to the bzr executable,
 
960
            for example `['--version']`.
 
961
        :param env_changes: A dictionary which lists changes to environment
 
962
            variables. A value of None will unset the env variable.
 
963
            The values must be strings. The change will only occur in the
 
964
            child, so you don't need to fix the environment after running.
 
965
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
966
            is not available.
 
967
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
 
968
 
 
969
        :returns: Popen object for the started process.
 
970
        """
 
971
        if skip_if_plan_to_signal:
 
972
            if not getattr(os, 'kill', None):
 
973
                raise TestSkipped("os.kill not available.")
 
974
 
 
975
        if env_changes is None:
 
976
            env_changes = {}
 
977
        old_env = {}
 
978
 
 
979
        def cleanup_environment():
 
980
            for env_var, value in env_changes.iteritems():
 
981
                old_env[env_var] = osutils.set_or_unset_env(env_var, value)
 
982
 
 
983
        def restore_environment():
 
984
            for env_var, value in old_env.iteritems():
 
985
                osutils.set_or_unset_env(env_var, value)
 
986
 
 
987
        bzr_path = self.get_bzr_path()
 
988
 
 
989
        cwd = None
 
990
        if working_dir is not None:
 
991
            cwd = osutils.getcwd()
 
992
            os.chdir(working_dir)
 
993
 
 
994
        try:
 
995
            # win32 subprocess doesn't support preexec_fn
 
996
            # so we will avoid using it on all platforms, just to
 
997
            # make sure the code path is used, and we don't break on win32
 
998
            cleanup_environment()
 
999
            command = [sys.executable, bzr_path]
 
1000
            if not allow_plugins:
 
1001
                command.append('--no-plugins')
 
1002
            command.extend(process_args)
 
1003
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
1004
        finally:
 
1005
            restore_environment()
 
1006
            if cwd is not None:
 
1007
                os.chdir(cwd)
 
1008
 
 
1009
        return process
 
1010
 
 
1011
    def _popen(self, *args, **kwargs):
 
1012
        """Place a call to Popen.
 
1013
 
 
1014
        Allows tests to override this method to intercept the calls made to
 
1015
        Popen for introspection.
 
1016
        """
 
1017
        return Popen(*args, **kwargs)
 
1018
 
 
1019
    def get_bzr_path(self):
 
1020
        """Return the path of the 'bzr' executable for this test suite."""
803
1021
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
804
 
        args = list(args)
805
 
        process = Popen([sys.executable, bzr_path]+args, stdout=PIPE, 
806
 
                         stderr=PIPE)
807
 
        out = process.stdout.read()
808
 
        err = process.stderr.read()
809
 
        retcode = process.wait()
810
 
        supplied_retcode = kwargs.get('retcode', 0)
811
 
        if supplied_retcode is not None:
812
 
            assert supplied_retcode == retcode
 
1022
        if not os.path.isfile(bzr_path):
 
1023
            # We are probably installed. Assume sys.argv is the right file
 
1024
            bzr_path = sys.argv[0]
 
1025
        return bzr_path
 
1026
 
 
1027
    def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
 
1028
                              universal_newlines=False, process_args=None):
 
1029
        """Finish the execution of process.
 
1030
 
 
1031
        :param process: the Popen object returned from start_bzr_subprocess.
 
1032
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
1033
            None is supplied, the status code is not checked.
 
1034
        :param send_signal: an optional signal to send to the process.
 
1035
        :param universal_newlines: Convert CRLF => LF
 
1036
        :returns: (stdout, stderr)
 
1037
        """
 
1038
        if send_signal is not None:
 
1039
            os.kill(process.pid, send_signal)
 
1040
        out, err = process.communicate()
 
1041
 
 
1042
        if universal_newlines:
 
1043
            out = out.replace('\r\n', '\n')
 
1044
            err = err.replace('\r\n', '\n')
 
1045
 
 
1046
        if retcode is not None and retcode != process.returncode:
 
1047
            if process_args is None:
 
1048
                process_args = "(unknown args)"
 
1049
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1050
            mutter('Error for bzr %s:\n%s', process_args, err)
 
1051
            self.fail('Command bzr %s failed with retcode %s != %s'
 
1052
                      % (process_args, retcode, process.returncode))
813
1053
        return [out, err]
814
1054
 
815
1055
    def check_inventory_shape(self, inv, shape):
864
1104
            sys.stderr = real_stderr
865
1105
            sys.stdin = real_stdin
866
1106
 
 
1107
    @symbol_versioning.deprecated_method(symbol_versioning.zero_eleven)
867
1108
    def merge(self, branch_from, wt_to):
868
1109
        """A helper for tests to do a ui-less merge.
869
1110
 
875
1116
        base_rev = common_ancestor(branch_from.last_revision(),
876
1117
                                   wt_to.branch.last_revision(),
877
1118
                                   wt_to.branch.repository)
878
 
        merge_inner(wt_to.branch, branch_from.basis_tree(), 
 
1119
        merge_inner(wt_to.branch, branch_from.basis_tree(),
879
1120
                    wt_to.branch.repository.revision_tree(base_rev),
880
1121
                    this_tree=wt_to)
881
 
        wt_to.add_pending_merge(branch_from.last_revision())
 
1122
        wt_to.add_parent_tree_id(branch_from.last_revision())
882
1123
 
883
1124
 
884
1125
BzrTestBase = TestCase
885
1126
 
 
1127
 
 
1128
class TestCaseWithMemoryTransport(TestCase):
 
1129
    """Common test class for tests that do not need disk resources.
 
1130
 
 
1131
    Tests that need disk resources should derive from TestCaseWithTransport.
 
1132
 
 
1133
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
 
1134
 
 
1135
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
1136
    a directory which does not exist. This serves to help ensure test isolation
 
1137
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
1138
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
1139
    file defaults for the transport in tests, nor does it obey the command line
 
1140
    override, so tests that accidentally write to the common directory should
 
1141
    be rare.
 
1142
    """
 
1143
 
 
1144
    TEST_ROOT = None
 
1145
    _TEST_NAME = 'test'
 
1146
 
 
1147
 
 
1148
    def __init__(self, methodName='runTest'):
 
1149
        # allow test parameterisation after test construction and before test
 
1150
        # execution. Variables that the parameteriser sets need to be 
 
1151
        # ones that are not set by setUp, or setUp will trash them.
 
1152
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
 
1153
        self.transport_server = default_transport
 
1154
        self.transport_readonly_server = None
 
1155
 
 
1156
    def failUnlessExists(self, path):
 
1157
        """Fail unless path, which may be abs or relative, exists."""
 
1158
        self.failUnless(osutils.lexists(path))
 
1159
 
 
1160
    def failIfExists(self, path):
 
1161
        """Fail if path, which may be abs or relative, exists."""
 
1162
        self.failIf(osutils.lexists(path))
 
1163
        
 
1164
    def get_transport(self):
 
1165
        """Return a writeable transport for the test scratch space"""
 
1166
        t = get_transport(self.get_url())
 
1167
        self.assertFalse(t.is_readonly())
 
1168
        return t
 
1169
 
 
1170
    def get_readonly_transport(self):
 
1171
        """Return a readonly transport for the test scratch space
 
1172
        
 
1173
        This can be used to test that operations which should only need
 
1174
        readonly access in fact do not try to write.
 
1175
        """
 
1176
        t = get_transport(self.get_readonly_url())
 
1177
        self.assertTrue(t.is_readonly())
 
1178
        return t
 
1179
 
 
1180
    def get_readonly_server(self):
 
1181
        """Get the server instance for the readonly transport
 
1182
 
 
1183
        This is useful for some tests with specific servers to do diagnostics.
 
1184
        """
 
1185
        if self.__readonly_server is None:
 
1186
            if self.transport_readonly_server is None:
 
1187
                # readonly decorator requested
 
1188
                # bring up the server
 
1189
                self.get_url()
 
1190
                self.__readonly_server = ReadonlyServer()
 
1191
                self.__readonly_server.setUp(self.__server)
 
1192
            else:
 
1193
                self.__readonly_server = self.transport_readonly_server()
 
1194
                self.__readonly_server.setUp()
 
1195
            self.addCleanup(self.__readonly_server.tearDown)
 
1196
        return self.__readonly_server
 
1197
 
 
1198
    def get_readonly_url(self, relpath=None):
 
1199
        """Get a URL for the readonly transport.
 
1200
 
 
1201
        This will either be backed by '.' or a decorator to the transport 
 
1202
        used by self.get_url()
 
1203
        relpath provides for clients to get a path relative to the base url.
 
1204
        These should only be downwards relative, not upwards.
 
1205
        """
 
1206
        base = self.get_readonly_server().get_url()
 
1207
        if relpath is not None:
 
1208
            if not base.endswith('/'):
 
1209
                base = base + '/'
 
1210
            base = base + relpath
 
1211
        return base
 
1212
 
 
1213
    def get_server(self):
 
1214
        """Get the read/write server instance.
 
1215
 
 
1216
        This is useful for some tests with specific servers that need
 
1217
        diagnostics.
 
1218
 
 
1219
        For TestCaseWithMemoryTransport this is always a MemoryServer, and there
 
1220
        is no means to override it.
 
1221
        """
 
1222
        if self.__server is None:
 
1223
            self.__server = MemoryServer()
 
1224
            self.__server.setUp()
 
1225
            self.addCleanup(self.__server.tearDown)
 
1226
        return self.__server
 
1227
 
 
1228
    def get_url(self, relpath=None):
 
1229
        """Get a URL (or maybe a path) for the readwrite transport.
 
1230
 
 
1231
        This will either be backed by '.' or to an equivalent non-file based
 
1232
        facility.
 
1233
        relpath provides for clients to get a path relative to the base url.
 
1234
        These should only be downwards relative, not upwards.
 
1235
        """
 
1236
        base = self.get_server().get_url()
 
1237
        if relpath is not None and relpath != '.':
 
1238
            if not base.endswith('/'):
 
1239
                base = base + '/'
 
1240
            # XXX: Really base should be a url; we did after all call
 
1241
            # get_url()!  But sometimes it's just a path (from
 
1242
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
 
1243
            # to a non-escaped local path.
 
1244
            if base.startswith('./') or base.startswith('/'):
 
1245
                base += relpath
 
1246
            else:
 
1247
                base += urlutils.escape(relpath)
 
1248
        return base
 
1249
 
 
1250
    def _make_test_root(self):
 
1251
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
 
1252
            return
 
1253
        i = 0
 
1254
        while True:
 
1255
            root = u'test%04d.tmp' % i
 
1256
            try:
 
1257
                os.mkdir(root)
 
1258
            except OSError, e:
 
1259
                if e.errno == errno.EEXIST:
 
1260
                    i += 1
 
1261
                    continue
 
1262
                else:
 
1263
                    raise
 
1264
            # successfully created
 
1265
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
 
1266
            break
 
1267
        # make a fake bzr directory there to prevent any tests propagating
 
1268
        # up onto the source directory's real branch
 
1269
        bzrdir.BzrDir.create_standalone_workingtree(
 
1270
            TestCaseWithMemoryTransport.TEST_ROOT)
 
1271
 
 
1272
    def makeAndChdirToTestDir(self):
 
1273
        """Create a temporary directories for this one test.
 
1274
        
 
1275
        This must set self.test_home_dir and self.test_dir and chdir to
 
1276
        self.test_dir.
 
1277
        
 
1278
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
 
1279
        """
 
1280
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
1281
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
 
1282
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
 
1283
        
 
1284
    def make_branch(self, relpath, format=None):
 
1285
        """Create a branch on the transport at relpath."""
 
1286
        repo = self.make_repository(relpath, format=format)
 
1287
        return repo.bzrdir.create_branch()
 
1288
 
 
1289
    def make_bzrdir(self, relpath, format=None):
 
1290
        try:
 
1291
            # might be a relative or absolute path
 
1292
            maybe_a_url = self.get_url(relpath)
 
1293
            segments = maybe_a_url.rsplit('/', 1)
 
1294
            t = get_transport(maybe_a_url)
 
1295
            if len(segments) > 1 and segments[-1] not in ('', '.'):
 
1296
                try:
 
1297
                    t.mkdir('.')
 
1298
                except errors.FileExists:
 
1299
                    pass
 
1300
            if format is None:
 
1301
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1302
            return format.initialize_on_transport(t)
 
1303
        except errors.UninitializableFormat:
 
1304
            raise TestSkipped("Format %s is not initializable." % format)
 
1305
 
 
1306
    def make_repository(self, relpath, shared=False, format=None):
 
1307
        """Create a repository on our default transport at relpath."""
 
1308
        made_control = self.make_bzrdir(relpath, format=format)
 
1309
        return made_control.create_repository(shared=shared)
 
1310
 
 
1311
    def make_branch_and_memory_tree(self, relpath, format=None):
 
1312
        """Create a branch on the default transport and a MemoryTree for it."""
 
1313
        b = self.make_branch(relpath, format=format)
 
1314
        return memorytree.MemoryTree.create_on_branch(b)
 
1315
 
 
1316
    def overrideEnvironmentForTesting(self):
 
1317
        os.environ['HOME'] = self.test_home_dir
 
1318
        os.environ['APPDATA'] = self.test_home_dir
 
1319
        
 
1320
    def setUp(self):
 
1321
        super(TestCaseWithMemoryTransport, self).setUp()
 
1322
        self._make_test_root()
 
1323
        _currentdir = os.getcwdu()
 
1324
        def _leaveDirectory():
 
1325
            os.chdir(_currentdir)
 
1326
        self.addCleanup(_leaveDirectory)
 
1327
        self.makeAndChdirToTestDir()
 
1328
        self.overrideEnvironmentForTesting()
 
1329
        self.__readonly_server = None
 
1330
        self.__server = None
 
1331
 
886
1332
     
887
 
class TestCaseInTempDir(TestCase):
 
1333
class TestCaseInTempDir(TestCaseWithMemoryTransport):
888
1334
    """Derived class that runs a test within a temporary directory.
889
1335
 
890
1336
    This is useful for tests that need to create a branch, etc.
897
1343
    InTempDir is an old alias for FunctionalTestCase.
898
1344
    """
899
1345
 
900
 
    TEST_ROOT = None
901
 
    _TEST_NAME = 'test'
902
1346
    OVERRIDE_PYTHON = 'python'
903
1347
 
904
1348
    def check_file_contents(self, filename, expect):
909
1353
            self.log("actually: %r" % contents)
910
1354
            self.fail("contents of %s not as expected" % filename)
911
1355
 
912
 
    def _make_test_root(self):
913
 
        if TestCaseInTempDir.TEST_ROOT is not None:
914
 
            return
915
 
        i = 0
916
 
        while True:
917
 
            root = u'test%04d.tmp' % i
918
 
            try:
919
 
                os.mkdir(root)
920
 
            except OSError, e:
921
 
                if e.errno == errno.EEXIST:
922
 
                    i += 1
923
 
                    continue
924
 
                else:
925
 
                    raise
926
 
            # successfully created
927
 
            TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
928
 
            break
929
 
        # make a fake bzr directory there to prevent any tests propagating
930
 
        # up onto the source directory's real branch
931
 
        bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
932
 
 
933
 
    def setUp(self):
934
 
        super(TestCaseInTempDir, self).setUp()
935
 
        self._make_test_root()
936
 
        _currentdir = os.getcwdu()
 
1356
    def makeAndChdirToTestDir(self):
 
1357
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
 
1358
        
 
1359
        For TestCaseInTempDir we create a temporary directory based on the test
 
1360
        name and then create two subdirs - test and home under it.
 
1361
        """
937
1362
        # shorten the name, to avoid test failures due to path length
938
1363
        short_id = self.id().replace('bzrlib.tests.', '') \
939
1364
                   .replace('__main__.', '')[-100:]
949
1374
                i = i + 1
950
1375
                continue
951
1376
            else:
952
 
                self.test_dir = candidate_dir
 
1377
                os.mkdir(candidate_dir)
 
1378
                self.test_home_dir = candidate_dir + '/home'
 
1379
                os.mkdir(self.test_home_dir)
 
1380
                self.test_dir = candidate_dir + '/work'
953
1381
                os.mkdir(self.test_dir)
954
1382
                os.chdir(self.test_dir)
955
1383
                break
956
 
        os.environ['HOME'] = self.test_dir
957
 
        os.environ['APPDATA'] = self.test_dir
958
 
        def _leaveDirectory():
959
 
            os.chdir(_currentdir)
960
 
        self.addCleanup(_leaveDirectory)
961
 
        
 
1384
 
962
1385
    def build_tree(self, shape, line_endings='native', transport=None):
963
1386
        """Build a test tree according to a pattern.
964
1387
 
999
1422
                # On jam's machine, make_kernel_like_tree is:
1000
1423
                #   put:    4.5-7.5s (averaging 6s)
1001
1424
                #   append: 2.9-4.5s
1002
 
                transport.append(urlutils.escape(name), StringIO(content))
 
1425
                #   put_non_atomic: 2.9-4.5s
 
1426
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
1003
1427
 
1004
1428
    def build_tree_contents(self, shape):
1005
1429
        build_tree_contents(shape)
1006
1430
 
1007
 
    def failUnlessExists(self, path):
1008
 
        """Fail unless path, which may be abs or relative, exists."""
1009
 
        self.failUnless(osutils.lexists(path))
1010
 
 
1011
 
    def failIfExists(self, path):
1012
 
        """Fail if path, which may be abs or relative, exists."""
1013
 
        self.failIf(osutils.lexists(path))
1014
 
        
1015
1431
    def assertFileEqual(self, content, path):
1016
1432
        """Fail if path does not contain 'content'."""
1017
1433
        self.failUnless(osutils.lexists(path))
1033
1449
    readwrite one must both define get_url() as resolving to os.getcwd().
1034
1450
    """
1035
1451
 
1036
 
    def __init__(self, methodName='testMethod'):
1037
 
        super(TestCaseWithTransport, self).__init__(methodName)
1038
 
        self.__readonly_server = None
1039
 
        self.__server = None
1040
 
        self.transport_server = default_transport
1041
 
        self.transport_readonly_server = None
1042
 
 
1043
 
    def get_readonly_url(self, relpath=None):
1044
 
        """Get a URL for the readonly transport.
1045
 
 
1046
 
        This will either be backed by '.' or a decorator to the transport 
1047
 
        used by self.get_url()
1048
 
        relpath provides for clients to get a path relative to the base url.
1049
 
        These should only be downwards relative, not upwards.
1050
 
        """
1051
 
        base = self.get_readonly_server().get_url()
1052
 
        if relpath is not None:
1053
 
            if not base.endswith('/'):
1054
 
                base = base + '/'
1055
 
            base = base + relpath
1056
 
        return base
1057
 
 
1058
 
    def get_readonly_server(self):
1059
 
        """Get the server instance for the readonly transport
1060
 
 
1061
 
        This is useful for some tests with specific servers to do diagnostics.
1062
 
        """
1063
 
        if self.__readonly_server is None:
1064
 
            if self.transport_readonly_server is None:
1065
 
                # readonly decorator requested
1066
 
                # bring up the server
1067
 
                self.get_url()
1068
 
                self.__readonly_server = ReadonlyServer()
1069
 
                self.__readonly_server.setUp(self.__server)
1070
 
            else:
1071
 
                self.__readonly_server = self.transport_readonly_server()
1072
 
                self.__readonly_server.setUp()
1073
 
            self.addCleanup(self.__readonly_server.tearDown)
1074
 
        return self.__readonly_server
1075
 
 
1076
1452
    def get_server(self):
1077
 
        """Get the read/write server instance.
 
1453
        """See TestCaseWithMemoryTransport.
1078
1454
 
1079
1455
        This is useful for some tests with specific servers that need
1080
1456
        diagnostics.
1085
1461
            self.addCleanup(self.__server.tearDown)
1086
1462
        return self.__server
1087
1463
 
1088
 
    def get_url(self, relpath=None):
1089
 
        """Get a URL for the readwrite transport.
1090
 
 
1091
 
        This will either be backed by '.' or to an equivalent non-file based
1092
 
        facility.
1093
 
        relpath provides for clients to get a path relative to the base url.
1094
 
        These should only be downwards relative, not upwards.
1095
 
        """
1096
 
        base = self.get_server().get_url()
1097
 
        if relpath is not None and relpath != '.':
1098
 
            if not base.endswith('/'):
1099
 
                base = base + '/'
1100
 
            base = base + urlutils.escape(relpath)
1101
 
        return base
1102
 
 
1103
 
    def get_transport(self):
1104
 
        """Return a writeable transport for the test scratch space"""
1105
 
        t = get_transport(self.get_url())
1106
 
        self.assertFalse(t.is_readonly())
1107
 
        return t
1108
 
 
1109
 
    def get_readonly_transport(self):
1110
 
        """Return a readonly transport for the test scratch space
1111
 
        
1112
 
        This can be used to test that operations which should only need
1113
 
        readonly access in fact do not try to write.
1114
 
        """
1115
 
        t = get_transport(self.get_readonly_url())
1116
 
        self.assertTrue(t.is_readonly())
1117
 
        return t
1118
 
 
1119
 
    def make_branch(self, relpath, format=None):
1120
 
        """Create a branch on the transport at relpath."""
1121
 
        repo = self.make_repository(relpath, format=format)
1122
 
        return repo.bzrdir.create_branch()
1123
 
 
1124
 
    def make_bzrdir(self, relpath, format=None):
1125
 
        try:
1126
 
            url = self.get_url(relpath)
1127
 
            mutter('relpath %r => url %r', relpath, url)
1128
 
            segments = url.split('/')
1129
 
            if segments and segments[-1] not in ('', '.'):
1130
 
                parent = '/'.join(segments[:-1])
1131
 
                t = get_transport(parent)
1132
 
                try:
1133
 
                    t.mkdir(segments[-1])
1134
 
                except errors.FileExists:
1135
 
                    pass
1136
 
            if format is None:
1137
 
                format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
1138
 
            # FIXME: make this use a single transport someday. RBC 20060418
1139
 
            return format.initialize_on_transport(get_transport(relpath))
1140
 
        except errors.UninitializableFormat:
1141
 
            raise TestSkipped("Format %s is not initializable." % format)
1142
 
 
1143
 
    def make_repository(self, relpath, shared=False, format=None):
1144
 
        """Create a repository on our default transport at relpath."""
1145
 
        made_control = self.make_bzrdir(relpath, format=format)
1146
 
        return made_control.create_repository(shared=shared)
1147
 
 
1148
1464
    def make_branch_and_tree(self, relpath, format=None):
1149
1465
        """Create a branch on the transport and a tree locally.
1150
1466
 
1151
 
        Returns the tree.
 
1467
        If the transport is not a LocalTransport, the Tree can't be created on
 
1468
        the transport.  In that case the working tree is created in the local
 
1469
        directory, and the returned tree's branch and repository will also be
 
1470
        accessed locally.
 
1471
 
 
1472
        This will fail if the original default transport for this test
 
1473
        case wasn't backed by the working directory, as the branch won't
 
1474
        be on disk for us to open it.  
 
1475
 
 
1476
        :param format: The BzrDirFormat.
 
1477
        :returns: the WorkingTree.
1152
1478
        """
1153
1479
        # TODO: always use the local disk path for the working tree,
1154
1480
        # this obviously requires a format that supports branch references
1158
1484
        try:
1159
1485
            return b.bzrdir.create_workingtree()
1160
1486
        except errors.NotLocalUrl:
1161
 
            # new formats - catch No tree error and create
1162
 
            # a branch reference and a checkout.
1163
 
            # old formats at that point - raise TestSkipped.
1164
 
            # TODO: rbc 20060208
1165
 
            return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
 
1487
            # We can only make working trees locally at the moment.  If the
 
1488
            # transport can't support them, then reopen the branch on a local
 
1489
            # transport, and create the working tree there.  
 
1490
            #
 
1491
            # Possibly we should instead keep
 
1492
            # the non-disk-backed branch and create a local checkout?
 
1493
            bd = bzrdir.BzrDir.open(relpath)
 
1494
            return bd.create_workingtree()
1166
1495
 
1167
1496
    def assertIsDirectory(self, relpath, transport):
1168
1497
        """Assert that relpath within transport is a directory.
1179
1508
            self.fail("path %s is not a directory; has mode %#o"
1180
1509
                      % (relpath, mode))
1181
1510
 
 
1511
    def setUp(self):
 
1512
        super(TestCaseWithTransport, self).setUp()
 
1513
        self.__server = None
 
1514
 
1182
1515
 
1183
1516
class ChrootedTestCase(TestCaseWithTransport):
1184
1517
    """A support class that provides readonly urls outside the local namespace.
1209
1542
 
1210
1543
def run_suite(suite, name='test', verbose=False, pattern=".*",
1211
1544
              stop_on_failure=False, keep_output=False,
1212
 
              transport=None, lsprof_timed=None):
1213
 
    TestCaseInTempDir._TEST_NAME = name
 
1545
              transport=None, lsprof_timed=None, bench_history=None):
1214
1546
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1215
1547
    if verbose:
1216
1548
        verbosity = 2
1222
1554
                            descriptions=0,
1223
1555
                            verbosity=verbosity,
1224
1556
                            keep_output=keep_output,
1225
 
                            pb=pb)
 
1557
                            pb=pb,
 
1558
                            bench_history=bench_history)
1226
1559
    runner.stop_on_failure=stop_on_failure
1227
1560
    if pattern != '.*':
1228
1561
        suite = filter_suite_by_re(suite, pattern)
1234
1567
             keep_output=False,
1235
1568
             transport=None,
1236
1569
             test_suite_factory=None,
1237
 
             lsprof_timed=None):
 
1570
             lsprof_timed=None,
 
1571
             bench_history=None):
1238
1572
    """Run the whole test suite under the enhanced runner"""
1239
1573
    # XXX: Very ugly way to do this...
1240
1574
    # Disable warning about old formats because we don't want it to disturb
1255
1589
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
1256
1590
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
1257
1591
                     transport=transport,
1258
 
                     lsprof_timed=lsprof_timed)
 
1592
                     lsprof_timed=lsprof_timed,
 
1593
                     bench_history=bench_history)
1259
1594
    finally:
1260
1595
        default_transport = old_transport
1261
1596
 
1274
1609
                   'bzrlib.tests.test_branch',
1275
1610
                   'bzrlib.tests.test_bundle',
1276
1611
                   'bzrlib.tests.test_bzrdir',
 
1612
                   'bzrlib.tests.test_cache_utf8',
1277
1613
                   'bzrlib.tests.test_command',
1278
1614
                   'bzrlib.tests.test_commit',
1279
1615
                   'bzrlib.tests.test_commit_merge',
1285
1621
                   'bzrlib.tests.test_errors',
1286
1622
                   'bzrlib.tests.test_escaped_store',
1287
1623
                   'bzrlib.tests.test_fetch',
 
1624
                   'bzrlib.tests.test_ftp_transport',
1288
1625
                   'bzrlib.tests.test_gpg',
1289
1626
                   'bzrlib.tests.test_graph',
1290
1627
                   'bzrlib.tests.test_hashcache',
1294
1631
                   'bzrlib.tests.test_ignores',
1295
1632
                   'bzrlib.tests.test_inv',
1296
1633
                   'bzrlib.tests.test_knit',
 
1634
                   'bzrlib.tests.test_lazy_import',
 
1635
                   'bzrlib.tests.test_lazy_regex',
1297
1636
                   'bzrlib.tests.test_lockdir',
1298
1637
                   'bzrlib.tests.test_lockable_files',
1299
1638
                   'bzrlib.tests.test_log',
 
1639
                   'bzrlib.tests.test_memorytree',
1300
1640
                   'bzrlib.tests.test_merge',
1301
1641
                   'bzrlib.tests.test_merge3',
1302
1642
                   'bzrlib.tests.test_merge_core',
1311
1651
                   'bzrlib.tests.test_plugins',
1312
1652
                   'bzrlib.tests.test_progress',
1313
1653
                   'bzrlib.tests.test_reconcile',
 
1654
                   'bzrlib.tests.test_registry',
1314
1655
                   'bzrlib.tests.test_repository',
 
1656
                   'bzrlib.tests.test_revert',
1315
1657
                   'bzrlib.tests.test_revision',
1316
1658
                   'bzrlib.tests.test_revisionnamespaces',
1317
1659
                   'bzrlib.tests.test_revisiontree',
1321
1663
                   'bzrlib.tests.test_setup',
1322
1664
                   'bzrlib.tests.test_sftp_transport',
1323
1665
                   'bzrlib.tests.test_smart_add',
 
1666
                   'bzrlib.tests.test_smart_transport',
1324
1667
                   'bzrlib.tests.test_source',
1325
1668
                   'bzrlib.tests.test_status',
1326
1669
                   'bzrlib.tests.test_store',
1333
1676
                   'bzrlib.tests.test_transform',
1334
1677
                   'bzrlib.tests.test_transport',
1335
1678
                   'bzrlib.tests.test_tree',
 
1679
                   'bzrlib.tests.test_treebuilder',
1336
1680
                   'bzrlib.tests.test_tsort',
1337
1681
                   'bzrlib.tests.test_tuned_gzip',
1338
1682
                   'bzrlib.tests.test_ui',
1339
1683
                   'bzrlib.tests.test_upgrade',
1340
1684
                   'bzrlib.tests.test_urlutils',
1341
1685
                   'bzrlib.tests.test_versionedfile',
 
1686
                   'bzrlib.tests.test_version',
 
1687
                   'bzrlib.tests.test_version_info',
1342
1688
                   'bzrlib.tests.test_weave',
1343
1689
                   'bzrlib.tests.test_whitebox',
1344
1690
                   'bzrlib.tests.test_workingtree',
1359
1705
    for m in MODULES_TO_TEST:
1360
1706
        suite.addTest(loader.loadTestsFromModule(m))
1361
1707
    for m in MODULES_TO_DOCTEST:
1362
 
        suite.addTest(doctest.DocTestSuite(m))
 
1708
        try:
 
1709
            suite.addTest(doctest.DocTestSuite(m))
 
1710
        except ValueError, e:
 
1711
            print '**failed to get doctest for: %s\n%s' %(m,e)
 
1712
            raise
1363
1713
    for name, plugin in bzrlib.plugin.all_plugins().items():
1364
1714
        if getattr(plugin, 'test_suite', None) is not None:
1365
1715
            suite.addTest(plugin.test_suite())