~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Andrew Bennetts
  • Date: 2010-10-13 00:26:41 UTC
  • mto: This revision was merged to the branch mainline in revision 5498.
  • Revision ID: andrew.bennetts@canonical.com-20101013002641-9tlh9k89mlj1666m
Keep docs-plain working.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
55
55
import testtools
56
56
# nb: check this before importing anything else from within it
57
57
_testtools_version = getattr(testtools, '__version__', ())
58
 
if _testtools_version < (0, 9, 5):
59
 
    raise ImportError("need at least testtools 0.9.5: %s is %r"
 
58
if _testtools_version < (0, 9, 2):
 
59
    raise ImportError("need at least testtools 0.9.2: %s is %r"
60
60
        % (testtools.__file__, _testtools_version))
61
61
from testtools import content
62
62
 
63
 
import bzrlib
64
63
from bzrlib import (
65
64
    branchbuilder,
66
65
    bzrdir,
67
66
    chk_map,
68
 
    commands as _mod_commands,
69
67
    config,
70
68
    debug,
71
69
    errors,
72
70
    hooks,
73
71
    lock as _mod_lock,
74
 
    lockdir,
75
72
    memorytree,
76
73
    osutils,
77
 
    plugin as _mod_plugin,
78
 
    pyutils,
79
74
    ui,
80
75
    urlutils,
81
76
    registry,
82
 
    symbol_versioning,
83
 
    trace,
84
77
    transport as _mod_transport,
85
78
    workingtree,
86
79
    )
 
80
import bzrlib.branch
 
81
import bzrlib.commands
 
82
import bzrlib.timestamp
 
83
import bzrlib.export
 
84
import bzrlib.inventory
 
85
import bzrlib.iterablefile
 
86
import bzrlib.lockdir
87
87
try:
88
88
    import bzrlib.lsprof
89
89
except ImportError:
90
90
    # lsprof not available
91
91
    pass
92
 
from bzrlib.smart import client, request
 
92
from bzrlib.merge import merge_inner
 
93
import bzrlib.merge3
 
94
import bzrlib.plugin
 
95
from bzrlib.smart import client, request, server
 
96
import bzrlib.store
 
97
from bzrlib import symbol_versioning
 
98
from bzrlib.symbol_versioning import (
 
99
    DEPRECATED_PARAMETER,
 
100
    deprecated_function,
 
101
    deprecated_in,
 
102
    deprecated_method,
 
103
    deprecated_passed,
 
104
    )
 
105
import bzrlib.trace
93
106
from bzrlib.transport import (
94
107
    memory,
95
108
    pathfilter,
96
109
    )
 
110
from bzrlib.trace import mutter, note
97
111
from bzrlib.tests import (
98
112
    test_server,
99
113
    TestUtil,
101
115
    )
102
116
from bzrlib.ui import NullProgressView
103
117
from bzrlib.ui.text import TextUIFactory
 
118
import bzrlib.version_info_formats.format_custom
 
119
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
104
120
 
105
121
# Mark this python module as being part of the implementation
106
122
# of unittest: this gives us better tracebacks where the last
123
139
TestSuite = TestUtil.TestSuite
124
140
TestLoader = TestUtil.TestLoader
125
141
 
126
 
# Tests should run in a clean and clearly defined environment. The goal is to
127
 
# keep them isolated from the running environment as mush as possible. The test
128
 
# framework ensures the variables defined below are set (or deleted if the
129
 
# value is None) before a test is run and reset to their original value after
130
 
# the test is run. Generally if some code depends on an environment variable,
131
 
# the tests should start without this variable in the environment. There are a
132
 
# few exceptions but you shouldn't violate this rule lightly.
133
 
isolated_environ = {
134
 
    'BZR_HOME': None,
135
 
    'HOME': None,
136
 
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
137
 
    # tests do check our impls match APPDATA
138
 
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
139
 
    'VISUAL': None,
140
 
    'EDITOR': None,
141
 
    'BZR_EMAIL': None,
142
 
    'BZREMAIL': None, # may still be present in the environment
143
 
    'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
144
 
    'BZR_PROGRESS_BAR': None,
145
 
    # This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
146
 
    # as a base class instead of TestCaseInTempDir. Tests inheriting from
147
 
    # TestCase should not use disk resources, BZR_LOG is one.
148
 
    'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
149
 
    'BZR_PLUGIN_PATH': None,
150
 
    'BZR_DISABLE_PLUGINS': None,
151
 
    'BZR_PLUGINS_AT': None,
152
 
    'BZR_CONCURRENCY': None,
153
 
    # Make sure that any text ui tests are consistent regardless of
154
 
    # the environment the test case is run in; you may want tests that
155
 
    # test other combinations.  'dumb' is a reasonable guess for tests
156
 
    # going to a pipe or a StringIO.
157
 
    'TERM': 'dumb',
158
 
    'LINES': '25',
159
 
    'COLUMNS': '80',
160
 
    'BZR_COLUMNS': '80',
161
 
    # Disable SSH Agent
162
 
    'SSH_AUTH_SOCK': None,
163
 
    # Proxies
164
 
    'http_proxy': None,
165
 
    'HTTP_PROXY': None,
166
 
    'https_proxy': None,
167
 
    'HTTPS_PROXY': None,
168
 
    'no_proxy': None,
169
 
    'NO_PROXY': None,
170
 
    'all_proxy': None,
171
 
    'ALL_PROXY': None,
172
 
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
173
 
    # least. If you do (care), please update this comment
174
 
    # -- vila 20080401
175
 
    'ftp_proxy': None,
176
 
    'FTP_PROXY': None,
177
 
    'BZR_REMOTE_PATH': None,
178
 
    # Generally speaking, we don't want apport reporting on crashes in
179
 
    # the test envirnoment unless we're specifically testing apport,
180
 
    # so that it doesn't leak into the real system environment.  We
181
 
    # use an env var so it propagates to subprocesses.
182
 
    'APPORT_DISABLE': '1',
183
 
    }
184
 
 
185
 
 
186
 
def override_os_environ(test, env=None):
187
 
    """Modify os.environ keeping a copy.
188
 
    
189
 
    :param test: A test instance
190
 
 
191
 
    :param env: A dict containing variable definitions to be installed
192
 
    """
193
 
    if env is None:
194
 
        env = isolated_environ
195
 
    test._original_os_environ = dict([(var, value)
196
 
                                      for var, value in os.environ.iteritems()])
197
 
    for var, value in env.iteritems():
198
 
        osutils.set_or_unset_env(var, value)
199
 
        if var not in test._original_os_environ:
200
 
            # The var is new, add it with a value of None, so
201
 
            # restore_os_environ will delete it
202
 
            test._original_os_environ[var] = None
203
 
 
204
 
 
205
 
def restore_os_environ(test):
206
 
    """Restore os.environ to its original state.
207
 
 
208
 
    :param test: A test instance previously passed to override_os_environ.
209
 
    """
210
 
    for var, value in test._original_os_environ.iteritems():
211
 
        # Restore the original value (or delete it if the value has been set to
212
 
        # None in override_os_environ).
213
 
        osutils.set_or_unset_env(var, value)
214
 
 
215
 
 
216
142
class ExtendedTestResult(testtools.TextTestResult):
217
143
    """Accepts, reports and accumulates the results of running tests.
218
144
 
269
195
        self._strict = strict
270
196
        self._first_thread_leaker_id = None
271
197
        self._tests_leaking_threads_count = 0
272
 
        self._traceback_from_test = None
273
198
 
274
199
    def stopTestRun(self):
275
200
        run = self.testsRun
335
260
 
336
261
    def _elapsedTestTimeString(self):
337
262
        """Return a time string for the overall time the current test has taken."""
338
 
        return self._formatTime(self._delta_to_float(
339
 
            self._now() - self._start_datetime))
 
263
        return self._formatTime(time.time() - self._start_time)
340
264
 
341
265
    def _testTimeString(self, testCase):
342
266
        benchmark_time = self._extractBenchmarkTime(testCase)
356
280
        what = re.sub(r'^bzrlib\.tests\.', '', what)
357
281
        return what
358
282
 
359
 
    # GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
360
 
    #                multiple times in a row, because the handler is added for
361
 
    #                each test but the container list is shared between cases.
362
 
    #                See lp:498869 lp:625574 and lp:637725 for background.
363
 
    def _record_traceback_from_test(self, exc_info):
364
 
        """Store the traceback from passed exc_info tuple till"""
365
 
        self._traceback_from_test = exc_info[2]
366
 
 
367
283
    def startTest(self, test):
368
284
        super(ExtendedTestResult, self).startTest(test)
369
285
        if self.count == 0:
372
288
        self.report_test_start(test)
373
289
        test.number = self.count
374
290
        self._recordTestStartTime()
375
 
        # Make testtools cases give us the real traceback on failure
376
 
        addOnException = getattr(test, "addOnException", None)
377
 
        if addOnException is not None:
378
 
            addOnException(self._record_traceback_from_test)
379
 
        # Only check for thread leaks on bzrlib derived test cases
380
 
        if isinstance(test, TestCase):
381
 
            test.addCleanup(self._check_leaked_threads, test)
382
 
 
383
 
    def stopTest(self, test):
384
 
        super(ExtendedTestResult, self).stopTest(test)
385
 
        # Manually break cycles, means touching various private things but hey
386
 
        getDetails = getattr(test, "getDetails", None)
387
 
        if getDetails is not None:
388
 
            getDetails().clear()
389
 
        type_equality_funcs = getattr(test, "_type_equality_funcs", None)
390
 
        if type_equality_funcs is not None:
391
 
            type_equality_funcs.clear()
392
 
        self._traceback_from_test = None
 
291
        # Only check for thread leaks if the test case supports cleanups
 
292
        addCleanup = getattr(test, "addCleanup", None)
 
293
        if addCleanup is not None:
 
294
            addCleanup(self._check_leaked_threads, test)
393
295
 
394
296
    def startTests(self):
395
297
        self.report_tests_starting()
413
315
 
414
316
    def _recordTestStartTime(self):
415
317
        """Record that a test has started."""
416
 
        self._start_datetime = self._now()
 
318
        self._start_time = time.time()
417
319
 
418
320
    def addError(self, test, err):
419
321
        """Tell result that test finished with an error.
421
323
        Called from the TestCase run() method when the test
422
324
        fails with an unexpected error.
423
325
        """
424
 
        self._post_mortem(self._traceback_from_test)
 
326
        self._post_mortem()
425
327
        super(ExtendedTestResult, self).addError(test, err)
426
328
        self.error_count += 1
427
329
        self.report_error(test, err)
434
336
        Called from the TestCase run() method when the test
435
337
        fails because e.g. an assert() method failed.
436
338
        """
437
 
        self._post_mortem(self._traceback_from_test)
 
339
        self._post_mortem()
438
340
        super(ExtendedTestResult, self).addFailure(test, err)
439
341
        self.failure_count += 1
440
342
        self.report_failure(test, err)
460
362
        self.known_failure_count += 1
461
363
        self.report_known_failure(test, err)
462
364
 
463
 
    def addUnexpectedSuccess(self, test, details=None):
464
 
        """Tell result the test unexpectedly passed, counting as a failure
465
 
 
466
 
        When the minimum version of testtools required becomes 0.9.8 this
467
 
        can be updated to use the new handling there.
468
 
        """
469
 
        super(ExtendedTestResult, self).addFailure(test, details=details)
470
 
        self.failure_count += 1
471
 
        self.report_unexpected_success(test,
472
 
            "".join(details["reason"].iter_text()))
473
 
        if self.stop_early:
474
 
            self.stop()
475
 
 
476
365
    def addNotSupported(self, test, feature):
477
366
        """The test will not be run because of a missing feature.
478
367
        """
495
384
        self.not_applicable_count += 1
496
385
        self.report_not_applicable(test, reason)
497
386
 
498
 
    def _post_mortem(self, tb=None):
 
387
    def _post_mortem(self):
499
388
        """Start a PDB post mortem session."""
500
389
        if os.environ.get('BZR_TEST_PDB', None):
501
 
            import pdb
502
 
            pdb.post_mortem(tb)
 
390
            import pdb;pdb.post_mortem()
503
391
 
504
392
    def progress(self, offset, whence):
505
393
        """The test is adjusting the count of tests to run."""
637
525
    def report_known_failure(self, test, err):
638
526
        pass
639
527
 
640
 
    def report_unexpected_success(self, test, reason):
641
 
        self.stream.write('FAIL: %s\n    %s: %s\n' % (
642
 
            self._test_description(test),
643
 
            "Unexpected success. Should have failed",
644
 
            reason,
645
 
            ))
646
 
 
647
528
    def report_skip(self, test, reason):
648
529
        pass
649
530
 
701
582
                % (self._testTimeString(test),
702
583
                   self._error_summary(err)))
