~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Andrew Bennetts
  • Date: 2010-09-24 02:19:53 UTC
  • mto: This revision was merged to the branch mainline in revision 5443.
  • Revision ID: andrew.bennetts@canonical.com-20100924021953-0cg1kjtifuvkbyzp
Fix typo in test method name.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
    'BZR_LOG': None,
146
 
    'BZR_PLUGIN_PATH': None,
147
 
    'BZR_DISABLE_PLUGINS': None,
148
 
    'BZR_PLUGINS_AT': None,
149
 
    'BZR_CONCURRENCY': None,
150
 
    # Make sure that any text ui tests are consistent regardless of
151
 
    # the environment the test case is run in; you may want tests that
152
 
    # test other combinations.  'dumb' is a reasonable guess for tests
153
 
    # going to a pipe or a StringIO.
154
 
    'TERM': 'dumb',
155
 
    'LINES': '25',
156
 
    'COLUMNS': '80',
157
 
    'BZR_COLUMNS': '80',
158
 
    # Disable SSH Agent
159
 
    'SSH_AUTH_SOCK': None,
160
 
    # Proxies
161
 
    'http_proxy': None,
162
 
    'HTTP_PROXY': None,
163
 
    'https_proxy': None,
164
 
    'HTTPS_PROXY': None,
165
 
    'no_proxy': None,
166
 
    'NO_PROXY': None,
167
 
    'all_proxy': None,
168
 
    'ALL_PROXY': None,
169
 
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
170
 
    # least. If you do (care), please update this comment
171
 
    # -- vila 20080401
172
 
    'ftp_proxy': None,
173
 
    'FTP_PROXY': None,
174
 
    'BZR_REMOTE_PATH': None,
175
 
    # Generally speaking, we don't want apport reporting on crashes in
176
 
    # the test envirnoment unless we're specifically testing apport,
177
 
    # so that it doesn't leak into the real system environment.  We
178
 
    # use an env var so it propagates to subprocesses.
179
 
    'APPORT_DISABLE': '1',
180
 
    }
181
 
 
182
 
 
183
 
def override_os_environ(test, env=None):
184
 
    """Modify os.environ keeping a copy.
185
 
    
186
 
    :param test: A test instance
187
 
 
188
 
    :param env: A dict containing variable definitions to be installed
189
 
    """
190
 
    if env is None:
191
 
        env = isolated_environ
192
 
    test._original_os_environ = dict([(var, value)
193
 
                                      for var, value in os.environ.iteritems()])
194
 
    for var, value in env.iteritems():
195
 
        osutils.set_or_unset_env(var, value)
196
 
        if var not in test._original_os_environ:
197
 
            # The var is new, add it with a value of None, so
198
 
            # restore_os_environ will delete it
199
 
            test._original_os_environ[var] = None
200
 
 
201
 
 
202
 
def restore_os_environ(test):
203
 
    """Restore os.environ to its original state.
204
 
 
205
 
    :param test: A test instance previously passed to override_os_environ.
206
 
    """
207
 
    for var, value in test._original_os_environ.iteritems():
208
 
        # Restore the original value (or delete it if the value has been set to
209
 
        # None in override_os_environ).
210
 
        osutils.set_or_unset_env(var, value)
