~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2006-10-11 00:23:23 UTC
  • mfrom: (2070 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2071.
  • Revision ID: john@arbash-meinel.com-20061011002323-82ba88c293d7caff
[merge] bzr.dev 2070

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005, 2006 by 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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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
73
from bzrlib.transport.local import LocalRelpathServer
 
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
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
 
109
111
    import bzrlib.tests.bzrdir_implementations
110
112
    import bzrlib.tests.interrepository_implementations
111
113
    import bzrlib.tests.interversionedfile_implementations
 
114
    import bzrlib.tests.intertree_implementations
112
115
    import bzrlib.tests.repository_implementations
113
116
    import bzrlib.tests.revisionstore_implementations
 
117
    import bzrlib.tests.tree_implementations
114
118
    import bzrlib.tests.workingtree_implementations
115
119
    return [
116
120
            bzrlib.doc,
119
123
            bzrlib.tests.bzrdir_implementations,
120
124
            bzrlib.tests.interrepository_implementations,
121
125
            bzrlib.tests.interversionedfile_implementations,
 
126
            bzrlib.tests.intertree_implementations,
122
127
            bzrlib.tests.repository_implementations,
123
128
            bzrlib.tests.revisionstore_implementations,
 
129
            bzrlib.tests.tree_implementations,
124
130
            bzrlib.tests.workingtree_implementations,
125
131
            ]
126
132
 
132
138
    """
133
139
    stop_early = False
134
140
    
135
 
    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
        """
136
148
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
137
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
138
165
    
139
166
    def extractBenchmarkTime(self, testCase):
140
167
        """Add a benchmark time for the current test case."""
212
239
        if isinstance(err[1], TestSkipped):
213
240
            return self.addSkipped(test, err)    
214
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()
215
247
        self.extractBenchmarkTime(test)
216
248
        if self.showAll:
217
249
            self.stream.writeln("ERROR %s" % self._testTimeString())
219
251
            self.stream.write('E')
220
252
        elif self.dots:
221
253
            self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
 
254
            self.pb.note(self._ellipsise_unimportant_words(
 
255
                            test.id() + ': ERROR',
 
256
                            osutils.terminal_width()))
222
257
        self.stream.flush()
223
258
        if self.stop_early:
224
259
            self.stop()
225
260
 
226
261
    def addFailure(self, test, err):
227
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()
228
268
        self.extractBenchmarkTime(test)
229
269
        if self.showAll:
230
270
            self.stream.writeln(" FAIL %s" % self._testTimeString())
232
272
            self.stream.write('F')
233
273
        elif self.dots:
234
274
            self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
 
275
            self.pb.note(self._ellipsise_unimportant_words(
 
276
                            test.id() + ': FAIL',
 
277
                            osutils.terminal_width()))
235
278
        self.stream.flush()
236
279
        if self.stop_early:
237
280
            self.stop()
238
281
 
239
282
    def addSuccess(self, test):
240
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()))
241
289
        if self.showAll:
242
290
            self.stream.writeln('   OK %s' % self._testTimeString())
243
291
            for bench_called, stats in getattr(test, '_benchcalls', []):
294
342
                 descriptions=0,
295
343
                 verbosity=1,
296
344
                 keep_output=False,
297
 
                 pb=None):
 
345
                 pb=None,
 
346
                 bench_history=None):
298
347
        self.stream = unittest._WritelnDecorator(stream)
299
348
        self.descriptions = descriptions
300
349
        self.verbosity = verbosity
301
350
        self.keep_output = keep_output
302
351
        self.pb = pb
 
352
        self._bench_history = bench_history
303
353
 
304
354
    def _makeResult(self):
305
355
        result = _MyResult(self.stream,
306
356
                           self.descriptions,
307
357
                           self.verbosity,
308
 
                           pb=self.pb)
 
358
                           pb=self.pb,
 
359
                           bench_history=self._bench_history)
309
360
        result.stop_early = self.stop_on_failure
310
361
        return result
311
362
 
340
391
        # This is still a little bogus, 
341
392
        # but only a little. Folk not using our testrunner will
342
393
        # have to delete their temp directories themselves.
343
 
        test_root = TestCaseInTempDir.TEST_ROOT
 
394
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
344
395
        if result.wasSuccessful() or not self.keep_output:
345
396
            if test_root is not None:
346
397
                # If LANG=C we probably have created some bogus paths
364
415
                self.stream.writeln(
365
416
                    "Failed tests working directories are in '%s'\n" %
366
417
                    test_root)
367
 
        TestCaseInTempDir.TEST_ROOT = None
 
418
        TestCaseWithMemoryTransport.TEST_ROOT = None
368
419
        if self.pb is not None:
369
420
            self.pb.clear()
370
421
        return result
385
436
 
386
437
class TestSkipped(Exception):
387
438
    """Indicates that a test was intentionally skipped, rather than failing."""
388
 
    # XXX: Not used yet
389
439
 
390
440
 
391
441
class CommandFailed(Exception):
441
491
 
442
492
    _log_file_name = None
443
493
    _log_contents = ''
 
494
    _keep_log_file = False
444
495
    # record lsprof data when performing benchmark calls.
445
496
    _gather_lsprof_in_benchmarks = False
446
497
 
542
593
            self.fail("%r is an instance of %s rather than %s" % (
543
594
                obj, obj.__class__, kls))
544
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
 
545
661
    def _startLogFile(self):
546
662
        """Send bzr and test log messages to a temporary file.
547
663
 
548
664
        The file is removed as the test is torn down.
549
665
        """
550
666
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
551
 
        encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
552
 
        self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
 