703
584
 
704
 
    def report_unexpected_success(self, test, reason):
705
 
        self.stream.write(' FAIL %s\n%s: %s\n'
706
 
                % (self._testTimeString(test),
707
 
                   "Unexpected success. Should have failed",
708
 
                   reason))
709
 
 
710
585
    def report_success(self, test):
711
586
        self.stream.write('   OK %s\n' % self._testTimeString(test))
712
587
        for bench_called, stats in getattr(test, '_benchcalls', []):
759
634
            encode = codec[0]
760
635
        else:
761
636
            encode = codec.encode
762
 
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
763
 
        #                so should swap to the plain codecs.StreamWriter
764
 
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
765
 
            "backslashreplace")
 
637
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream)
766
638
        stream.encoding = new_encoding
767
639
        self.stream = stream
768
640
        self.descriptions = descriptions
918
790
        return NullProgressView()
919
791
 
920
792
 
921
 
def isolated_doctest_setUp(test):
922
 
    override_os_environ(test)
923
 
 
924
 
 
925
 
def isolated_doctest_tearDown(test):
926
 
    restore_os_environ(test)
927
 
 
928
 
 
929
 
def IsolatedDocTestSuite(*args, **kwargs):
930
 
    """Overrides doctest.DocTestSuite to handle isolation.
931
 
 
932
 
    The method is really a factory and users are expected to use it as such.
933
 
    """
