~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-01-11 15:45:55 UTC
  • mfrom: (5588.1.1 bzr.dev)
  • Revision ID: pqm@pqm.ubuntu.com-20110111154555-xmu386vs0qoigyhl
(vila) Document the packaging helper scripts. (Max Bowsher)

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, 2):
59
 
    raise ImportError("need at least testtools 0.9.2: %s is %r"
 
58
if _testtools_version < (0, 9, 5):
 
59
    raise ImportError("need at least testtools 0.9.5: %s is %r"
60
60
        % (testtools.__file__, _testtools_version))
61
61
from testtools import content
62
62
 
 
63
import bzrlib
63
64
from bzrlib import (
64
65
    branchbuilder,
65
66
    bzrdir,
66
67
    chk_map,
 
68
    commands as _mod_commands,
67
69
    config,
68
70
    debug,
69
71
    errors,
70
72
    hooks,
71
73
    lock as _mod_lock,
 
74
    lockdir,
72
75
    memorytree,
73
76
    osutils,
 
77
    plugin as _mod_plugin,
 
78
    pyutils,
74
79
    ui,
75
80
    urlutils,
76
81
    registry,
 
82
    symbol_versioning,
 
83
    trace,
77
84
    transport as _mod_transport,
78
85
    workingtree,
79
86
    )
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.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
 
92
from bzrlib.smart import client, request
106
93
from bzrlib.transport import (
107
94
    memory,
108
95
    pathfilter,
109
96
    )
110
 
from bzrlib.trace import mutter, note
111
97
from bzrlib.tests import (
112
98
    test_server,
113
99
    TestUtil,
115
101
    )
116
102
from bzrlib.ui import NullProgressView
117
103
from bzrlib.ui.text import TextUIFactory
118
 
import bzrlib.version_info_formats.format_custom
119
 
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
120
104
 
121
105
# Mark this python module as being part of the implementation
122
106
# of unittest: this gives us better tracebacks where the last
139
123
TestSuite = TestUtil.TestSuite
140
124
TestLoader = TestUtil.TestLoader
141
125
 
 
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
 
142
213
class ExtendedTestResult(testtools.TextTestResult):
143
214
    """Accepts, reports and accumulates the results of running tests.
144
215
 
195
266
        self._strict = strict
196
267
        self._first_thread_leaker_id = None
197
268
        self._tests_leaking_threads_count = 0
 
269
        self._traceback_from_test = None
198
270
 
199
271
    def stopTestRun(self):
200
272
        run = self.testsRun
260
332
 
261
333
    def _elapsedTestTimeString(self):
262
334
        """Return a time string for the overall time the current test has taken."""
263
 
        return self._formatTime(time.time() - self._start_time)
 
335
        return self._formatTime(self._delta_to_float(
 
336
            self._now() - self._start_datetime))
264
337
 
265
338
    def _testTimeString(self, testCase):
266
339
        benchmark_time = self._extractBenchmarkTime(testCase)
280
353
        what = re.sub(r'^bzrlib\.tests\.', '', what)
281
354
        return what
282
355
 
 
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
 
283
364
    def startTest(self, test):
284
365
        super(ExtendedTestResult, self).startTest(test)
285
366
        if self.count == 0:
288
369
        self.report_test_start(test)
289
370
        test.number = self.count
290
371
        self._recordTestStartTime()
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)
 
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)
295
379
 
296
380
    def startTests(self):
297
381
        self.report_tests_starting()
298
382
        self._active_threads = threading.enumerate()
299
383
 
 
384
    def stopTest(self, test):
 
385
        self._traceback_from_test = None
 
386
 
300
387
    def _check_leaked_threads(self, test):
301
388
        """See if any threads have leaked since last call
302
389
 
315
402
 
316
403
    def _recordTestStartTime(self):
317
404
        """Record that a test has started."""
318
 
        self._start_time = time.time()
 
405
        self._start_datetime = self._now()
319
406
 
320
407
    def addError(self, test, err):
321
408
        """Tell result that test finished with an error.
323
410
        Called from the TestCase run() method when the test
324
411
        fails with an unexpected error.
325
412
        """
326
 
        self._post_mortem()
 
413
        self._post_mortem(self._traceback_from_test)
327
414
        super(ExtendedTestResult, self).addError(test, err)
328
415
        self.error_count += 1
329
416
        self.report_error(test, err)
336
423
        Called from the TestCase run() method when the test
337
424
        fails because e.g. an assert() method failed.
338
425
        """
339
 
        self._post_mortem()
 
426
        self._post_mortem(self._traceback_from_test)
340
427
        super(ExtendedTestResult, self).addFailure(test, err)
341
428
        self.failure_count += 1
342
429
        self.report_failure(test, err)
384
471
        self.not_applicable_count += 1
385
472
        self.report_not_applicable(test, reason)
386
473
 
387
 
    def _post_mortem(self):
 
474
    def _post_mortem(self, tb=None):
388
475
        """Start a PDB post mortem session."""
389
476
        if os.environ.get('BZR_TEST_PDB', None):
390
 
            import pdb;pdb.post_mortem()
 
477
            import pdb
 
478
            pdb.post_mortem(tb)
391
479
 
392
480
    def progress(self, offset, whence):
393
481
        """The test is adjusting the count of tests to run."""
634
722
            encode = codec[0]
635
723
        else:
636
724
            encode = codec.encode
637
 
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream)
 
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")
638
729
        stream.encoding = new_encoding
639
730
        self.stream = stream
640
731
        self.descriptions = descriptions
790
881
        return NullProgressView()
791
882
 
792
883
 
 
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
 
793
903
class TestCase(testtools.TestCase):
794
904
    """Base class for bzr unit tests.
795
905
 
840
950
        self._track_transports()
841
951
        self._track_locks()
842
952
        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)