667
        self._log_file = os.fdopen(fileno, 'w+')
553
668
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
554
669
        self._log_file_name = name
555
670
        self.addCleanup(self._finishLogFile)
557
672
    def _finishLogFile(self):
558
673
        """Finished with the log file.
559
674
 
560
 
        Read contents into memory, close, and delete.
 
675
        Close the file and delete it, unless setKeepLogfile was called.
561
676
        """
562
677
        if self._log_file is None:
563
678
            return
564
679
        bzrlib.trace.disable_test_log(self._log_nonce)
565
 
        self._log_file.seek(0)
566
 
        self._log_contents = self._log_file.read()
567
680
        self._log_file.close()
568
 
        os.remove(self._log_file_name)
569
 
        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
570
689
 
571
690
    def addCleanup(self, callable):
572
691
        """Arrange to run a callable when this case is torn down.
581
700
 
582
701
    def _cleanEnvironment(self):
583
702
        new_env = {
 
703
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
584
704
            'HOME': os.getcwd(),
585
705
            'APPDATA': os.getcwd(),
586
 
            'BZREMAIL': None,
 
706
            'BZR_EMAIL': None,
 
707
            'BZREMAIL': None, # may still be present in the environment
587
708
            'EMAIL': None,
 
709
            'BZR_PROGRESS_BAR': None,
588
710
        }
589
711
        self.__old_env = {}
590
712
        self.addCleanup(self._restoreEnvironment)
591
713
        for name, value in new_env.iteritems():
592
714
            self._captureVar(name, value)
593
715
 
594
 
 
595
716
    def _captureVar(self, name, newvalue):
596
 
        """Set an environment variable, preparing it to be reset when finished."""
597
 
        self.__old_env[name] = os.environ.get(name, None)
598
 
        if newvalue is None:
599
 
            if name in os.environ:
600
 
                del os.environ[name]
601
 
        else:
602
 
            os.environ[name] = newvalue
603
 
 
604
 
    @staticmethod
605
 
    def _restoreVar(name, value):
606
 
        if value is None:
607
 
            if name in os.environ:
608
 
                del os.environ[name]
609
 
        else:
610
 
            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)
611
719
 
612
720
    def _restoreEnvironment(self):
613
721
        for name, value in self.__old_env.iteritems():
614
 
            self._restoreVar(name, value)
 
722
            osutils.set_or_unset_env(name, value)
615
723
 
616
724
    def tearDown(self):
617
725
        self._runCleanups()
652
760
    def log(self, *args):
653
761
        mutter(*args)
654
762
 
655
 
    def _get_log(self):
656
 
        """Return as a string the log for this test"""
657
 
        if self._log_file_name:
658
 
            return open(self._log_file_name).read()
659
 
        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:
660
771
            return self._log_contents
661
 
        # 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"
662
784
 
663
785
    def capture(self, cmd, retcode=0):
664
786
        """Shortcut that splits cmd into words, runs, and returns stdout"""
665
787
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
666
788
 
667
 
    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):
668
791
        """Invoke bzr and return (stdout, stderr).
669
792
 
670
793
        Useful for code that wants to check the contents of the
685
808
        :param retcode: expected return code, or None for don't-care.
686
809
        :param encoding: encoding for sys.stdout and sys.stderr
687
810
        :param stdin: A string to be used as stdin for the command.
 
811
        :param working_dir: Change to this directory before running
688
812
        """
689
813
        if encoding is None:
690
814
            encoding = bzrlib.user_encoding
706
830
            stdout=stdout,
707
831
            stderr=stderr)
708
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
 
709
839
        try:
710
840
            result = self.apply_redirected(stdin, stdout, stderr,
711
841
                                           bzrlib.commands.run_bzr_catch_errors,
713
843
        finally:
714
844
            logger.removeHandler(handler)
715
845
            bzrlib.ui.ui_factory = old_ui_factory
 
846
            if cwd is not None:
 
847
                os.chdir(cwd)
716
848
 
717
849
        out = stdout.getvalue()
718
850
        err = stderr.getvalue()
739
871
        retcode = kwargs.pop('retcode', 0)
740
872
        encoding = kwargs.pop('encoding', None)
741
873
        stdin = kwargs.pop('stdin', None)
742
 
        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)
743
877
 
744
878
    def run_bzr_decode(self, *args, **kwargs):
745
 
        if kwargs.has_key('encoding'):
 
879
        if 'encoding' in kwargs:
746
880
            encoding = kwargs['encoding']
747
881
        else:
748
882
            encoding = bzrlib.user_encoding
787
921
        profiled or debugged so easily.
788
922
 
789
923
        :param retcode: The status code that is expected.  Defaults to 0.  If
790
 
        None is supplied, the status code is not checked.
791
 
        """
 
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
        """
 
931
        env_changes = kwargs.get('env_changes', {})
 
932
        working_dir = kwargs.get('working_dir', None)
 
933
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
 
934
                                            working_dir=working_dir)
 
935
        # We distinguish between retcode=None and retcode not passed.
 
936
        supplied_retcode = kwargs.get('retcode', 0)
 
937
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
 
938
            universal_newlines=kwargs.get('universal_newlines', False),
 
939
            process_args=args)
 
940
 
 
941
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
942
                             skip_if_plan_to_signal=False,
 
943
                             working_dir=None):
 
944
        """Start bzr in a subprocess for testing.
 
945
 
 
946
        This starts a new Python interpreter and runs bzr in there.
 
947
        This should only be used for tests that have a justifiable need for
 
948
        this isolation: e.g. they are testing startup time, or signal
 
949
        handling, or early startup code, etc.  Subprocess code can't be
 