211
 
 
212
 
 
213
142
class ExtendedTestResult(testtools.TextTestResult):
214
143
    """Accepts, reports and accumulates the results of running tests.
215
144
 
266
195
        self._strict = strict
267
196
        self._first_thread_leaker_id = None
268
197
        self._tests_leaking_threads_count = 0
269
 
        self._traceback_from_test = None
270
198
 
271
199
    def stopTestRun(self):
272
200
        run = self.testsRun
332
260
 
333
261
    def _elapsedTestTimeString(self):
334
262
        """Return a time string for the overall time the current test has taken."""
335
 
        return self._formatTime(self._delta_to_float(
336
 
            self._now() - self._start_datetime))
 
263
        return self._formatTime(time.time() - self._start_time)
337
264
 
338
265
    def _testTimeString(self, testCase):
339
266
        benchmark_time = self._extractBenchmarkTime(testCase)
353
280
        what = re.sub(r'^bzrlib\.tests\.', '', what)
354
281
        return what
355
282
 
356
 
    # GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
357
 
    #                multiple times in a row, because the handler is added for
358
 
    #                each test but the container list is shared between cases.
359
 
    #                See lp:498869 lp:625574 and lp:637725 for background.
360
 
    def _record_traceback_from_test(self, exc_info):
361
 
        """Store the traceback from passed exc_info tuple till"""
362
 
        self._traceback_from_test = exc_info[2]
363
 
 
364
283
    def startTest(self, test):
365
284
        super(ExtendedTestResult, self).startTest(test)
366
285
        if self.count == 0:
369
288
        self.report_test_start(test)
370
289
        test.number = self.count
371
290
        self._recordTestStartTime()
372
 
        # Make testtools cases give us the real traceback on failure
373
 
        addOnException = getattr(test, "addOnException", None)
374
 
        if addOnException is not None:
375
 
            addOnException(self._record_traceback_from_test)
376
 
        # Only check for thread leaks on bzrlib derived test cases
377
 
        if isinstance(test, TestCase):
378
 
            test.addCleanup(self._check_leaked_threads, test)
 
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)
379
295
 
380
296
    def startTests(self):
381
297
        self.report_tests_starting()
382
298
        self._active_threads = threading.enumerate()
383
299
 
384
 
    def stopTest(self, test):
385
 
        self._traceback_from_test = None
386
 
 
387
300
    def _check_leaked_threads(self, test):
388
301
        """See if any threads have leaked since last call
389
302
 
402
315
 
403
316
    def _recordTestStartTime(self):
404
317
        """Record that a test has started."""
405
 
        self._start_datetime = self._now()
 
318
        self._start_time = time.time()
406
319
 
407
320
    def addError(self, test, err):
408
321
        """Tell result that test finished with an error.
410
323
        Called from the TestCase run() method when the test
411
324
        fails with an unexpected error.
412
325
        """
413
 
        self._post_mortem(self._traceback_from_test)
 
326
        self._post_mortem()
414
327
        super(ExtendedTestResult, self).addError(test, err)
415
328
        self.error_count += 1
416
329
        self.report_error(test, err)
423
336
        Called from the TestCase run() method when the test
424
337
        fails because e.g. an assert() method failed.
425
338
        """
426
 
        self._post_mortem(self._traceback_from_test)
 
339
        self._post_mortem()
427
340
        super(ExtendedTestResult, self).addFailure(test, err)
428
341
        self.failure_count += 1
429
342
        self.report_failure(test, err)
471
384
        self.not_applicable_count += 1
472
385
        self.report_not_applicable(test, reason)
473
386
 
474
 
    def _post_mortem(self, tb=None):
 
387
    def _post_mortem(self):
475
388
        """Start a PDB post mortem session."""
476
389
        if os.environ.get('BZR_TEST_PDB', None):
477
 
            import pdb
478
 
            pdb.post_mortem(tb)
 
390
            import pdb;pdb.post_mortem()
479
391
 
480
392
    def progress(self, offset, whence):
481
393
        """The test is adjusting the count of tests to run."""
722
634
            encode = codec[0]
723
635
        else:
724
636
            encode = codec.encode
725
 
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
726
 
        #                so should swap to the plain codecs.StreamWriter
727
 
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
728
 
            "backslashreplace")
 
637
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream)
729
638
        stream.encoding = new_encoding
730
639
        self.stream = stream
731
640
        self.descriptions = descriptions
881
790
        return NullProgressView()
882
791
 
883
792
 
884
 
def isolated_doctest_setUp(test):
885
 
    override_os_environ(test)
886
 
 
887
 
 
888
 
def isolated_doctest_tearDown(test):
889
 
    restore_os_environ(test)
890
 
 
891
 
 
892
 
def IsolatedDocTestSuite(*args, **kwargs):
893
 
    """Overrides doctest.DocTestSuite to handle isolation.