843
957
 
844
958
    def debug(self):
845
959
        # debug a frame up.
877
991
 
878
992
    def _clear_hooks(self):
879
993
        # prevent hooks affecting tests
 
994
        known_hooks = hooks.known_hooks
880
995
        self._preserved_hooks = {}
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)
 
996
        for key, (parent, name) in known_hooks.iter_parent_objects():
 
997
            current_hooks = getattr(parent, name)
884
998
            self._preserved_hooks[parent] = (name, current_hooks)
885
999
        self.addCleanup(self._restoreHooks)
886
 
        for key, factory in hooks.known_hooks.items():
887
 
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
1000
        for key, (parent, name) in known_hooks.iter_parent_objects():
 
1001
            factory = known_hooks.get(key)
888
1002
            setattr(parent, name, factory())
889
1003
        # this hook should always be installed
890
1004
        request._install_hook()
1102
1216
        except UnicodeError, e:
1103
1217
            # If we can't compare without getting a UnicodeError, then
1104
1218
            # obviously they are different
1105
 
            mutter('UnicodeError: %s', e)
 
1219
            trace.mutter('UnicodeError: %s', e)
1106
1220
        if message:
1107
1221
            message += '\n'
1108
1222
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
1168
1282
    def assertLogsError(self, exception_class, func, *args, **kwargs):
1169
1283
        """Assert that func(*args, **kwargs) quietly logs a specific exception.
1170
1284
        """
1171
 
        from bzrlib import trace
1172
1285
        captured = []
1173
1286
        orig_log_exception_quietly = trace.log_exception_quietly
1174
1287
        try:
1468
1581
        The file is removed as the test is torn down.
1469
1582
        """
1470
1583
        self._log_file = StringIO()
1471
 
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
 
1584
        self._log_memento = trace.push_log_file(self._log_file)
1472
1585
        self.addCleanup(self._finishLogFile)
1473
1586
 
1474
1587
    def _finishLogFile(self):
1476
1589
 
1477
1590
        Close the file and delete it, unless setKeepLogfile was called.
1478
1591
        """
1479
 
        if bzrlib.trace._trace_file:
 
1592
        if trace._trace_file:
1480
1593
            # flush the log file, to get all content
1481
 
            bzrlib.trace._trace_file.flush()
1482
 
        bzrlib.trace.pop_log_file(self._log_memento)
 
1594
            trace._trace_file.flush()
 
1595
        trace.pop_log_file(self._log_memento)
1483
1596
        # Cache the log result and delete the file on disk
1484
1597
        self._get_log(False)
1485
1598
 
1515
1628
            setattr(obj, attr_name, new)
1516
1629
        return value
1517
1630
 
 
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
 
1518
1645
    def _cleanEnvironment(self):
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)
 
1646
        for name, value in isolated_environ.iteritems():
 
1647
            self.overrideEnv(name, value)
1579
1648
 
1580
1649
    def _restoreHooks(self):
1581
1650
        for klass, (name, hooks) in self._preserved_hooks.items():
1675
1744
            self._benchtime += time.time() - start
1676
1745
 
1677
1746
    def log(self, *args):
1678
 
        mutter(*args)
 
1747
        trace.mutter(*args)
