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
89
90
except ImportError:
90
91
# lsprof not available
92
from bzrlib.merge import merge_inner
93
93
import bzrlib.merge3
94
94
import bzrlib.plugin
95
from bzrlib.smart import client, request, server
95
from bzrlib.smart import client, request
96
96
import bzrlib.store
97
97
from bzrlib import symbol_versioning
98
98
from bzrlib.symbol_versioning import (
116
116
from bzrlib.ui import NullProgressView
117
117
from bzrlib.ui.text import TextUIFactory
118
118
import bzrlib.version_info_formats.format_custom
119
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
121
120
# Mark this python module as being part of the implementation
122
121
# of unittest: this gives us better tracebacks where the last
261
261
def _elapsedTestTimeString(self):
262
262
"""Return a time string for the overall time the current test has taken."""
263
return self._formatTime(time.time() - self._start_time)
263
return self._formatTime(self._delta_to_float(
264
self._now() - self._start_datetime))
265
266
def _testTimeString(self, testCase):
266
267
benchmark_time = self._extractBenchmarkTime(testCase)
280
281
what = re.sub(r'^bzrlib\.tests\.', '', what)
284
# GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
285
# multiple times in a row, because the handler is added for
286
# each test but the container list is shared between cases.
287
# See lp:498869 lp:625574 and lp:637725 for background.
288
def _record_traceback_from_test(self, exc_info):
289
"""Store the traceback from passed exc_info tuple till"""
290
self._traceback_from_test = exc_info[2]
283
292
def startTest(self, test):
284
293
super(ExtendedTestResult, self).startTest(test)
285
294
if self.count == 0:
288
297
self.report_test_start(test)
289
298
test.number = self.count
290
299
self._recordTestStartTime()
300
# Make testtools cases give us the real traceback on failure
301
addOnException = getattr(test, "addOnException", None)
302
if addOnException is not None:
303
addOnException(self._record_traceback_from_test)
291
304
# Only check for thread leaks if the test case supports cleanups
292
305
addCleanup = getattr(test, "addCleanup", None)
293
306
if addCleanup is not None:
297
310
self.report_tests_starting()
298
311
self._active_threads = threading.enumerate()
313
def stopTest(self, test):
314
self._traceback_from_test = None
300
316
def _check_leaked_threads(self, test):
301
317
"""See if any threads have leaked since last call
316
332
def _recordTestStartTime(self):
317
333
"""Record that a test has started."""
318
self._start_time = time.time()
334
self._start_datetime = self._now()
320
336
def addError(self, test, err):
321
337
"""Tell result that test finished with an error.
323
339
Called from the TestCase run() method when the test
324
340
fails with an unexpected error.
342
self._post_mortem(self._traceback_from_test)
327
343
super(ExtendedTestResult, self).addError(test, err)
328
344
self.error_count += 1
329
345
self.report_error(test, err)
336
352
Called from the TestCase run() method when the test
337
353
fails because e.g. an assert() method failed.
355
self._post_mortem(self._traceback_from_test)
340
356
super(ExtendedTestResult, self).addFailure(test, err)
341
357
self.failure_count += 1
342
358
self.report_failure(test, err)
384
400
self.not_applicable_count += 1
385
401
self.report_not_applicable(test, reason)
387
def _post_mortem(self):
403
def _post_mortem(self, tb=None):
388
404
"""Start a PDB post mortem session."""
389
405
if os.environ.get('BZR_TEST_PDB', None):
390
import pdb;pdb.post_mortem()
392
409
def progress(self, offset, whence):
393
410
"""The test is adjusting the count of tests to run."""
634
651
encode = codec[0]
636
653
encode = codec.encode
637
stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream)
654
# GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
655
# so should swap to the plain codecs.StreamWriter
656
stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
638
658
stream.encoding = new_encoding
639
659
self.stream = stream
640
660
self.descriptions = descriptions
840
860
self._track_transports()
841
861
self._track_locks()
842
862
self._clear_debug_flags()
863
# Isolate global verbosity level, to make sure it's reproducible
864
# between tests. We should get rid of this altogether: bug 656694. --
866
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
845
869
# debug a frame up.
878
902
def _clear_hooks(self):
879
903
# prevent hooks affecting tests
904
known_hooks = hooks.known_hooks
880
905
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)
906
for key, (parent, name) in known_hooks.iter_parent_objects():
907
current_hooks = getattr(parent, name)
884
908
self._preserved_hooks[parent] = (name, current_hooks)
885
909
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)
910
for key, (parent, name) in known_hooks.iter_parent_objects():
911
factory = known_hooks.get(key)
888
912
setattr(parent, name, factory())
889
913
# this hook should always be installed
890
914
request._install_hook()
2430
2454
self.addCleanup(t.disconnect)
2433
orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
2457
orig_get_transport = self.overrideAttr(_mod_transport, '_get_transport',
2434
2458
get_transport_with_cleanup)
2435
2459
self._make_test_root()
2436
2460
self.addCleanup(os.chdir, os.getcwdu())
3334
class ForwardingResult(unittest.TestResult):
3336
def __init__(self, target):
3337
unittest.TestResult.__init__(self)
3338
self.result = target
3340
def startTest(self, test):
3341
self.result.startTest(test)
3343
def stopTest(self, test):
3344
self.result.stopTest(test)
3346
def startTestRun(self):
3347
self.result.startTestRun()
3349
def stopTestRun(self):
3350
self.result.stopTestRun()
3352
def addSkip(self, test, reason):
3353
self.result.addSkip(test, reason)
3355
def addSuccess(self, test):
3356
self.result.addSuccess(test)
3358
def addError(self, test, err):
3359
self.result.addError(test, err)
3361
def addFailure(self, test, err):
3362
self.result.addFailure(test, err)
3363
ForwardingResult = testtools.ExtendedToOriginalDecorator
3366
class ProfileResult(ForwardingResult):
3358
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3367
3359
"""Generate profiling data for all activity between start and success.
3369
3361
The profile data is appended to the test's _benchcalls attribute and can
3381
3373
# unavoidably fail.
3382
3374
bzrlib.lsprof.BzrProfiler.profiler_block = 0
3383
3375
self.profiler.start()
3384
ForwardingResult.startTest(self, test)
3376
testtools.ExtendedToOriginalDecorator.startTest(self, test)
3386
3378
def addSuccess(self, test):
3387
3379
stats = self.profiler.stop()
3391
3383
test._benchcalls = []
3392
3384
calls = test._benchcalls
3393
3385
calls.append(((test.id(), "", ""), stats))
3394
ForwardingResult.addSuccess(self, test)
3386
testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
3396
3388
def stopTest(self, test):
3397
ForwardingResult.stopTest(self, test)
3389
testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3398
3390
self.profiler = None
3773
3765
'bzrlib.tests.test_permissions',
3774
3766
'bzrlib.tests.test_plugins',
3775
3767
'bzrlib.tests.test_progress',
3768
'bzrlib.tests.test_pyutils',
3776
3769
'bzrlib.tests.test_read_bundle',
3777
3770
'bzrlib.tests.test_reconcile',
3778
3771
'bzrlib.tests.test_reconfigure',
3787
3780
'bzrlib.tests.test_rio',
3788
3781
'bzrlib.tests.test_rules',
3789
3782
'bzrlib.tests.test_sampler',
3783
'bzrlib.tests.test_scenarios',
3790
3784
'bzrlib.tests.test_script',
3791
3785
'bzrlib.tests.test_selftest',
3792
3786
'bzrlib.tests.test_serializer',
3851
'bzrlib.branchbuilder',
3845
# FIXME: Fixing bug #690563 revealed an isolation problem in the single
3846
# doctest for branchbuilder. Uncomment this when bug #321320 is fixed
3847
# to ensure the issue is addressed (note that to reproduce the bug in
3848
# the doctest below, one should comment the 'email' config var in
3849
# bazaar.conf (or anywhere else). This means an setup where *no* user
3850
# is being set at all in the environment.
3851
# 'bzrlib.branchbuilder',
3852
3852
'bzrlib.decorators',
3853
3853
'bzrlib.export',
3854
3854
'bzrlib.inventory',
3971
def multiply_scenarios(scenarios_left, scenarios_right):
3973
def multiply_scenarios(*scenarios):
3974
"""Multiply two or more iterables of scenarios.
3976
It is safe to pass scenario generators or iterators.
3978
:returns: A list of compound scenarios: the cross-product of all
3979
scenarios, with the names concatenated and the parameters
3982
return reduce(_multiply_two_scenarios, map(list, scenarios))
3985
def _multiply_two_scenarios(scenarios_left, scenarios_right):
3972
3986
"""Multiply two sets of scenarios.
3974
3988
:returns: the cartesian product of the two sets of scenarios, that is
4098
4112
the module is available.
4101
py_module = __import__(py_module_name, {}, {}, ['NO_SUCH_ATTRIB'])
4115
py_module = pyutils.get_named_object(py_module_name)
4103
4117
('python', {'module': py_module}),
4257
4271
symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
4258
4272
# Import the new feature and use it as a replacement for the
4259
4273
# deprecated one.
4260
mod = __import__(self._replacement_module, {}, {},
4261
[self._replacement_name])
4262
self._feature = getattr(mod, self._replacement_name)
4274
self._feature = pyutils.get_named_object(
4275
self._replacement_module, self._replacement_name)
4264
4277
def _probe(self):