894
 
 
895
 
    The method is really a factory and users are expected to use it as such.
896
 
    """
897
 
    
898
 
    kwargs['setUp'] = isolated_doctest_setUp
899
 
    kwargs['tearDown'] = isolated_doctest_tearDown
900
 
    return doctest.DocTestSuite(*args, **kwargs)
901
 
 
902
 
 
903
793
class TestCase(testtools.TestCase):
904
794
    """Base class for bzr unit tests.
905
795
 
950
840
        self._track_transports()
951
841
        self._track_locks()
952
842
        self._clear_debug_flags()
953
 
        # Isolate global verbosity level, to make sure it's reproducible
954
 
        # between tests.  We should get rid of this altogether: bug 656694. --
955
 
        # mbp 20101008
956
 
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
957
843
 
958
844
    def debug(self):
959
845
        # debug a frame up.
960
846
        import pdb
961
847
        pdb.Pdb().set_trace(sys._getframe().f_back)
962
848
 
963
 
    def discardDetail(self, name):
964
 
        """Extend the addDetail, getDetails api so we can remove a detail.
965
 
 
966
 
        eg. bzr always adds the 'log' detail at startup, but we don't want to
967
 
        include it for skipped, xfail, etc tests.
968
 
 
969
 
        It is safe to call this for a detail that doesn't exist, in case this
970
 
        gets called multiple times.
971
 
        """
972
 
        # We cheat. details is stored in __details which means we shouldn't
973
 
        # touch it. but getDetails() returns the dict directly, so we can
974
 
        # mutate it.
975
 
        details = self.getDetails()
976
 
        if name in details:
977
 
            del details[name]
978
 
 
979
849
    def _clear_debug_flags(self):
980
850
        """Prevent externally set debug flags affecting tests.
981
851
 
991
861
 
992
862
    def _clear_hooks(self):
993
863
        # prevent hooks affecting tests
994
 
        known_hooks = hooks.known_hooks
995
864
        self._preserved_hooks = {}
996
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
997
 
            current_hooks = getattr(parent, name)
 
865
        for key, factory in hooks.known_hooks.items():
 
866
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
867
            current_hooks = hooks.known_hooks_key_to_object(key)
998
868
            self._preserved_hooks[parent] = (name, current_hooks)
999
869
        self.addCleanup(self._restoreHooks)
1000
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1001
 
            factory = known_hooks.get(key)
 
870
        for key, factory in hooks.known_hooks.items():
 
871
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
1002
872
            setattr(parent, name, factory())
1003
873
        # this hook should always be installed
1004
874
        request._install_hook()
1098
968
            try:
1099
969
                workingtree.WorkingTree.open(path)
1100
970
            except (errors.NotBranchError, errors.NoWorkingTree):
1101
 
                raise TestSkipped('Needs a working tree of bzr sources')
 
971
                return
1102
972
        finally:
1103
973
            self.enable_directory_isolation()
1104
974
 
1216
1086
        except UnicodeError, e:
1217
1087
            # If we can't compare without getting a UnicodeError, then
1218
1088
            # obviously they are different
1219
 
            trace.mutter('UnicodeError: %s', e)
 
1089
            mutter('UnicodeError: %s', e)
1220
1090
        if message:
1221
1091
            message += '\n'
1222
1092
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
1282
1152
    def assertLogsError(self, exception_class, func, *args, **kwargs):
1283
1153
        """Assert that func(*args, **kwargs) quietly logs a specific exception.
1284
1154
        """
 
1155
        from bzrlib import trace
1285
1156
        captured = []
1286
1157
        orig_log_exception_quietly = trace.log_exception_quietly
1287
1158
        try:
1581
1452
        The file is removed as the test is torn down.
1582
1453
        """
1583
1454
        self._log_file = StringIO()