1679
1748
 
1680
1749
    def _get_log(self, keep_log_file=False):
1681
1750
        """Internal helper to get the log from bzrlib.trace for this test.
1766
1835
 
1767
1836
        try:
1768
1837
            try:
1769
 
                result = self.apply_redirected(ui.ui_factory.stdin,
 
1838
                result = self.apply_redirected(
 
1839
                    ui.ui_factory.stdin,
1770
1840
                    stdout, stderr,
1771
 
                    bzrlib.commands.run_bzr_catch_user_errors,
 
1841
                    _mod_commands.run_bzr_catch_user_errors,
1772
1842
                    args)
1773
1843
            except KeyboardInterrupt:
1774
1844
                # Reraise KeyboardInterrupt with contents of redirected stdout
2024
2094
        if retcode is not None and retcode != process.returncode:
2025
2095
            if process_args is None:
2026
2096
                process_args = "(unknown args)"
2027
 
            mutter('Output of bzr %s:\n%s', process_args, out)
2028
 
            mutter('Error for bzr %s:\n%s', process_args, err)
 
2097
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
 
2098
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
2029
2099
            self.fail('Command bzr %s failed with retcode %s != %s'
2030
2100
                      % (process_args, retcode, process.returncode))
2031
2101
        return [out, err]
2088
2158
 
2089
2159
        Tests that expect to provoke LockContention errors should call this.
2090
2160
        """
2091
 
        self.overrideAttr(bzrlib.lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
2161
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
2092
2162
 
2093
2163
    def make_utf8_encoded_stringio(self, encoding_type=None):
2094
2164
        """Return a StringIOWrapper instance, that will encode Unicode
2418
2488
        test_home_dir = self.test_home_dir
2419
2489
        if isinstance(test_home_dir, unicode):
2420
2490
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2421
 
        os.environ['HOME'] = test_home_dir
2422
 
        os.environ['BZR_HOME'] = test_home_dir
 
2491
        self.overrideEnv('HOME', test_home_dir)
 
2492
        self.overrideEnv('BZR_HOME', test_home_dir)
2423
2493
 
2424
2494
    def setUp(self):
2425
2495
        super(TestCaseWithMemoryTransport, self).setUp()
2430
2500
                self.addCleanup(t.disconnect)
2431
2501
            return t
2432
2502
 
2433
 
        orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
 
2503
        orig_get_transport = self.overrideAttr(_mod_transport, '_get_transport',
2434
2504
                                               get_transport_with_cleanup)
2435
2505
        self._make_test_root()
2436
2506
        self.addCleanup(os.chdir, os.getcwdu())
3331
3401
    return result
3332
3402
 
3333
3403
 
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):
 
3404
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3367
3405
    """Generate profiling data for all activity between start and success.
3368
3406
    
3369
3407
    The profile data is appended to the test's _benchcalls attribute and can
3381
3419
        # unavoidably fail.
3382
3420
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
3383
3421
        self.profiler.start()
3384
 
        ForwardingResult.startTest(self, test)
 
3422
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
3385
3423
 
3386
3424
    def addSuccess(self, test):
3387
3425
        stats = self.profiler.stop()
3391
3429
            test._benchcalls = []
3392
3430
            calls = test._benchcalls
3393
3431
        calls.append(((test.id(), "", ""), stats))
3394
 
        ForwardingResult.addSuccess(self, test)
 
3432
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
3395
3433
 
3396
3434
    def stopTest(self, test):
3397
 
        ForwardingResult.stopTest(self, test)
 
3435
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3398
3436
        self.profiler = None
3399
3437
 
3400
3438
 
3607
3645
                key, obj, help=help, info=info, override_existing=False)
3608
3646
        except KeyError:
3609
3647
            actual = self.get(key)
3610
 
            note('Test prefix alias %s is already used for %s, ignoring %s'
3611
 
                 % (key, actual, obj))
 
3648
            trace.note(
 
3649
                'Test prefix alias %s is already used for %s, ignoring %s'
 
3650
                % (key, actual, obj))
3612
3651
 
3613
3652
    def resolve_alias(self, id_start):
3614
3653
        """Replace the alias by the prefix in the given string.
3773
3812
        'bzrlib.tests.test_permissions',
3774
3813
        'bzrlib.tests.test_plugins',
3775
3814
        'bzrlib.tests.test_progress',
 
3815
        'bzrlib.tests.test_pyutils',
3776
3816
        'bzrlib.tests.test_read_bundle',
3777
3817
        'bzrlib.tests.test_reconcile',
3778
3818
        'bzrlib.tests.test_reconfigure',
3787
3827
        'bzrlib.tests.test_rio',
3788
3828
        'bzrlib.tests.test_rules',
3789
3829
        'bzrlib.tests.test_sampler',
 
3830
        'bzrlib.tests.test_scenarios',
3790
3831
        'bzrlib.tests.test_script',
3791
3832
        'bzrlib.tests.test_selftest',
3792
3833
        'bzrlib.tests.test_serializer',
3856
3897
        'bzrlib.lockdir',
3857
3898
        'bzrlib.merge3',
3858
3899
        'bzrlib.option',
 
3900
        'bzrlib.pyutils',
3859
3901
        'bzrlib.symbol_versioning',
3860
3902
        'bzrlib.tests',
3861
3903
        'bzrlib.tests.fixtures',
3862
3904
        'bzrlib.timestamp',
 
3905
        'bzrlib.transport.http',
3863
3906
        'bzrlib.version_info_formats.format_custom',
3864
3907
        ]
3865
3908
 
3918
3961
        try:
3919
3962
            # note that this really does mean "report only" -- doctest
3920
3963
            # still runs the rest of the examples
3921
 
            doc_suite = doctest.DocTestSuite(mod,
3922
 
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
3964
            doc_suite = IsolatedDocTestSuite(
 
3965
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
3923
3966
        except ValueError, e:
3924
3967
            print '**failed to get doctest for: %s\n%s' % (mod, e)
3925
3968
            raise
3928
3971
        suite.addTest(doc_suite)
3929
3972
 
3930
3973
    default_encoding = sys.getdefaultencoding()
3931
 
    for name, plugin in bzrlib.plugin.plugins().items():
 
3974
    for name, plugin in _mod_plugin.plugins().items():
3932
3975
        if not interesting_module(plugin.module.__name__):
3933
3976
            continue
3934
3977
        plugin_suite = plugin.test_suite()
3940
3983
        if plugin_suite is not None:
3941
3984
            suite.addTest(plugin_suite)
3942
3985
        if default_encoding != sys.getdefaultencoding():
3943
 
            bzrlib.trace.warning(
 
3986
            trace.warning(
3944
3987
                'Plugin "%s" tried to reset default encoding to: %s', name,
3945
3988
                sys.getdefaultencoding())
3946
3989
            reload(sys)
3961
4004
            # Some tests mentioned in the list are not in the test suite. The
3962
4005
            # list may be out of date, report to the tester.
3963
4006
            for id in not_found:
3964
 
                bzrlib.trace.warning('"%s" not found in the test suite', id)
 
4007
                trace.warning('"%s" not found in the test suite', id)
3965
4008
        for id in duplicates:
3966
 
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
 
4009
            trace.warning('"%s" is used as an id by several tests', id)
3967
4010
 
3968
4011
    return suite
3969
4012
 
3970
4013
 
3971
 
def multiply_scenarios(scenarios_left, scenarios_right):
 
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):
3972
4027
    """Multiply two sets of scenarios.
3973
4028
 
3974
4029
    :returns: the cartesian product of the two sets of scenarios, that is
4098
4153
        the module is available.
4099
4154
    """
4100
4155
 
4101
 
    py_module = __import__(py_module_name, {}, {}, ['NO_SUCH_ATTRIB'])
 
4156
    py_module = pyutils.get_named_object(py_module_name)
4102
4157
    scenarios = [
4103
4158
        ('python', {'module': py_module}),
4104
4159
    ]
4257
4312
            symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
4258
4313
            # Import the new feature and use it as a replacement for the
4259
4314
            # deprecated one.
4260
 
            mod = __import__(self._replacement_module, {}, {},
4261
 
                             [self._replacement_name])
4262
 
            self._feature = getattr(mod, self._replacement_name)
 
4315
            self._feature = pyutils.get_named_object(
 
4316
                self._replacement_module, self._replacement_name)
4263
4317
 
4264
4318
    def _probe(self):
4265
4319
        self._ensure()
4296
4350
        return self.module_name
4297
4351
 
4298
4352
 
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
 
 
4306
4353
def probe_unicode_in_user_encoding():
4307
4354
    """Try to encode several unicode strings to use in unicode-aware tests.
4308
4355
    Return first successfull match.
4495
4542
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
4496
4543
 
4497
4544
 
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')
4502
4545
# Only define SubUnitBzrRunner if subunit is available.
4503
4546
try:
4504
4547
    from subunit import TestProtocolClient