934
 
 
935
 
    kwargs['setUp'] = isolated_doctest_setUp
936
 
    kwargs['tearDown'] = isolated_doctest_tearDown
937
 
    return doctest.DocTestSuite(*args, **kwargs)
938
 
 
939
 
 
940
793
class TestCase(testtools.TestCase):
941
794
    """Base class for bzr unit tests.
942
795
 
974
827
        super(TestCase, self).setUp()
975
828
        for feature in getattr(self, '_test_needs_features', []):
976
829
            self.requireFeature(feature)
 
830
        self._log_contents = None
 
831
        self.addDetail("log", content.Content(content.ContentType("text",
 
832
            "plain", {"charset": "utf8"}),
 
833
            lambda:[self._get_log(keep_log_file=True)]))
977
834
        self._cleanEnvironment()
978
835
        self._silenceUI()
979
836
        self._startLogFile()
983
840
        self._track_transports()
984
841
        self._track_locks()
985
842
        self._clear_debug_flags()
986
 
        # Isolate global verbosity level, to make sure it's reproducible
987
 
        # between tests.  We should get rid of this altogether: bug 656694. --
988
 
        # mbp 20101008
989
 
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
990
 
        # Isolate config option expansion until its default value for bzrlib is
991
 
        # settled on or a the FIXME associated with _get_expand_default_value
992
 
        # is addressed -- vila 20110219
993
 
        self.overrideAttr(config, '_expand_default_value', None)
994
 
        self._log_files = set()
995
 
        # Each key in the ``_counters`` dict holds a value for a different
996
 
        # counter. When the test ends, addDetail() should be used to output the
997
 
        # counter values. This happens in install_counter_hook().
998
 
        self._counters = {}
999
 
        if 'config_stats' in selftest_debug_flags:
1000
 
            self._install_config_stats_hooks()
1001
843
 
1002
844
    def debug(self):
1003
845
        # debug a frame up.
1020
862
        if name in details:
1021
863
            del details[name]
1022
864
 
1023
 
    def install_counter_hook(self, hooks, name, counter_name=None):
1024
 
        """Install a counting hook.
1025
 
 
1026
 
        Any hook can be counted as long as it doesn't need to return a value.
1027
 
 
1028
 
        :param hooks: Where the hook should be installed.
1029
 
 
1030
 
        :param name: The hook name that will be counted.
1031
 
 
1032
 
        :param counter_name: The counter identifier in ``_counters``, defaults
1033
 
            to ``name``.
1034
 
        """
1035
 
        _counters = self._counters # Avoid closing over self
1036
 
        if counter_name is None:
1037
 
            counter_name = name
1038
 
        if _counters.has_key(counter_name):
1039
 
            raise AssertionError('%s is already used as a counter name'
1040
 
                                  % (counter_name,))
1041
 
        _counters[counter_name] = 0
1042
 
        self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1043
 
            lambda: ['%d' % (_counters[counter_name],)]))
1044
 
        def increment_counter(*args, **kwargs):
1045
 
            _counters[counter_name] += 1
1046
 
        label = 'count %s calls' % (counter_name,)
1047
 
        hooks.install_named_hook(name, increment_counter, label)
1048
 
        self.addCleanup(hooks.uninstall_named_hook, name, label)
1049
 
 
1050
 
    def _install_config_stats_hooks(self):
1051
 
        """Install config hooks to count hook calls.
1052
 
 
1053
 
        """
1054
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1055
 
            self.install_counter_hook(config.ConfigHooks, hook_name,
1056
 
                                       'config.%s' % (hook_name,))
1057
 
 
1058
 
        # The OldConfigHooks are private and need special handling to protect
1059
 
        # against recursive tests (tests that run other tests), so we just do
1060
 
        # manually what registering them into _builtin_known_hooks will provide
1061
 
        # us.
1062
 
        self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1063
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1064
 
            self.install_counter_hook(config.OldConfigHooks, hook_name,
1065
 
                                      'old_config.%s' % (hook_name,))
1066
 
 
1067
865
    def _clear_debug_flags(self):
1068
866
        """Prevent externally set debug flags affecting tests.
1069
867
 
1079
877
 
1080
878
    def _clear_hooks(self):
1081
879
        # prevent hooks affecting tests
1082
 
        known_hooks = hooks.known_hooks
1083
880
        self._preserved_hooks = {}
1084
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1085
 
            current_hooks = getattr(parent, name)
 
881
        for key, factory in hooks.known_hooks.items():
 
882
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
883
            current_hooks = hooks.known_hooks_key_to_object(key)
1086
884
            self._preserved_hooks[parent] = (name, current_hooks)
1087
 
        self._preserved_lazy_hooks = hooks._lazy_hooks
1088
 
        hooks._lazy_hooks = {}
1089
885
        self.addCleanup(self._restoreHooks)
1090
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1091
 
            factory = known_hooks.get(key)
 
886
        for key, factory in hooks.known_hooks.items():
 
887
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
1092
888
            setattr(parent, name, factory())
1093
889
        # this hook should always be installed
1094
890
        request._install_hook()
1123
919
        # break some locks on purpose and should be taken into account by
1124
920
        # considering that breaking a lock is just a dirty way of releasing it.
1125
921
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1126
 
            message = (
1127
 
                'Different number of acquired and '
1128
 
                'released or broken locks.\n'
1129
 
                'acquired=%s\n'
1130
 
                'released=%s\n'
1131
 
                'broken=%s\n' %
1132
 
                (acquired_locks, released_locks, broken_locks))
 
922
            message = ('Different number of acquired and '
 
923
                       'released or broken locks. (%s, %s + %s)' %
 
924
                       (acquired_locks, released_locks, broken_locks))
1133
925
            if not self._lock_check_thorough:
1134
926
                # Rather than fail, just warn
1135
927
                print "Broken test %s: %s" % (self, message)
1310
1102
        except UnicodeError, e:
1311
1103
            # If we can't compare without getting a UnicodeError, then
1312
1104
            # obviously they are different
1313
 
            trace.mutter('UnicodeError: %s', e)
 
1105
            mutter('UnicodeError: %s', e)
1314
1106
        if message:
1315
1107
            message += '\n'
1316
1108
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
1355
1147
                         'st_mtime did not match')
1356
1148
        self.assertEqual(expected.st_ctime, actual.st_ctime,
1357
1149
                         'st_ctime did not match')
1358
 
        if sys.platform == 'win32':
 
1150
        if sys.platform != 'win32':
1359
1151
            # On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
1360
1152
            # is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
1361
 
            # odd. We just force it to always be 0 to avoid any problems.
1362
 
            self.assertEqual(0, expected.st_dev)
1363
 
            self.assertEqual(0, actual.st_dev)
1364
 
            self.assertEqual(0, expected.st_ino)
1365
 
            self.assertEqual(0, actual.st_ino)
1366
 
        else:
 
1153
            # odd. Regardless we shouldn't actually try to assert anything
 
1154
            # about their values
1367
1155
            self.assertEqual(expected.st_dev, actual.st_dev,
1368
1156
                             'st_dev did not match')
1369
1157
            self.assertEqual(expected.st_ino, actual.st_ino,
1378
1166
                length, len(obj_with_len), obj_with_len))
1379
1167
 
1380
1168
    def assertLogsError(self, exception_class, func, *args, **kwargs):
1381
 
        """Assert that `func(*args, **kwargs)` quietly logs a specific error.
 
1169
        """Assert that func(*args, **kwargs) quietly logs a specific exception.
1382
1170
        """
 
1171
        from bzrlib import trace
1383
1172
        captured = []
1384
1173
        orig_log_exception_quietly = trace.log_exception_quietly
1385
1174
        try:
1386
1175
            def capture():
1387
1176
                orig_log_exception_quietly()
1388
 
                captured.append(sys.exc_info()[1])
 
1177
                captured.append(sys.exc_info())
1389
1178
            trace.log_exception_quietly = capture
1390
1179
            func(*args, **kwargs)
1391
1180
        finally:
1392
1181
            trace.log_exception_quietly = orig_log_exception_quietly
1393
1182
        self.assertLength(1, captured)
1394
 
        err = captured[0]
 
1183
        err = captured[0][1]
1395
1184
        self.assertIsInstance(err, exception_class)
1396
1185
        return err
1397
1186
 
1434
1223
        if haystack.find(needle) == -1:
1435
1224
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
1436
1225
 
1437
 
    def assertNotContainsString(self, haystack, needle):
1438
 
        if haystack.find(needle) != -1:
1439
 
            self.fail("string %r found in '''%s'''" % (needle, haystack))
1440
 
 
1441
1226
    def assertSubset(self, sublist, superlist):
1442
1227
        """Assert that every entry in sublist is present in superlist."""
1443
1228
        missing = set(sublist) - set(superlist)
1532
1317
 
1533
1318
    def assertFileEqual(self, content, path):
1534
1319
        """Fail if path does not contain 'content'."""
1535
 
        self.assertPathExists(path)
 
1320
        self.failUnlessExists(path)
1536
1321
        f = file(path, 'rb')
1537
1322
        try:
1538
1323
            s = f.read()
1548
1333
        else:
1549
1334
            self.assertEqual(expected_docstring, obj.__doc__)
1550
1335
 
1551
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1552
1336
    def failUnlessExists(self, path):
1553
 
        return self.assertPathExists(path)
1554
 
 
1555
 
    def assertPathExists(self, path):
1556
1337
        """Fail unless path or paths, which may be abs or relative, exist."""
1557
1338
        if not isinstance(path, basestring):
1558
1339
            for p in path:
1559
 
                self.assertPathExists(p)
 
1340
                self.failUnlessExists(p)
1560
1341
        else:
1561
 
            self.assertTrue(osutils.lexists(path),
1562
 
                path + " does not exist")
 
1342
            self.failUnless(osutils.lexists(path),path+" does not exist")
1563
1343
 
1564
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1565
1344
    def failIfExists(self, path):
1566
 
        return self.assertPathDoesNotExist(path)
1567
 
 
1568
 
    def assertPathDoesNotExist(self, path):
1569
1345
        """Fail if path or paths, which may be abs or relative, exist."""
1570
1346
        if not isinstance(path, basestring):
1571
1347
            for p in path:
1572
 
                self.assertPathDoesNotExist(p)
 
1348
                self.failIfExists(p)
1573
1349
        else:
1574
 
            self.assertFalse(osutils.lexists(path),
1575
 
                path + " exists")
 
1350
            self.failIf(osutils.lexists(path),path+" exists")
1576
1351
 
1577
1352
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1578
1353
        """A helper for callDeprecated and applyDeprecated.
1604
1379
        not other callers that go direct to the warning module.
1605
1380
 
1606
1381
        To test that a deprecated method raises an error, do something like
1607
 
        this (remember that both assertRaises and applyDeprecated delays *args
1608
 
        and **kwargs passing)::
 
1382
        this::
1609
1383
 