1584
 
        self._log_memento = trace.push_log_file(self._log_file)
 
1455
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1585
1456
        self.addCleanup(self._finishLogFile)
1586
1457
 
1587
1458
    def _finishLogFile(self):
1589
1460
 
1590
1461
        Close the file and delete it, unless setKeepLogfile was called.
1591
1462
        """
1592
 
        if trace._trace_file:
 
1463
        if bzrlib.trace._trace_file:
1593
1464
            # flush the log file, to get all content
1594
 
            trace._trace_file.flush()
1595
 
        trace.pop_log_file(self._log_memento)
 
1465
            bzrlib.trace._trace_file.flush()
 
1466
        bzrlib.trace.pop_log_file(self._log_memento)
1596
1467
        # Cache the log result and delete the file on disk
1597
1468
        self._get_log(False)
1598
1469
 
1628
1499
            setattr(obj, attr_name, new)
1629
1500
        return value
1630
1501
 
1631
 
    def overrideEnv(self, name, new):
1632
 
        """Set an environment variable, and reset it after the test.
1633
 
 
1634
 
        :param name: The environment variable name.
1635
 
 
1636
 
        :param new: The value to set the variable to. If None, the 
1637
 
            variable is deleted from the environment.
1638
 
 
1639
 
        :returns: The actual variable value.
1640
 
        """
1641
 
        value = osutils.set_or_unset_env(name, new)
1642
 
        self.addCleanup(osutils.set_or_unset_env, name, value)
1643
 
        return value
1644
 
 
1645
1502
    def _cleanEnvironment(self):
1646
 
        for name, value in isolated_environ.iteritems():
1647
 
            self.overrideEnv(name, value)
 
1503
        new_env = {
 
1504
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
 
1505
            'HOME': os.getcwd(),
 
1506
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
1507
            # tests do check our impls match APPDATA
 
1508
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
1509
            'VISUAL': None,
 
1510
            'EDITOR': None,
 
1511
            'BZR_EMAIL': None,
 
1512
            'BZREMAIL': None, # may still be present in the environment
 
1513
            'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
 
1514
            'BZR_PROGRESS_BAR': None,
 
1515
            'BZR_LOG': None,
 
1516
            'BZR_PLUGIN_PATH': None,
 
1517
            'BZR_DISABLE_PLUGINS': None,
 
1518
            'BZR_PLUGINS_AT': None,
 
1519
            'BZR_CONCURRENCY': None,
 
1520
            # Make sure that any text ui tests are consistent regardless of
 
1521
            # the environment the test case is run in; you may want tests that
 
1522
            # test other combinations.  'dumb' is a reasonable guess for tests
 
1523
            # going to a pipe or a StringIO.
 
1524
            'TERM': 'dumb',
 
1525
            'LINES': '25',
 
1526
            'COLUMNS': '80',
 
1527
            'BZR_COLUMNS': '80',
 
1528
            # SSH Agent
 
1529
            'SSH_AUTH_SOCK': None,
 
1530
            # Proxies
 
1531
            'http_proxy': None,
 
1532
            'HTTP_PROXY': None,
 
1533
            'https_proxy': None,
 
1534
            'HTTPS_PROXY': None,
 
1535
            'no_proxy': None,
 
1536
            'NO_PROXY': None,
 
1537
            'all_proxy': None,
 
1538
            'ALL_PROXY': None,
 
1539
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
1540
            # least. If you do (care), please update this comment
 
1541
            # -- vila 20080401
 
1542
            'ftp_proxy': None,
 
1543
            'FTP_PROXY': None,
 
1544
            'BZR_REMOTE_PATH': None,
 
1545
            # Generally speaking, we don't want apport reporting on crashes in
 
1546
            # the test envirnoment unless we're specifically testing apport,
 
1547
            # so that it doesn't leak into the real system environment.  We
 
1548
            # use an env var so it propagates to subprocesses.
 
1549
            'APPORT_DISABLE': '1',
 
1550
        }
 
1551
        self._old_env = {}
 
1552
        self.addCleanup(self._restoreEnvironment)
 
1553
        for name, value in new_env.iteritems():
 
1554
            self._captureVar(name, value)
 
1555
 
 
1556
    def _captureVar(self, name, newvalue):
 
1557
        """Set an environment variable, and reset it when finished."""
 
1558
        self._old_env[name] = osutils.set_or_unset_env(name, newvalue)
 
1559
 
 
1560
    def _restoreEnvironment(self):
 
1561
        for name, value in self._old_env.iteritems():
 
1562
            osutils.set_or_unset_env(name, value)
1648
1563
 
1649
1564
    def _restoreHooks(self):
1650
1565
        for klass, (name, hooks) in self._preserved_hooks.items():
1654
1569
        """This test has failed for some known reason."""
1655
1570
        raise KnownFailure(reason)
1656
1571
 
1657
 
    def _suppress_log(self):
1658
 
        """Remove the log info from details."""
1659
 
        self.discardDetail('log')
1660
 
 
1661
1572
    def _do_skip(self, result, reason):
1662
 
        self._suppress_log()
1663
1573
        addSkip = getattr(result, 'addSkip', None)
1664
1574
        if not callable(addSkip):
1665
1575
            result.addSuccess(result)
1668
1578
 
1669
1579
    @staticmethod
1670
1580
    def _do_known_failure(self, result, e):
1671
 
        self._suppress_log()
1672
1581
        err = sys.exc_info()
1673
1582
        addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1674
1583
        if addExpectedFailure is not None:
1682
1591
            reason = 'No reason given'
1683
1592
        else:
1684
1593
            reason = e.args[0]
1685
 
        self._suppress_log ()
1686
1594
        addNotApplicable = getattr(result, 'addNotApplicable', None)
1687
1595
        if addNotApplicable is not None:
1688
1596
            result.addNotApplicable(self, reason)
1690
1598
            self._do_skip(result, reason)
1691
1599
 
1692
1600
    @staticmethod
1693
 
    def _report_skip(self, result, err):
1694
 
        """Override the default _report_skip.