950
        profiled or debugged so easily.
 
951
 
 
952
        :param process_args: a list of arguments to pass to the bzr executable,
 
953
            for example `['--version']`.
 
954
        :param env_changes: A dictionary which lists changes to environment
 
955
            variables. A value of None will unset the env variable.
 
956
            The values must be strings. The change will only occur in the
 
957
            child, so you don't need to fix the environment after running.
 
958
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
959
            is not available.
 
960
 
 
961
        :returns: Popen object for the started process.
 
962
        """
 
963
        if skip_if_plan_to_signal:
 
964
            if not getattr(os, 'kill', None):
 
965
                raise TestSkipped("os.kill not available.")
 
966
 
 
967
        if env_changes is None:
 
968
            env_changes = {}
 
969
        old_env = {}
 
970
 
 
971
        def cleanup_environment():
 
972
            for env_var, value in env_changes.iteritems():
 
973
                old_env[env_var] = osutils.set_or_unset_env(env_var, value)
 
974
 
 
975
        def restore_environment():
 
976
            for env_var, value in old_env.iteritems():
 
977
                osutils.set_or_unset_env(env_var, value)
 
978
 
 
979
        bzr_path = self.get_bzr_path()
 
980
 
 
981
        cwd = None
 
982
        if working_dir is not None:
 
983
            cwd = osutils.getcwd()
 
984
            os.chdir(working_dir)
 
985
 
 
986
        try:
 
987
            # win32 subprocess doesn't support preexec_fn
 
988
            # so we will avoid using it on all platforms, just to
 
989
            # make sure the code path is used, and we don't break on win32
 
990
            cleanup_environment()
 
991
            process = Popen([sys.executable, bzr_path] + list(process_args),
 
992
                             stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
993
        finally:
 
994
            restore_environment()
 
995
            if cwd is not None:
 
996
                os.chdir(cwd)
 
997
 
 
998
        return process
 
999
 
 
1000
    def get_bzr_path(self):
 
1001
        """Return the path of the 'bzr' executable for this test suite."""
792
1002
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
793
 
        args = list(args)
794
 
        process = Popen([sys.executable, bzr_path]+args, stdout=PIPE, 
795
 
                         stderr=PIPE)
796
 
        out = process.stdout.read()
797
 
        err = process.stderr.read()
798
 
        retcode = process.wait()
799
 
        supplied_retcode = kwargs.get('retcode', 0)
800
 
        if supplied_retcode is not None:
801
 
            assert supplied_retcode == retcode
 
1003
        if not os.path.isfile(bzr_path):
 
1004
            # We are probably installed. Assume sys.argv is the right file
 
1005
            bzr_path = sys.argv[0]
 
1006
        return bzr_path
 
1007
 
 
1008
    def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
 
1009
                              universal_newlines=False, process_args=None):
 
1010
        """Finish the execution of process.
 
1011
 
 
1012
        :param process: the Popen object returned from start_bzr_subprocess.
 
1013
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
1014
            None is supplied, the status code is not checked.
 
1015
        :param send_signal: an optional signal to send to the process.
 
1016
        :param universal_newlines: Convert CRLF => LF
 
1017
        :returns: (stdout, stderr)
 
1018
        """
 
1019
        if send_signal is not None:
 
1020
            os.kill(process.pid, send_signal)
 
1021
        out, err = process.communicate()
 
1022
 
 
1023
        if universal_newlines:
 
1024
            out = out.replace('\r\n', '\n')
 
1025
            err = err.replace('\r\n', '\n')
 
1026
 
 
1027
        if retcode is not None and retcode != process.returncode:
 
1028
            if process_args is None:
 
1029
                process_args = "(unknown args)"
 
1030
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1031
            mutter('Error for bzr %s:\n%s', process_args, err)
 
1032
            self.fail('Command bzr %s failed with retcode %s != %s'
 
1033
                      % (process_args, retcode, process.returncode))
802
1034
        return [out, err]
803
1035
 
804
1036
    def check_inventory_shape(self, inv, shape):
853
1085
            sys.stderr = real_stderr
854
1086
            sys.stdin = real_stdin
855
1087
 
 
1088
    @symbol_versioning.deprecated_method(symbol_versioning.zero_eleven)
856
1089
    def merge(self, branch_from, wt_to):
857
1090
        """A helper for tests to do a ui-less merge.
858
1091
 
864
1097
        base_rev = common_ancestor(branch_from.last_revision(),
865
1098
                                   wt_to.branch.last_revision(),
866
1099
                                   wt_to.branch.repository)
867
 
        merge_inner(wt_to.branch, branch_from.basis_tree(), 
 
1100
        merge_inner(wt_to.branch, branch_from.basis_tree(),
868
1101
                    wt_to.branch.repository.revision_tree(base_rev),
869
1102
                    this_tree=wt_to)
870
 
        wt_to.add_pending_merge(branch_from.last_revision())
 
1103
        wt_to.add_parent_tree_id(branch_from.last_revision())
871
1104
 
872
1105
 
873
1106
BzrTestBase = TestCase
874
1107
 
 
1108
 
 
1109
class TestCaseWithMemoryTransport(TestCase):
 
1110
    """Common test class for tests that do not need disk resources.
 
1111
 
 
1112
    Tests that need disk resources should derive from TestCaseWithTransport.
 
1113
 
 
1114
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
 
1115
 
 
1116
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
1117
    a directory which does not exist. This serves to help ensure test isolation
 
1118
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
1119
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
1120
    file defaults for the transport in tests, nor does it obey the command line
 
1121
    override, so tests that accidentally write to the common directory should
 
1122
    be rare.
 
1123
    """
 
1124
 
 
1125
    TEST_ROOT = None
 
1126
    _TEST_NAME = 'test'
 
1127
 
 
1128
 
 
1129
    def __init__(self, methodName='runTest'):
 
1130
        # allow test parameterisation after test construction and before test
 
1131
        # execution. Variables that the parameteriser sets need to be 
 
1132
        # ones that are not set by setUp, or setUp will trash them.
 
1133
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
 
1134
        self.transport_server = default_transport
 
1135
        self.transport_readonly_server = None
 
1136
 
 
1137
    def failUnlessExists(self, path):
 
1138
        """Fail unless path, which may be abs or relative, exists."""
 
1139
        self.failUnless(osutils.lexists(path))
 
1140
 
 
1141
    def failIfExists(self, path):
 
1142
        """Fail if path, which may be abs or relative, exists."""
 
1143
        self.failIf(osutils.lexists(path))
 
1144
        
 
1145
    def get_transport(self):
 
1146
        """Return a writeable transport for the test scratch space"""
 
1147
        t = get_transport(self.get_url())
 
1148
        self.assertFalse(t.is_readonly())
 
1149
        return t
 
1150
 
 
1151
    def get_readonly_transport(self):
 
1152
        """Return a readonly transport for the test scratch space
 
1153
        
 
1154
        This can be used to test that operations which should only need
 
1155
        readonly access in fact do not try to write.
 
1156
        """
 
1157
        t = get_transport(self.get_readonly_url())
 
1158
        self.assertTrue(t.is_readonly())
 
1159
        return t
 
1160
 
 
1161
    def get_readonly_server(self):
 
1162
        """Get the server instance for the readonly transport
 
1163
 
 
1164
        This is useful for some tests with specific servers to do diagnostics.
 
1165
        """
 
1166
        if self.__readonly_server is None:
 
1167
            if self.transport_readonly_server is None:
 
1168
                # readonly decorator requested
 
1169
                # bring up the server
 
1170
                self.get_url()
 
1171
                self.__readonly_server = ReadonlyServer()
 
1172
                self.__readonly_server.setUp(self.__server)
 
1173
            else:
 
1174
                self.__readonly_server = self.transport_readonly_server()
 
1175
                self.__readonly_server.setUp()
 
1176
            self.addCleanup(self.__readonly_server.tearDown)
 
1177
        return self.__readonly_server
 
1178
 
 
1179
    def get_readonly_url(self, relpath=None):
 
1180
        """Get a URL for the readonly transport.
 
1181
 
 
1182
        This will either be backed by '.' or a decorator to the transport 
 
1183
        used by self.get_url()
 
1184
        relpath provides for clients to get a path relative to the base url.
 
1185
        These should only be downwards relative, not upwards.
 
1186
        """
 
1187
        base = self.get_readonly_server().get_url()
 
1188
        if relpath is not None:
 
1189
            if not base.endswith('/'):
 
1190
                base = base + '/'
 
1191
            base = base + relpath
 
1192
        return base
 
1193
 
 
1194
    def get_server(self):
 
1195
        """Get the read/write server instance.
 
1196
 
 
1197
        This is useful for some tests with specific servers that need
 
1198
        diagnostics.
 
1199
 
 
1200
        For TestCaseWithMemoryTransport this is always a MemoryServer, and there
 
1201
        is no means to override it.
 
1202
        """
 
1203
        if self.__server is None:
 
1204
            self.__server = MemoryServer()
 
1205
            self.__server.setUp()
 
1206
            self.addCleanup(self.__server.tearDown)
 
1207
        return self.__server
 
1208
 
 
1209
    def get_url(self, relpath=None):
 
1210
        """Get a URL (or maybe a path) for the readwrite transport.
 
1211
 
 
1212
        This will either be backed by '.' or to an equivalent non-file based
 
1213
        facility.
 
1214
        relpath provides for clients to get a path relative to the base url.
 
1215
        These should only be downwards relative, not upwards.
 
1216
        """
 
1217
        base = self.get_server().get_url()
 
1218
        if relpath is not None and relpath != '.':
 
1219
            if not base.endswith('/'):
 
1220
                base = base + '/'
 
1221
            # XXX: Really base should be a url; we did after all call
 
1222
            # get_url()!  But sometimes it's just a path (from
 
1223
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
 
1224
            # to a non-escaped local path.
 
1225
            if base.startswith('./') or base.startswith('/'):
 
1226
                base += relpath
 
1227
            else:
 
1228
                base += urlutils.escape(relpath)
 
1229
        return base
 
1230
 
 
1231
    def _make_test_root(self):
 
1232
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
 
1233
            return
 
1234
        i = 0
 
1235
        while True:
 
1236
            root = u'test%04d.tmp' % i
 
1237
            try:
 
1238
                os.mkdir(root)
 
1239
            except OSError, e:
 
1240
                if e.errno == errno.EEXIST:
 
1241
                    i += 1
 
1242
                    continue
 
1243
                else:
 
1244
                    raise
 
1245
            # successfully created
 
1246
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
 
1247
            break
 
1248
        # make a fake bzr directory there to prevent any tests propagating
 
1249
        # up onto the source directory's real branch
 
1250
        bzrdir.BzrDir.create_standalone_workingtree(
 
1251
            TestCaseWithMemoryTransport.TEST_ROOT)
 
1252
 
 
1253
    def makeAndChdirToTestDir(self):
 
1254
        """Create a temporary directories for this one test.
 
1255
        
 
1256
        This must set self.test_home_dir and self.test_dir and chdir to
 
1257
        self.test_dir.
 
1258
        
 
1259
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
 
1260
        """
 
1261
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
1262
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
 
1263
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
 
1264
        
 
1265
    def make_branch(self, relpath, format=None):
 
1266
        """Create a branch on the transport at relpath."""
 
1267
        repo = self.make_repository(relpath, format=format)
 
1268
        return repo.bzrdir.create_branch()
 
1269
 
 
1270
    def make_bzrdir(self, relpath, format=None):
 
1271
        try:
 
1272
            # might be a relative or absolute path
 
1273
            maybe_a_url = self.get_url(relpath)
 
1274
            segments = maybe_a_url.rsplit('/', 1)
 
1275
            t = get_transport(maybe_a_url)
 
1276
            if len(segments) > 1 and segments[-1] not in ('', '.'):
 
1277
                try:
 
1278
                    t.mkdir('.')
 
1279
                except errors.FileExists:
 
1280
                    pass
 
1281
            if format is None:
 
1282
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1283
            return format.initialize_on_transport(t)
 
1284
        except errors.UninitializableFormat:
 
1285
            raise TestSkipped("Format %s is not initializable." % format)
 
1286
 
 
1287
    def make_repository(self, relpath, shared=False, format=None):
 
1288
        """Create a repository on our default transport at relpath."""
 
1289
        made_control = self.make_bzrdir(relpath, format=format)
 
1290
        return made_control.create_repository(shared=shared)
 
1291
 
 
1292
    def make_branch_and_memory_tree(self, relpath):
 
1293
        """Create a branch on the default transport and a MemoryTree for it."""
 
1294
        b = self.make_branch(relpath)
 
1295
        return memorytree.MemoryTree.create_on_branch(b)
 
1296
 
 
1297
    def overrideEnvironmentForTesting(self):
 
1298
        os.environ['HOME'] = self.test_home_dir
 
1299
        os.environ['APPDATA'] = self.test_home_dir
 
1300
        
 
1301
    def setUp(self):
 
1302
        super(TestCaseWithMemoryTransport, self).setUp()
 
1303
        self._make_test_root()
 
1304
        _currentdir = os.getcwdu()
 
1305
        def _leaveDirectory():
 
1306
            os.chdir(_currentdir)
 
1307
        self.addCleanup(_leaveDirectory)
 
1308
        self.makeAndChdirToTestDir()
 
1309
        self.overrideEnvironmentForTesting()
 
1310
        self.__readonly_server = None
 
1311
        self.__server = None
 
1312
 
875
1313
     
876
 
class TestCaseInTempDir(TestCase):
 
1314
class TestCaseInTempDir(TestCaseWithMemoryTransport):
877
1315
    """Derived class that runs a test within a temporary directory.
878
1316
 
879
1317
    This is useful for tests that need to create a branch, etc.
886
1324
    InTempDir is an old alias for FunctionalTestCase.
887
1325
    """
888
1326
 
889
 
    TEST_ROOT = None
890
 
    _TEST_NAME = 'test'
891
1327
    OVERRIDE_PYTHON = 'python'
892
1328
 
893
1329
    def check_file_contents(self, filename, expect):
898
1334
            self.log("actually: %r" % contents)
899
1335
            self.fail("contents of %s not as expected" % filename)
900
1336
 
901
 
    def _make_test_root(self):
902
 
        if TestCaseInTempDir.TEST_ROOT is not None:
903
 
            return
904
 
        i = 0
905
 
        while True:
906
 
            root = u'test%04d.tmp' % i
907
 
            try:
908
 
                os.mkdir(root)
909
 
            except OSError, e:
910
 
                if e.errno == errno.EEXIST:
911
 
                    i += 1
912
 
                    continue
913
 
                else:
914
 
                    raise
915
 
            # successfully created
916
 
            TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
917
 
            break
918
 
        # make a fake bzr directory there to prevent any tests propagating
919
 
        # up onto the source directory's real branch
920
 
        bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
921
 
 
922
 
    def setUp(self):
923
 
        super(TestCaseInTempDir, self).setUp()
924
 
        self._make_test_root()
925
 
        _currentdir = os.getcwdu()
 
1337
    def makeAndChdirToTestDir(self):
 
1338
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
 
1339
        
 
1340
        For TestCaseInTempDir we create a temporary directory based on the test
 
1341
        name and then create two subdirs - test and home under it.
 
1342
        """
926
1343
        # shorten the name, to avoid test failures due to path length
927
1344
        short_id = self.id().replace('bzrlib.tests.', '') \
928
1345
                   .replace('__main__.', '')[-100:]
938
1355
                i = i + 1
939
1356
                continue
940
1357
            else:
941
 
                self.test_dir = candidate_dir
 
1358
                os.mkdir(candidate_dir)
 
1359
                self.test_home_dir = candidate_dir + '/home'
 
1360
                os.mkdir(self.test_home_dir)
 
1361
                self.test_dir = candidate_dir + '/work'
942
1362
                os.mkdir(self.test_dir)
943
1363
                os.chdir(self.test_dir)
944
1364
                break
945
 
        os.environ['HOME'] = self.test_dir
946
 
        os.environ['APPDATA'] = self.test_dir
947
 
        def _leaveDirectory():
948
 
            os.chdir(_currentdir)
949
 
        self.addCleanup(_leaveDirectory)
950
 
        
 
1365
 
951
1366
    def build_tree(self, shape, line_endings='native', transport=None):
952
1367
        """Build a test tree according to a pattern.
953
1368
 
954
1369
        shape is a sequence of file specifications.  If the final
955
1370
        character is '/', a directory is created.
956
1371
 
 
1372
        This assumes that all the elements in the tree being built are new.
 
1373
 
957
1374
        This doesn't add anything to a branch.
958
1375
        :param line_endings: Either 'binary' or 'native'
959
1376
                             in binary mode, exact contents are written
964
1381
                          VFS's. If the transport is readonly or None,
965
1382
                          "." is opened automatically.
966
1383
        """
967
 
        # XXX: It's OK to just create them using forward slashes on windows?
 
1384
        # It's OK to just create them using forward slashes on windows.
968
1385
        if transport is None or transport.is_readonly():
969
1386
            transport = get_transport(".")
970
1387
        for name in shape:
979
1396
                else:
980
1397
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
981
1398
                content = "contents of %s%s" % (name.encode('utf-8'), end)
982
 
                transport.put(urlutils.escape(name), StringIO(content))
 
1399
                # Technically 'put()' is the right command. However, put
 
1400
                # uses an AtomicFile, which requires an extra rename into place
 
1401
                # As long as the files didn't exist in the past, append() will
 
1402
                # do the same thing as put()
 
1403
                # On jam's machine, make_kernel_like_tree is:
 
1404
                #   put:    4.5-7.5s (averaging 6s)
 
1405
                #   append: 2.9-4.5s
 
1406
                #   put_non_atomic: 2.9-4.5s
 
1407
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
983
1408
 
984
1409
    def build_tree_contents(self, shape):
985
1410
        build_tree_contents(shape)
986
1411
 
987
 
    def failUnlessExists(self, path):
988
 
        """Fail unless path, which may be abs or relative, exists."""
989
 
        self.failUnless(osutils.lexists(path))
990
 
 
991
 
    def failIfExists(self, path):
992
 
        """Fail if path, which may be abs or relative, exists."""
993
 
        self.failIf(osutils.lexists(path))
994
 
        
995
1412
    def assertFileEqual(self, content, path):
996
1413
        """Fail if path does not contain 'content'."""
997
1414
        self.failUnless(osutils.lexists(path))
1013
1430
    readwrite one must both define get_url() as resolving to os.getcwd().
1014
1431
    """
1015
1432
 
1016
 
    def __init__(self, methodName='testMethod'):
1017
 
        super(TestCaseWithTransport, self).__init__(methodName)
1018
 
        self.__readonly_server = None
1019
 
        self.__server = None
1020
 
        self.transport_server = default_transport
1021
 
        self.transport_readonly_server = None
1022
 
 
1023
 
    def get_readonly_url(self, relpath=None):
1024
 
        """Get a URL for the readonly transport.
1025
 
 
1026
 
        This will either be backed by '.' or a decorator to the transport 
1027
 
        used by self.get_url()
1028
 
        relpath provides for clients to get a path relative to the base url.
1029
 
        These should only be downwards relative, not upwards.
1030
 
        """
1031
 
        base = self.get_readonly_server().get_url()
1032
 
        if relpath is not None:
1033
 
            if not base.endswith('/'):
1034
 
                base = base + '/'
1035
 
            base = base + relpath
1036
 
        return base
1037
 
 
1038
 
    def get_readonly_server(self):
1039
 
        """Get the server instance for the readonly transport
1040
 
 
1041
 
        This is useful for some tests with specific servers to do diagnostics.
1042
 
        """
1043
 
        if self.__readonly_server is None:
1044
 
            if self.transport_readonly_server is None:
1045
 
                # readonly decorator requested
1046
 
                # bring up the server
1047
 
                self.get_url()
1048
 
                self.__readonly_server = ReadonlyServer()
1049
 
                self.__readonly_server.setUp(self.__server)
1050
 
            else:
1051
 
                self.__readonly_server = self.transport_readonly_server()
1052
 
                self.__readonly_server.setUp()
1053
 
            self.addCleanup(self.__readonly_server.tearDown)
1054
 
        return self.__readonly_server
1055
 
 
1056
1433
    def get_server(self):
1057
 
        """Get the read/write server instance.
 
1434
        """See TestCaseWithMemoryTransport.
1058
1435
 
1059
1436
        This is useful for some tests with specific servers that need
1060
1437
        diagnostics.
1065
1442
            self.addCleanup(self.__server.tearDown)
1066
1443
        return self.__server
1067
1444
 
1068
 
    def get_url(self, relpath=None):
1069
 
        """Get a URL for the readwrite transport.
1070
 
 
1071
 
        This will either be backed by '.' or to an equivalent non-file based
1072
 
        facility.
1073
 
        relpath provides for clients to get a path relative to the base url.
1074
 
        These should only be downwards relative, not upwards.
1075
 
        """
1076
 
        base = self.get_server().get_url()
1077
 
        if relpath is not None and relpath != '.':
1078
 
            if not base.endswith('/'):
1079
 
                base = base + '/'
1080
 
            base = base + urlutils.escape(relpath)
1081
 
        return base
1082
 
 
1083
 
    def get_transport(self):
1084
 
        """Return a writeable transport for the test scratch space"""
1085
 
        t = get_transport(self.get_url())
1086
 
        self.assertFalse(t.is_readonly())
1087
 
        return t
1088
 
 
1089
 
    def get_readonly_transport(self):
1090
 
        """Return a readonly transport for the test scratch space
1091
 
        
1092
 
        This can be used to test that operations which should only need
1093
 
        readonly access in fact do not try to write.
1094
 
        """
1095
 
        t = get_transport(self.get_readonly_url())
1096
 
        self.assertTrue(t.is_readonly())
1097
 
        return t
1098
 
 
1099
 
    def make_branch(self, relpath, format=None):
1100
 
        """Create a branch on the transport at relpath."""
1101
 
        repo = self.make_repository(relpath, format=format)
1102
 
        return repo.bzrdir.create_branch()
1103
 
 
1104
 
    def make_bzrdir(self, relpath, format=None):
1105
 
        try:
1106
 
            url = self.get_url(relpath)
1107
 
            mutter('relpath %r => url %r', relpath, url)
1108
 
            segments = url.split('/')
1109
 
            if segments and segments[-1] not in ('', '.'):
1110
 
                parent = '/'.join(segments[:-1])
1111
 
                t = get_transport(parent)
1112
 
                try:
1113
 
                    t.mkdir(segments[-1])
1114
 
                except errors.FileExists:
1115
 
                    pass
1116
 
            if format is None:
1117
 
                format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
1118
 
            # FIXME: make this use a single transport someday. RBC 20060418
1119
 
            return format.initialize_on_transport(get_transport(relpath))
1120
 
        except errors.UninitializableFormat:
1121
 
            raise TestSkipped("Format %s is not initializable." % format)
1122
 
 
1123
 
    def make_repository(self, relpath, shared=False, format=None):
1124
 
        """Create a repository on our default transport at relpath."""
1125
 
        made_control = self.make_bzrdir(relpath, format=format)
1126
 
        return made_control.create_repository(shared=shared)
1127
 
 
1128
1445
    def make_branch_and_tree(self, relpath, format=None):
1129
1446
        """Create a branch on the transport and a tree locally.
1130
1447
 
1131
 
        Returns the tree.
 
1448
        If the transport is not a LocalTransport, the Tree can't be created on
 
1449
        the transport.  In that case the working tree is created in the local
 
1450
        directory, and the returned tree's branch and repository will also be
 
1451
        accessed locally.
 
1452
 
 
1453
        This will fail if the original default transport for this test
 
1454
        case wasn't backed by the working directory, as the branch won't
 
1455
        be on disk for us to open it.  
 
1456
 
 
1457
        :param format: The BzrDirFormat.
 
1458
        :returns: the WorkingTree.
1132
1459
        """
1133
1460
        # TODO: always use the local disk path for the working tree,
1134
1461
        # this obviously requires a format that supports branch references
1138
1465
        try:
1139
1466
            return b.bzrdir.create_workingtree()
1140
1467
        except errors.NotLocalUrl:
1141
 
            # new formats - catch No tree error and create
1142
 
            # a branch reference and a checkout.
1143
 
            # old formats at that point - raise TestSkipped.
1144
 
            # TODO: rbc 20060208
1145
 
            return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
 
1468
            # We can only make working trees locally at the moment.  If the
 
1469
            # transport can't support them, then reopen the branch on a local
 
1470
            # transport, and create the working tree there.  
 
1471
            #
 
1472
            # Possibly we should instead keep
 
1473
            # the non-disk-backed branch and create a local checkout?
 
1474
            bd = bzrdir.BzrDir.open(relpath)
 
1475
            return bd.create_workingtree()
1146
1476
 
1147
1477
    def assertIsDirectory(self, relpath, transport):
1148
1478
        """Assert that relpath within transport is a directory.
1159
1489
            self.fail("path %s is not a directory; has mode %#o"
1160
1490
                      % (relpath, mode))
1161
1491
 
 
1492
    def setUp(self):
 
1493
        super(TestCaseWithTransport, self).setUp()
 
1494
        self.__server = None
 
1495
        self.transport_server = default_transport
 
1496
 
1162
1497
 
1163
1498
class ChrootedTestCase(TestCaseWithTransport):
1164
1499
    """A support class that provides readonly urls outside the local namespace.
1189
1524
 
1190
1525
def run_suite(suite, name='test', verbose=False, pattern=".*",
1191
1526
              stop_on_failure=False, keep_output=False,
1192
 
              transport=None, lsprof_timed=None):
1193
 
    TestCaseInTempDir._TEST_NAME = name
 
1527
              transport=None, lsprof_timed=None, bench_history=None):
1194
1528
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1195
1529
    if verbose:
1196
1530
        verbosity = 2
1202
1536
                            descriptions=0,
1203
1537
                            verbosity=verbosity,
1204
1538
                            keep_output=keep_output,
1205
 
                            pb=pb)
 
1539
                            pb=pb,
 
1540
                            bench_history=bench_history)
1206
1541
    runner.stop_on_failure=stop_on_failure
1207
1542
    if pattern != '.*':
1208
1543
        suite = filter_suite_by_re(suite, pattern)
1214
1549
             keep_output=False,
1215
1550
             transport=None,
1216
1551
             test_suite_factory=None,
1217
 
             lsprof_timed=None):
 
1552
             lsprof_timed=None,
 
1553
             bench_history=None):
1218
1554
    """Run the whole test suite under the enhanced runner"""
 
1555
    # XXX: Very ugly way to do this...
 
1556
    # Disable warning about old formats because we don't want it to disturb
 
1557
    # any blackbox tests.
 
1558
    from bzrlib import repository
 
1559
    repository._deprecation_warning_done = True
 
1560
 
1219
1561
    global default_transport
1220
1562
    if transport is None:
1221
1563
        transport = default_transport
1229
1571
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
1230
1572
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
1231
1573
                     transport=transport,
1232
 
                     lsprof_timed=lsprof_timed)
 
1574
                     lsprof_timed=lsprof_timed,
 
1575
                     bench_history=bench_history)
1233
1576
    finally:
1234
1577
        default_transport = old_transport
1235
1578
 
1243
1586
    testmod_names = [
1244
1587
                   'bzrlib.tests.test_ancestry',
1245
1588
                   'bzrlib.tests.test_api',
 
1589
                   'bzrlib.tests.test_atomicfile',
1246
1590
                   'bzrlib.tests.test_bad_files',
1247
1591
                   'bzrlib.tests.test_branch',
1248
1592
                   'bzrlib.tests.test_bundle',
1249
1593
                   'bzrlib.tests.test_bzrdir',
 
1594
                   'bzrlib.tests.test_cache_utf8',
1250
1595
                   'bzrlib.tests.test_command',
1251
1596
                   'bzrlib.tests.test_commit',
1252
1597
                   'bzrlib.tests.test_commit_merge',
1255
1600
                   'bzrlib.tests.test_decorators',
1256
1601
                   'bzrlib.tests.test_diff',
1257
1602
                   'bzrlib.tests.test_doc_generate',
1258
 
                   'bzrlib.tests.test_emptytree',
1259
1603
                   'bzrlib.tests.test_errors',
1260
1604
                   'bzrlib.tests.test_escaped_store',
1261
1605
                   'bzrlib.tests.test_fetch',
 
1606
                   'bzrlib.tests.test_ftp_transport',
1262
1607
                   'bzrlib.tests.test_gpg',
1263
1608
                   'bzrlib.tests.test_graph',
1264
1609
                   'bzrlib.tests.test_hashcache',
1265
1610
                   'bzrlib.tests.test_http',
1266
1611
                   'bzrlib.tests.test_http_response',
1267
1612
                   'bzrlib.tests.test_identitymap',
 
1613
                   'bzrlib.tests.test_ignores',
1268
1614
                   'bzrlib.tests.test_inv',
1269
1615
                   'bzrlib.tests.test_knit',
 
1616
                   'bzrlib.tests.test_lazy_import',
 
1617
                   'bzrlib.tests.test_lazy_regex',
1270
1618
                   'bzrlib.tests.test_lockdir',
1271
1619
                   'bzrlib.tests.test_lockable_files',
1272
1620
                   'bzrlib.tests.test_log',
 
1621
                   'bzrlib.tests.test_memorytree',
1273
1622
                   'bzrlib.tests.test_merge',
1274
1623
                   'bzrlib.tests.test_merge3',
1275
1624
                   'bzrlib.tests.test_merge_core',
1285
1634
                   'bzrlib.tests.test_progress',
1286
1635
                   'bzrlib.tests.test_reconcile',
1287
1636
                   'bzrlib.tests.test_repository',
 
1637
                   'bzrlib.tests.test_revert',
1288
1638
                   'bzrlib.tests.test_revision',
1289
1639
                   'bzrlib.tests.test_revisionnamespaces',
1290
 
                   'bzrlib.tests.test_revprops',
1291
1640
                   'bzrlib.tests.test_revisiontree',
1292
1641
                   'bzrlib.tests.test_rio',
1293
1642
                   'bzrlib.tests.test_sampler',
1295
1644
                   'bzrlib.tests.test_setup',
1296
1645
                   'bzrlib.tests.test_sftp_transport',
1297
1646
                   'bzrlib.tests.test_smart_add',
 
1647
                   'bzrlib.tests.test_smart_transport',
1298
1648
                   'bzrlib.tests.test_source',
1299
1649
                   'bzrlib.tests.test_status',
1300
1650
                   'bzrlib.tests.test_store',
1306
1656
                   'bzrlib.tests.test_transactions',
1307
1657
                   'bzrlib.tests.test_transform',
1308
1658
                   'bzrlib.tests.test_transport',
 
1659
                   'bzrlib.tests.test_tree',
 
1660
                   'bzrlib.tests.test_treebuilder',
1309
1661
                   'bzrlib.tests.test_tsort',
1310
1662
                   'bzrlib.tests.test_tuned_gzip',
1311
1663
                   'bzrlib.tests.test_ui',
1312
1664
                   'bzrlib.tests.test_upgrade',
1313
1665
                   'bzrlib.tests.test_urlutils',
1314
1666
                   'bzrlib.tests.test_versionedfile',
 
1667
                   'bzrlib.tests.test_version',
 
1668
                   'bzrlib.tests.test_version_info',
1315
1669
                   'bzrlib.tests.test_weave',
1316
1670
                   'bzrlib.tests.test_whitebox',
1317
1671
                   'bzrlib.tests.test_workingtree',
1323
1677
        ]
1324
1678
    suite = TestUtil.TestSuite()
1325
1679
    loader = TestUtil.TestLoader()
 
1680
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1326
1681
    from bzrlib.transport import TransportTestProviderAdapter
1327
1682
    adapter = TransportTestProviderAdapter()
1328
1683
    adapt_modules(test_transport_implementations, adapter, loader, suite)
1329
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1330
1684
    for package in packages_to_test():
1331
1685
        suite.addTest(package.test_suite())
1332
1686
    for m in MODULES_TO_TEST:
1333
1687
        suite.addTest(loader.loadTestsFromModule(m))
1334
1688
    for m in MODULES_TO_DOCTEST:
1335
 
        suite.addTest(doctest.DocTestSuite(m))
 
1689
        try:
 
1690
            suite.addTest(doctest.DocTestSuite(m))
 
1691
        except ValueError, e:
 
1692
            print '**failed to get doctest for: %s\n%s' %(m,e)
 
1693
            raise
1336
1694
    for name, plugin in bzrlib.plugin.all_plugins().items():
1337
1695
        if getattr(plugin, 'test_suite', None) is not None:
1338
1696
            suite.addTest(plugin.test_suite())