1610
1384
            self.assertRaises(errors.ReservedId,
1611
1385
                self.applyDeprecated,
1693
1467
 
1694
1468
        The file is removed as the test is torn down.
1695
1469
        """
1696
 
        pseudo_log_file = StringIO()
1697
 
        def _get_log_contents_for_weird_testtools_api():
1698
 
            return [pseudo_log_file.getvalue().decode(
1699
 
                "utf-8", "replace").encode("utf-8")]
1700
 
        self.addDetail("log", content.Content(content.ContentType("text",
1701
 
            "plain", {"charset": "utf8"}),
1702
 
            _get_log_contents_for_weird_testtools_api))
1703
 
        self._log_file = pseudo_log_file
1704
 
        self._log_memento = trace.push_log_file(self._log_file)
 
1470
        self._log_file = StringIO()
 
1471
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1705
1472
        self.addCleanup(self._finishLogFile)
1706
1473
 
1707
1474
    def _finishLogFile(self):
1708
1475
        """Finished with the log file.
1709
1476
 
1710
 
        Close the file and delete it.
 
1477
        Close the file and delete it, unless setKeepLogfile was called.
1711
1478
        """
1712
 
        if trace._trace_file:
 
1479
        if bzrlib.trace._trace_file:
1713
1480
            # flush the log file, to get all content
1714
 
            trace._trace_file.flush()
1715
 
        trace.pop_log_file(self._log_memento)
 
1481
            bzrlib.trace._trace_file.flush()
 
1482
        bzrlib.trace.pop_log_file(self._log_memento)
 
1483
        # Cache the log result and delete the file on disk
 
1484
        self._get_log(False)
1716
1485
 
1717
1486
    def thisFailsStrictLockCheck(self):
1718
1487
        """It is known that this test would fail with -Dstrict_locks.
1746
1515
            setattr(obj, attr_name, new)
1747
1516
        return value
1748
1517
 
1749
 
    def overrideEnv(self, name, new):
1750
 
        """Set an environment variable, and reset it after the test.
1751
 
 
1752
 
        :param name: The environment variable name.
1753
 
 
1754
 
        :param new: The value to set the variable to. If None, the 
1755
 
            variable is deleted from the environment.
1756
 
 
1757
 
        :returns: The actual variable value.
1758
 
        """
1759
 
        value = osutils.set_or_unset_env(name, new)
1760
 
        self.addCleanup(osutils.set_or_unset_env, name, value)
1761
 
        return value
1762
 
 
1763
1518
    def _cleanEnvironment(self):
1764
 
        for name, value in isolated_environ.iteritems():
1765
 
            self.overrideEnv(name, value)
 
1519
        new_env = {
 
1520
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
 
1521
            'HOME': os.getcwd(),
 
1522
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
1523
            # tests do check our impls match APPDATA
 
1524
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
1525
            'VISUAL': None,
 
1526
            'EDITOR': None,
 
1527
            'BZR_EMAIL': None,
 
1528
            'BZREMAIL': None, # may still be present in the environment
 
1529
            'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
 
1530
            'BZR_PROGRESS_BAR': None,
 
1531
            'BZR_LOG': None,
 
1532
            'BZR_PLUGIN_PATH': None,
 
1533
            'BZR_DISABLE_PLUGINS': None,
 
1534
            'BZR_PLUGINS_AT': None,
 
1535
            'BZR_CONCURRENCY': None,
 
1536
            # Make sure that any text ui tests are consistent regardless of
 
1537
            # the environment the test case is run in; you may want tests that
 
1538
            # test other combinations.  'dumb' is a reasonable guess for tests
 
1539
            # going to a pipe or a StringIO.
 
1540
            'TERM': 'dumb',
 
1541
            'LINES': '25',
 
1542
            'COLUMNS': '80',
 
1543
            'BZR_COLUMNS': '80',
 
1544
            # SSH Agent
 
1545
            'SSH_AUTH_SOCK': None,
 
1546
            # Proxies
 
1547
            'http_proxy': None,
 
1548
            'HTTP_PROXY': None,
 
1549
            'https_proxy': None,
 
1550
            'HTTPS_PROXY': None,
 
1551
            'no_proxy': None,
 
1552
            'NO_PROXY': None,
 
1553
            'all_proxy': None,
 
1554
            'ALL_PROXY': None,
 
1555
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
1556
            # least. If you do (care), please update this comment
 
1557
            # -- vila 20080401
 
1558
            'ftp_proxy': None,
 
1559
            'FTP_PROXY': None,
 
1560
            'BZR_REMOTE_PATH': None,
 
1561
            # Generally speaking, we don't want apport reporting on crashes in
 
1562
            # the test envirnoment unless we're specifically testing apport,
 
1563
            # so that it doesn't leak into the real system environment.  We
 
1564
            # use an env var so it propagates to subprocesses.
 
1565
            'APPORT_DISABLE': '1',
 
1566
        }
 
1567
        self._old_env = {}
 
1568
        self.addCleanup(self._restoreEnvironment)
 
1569
        for name, value in new_env.iteritems():
 
1570
            self._captureVar(name, value)
 
1571
 
 
1572
    def _captureVar(self, name, newvalue):
 
1573
        """Set an environment variable, and reset it when finished."""
 
1574
        self._old_env[name] = osutils.set_or_unset_env(name, newvalue)
 
1575
 
 
1576
    def _restoreEnvironment(self):
 
1577
        for name, value in self._old_env.iteritems():
 
1578
            osutils.set_or_unset_env(name, value)
1766
1579
 
1767
1580
    def _restoreHooks(self):
1768
1581
        for klass, (name, hooks) in self._preserved_hooks.items():
1769
1582
            setattr(klass, name, hooks)
1770
 
        self._preserved_hooks.clear()
1771
 
        bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1772
 
        self._preserved_lazy_hooks.clear()
1773
1583
 
1774
1584
    def knownFailure(self, reason):
1775
1585
        """This test has failed for some known reason."""
1865
1675
            self._benchtime += time.time() - start
1866
1676
 
1867
1677
    def log(self, *args):
1868
 
        trace.mutter(*args)
 
1678
        mutter(*args)
 
1679
 
 
1680
    def _get_log(self, keep_log_file=False):
 
1681
        """Internal helper to get the log from bzrlib.trace for this test.
 
1682
 
 
1683
        Please use self.getDetails, or self.get_log to access this in test case
 
1684
        code.
 
1685
 
 
1686
        :param keep_log_file: When True, if the log is still a file on disk
 
1687
            leave it as a file on disk. When False, if the log is still a file
 
1688
            on disk, the log file is deleted and the log preserved as
 
1689
            self._log_contents.
 
1690
        :return: A string containing the log.
 
1691
        """
 
1692
        if self._log_contents is not None:
 
1693
            try:
 
1694
                self._log_contents.decode('utf8')
 
1695
            except UnicodeDecodeError:
 
1696
                unicodestr = self._log_contents.decode('utf8', 'replace')
 
1697
                self._log_contents = unicodestr.encode('utf8')
 
1698
            return self._log_contents
 
1699
        if self._log_file is not None:
 
1700
            log_contents = self._log_file.getvalue()
 
1701
            try:
 
1702
                log_contents.decode('utf8')
 
1703
            except UnicodeDecodeError:
 
1704
                unicodestr = log_contents.decode('utf8', 'replace')
 
1705
                log_contents = unicodestr.encode('utf8')
 
1706
            if not keep_log_file:
 
1707
                self._log_file = None
 
1708
                # Permit multiple calls to get_log until we clean it up in
 
1709
                # finishLogFile
 
1710
                self._log_contents = log_contents
 
1711
            return log_contents
 
1712
        else:
 
1713
            return "No log file content."
1869
1714
 
1870
1715
    def get_log(self):
1871
1716
        """Get a unicode string containing the log from bzrlib.trace.
1921
1766
 
1922
1767
        try:
1923
1768
            try:
1924
 
                result = self.apply_redirected(
1925
 
                    ui.ui_factory.stdin,
 
1769
                result = self.apply_redirected(ui.ui_factory.stdin,
1926
1770
                    stdout, stderr,
1927
 
                    _mod_commands.run_bzr_catch_user_errors,
 
1771
                    bzrlib.commands.run_bzr_catch_user_errors,
1928
1772
                    args)
1929
1773
            except KeyboardInterrupt:
1930
1774
                # Reraise KeyboardInterrupt with contents of redirected stdout
2072
1916
    def start_bzr_subprocess(self, process_args, env_changes=None,
2073
1917
                             skip_if_plan_to_signal=False,
2074
1918
                             working_dir=None,
2075
 
                             allow_plugins=False, stderr=subprocess.PIPE):
 
1919
                             allow_plugins=False):
2076
1920
        """Start bzr in a subprocess for testing.
2077
1921
 
2078
1922
        This starts a new Python interpreter and runs bzr in there.
2090
1934
        :param skip_if_plan_to_signal: raise TestSkipped when true and system
2091
1935
            doesn't support signalling subprocesses.
2092
1936
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
2093
 
        :param stderr: file to use for the subprocess's stderr.  Valid values
2094
 
            are those valid for the stderr argument of `subprocess.Popen`.
2095
 
            Default value is ``subprocess.PIPE``.
2096
1937
 
2097
1938
        :returns: Popen object for the started process.
2098
1939
        """
2124
1965
            # so we will avoid using it on all platforms, just to
2125
1966
            # make sure the code path is used, and we don't break on win32
2126
1967
            cleanup_environment()
2127
 
            # Include the subprocess's log file in the test details, in case
2128
 
            # the test fails due to an error in the subprocess.
2129
 
            self._add_subprocess_log(trace._get_bzr_log_filename())
2130
1968
            command = [sys.executable]
2131
1969
            # frozen executables don't need the path to bzr
2132
1970
            if getattr(sys, "frozen", None) is None:
2136
1974
            command.extend(process_args)
2137
1975
            process = self._popen(command, stdin=subprocess.PIPE,
2138
1976
                                  stdout=subprocess.PIPE,
2139
 
                                  stderr=stderr)
 
1977
                                  stderr=subprocess.PIPE)
2140
1978
        finally:
2141
1979
            restore_environment()
2142
1980
            if cwd is not None:
2144
1982
 
2145
1983
        return process
2146
1984
 
2147
 
    def _add_subprocess_log(self, log_file_path):
2148
 
        if len(self._log_files) == 0:
2149
 
            # Register an addCleanup func.  We do this on the first call to
2150
 
            # _add_subprocess_log rather than in TestCase.setUp so that this
2151
 
            # addCleanup is registered after any cleanups for tempdirs that
2152
 
            # subclasses might create, which will probably remove the log file
2153
 
            # we want to read.
2154
 
            self.addCleanup(self._subprocess_log_cleanup)
2155
 
        # self._log_files is a set, so if a log file is reused we won't grab it
2156
 
        # twice.
2157
 
        self._log_files.add(log_file_path)
2158
 
 
2159
 
    def _subprocess_log_cleanup(self):
2160
 
        for count, log_file_path in enumerate(self._log_files):
2161
 
            # We use buffer_now=True to avoid holding the file open beyond
2162
 
            # the life of this function, which might interfere with e.g.
2163
 
            # cleaning tempdirs on Windows.
2164
 
            # XXX: Testtools 0.9.5 doesn't have the content_from_file helper
2165
 
            #detail_content = content.content_from_file(
2166
 
            #    log_file_path, buffer_now=True)
2167
 
            with open(log_file_path, 'rb') as log_file:
2168
 
                log_file_bytes = log_file.read()
2169
 
            detail_content = content.Content(content.ContentType("text",
2170
 
                "plain", {"charset": "utf8"}), lambda: [log_file_bytes])
2171
 
            self.addDetail("start_bzr_subprocess-log-%d" % (count,),
2172
 
                detail_content)
2173
 
 
2174
1985
    def _popen(self, *args, **kwargs):
2175
1986
        """Place a call to Popen.
2176
1987
 
2213
2024
        if retcode is not None and retcode != process.returncode:
2214
2025
            if process_args is None:
2215
2026
                process_args = "(unknown args)"
2216
 
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
2217
 
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
 
2027
            mutter('Output of bzr %s:\n%s', process_args, out)
 
2028
            mutter('Error for bzr %s:\n%s', process_args, err)
2218
2029
            self.fail('Command bzr %s failed with retcode %s != %s'
2219
2030
                      % (process_args, retcode, process.returncode))
2220
2031
        return [out, err]
2221
2032
 
2222
 
    def check_tree_shape(self, tree, shape):
2223
 
        """Compare a tree to a list of expected names.
 
2033
    def check_inventory_shape(self, inv, shape):
 
2034
        """Compare an inventory to a list of expected names.
2224
2035
 
2225
2036
        Fail if they are not precisely equal.
2226
2037
        """
2227
2038
        extras = []
2228
2039
        shape = list(shape)             # copy
2229
 
        for path, ie in tree.iter_entries_by_dir():
 
2040
        for path, ie in inv.entries():
2230
2041
            name = path.replace('\\', '/')
2231
2042
            if ie.kind == 'directory':
2232
2043
                name = name + '/'
2233
 
            if name == "/":
2234
 
                pass # ignore root entry
2235
 
            elif name in shape:
 
2044
            if name in shape:
2236
2045
                shape.remove(name)
2237
2046
            else:
2238
2047
                extras.append(name)
2279
2088
 
2280
2089
        Tests that expect to provoke LockContention errors should call this.
2281
2090
        """
2282
 
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
2091
        self.overrideAttr(bzrlib.lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
2283
2092
 
2284
2093
    def make_utf8_encoded_stringio(self, encoding_type=None):
2285
2094
        """Return a StringIOWrapper instance, that will encode Unicode
2328
2137
class TestCaseWithMemoryTransport(TestCase):
2329
2138
    """Common test class for tests that do not need disk resources.
2330
2139
 
2331
 
    Tests that need disk resources should derive from TestCaseInTempDir
2332
 
    orTestCaseWithTransport.
 
2140
    Tests that need disk resources should derive from TestCaseWithTransport.
2333
2141
 
2334
2142
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
2335
2143
 
2336
 
    For TestCaseWithMemoryTransport the ``test_home_dir`` is set to the name of
 
2144
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
2337
2145
    a directory which does not exist. This serves to help ensure test isolation
2338
 
    is preserved. ``test_dir`` is set to the TEST_ROOT, as is cwd, because they
2339
 
    must exist. However, TestCaseWithMemoryTransport does not offer local file
2340
 
    defaults for the transport in tests, nor does it obey the command line
 
2146
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
2147
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
2148
    file defaults for the transport in tests, nor does it obey the command line
2341
2149
    override, so tests that accidentally write to the common directory should
2342
2150
    be rare.
2343
2151
 
2344
 
    :cvar TEST_ROOT: Directory containing all temporary directories, plus a
2345
 
        ``.bzr`` directory that stops us ascending higher into the filesystem.
 
2152
    :cvar TEST_ROOT: Directory containing all temporary directories, plus
 
2153
    a .bzr directory that stops us ascending higher into the filesystem.
2346
2154
    """
2347
2155
 
2348
2156
    TEST_ROOT = None
2610
2418
        test_home_dir = self.test_home_dir
2611
2419
        if isinstance(test_home_dir, unicode):
2612
2420
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2613
 
        self.overrideEnv('HOME', test_home_dir)
2614
 
        self.overrideEnv('BZR_HOME', test_home_dir)
 
2421
        os.environ['HOME'] = test_home_dir
 
2422
        os.environ['BZR_HOME'] = test_home_dir
2615
2423
 
2616
2424
    def setUp(self):
2617
2425
        super(TestCaseWithMemoryTransport, self).setUp()
2672
2480
 
2673
2481
    OVERRIDE_PYTHON = 'python'
2674
2482
 
2675
 
    def setUp(self):
2676
 
        super(TestCaseInTempDir, self).setUp()
2677
 
        # Remove the protection set in isolated_environ, we have a proper
2678
 
        # access to disk resources now.
2679
 
        self.overrideEnv('BZR_LOG', None)
2680
 
 
2681
2483
    def check_file_contents(self, filename, expect):
2682
2484
        self.log("check contents of file %s" % filename)
2683
2485
        f = file(filename)
3529
3331
    return result
3530
3332
 
3531
3333
 
3532
 
class ProfileResult(testtools.ExtendedToOriginalDecorator):
 
3334
class ForwardingResult(unittest.TestResult):
 
3335
 
 
3336
    def __init__(self, target):
 
3337
        unittest.TestResult.__init__(self)
 
3338
        self.result = target
 
3339
 
 
3340
    def startTest(self, test):
 
3341
        self.result.startTest(test)
 
3342
 
 
3343
    def stopTest(self, test):
 
3344
        self.result.stopTest(test)
 
3345
 
 
3346
    def startTestRun(self):
 
3347
        self.result.startTestRun()
 
3348
 
 
3349
    def stopTestRun(self):
 
3350
        self.result.stopTestRun()
 
3351
 
 
3352
    def addSkip(self, test, reason):
 
3353
        self.result.addSkip(test, reason)
 
3354
 
 
3355
    def addSuccess(self, test):
 
3356
        self.result.addSuccess(test)
 
3357
 
 
3358
    def addError(self, test, err):
 
3359
        self.result.addError(test, err)
 
3360
 
 
3361
    def addFailure(self, test, err):
 
3362
        self.result.addFailure(test, err)
 
3363
ForwardingResult = testtools.ExtendedToOriginalDecorator
 
3364
 
 
3365
 
 
3366
class ProfileResult(ForwardingResult):
3533
3367
    """Generate profiling data for all activity between start and success.
3534
3368
    
3535
3369
    The profile data is appended to the test's _benchcalls attribute and can
3547
3381
        # unavoidably fail.
3548
3382
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
3549
3383
        self.profiler.start()
3550
 
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
 
3384
        ForwardingResult.startTest(self, test)
3551
3385
 
3552
3386
    def addSuccess(self, test):
3553
3387
        stats = self.profiler.stop()
3557
3391
            test._benchcalls = []
3558
3392
            calls = test._benchcalls
3559
3393
        calls.append(((test.id(), "", ""), stats))
3560
 
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
 
3394
        ForwardingResult.addSuccess(self, test)
3561
3395
 
3562
3396
    def stopTest(self, test):
3563
 
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
 
3397
        ForwardingResult.stopTest(self, test)
3564
3398
        self.profiler = None
3565
3399
 
3566
3400
 
3574
3408
#                           with proper exclusion rules.
3575
3409
#   -Ethreads               Will display thread ident at creation/join time to
3576
3410
#                           help track thread leaks
3577
 
 
3578
 
#   -Econfig_stats          Will collect statistics using addDetail
3579
3411
selftest_debug_flags = set()
3580
3412
 
3581
3413
 
3775
3607
                key, obj, help=help, info=info, override_existing=False)
3776
3608
        except KeyError:
3777
3609
            actual = self.get(key)
3778
 
            trace.note(
3779
 
                'Test prefix alias %s is already used for %s, ignoring %s'
3780
 
                % (key, actual, obj))
 
3610
            note('Test prefix alias %s is already used for %s, ignoring %s'
 
3611
                 % (key, actual, obj))
3781
3612
 
3782
3613
    def resolve_alias(self, id_start):
3783
3614
        """Replace the alias by the prefix in the given string.
3833
3664
        'bzrlib.tests.per_repository',
3834
3665
        'bzrlib.tests.per_repository_chk',
3835
3666
        'bzrlib.tests.per_repository_reference',
3836
 
        'bzrlib.tests.per_repository_vf',
3837
3667
        'bzrlib.tests.per_uifactory',
3838
3668
        'bzrlib.tests.per_versionedfile',
3839
3669
        'bzrlib.tests.per_workingtree',
3873
3703
        'bzrlib.tests.test_commit_merge',
3874
3704
        'bzrlib.tests.test_config',
3875
3705
        'bzrlib.tests.test_conflicts',
3876
 
        'bzrlib.tests.test_controldir',
3877
3706
        'bzrlib.tests.test_counted_lock',
3878
3707
        'bzrlib.tests.test_crash',
3879
3708
        'bzrlib.tests.test_decorators',
3880
3709
        'bzrlib.tests.test_delta',
3881
3710
        'bzrlib.tests.test_debug',
 
3711
        'bzrlib.tests.test_deprecated_graph',
3882
3712
        'bzrlib.tests.test_diff',
3883
3713
        'bzrlib.tests.test_directory_service',
3884
3714
        'bzrlib.tests.test_dirstate',
3886
3716
        'bzrlib.tests.test_eol_filters',
3887
3717
        'bzrlib.tests.test_errors',
3888
3718
        'bzrlib.tests.test_export',
3889
 
        'bzrlib.tests.test_export_pot',
3890
3719
        'bzrlib.tests.test_extract',
3891
3720
        'bzrlib.tests.test_fetch',
3892
3721
        'bzrlib.tests.test_fixtures',
3906
3735
        'bzrlib.tests.test_http',
3907
3736
        'bzrlib.tests.test_http_response',
3908
3737
        'bzrlib.tests.test_https_ca_bundle',
3909
 
        'bzrlib.tests.test_i18n',
3910
3738
        'bzrlib.tests.test_identitymap',
3911
3739
        'bzrlib.tests.test_ignores',
3912
3740
        'bzrlib.tests.test_index',
3931
3759
        'bzrlib.tests.test_merge3',
3932
3760
        'bzrlib.tests.test_merge_core',
3933
3761
        'bzrlib.tests.test_merge_directive',
3934
 
        'bzrlib.tests.test_mergetools',
3935
3762
        'bzrlib.tests.test_missing',
3936
3763
        'bzrlib.tests.test_msgeditor',
3937
3764
        'bzrlib.tests.test_multiparent',
3946
3773
        'bzrlib.tests.test_permissions',
3947
3774
        'bzrlib.tests.test_plugins',
3948
3775
        'bzrlib.tests.test_progress',
3949
 
        'bzrlib.tests.test_pyutils',
3950
3776
        'bzrlib.tests.test_read_bundle',
3951
3777
        'bzrlib.tests.test_reconcile',
3952
3778
        'bzrlib.tests.test_reconfigure',
3961
3787
        'bzrlib.tests.test_rio',
3962
3788
        'bzrlib.tests.test_rules',
3963
3789
        'bzrlib.tests.test_sampler',
3964
 
        'bzrlib.tests.test_scenarios',
3965
3790
        'bzrlib.tests.test_script',
3966
3791
        'bzrlib.tests.test_selftest',
3967
3792
        'bzrlib.tests.test_serializer',
3987
3812
        'bzrlib.tests.test_testament',
3988
3813
        'bzrlib.tests.test_textfile',
3989
3814
        'bzrlib.tests.test_textmerge',
3990
 
        'bzrlib.tests.test_cethread',
3991
3815
        'bzrlib.tests.test_timestamp',
3992
3816
        'bzrlib.tests.test_trace',
3993
3817
        'bzrlib.tests.test_transactions',
4004
3828
        'bzrlib.tests.test_upgrade',
4005
3829
        'bzrlib.tests.test_upgrade_stacked',
4006
3830
        'bzrlib.tests.test_urlutils',
4007
 
        'bzrlib.tests.test_utextwrap',
4008
3831
        'bzrlib.tests.test_version',
4009
3832
        'bzrlib.tests.test_version_info',
4010
3833
        'bzrlib.tests.test_versionedfile',
4027
3850
        'bzrlib',
4028
3851
        'bzrlib.branchbuilder',
4029
3852
        'bzrlib.decorators',
 
3853
        'bzrlib.export',
4030
3854
        'bzrlib.inventory',
4031
3855
        'bzrlib.iterablefile',
4032
3856
        'bzrlib.lockdir',
4033
3857
        'bzrlib.merge3',
4034
3858
        'bzrlib.option',
4035
 
        'bzrlib.pyutils',
4036
3859
        'bzrlib.symbol_versioning',
4037
3860
        'bzrlib.tests',
4038
3861
        'bzrlib.tests.fixtures',
4039
3862
        'bzrlib.timestamp',
4040
 
        'bzrlib.transport.http',
4041
3863
        'bzrlib.version_info_formats.format_custom',
4042
3864
        ]
4043
3865
 
4096
3918
        try:
4097
3919
            # note that this really does mean "report only" -- doctest
4098
3920
            # still runs the rest of the examples
4099
 
            doc_suite = IsolatedDocTestSuite(
4100
 
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
3921
            doc_suite = doctest.DocTestSuite(mod,
 
3922
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
4101
3923
        except ValueError, e:
4102
3924
            print '**failed to get doctest for: %s\n%s' % (mod, e)
4103
3925
            raise
4106
3928
        suite.addTest(doc_suite)
4107
3929
 
4108
3930
    default_encoding = sys.getdefaultencoding()
4109
 
    for name, plugin in _mod_plugin.plugins().items():
 
3931
    for name, plugin in bzrlib.plugin.plugins().items():
4110
3932
        if not interesting_module(plugin.module.__name__):
4111
3933
            continue
4112
3934
        plugin_suite = plugin.test_suite()
4118
3940
        if plugin_suite is not None:
4119
3941
            suite.addTest(plugin_suite)
4120
3942
        if default_encoding != sys.getdefaultencoding():
4121
 
            trace.warning(
 
3943
            bzrlib.trace.warning(
4122
3944
                'Plugin "%s" tried to reset default encoding to: %s', name,
4123
3945
                sys.getdefaultencoding())
4124
3946
            reload(sys)
4139
3961
            # Some tests mentioned in the list are not in the test suite. The
4140
3962
            # list may be out of date, report to the tester.
4141
3963
            for id in not_found:
4142
 
                trace.warning('"%s" not found in the test suite', id)
 
3964
                bzrlib.trace.warning('"%s" not found in the test suite', id)
4143
3965
        for id in duplicates:
4144
 
            trace.warning('"%s" is used as an id by several tests', id)
 
3966
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
4145
3967
 
4146
3968
    return suite
4147
3969
 
4148
3970
 
4149
 
def multiply_scenarios(*scenarios):
4150
 
    """Multiply two or more iterables of scenarios.
4151
 
 
4152
 
    It is safe to pass scenario generators or iterators.
4153
 
 
4154
 
    :returns: A list of compound scenarios: the cross-product of all 
4155
 
        scenarios, with the names concatenated and the parameters
4156
 
        merged together.
4157
 
    """
4158
 
    return reduce(_multiply_two_scenarios, map(list, scenarios))
4159
 
 
4160
 
 
4161
 
def _multiply_two_scenarios(scenarios_left, scenarios_right):
 
3971
def multiply_scenarios(scenarios_left, scenarios_right):
4162
3972
    """Multiply two sets of scenarios.
4163
3973
 
4164
3974
    :returns: the cartesian product of the two sets of scenarios, that is
4288
4098
        the module is available.
4289
4099
    """
4290
4100
 
4291
 
    py_module = pyutils.get_named_object(py_module_name)
 
4101
    py_module = __import__(py_module_name, {}, {}, ['NO_SUCH_ATTRIB'])
4292
4102
    scenarios = [
4293
4103
        ('python', {'module': py_module}),
4294
4104
    ]
4447
4257
            symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
4448
4258
            # Import the new feature and use it as a replacement for the
4449
4259
            # deprecated one.
4450
 
            self._feature = pyutils.get_named_object(
4451
 
                self._replacement_module, self._replacement_name)
 
4260
            mod = __import__(self._replacement_module, {}, {},
 
4261
                             [self._replacement_name])
 
4262
            self._feature = getattr(mod, self._replacement_name)
4452
4263
 
4453
4264
    def _probe(self):
4454
4265
        self._ensure()
4485
4296
        return self.module_name
4486
4297
 
4487
4298
 
 
4299
# This is kept here for compatibility, it is recommended to use
 
4300
# 'bzrlib.tests.feature.paramiko' instead
 
4301
ParamikoFeature = _CompatabilityThunkFeature(
 
4302
    deprecated_in((2,1,0)),
 
4303
    'bzrlib.tests.features', 'ParamikoFeature', 'paramiko')
 
4304
 
 
4305
 
4488
4306
def probe_unicode_in_user_encoding():
4489
4307
    """Try to encode several unicode strings to use in unicode-aware tests.
4490
4308
    Return first successfull match.
4677
4495
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
4678
4496
 
4679
4497
 
 
4498
# Kept for compatibility, use bzrlib.tests.features.subunit instead
 
4499
SubUnitFeature = _CompatabilityThunkFeature(
 
4500
    deprecated_in((2,1,0)),
 
4501
    'bzrlib.tests.features', 'SubUnitFeature', 'subunit')
4680
4502
# Only define SubUnitBzrRunner if subunit is available.
4681
4503
try:
4682
4504
    from subunit import TestProtocolClient