1695
 
 
1696
 
        We want to strip the 'log' detail. If we waint until _do_skip, it has
1697
 
        already been formatted into the 'reason' string, and we can't pull it
1698
 
        out again.
1699
 
        """
1700
 
        self._suppress_log()
1701
 
        super(TestCase, self)._report_skip(self, result, err)
1702
 
 
1703
 
    @staticmethod
1704
 
    def _report_expected_failure(self, result, err):
1705
 
        """Strip the log.
1706
 
 
1707
 
        See _report_skip for motivation.
1708
 
        """
1709
 
        self._suppress_log()
1710
 
        super(TestCase, self)._report_expected_failure(self, result, err)
1711
 
 
1712
 
    @staticmethod
1713
1601
    def _do_unsupported_or_skip(self, result, e):
1714
1602
        reason = e.args[0]
1715
 
        self._suppress_log()
1716
1603
        addNotSupported = getattr(result, 'addNotSupported', None)
1717
1604
        if addNotSupported is not None:
1718
1605
            result.addNotSupported(self, reason)
1744
1631
            self._benchtime += time.time() - start
1745
1632
 
1746
1633
    def log(self, *args):
1747
 
        trace.mutter(*args)
 
1634
        mutter(*args)
1748
1635
 
1749
1636
    def _get_log(self, keep_log_file=False):
1750
1637
        """Internal helper to get the log from bzrlib.trace for this test.
1835
1722
 
1836
1723
        try:
1837
1724
            try:
1838
 
                result = self.apply_redirected(
1839
 
                    ui.ui_factory.stdin,
 
1725
                result = self.apply_redirected(ui.ui_factory.stdin,
1840
1726
                    stdout, stderr,
1841
 
                    _mod_commands.run_bzr_catch_user_errors,
 
1727
                    bzrlib.commands.run_bzr_catch_user_errors,
1842
1728
                    args)
1843
1729
            except KeyboardInterrupt:
1844
1730
                # Reraise KeyboardInterrupt with contents of redirected stdout
2094
1980
        if retcode is not None and retcode != process.returncode:
2095
1981
            if process_args is None:
2096
1982
                process_args = "(unknown args)"
2097
 
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
2098
 
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
 
1983
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1984
            mutter('Error for bzr %s:\n%s', process_args, err)
2099
1985
            self.fail('Command bzr %s failed with retcode %s != %s'
2100
1986
                      % (process_args, retcode, process.returncode))
2101
1987
        return [out, err]
2158
2044
 
2159
2045
        Tests that expect to provoke LockContention errors should call this.
2160
2046
        """
2161
 
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
2047
        self.overrideAttr(bzrlib.lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
2162
2048
 
2163
2049
    def make_utf8_encoded_stringio(self, encoding_type=None):
2164
2050
        """Return a StringIOWrapper instance, that will encode Unicode
2488
2374
        test_home_dir = self.test_home_dir
2489
2375
        if isinstance(test_home_dir, unicode):
2490
2376
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2491
 
        self.overrideEnv('HOME', test_home_dir)
2492
 
        self.overrideEnv('BZR_HOME', test_home_dir)
 
2377
        os.environ['HOME'] = test_home_dir
 
2378
        os.environ['BZR_HOME'] = test_home_dir
2493
2379
 
2494
2380
    def setUp(self):
2495
2381
        super(TestCaseWithMemoryTransport, self).setUp()
2500
2386
                self.addCleanup(t.disconnect)
2501
2387
            return t
2502
2388
 
2503
 
        orig_get_transport = self.overrideAttr(_mod_transport, '_get_transport',
 
2389
        orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
2504
2390
                                               get_transport_with_cleanup)
2505
2391
        self._make_test_root()
2506
2392
        self.addCleanup(os.chdir, os.getcwdu())
3401
3287
    return result
3402
3288
 
3403
3289
 
3404
 
class ProfileResult(testtools.ExtendedToOriginalDecorator):
 
3290
class ForwardingResult(unittest.TestResult):
 
3291
 
 
3292
    def __init__(self, target):
 
3293
        unittest.TestResult.__init__(self)
 
3294
        self.result = target
 
3295
 
 
3296
    def startTest(self, test):
 
3297
        self.result.startTest(test)
 
3298
 
 
3299
    def stopTest(self, test):
 
3300
        self.result.stopTest(test)
 
3301
 
 
3302
    def startTestRun(self):
 
3303
        self.result.startTestRun()
 
3304
 
 
3305
    def stopTestRun(self):
 
3306
        self.result.stopTestRun()
 
3307
 
 
3308
    def addSkip(self, test, reason):
 
3309
        self.result.addSkip(test, reason)
 
3310
 
 
3311
    def addSuccess(self, test):
 
3312
        self.result.addSuccess(test)
 
3313
 
 
3314
    def addError(self, test, err):
 
3315
        self.result.addError(test, err)
 
3316
 
 
3317
    def addFailure(self, test, err):
 
3318
        self.result.addFailure(test, err)
 
3319
ForwardingResult = testtools.ExtendedToOriginalDecorator
 
3320
 
 
3321
 
 
3322
class ProfileResult(ForwardingResult):
3405
3323
    """Generate profiling data for all activity between start and success.
3406
3324
    
3407
3325
    The profile data is appended to the test's _benchcalls attribute and can
3419
3337
        # unavoidably fail.
3420
3338
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
3421
3339
        self.profiler.start()
3422
 
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
 
3340
        ForwardingResult.startTest(self, test)
3423
3341
 
3424
3342
    def addSuccess(self, test):
3425
3343
        stats = self.profiler.stop()
3429
3347
            test._benchcalls = []
3430
3348
            calls = test._benchcalls
3431
3349
        calls.append(((test.id(), "", ""), stats))
3432
 
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
 
3350
        ForwardingResult.addSuccess(self, test)
3433
3351
 
3434
3352
    def stopTest(self, test):
3435
 
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
 
3353
        ForwardingResult.stopTest(self, test)
3436
3354
        self.profiler = None
3437
3355
 
3438
3356
 
3645
3563
                key, obj, help=help, info=info, override_existing=False)
3646
3564
        except KeyError:
3647
3565
            actual = self.get(key)
3648
 
            trace.note(
3649
 
                'Test prefix alias %s is already used for %s, ignoring %s'
3650
 
                % (key, actual, obj))
 
3566
            note('Test prefix alias %s is already used for %s, ignoring %s'
 
3567
                 % (key, actual, obj))
3651
3568
 
3652
3569
    def resolve_alias(self, id_start):
3653
3570
        """Replace the alias by the prefix in the given string.
3812
3729
        'bzrlib.tests.test_permissions',
3813
3730
        'bzrlib.tests.test_plugins',
3814
3731
        'bzrlib.tests.test_progress',
3815
 
        'bzrlib.tests.test_pyutils',
3816
3732
        'bzrlib.tests.test_read_bundle',
3817
3733
        'bzrlib.tests.test_reconcile',
3818
3734
        'bzrlib.tests.test_reconfigure',
3827
3743
        'bzrlib.tests.test_rio',
3828
3744
        'bzrlib.tests.test_rules',
3829
3745
        'bzrlib.tests.test_sampler',
3830
 
        'bzrlib.tests.test_scenarios',
3831
3746
        'bzrlib.tests.test_script',
3832
3747
        'bzrlib.tests.test_selftest',
3833
3748
        'bzrlib.tests.test_serializer',
3897
3812
        'bzrlib.lockdir',
3898
3813
        'bzrlib.merge3',
3899
3814
        'bzrlib.option',
3900
 
        'bzrlib.pyutils',
3901
3815
        'bzrlib.symbol_versioning',
3902
3816
        'bzrlib.tests',
3903
3817
        'bzrlib.tests.fixtures',
3904
3818
        'bzrlib.timestamp',
3905
 
        'bzrlib.transport.http',
3906
3819
        'bzrlib.version_info_formats.format_custom',
3907
3820
        ]
3908
3821
 
3961
3874
        try:
3962
3875
            # note that this really does mean "report only" -- doctest
3963
3876
            # still runs the rest of the examples
3964
 
            doc_suite = IsolatedDocTestSuite(
3965
 
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
3877
            doc_suite = doctest.DocTestSuite(mod,
 
3878
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
3966
3879
        except ValueError, e:
3967
3880
            print '**failed to get doctest for: %s\n%s' % (mod, e)
3968
3881
            raise
3971
3884
        suite.addTest(doc_suite)
3972
3885
 
3973
3886
    default_encoding = sys.getdefaultencoding()
3974
 
    for name, plugin in _mod_plugin.plugins().items():
 
3887
    for name, plugin in bzrlib.plugin.plugins().items():
3975
3888
        if not interesting_module(plugin.module.__name__):
3976
3889
            continue
3977
3890
        plugin_suite = plugin.test_suite()
3983
3896
        if plugin_suite is not None:
3984
3897
            suite.addTest(plugin_suite)
3985
3898
        if default_encoding != sys.getdefaultencoding():
3986
 
            trace.warning(
 
3899
            bzrlib.trace.warning(
3987
3900
                'Plugin "%s" tried to reset default encoding to: %s', name,
3988
3901
                sys.getdefaultencoding())
3989
3902
            reload(sys)
4004
3917
            # Some tests mentioned in the list are not in the test suite. The
4005
3918
            # list may be out of date, report to the tester.
4006
3919
            for id in not_found:
4007
 
                trace.warning('"%s" not found in the test suite', id)
 
3920
                bzrlib.trace.warning('"%s" not found in the test suite', id)
4008
3921
        for id in duplicates:
4009
 
            trace.warning('"%s" is used as an id by several tests', id)
 
3922
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
4010
3923
 
4011
3924
    return suite
4012
3925
 
4013
3926
 
4014
 
def multiply_scenarios(*scenarios):
4015
 
    """Multiply two or more iterables of scenarios.
4016
 
 
4017
 
    It is safe to pass scenario generators or iterators.
4018
 
 
4019
 
    :returns: A list of compound scenarios: the cross-product of all 
4020
 
        scenarios, with the names concatenated and the parameters
4021
 
        merged together.
4022
 
    """
4023
 
    return reduce(_multiply_two_scenarios, map(list, scenarios))
4024
 
 
4025
 
 
4026
 
def _multiply_two_scenarios(scenarios_left, scenarios_right):
 
3927
def multiply_scenarios(scenarios_left, scenarios_right):
4027
3928
    """Multiply two sets of scenarios.
4028
3929
 
4029
3930
    :returns: the cartesian product of the two sets of scenarios, that is
4153
4054
        the module is available.
4154
4055
    """
4155
4056
 
4156
 
    py_module = pyutils.get_named_object(py_module_name)
 
4057
    py_module = __import__(py_module_name, {}, {}, ['NO_SUCH_ATTRIB'])
4157
4058
    scenarios = [
4158
4059
        ('python', {'module': py_module}),
4159
4060
    ]
4312
4213
            symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
4313
4214
            # Import the new feature and use it as a replacement for the
4314
4215
            # deprecated one.
4315
 
            self._feature = pyutils.get_named_object(
4316
 
                self._replacement_module, self._replacement_name)
 
4216
            mod = __import__(self._replacement_module, {}, {},
 
4217
                             [self._replacement_name])
 
4218
            self._feature = getattr(mod, self._replacement_name)
4317
4219
 
4318
4220
    def _probe(self):
4319
4221
        self._ensure()
4350
4252
        return self.module_name
4351
4253
 
4352
4254
 
 
4255
# This is kept here for compatibility, it is recommended to use
 
4256
# 'bzrlib.tests.feature.paramiko' instead
 
4257
ParamikoFeature = _CompatabilityThunkFeature(
 
4258
    deprecated_in((2,1,0)),
 
4259
    'bzrlib.tests.features', 'ParamikoFeature', 'paramiko')
 
4260
 
 
4261
 
4353
4262
def probe_unicode_in_user_encoding():
4354
4263
    """Try to encode several unicode strings to use in unicode-aware tests.
4355
4264
    Return first successfull match.
4542
4451
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
4543
4452
 
4544
4453
 
 
4454
# Kept for compatibility, use bzrlib.tests.features.subunit instead
 
4455
SubUnitFeature = _CompatabilityThunkFeature(
 
4456
    deprecated_in((2,1,0)),
 
4457
    'bzrlib.tests.features', 'SubUnitFeature', 'subunit')
4545
4458
# Only define SubUnitBzrRunner if subunit is available.
4546
4459
try:
4547
4460
    from subunit import TestProtocolClient
4548
4461
    from subunit.test_results import AutoTimingTestResultDecorator
4549
 
    class SubUnitBzrProtocolClient(TestProtocolClient):
4550
 
 
4551
 
        def addSuccess(self, test, details=None):
4552
 
            # The subunit client always includes the details in the subunit
4553
 
            # stream, but we don't want to include it in ours.
4554
 
            if details is not None and 'log' in details:
4555
 
                del details['log']
4556
 
            return super(SubUnitBzrProtocolClient, self).addSuccess(
4557
 
                test, details)
4558
 
 
4559
4462
    class SubUnitBzrRunner(TextTestRunner):
4560
4463
        def run(self, test):
4561
4464
            result = AutoTimingTestResultDecorator(
4562
 
                SubUnitBzrProtocolClient(self.stream))
 
4465
                TestProtocolClient(self.stream))
4563
4466
            test.run(result)
4564
4467
            return result
4565
4468
except ImportError: