27
31
from cStringIO import StringIO
37
from pprint import pformat
42
from subprocess import Popen, PIPE
50
# nb: check this before importing anything else from within it
51
_testtools_version = getattr(testtools, '__version__', ())
52
if _testtools_version < (0, 9, 5):
53
raise ImportError("need at least testtools 0.9.5: %s is %r"
54
% (testtools.__file__, _testtools_version))
55
from testtools import content
58
50
from bzrlib import (
62
commands as _mod_commands,
72
plugin as _mod_plugin,
79
transport as _mod_transport,
62
import bzrlib.commands
63
import bzrlib.timestamp
65
import bzrlib.inventory
66
import bzrlib.iterablefile
83
69
import bzrlib.lsprof
84
70
except ImportError:
85
71
# lsprof not available
87
from bzrlib.smart import client, request
88
from bzrlib.transport import (
73
from bzrlib.merge import merge_inner
77
from bzrlib.revision import common_ancestor
79
from bzrlib import symbol_versioning
92
80
from bzrlib.symbol_versioning import (
96
from bzrlib.tests import (
101
from bzrlib.ui import NullProgressView
102
from bzrlib.ui.text import TextUIFactory
85
from bzrlib.transport import get_transport
86
import bzrlib.transport
87
from bzrlib.transport.local import LocalURLServer
88
from bzrlib.transport.memory import MemoryServer
89
from bzrlib.transport.readonly import ReadonlyServer
90
from bzrlib.trace import mutter, note
91
from bzrlib.tests import TestUtil
92
from bzrlib.tests.HttpServer import HttpServer
93
from bzrlib.tests.TestUtil import (
97
from bzrlib.tests.treeshape import build_tree_contents
98
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
104
100
# Mark this python module as being part of the implementation
105
101
# of unittest: this gives us better tracebacks where the last
106
102
# shown frame is the test code, not our assertXYZ.
109
default_transport = test_server.LocalURLServer
112
_unitialized_attr = object()
113
"""A sentinel needed to act as a default value in a method signature."""
116
# Subunit result codes, defined here to prevent a hard dependency on subunit.
120
# These are intentionally brought into this namespace. That way plugins, etc
121
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
122
TestSuite = TestUtil.TestSuite
123
TestLoader = TestUtil.TestLoader
125
# Tests should run in a clean and clearly defined environment. The goal is to
126
# keep them isolated from the running environment as mush as possible. The test
127
# framework ensures the variables defined below are set (or deleted if the
128
# value is None) before a test is run and reset to their original value after
129
# the test is run. Generally if some code depends on an environment variable,
130
# the tests should start without this variable in the environment. There are a
131
# few exceptions but you shouldn't violate this rule lightly.
135
# bzr now uses the Win32 API and doesn't rely on APPDATA, but the
136
# tests do check our impls match APPDATA
137
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
141
'BZREMAIL': None, # may still be present in the environment
142
'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
143
'BZR_PROGRESS_BAR': None,
144
# This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
145
# as a base class instead of TestCaseInTempDir. Tests inheriting from
146
# TestCase should not use disk resources, BZR_LOG is one.
147
'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
148
'BZR_PLUGIN_PATH': None,
149
'BZR_DISABLE_PLUGINS': None,
150
'BZR_PLUGINS_AT': None,
151
'BZR_CONCURRENCY': None,
152
# Make sure that any text ui tests are consistent regardless of
153
# the environment the test case is run in; you may want tests that
154
# test other combinations. 'dumb' is a reasonable guess for tests
155
# going to a pipe or a StringIO.
161
'SSH_AUTH_SOCK': None,
171
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
172
# least. If you do (care), please update this comment
176
'BZR_REMOTE_PATH': None,
177
# Generally speaking, we don't want apport reporting on crashes in
178
# the test envirnoment unless we're specifically testing apport,
179
# so that it doesn't leak into the real system environment. We
180
# use an env var so it propagates to subprocesses.
181
'APPORT_DISABLE': '1',
185
def override_os_environ(test, env=None):
186
"""Modify os.environ keeping a copy.
188
:param test: A test instance
190
:param env: A dict containing variable definitions to be installed
193
env = isolated_environ
194
test._original_os_environ = dict([(var, value)
195
for var, value in os.environ.iteritems()])
196
for var, value in env.iteritems():
197
osutils.set_or_unset_env(var, value)
198
if var not in test._original_os_environ:
199
# The var is new, add it with a value of None, so
200
# restore_os_environ will delete it
201
test._original_os_environ[var] = None
204
def restore_os_environ(test):
205
"""Restore os.environ to its original state.
207
:param test: A test instance previously passed to override_os_environ.
209
for var, value in test._original_os_environ.iteritems():
210
# Restore the original value (or delete it if the value has been set to
211
# None in override_os_environ).
212
osutils.set_or_unset_env(var, value)
215
class ExtendedTestResult(testtools.TextTestResult):
105
default_transport = LocalURLServer
108
MODULES_TO_DOCTEST = [
121
def packages_to_test():
122
"""Return a list of packages to test.
124
The packages are not globally imported so that import failures are
125
triggered when running selftest, not when importing the command.
128
import bzrlib.tests.blackbox
129
import bzrlib.tests.branch_implementations
130
import bzrlib.tests.bzrdir_implementations
131
import bzrlib.tests.interrepository_implementations
132
import bzrlib.tests.interversionedfile_implementations
133
import bzrlib.tests.intertree_implementations
134
import bzrlib.tests.per_lock
135
import bzrlib.tests.repository_implementations
136
import bzrlib.tests.revisionstore_implementations
137
import bzrlib.tests.tree_implementations
138
import bzrlib.tests.workingtree_implementations
141
bzrlib.tests.blackbox,
142
bzrlib.tests.branch_implementations,
143
bzrlib.tests.bzrdir_implementations,
144
bzrlib.tests.interrepository_implementations,
145
bzrlib.tests.interversionedfile_implementations,
146
bzrlib.tests.intertree_implementations,
147
bzrlib.tests.per_lock,
148
bzrlib.tests.repository_implementations,
149
bzrlib.tests.revisionstore_implementations,
150
bzrlib.tests.tree_implementations,
151
bzrlib.tests.workingtree_implementations,
155
class ExtendedTestResult(unittest._TextTestResult):
216
156
"""Accepts, reports and accumulates the results of running tests.
218
Compared to the unittest version this class adds support for
219
profiling, benchmarking, stopping as soon as a test fails, and
220
skipping tests. There are further-specialized subclasses for
221
different types of display.
223
When a test finishes, in whatever way, it calls one of the addSuccess,
224
addFailure or addError classes. These in turn may redirect to a more
225
specific case for the special test results supported by our extended
228
Note that just one of these objects is fed the results from many tests.
158
Compared to this unittest version this class adds support for profiling,
159
benchmarking, stopping as soon as a test fails, and skipping tests.
160
There are further-specialized subclasses for different types of display.
231
163
stop_early = False
233
165
def __init__(self, stream, descriptions, verbosity,
234
166
bench_history=None,
237
169
"""Construct new TestResult.
239
171
:param bench_history: Optionally, a writable file object to accumulate
240
172
benchmark results.
242
testtools.TextTestResult.__init__(self, stream)
174
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
243
175
if bench_history is not None:
244
176
from bzrlib.version import _get_bzr_source_tree
245
177
src_tree = _get_bzr_source_tree()
353
222
def _shortened_test_description(self, test):
355
what = re.sub(r'^bzrlib\.tests\.', '', what)
224
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
358
# GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
359
# multiple times in a row, because the handler is added for
360
# each test but the container list is shared between cases.
361
# See lp:498869 lp:625574 and lp:637725 for background.
362
def _record_traceback_from_test(self, exc_info):
363
"""Store the traceback from passed exc_info tuple till"""
364
self._traceback_from_test = exc_info[2]
366
227
def startTest(self, test):
367
super(ExtendedTestResult, self).startTest(test)
228
unittest.TestResult.startTest(self, test)
371
229
self.report_test_start(test)
372
230
test.number = self.count
373
231
self._recordTestStartTime()
374
# Make testtools cases give us the real traceback on failure
375
addOnException = getattr(test, "addOnException", None)
376
if addOnException is not None:
377
addOnException(self._record_traceback_from_test)
378
# Only check for thread leaks on bzrlib derived test cases
379
if isinstance(test, TestCase):
380
test.addCleanup(self._check_leaked_threads, test)
382
def stopTest(self, test):
383
super(ExtendedTestResult, self).stopTest(test)
384
# Manually break cycles, means touching various private things but hey
385
getDetails = getattr(test, "getDetails", None)
386
if getDetails is not None:
388
# Clear _type_equality_funcs to try to stop TestCase instances
389
# from wasting memory. 'clear' is not available in all Python
390
# versions (bug 809048)
391
type_equality_funcs = getattr(test, "_type_equality_funcs", None)
392
if type_equality_funcs is not None:
393
tef_clear = getattr(type_equality_funcs, "clear", None)
394
if tef_clear is None:
395
tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
396
if tef_instance_dict is not None:
397
tef_clear = tef_instance_dict.clear
398
if tef_clear is not None:
400
self._traceback_from_test = None
402
def startTests(self):
403
self.report_tests_starting()
404
self._active_threads = threading.enumerate()
406
def _check_leaked_threads(self, test):
407
"""See if any threads have leaked since last call
409
A sample of live threads is stored in the _active_threads attribute,
410
when this method runs it compares the current live threads and any not
411
in the previous sample are treated as having leaked.
413
now_active_threads = set(threading.enumerate())
414
threads_leaked = now_active_threads.difference(self._active_threads)
416
self._report_thread_leak(test, threads_leaked, now_active_threads)
417
self._tests_leaking_threads_count += 1
418
if self._first_thread_leaker_id is None:
419
self._first_thread_leaker_id = test.id()
420
self._active_threads = now_active_threads
422
233
def _recordTestStartTime(self):
423
234
"""Record that a test has started."""
424
self._start_datetime = self._now()
235
self._start_time = time.time()
237
def _cleanupLogFile(self, test):
238
# We can only do this if we have one of our TestCases, not if
240
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
241
if setKeepLogfile is not None:
426
244
def addError(self, test, err):
427
"""Tell result that test finished with an error.
429
Called from the TestCase run() method when the test
430
fails with an unexpected error.
432
self._post_mortem(self._traceback_from_test)
433
super(ExtendedTestResult, self).addError(test, err)
245
self.extractBenchmarkTime(test)
246
self._cleanupLogFile(test)
247
if isinstance(err[1], TestSkipped):
248
return self.addSkipped(test, err)
249
elif isinstance(err[1], UnavailableFeature):
250
return self.addNotSupported(test, err[1].args[0])
251
unittest.TestResult.addError(self, test, err)
434
252
self.error_count += 1
435
253
self.report_error(test, err)
436
254
if self.stop_early:
439
257
def addFailure(self, test, err):
440
"""Tell result that test failed.
442
Called from the TestCase run() method when the test
443
fails because e.g. an assert() method failed.
445
self._post_mortem(self._traceback_from_test)
446
super(ExtendedTestResult, self).addFailure(test, err)
258
self._cleanupLogFile(test)
259
self.extractBenchmarkTime(test)
260
if isinstance(err[1], KnownFailure):
261
return self.addKnownFailure(test, err)
262
unittest.TestResult.addFailure(self, test, err)
447
263
self.failure_count += 1
448
264
self.report_failure(test, err)
449
265
if self.stop_early:
452
def addSuccess(self, test, details=None):
453
"""Tell result that test completed successfully.
455
Called from the TestCase run()
457
if self._bench_history is not None:
458
benchmark_time = self._extractBenchmarkTime(test, details)
459
if benchmark_time is not None:
460
self._bench_history.write("%s %s\n" % (
461
self._formatTime(benchmark_time),
463
self.report_success(test)
464
super(ExtendedTestResult, self).addSuccess(test)
465
test._log_contents = ''
467
def addExpectedFailure(self, test, err):
268
def addKnownFailure(self, test, err):
468
269
self.known_failure_count += 1
469
270
self.report_known_failure(test, err)
471
def addUnexpectedSuccess(self, test, details=None):
472
"""Tell result the test unexpectedly passed, counting as a failure
474
When the minimum version of testtools required becomes 0.9.8 this
475
can be updated to use the new handling there.
477
super(ExtendedTestResult, self).addFailure(test, details=details)
478
self.failure_count += 1
479
self.report_unexpected_success(test,
480
"".join(details["reason"].iter_text()))
484
272
def addNotSupported(self, test, feature):
485
"""The test will not be run because of a missing feature.
487
# this can be called in two different ways: it may be that the
488
# test started running, and then raised (through requireFeature)
489
# UnavailableFeature. Alternatively this method can be called
490
# while probing for features before running the test code proper; in
491
# that case we will see startTest and stopTest, but the test will
492
# never actually run.
493
273
self.unsupported.setdefault(str(feature), 0)
494
274
self.unsupported[str(feature)] += 1
495
275
self.report_unsupported(test, feature)
497
def addSkip(self, test, reason):
498
"""A test has not run for 'reason'."""
500
self.report_skip(test, reason)
502
def addNotApplicable(self, test, reason):
503
self.not_applicable_count += 1
504
self.report_not_applicable(test, reason)
506
def _post_mortem(self, tb=None):
507
"""Start a PDB post mortem session."""
508
if os.environ.get('BZR_TEST_PDB', None):
512
def progress(self, offset, whence):
513
"""The test is adjusting the count of tests to run."""
514
if whence == SUBUNIT_SEEK_SET:
515
self.num_tests = offset
516
elif whence == SUBUNIT_SEEK_CUR:
517
self.num_tests += offset
519
raise errors.BzrError("Unknown whence %r" % whence)
521
def report_tests_starting(self):
522
"""Display information before the test run begins"""
523
if getattr(sys, 'frozen', None) is None:
524
bzr_path = osutils.realpath(sys.argv[0])
526
bzr_path = sys.executable
528
'bzr selftest: %s\n' % (bzr_path,))
531
bzrlib.__path__[0],))
533
' bzr-%s python-%s %s\n' % (
534
bzrlib.version_string,
535
bzrlib._format_version_tuple(sys.version_info),
536
platform.platform(aliased=1),
538
self.stream.write('\n')
540
def report_test_start(self, test):
541
"""Display information on the test just about to be run"""
543
def _report_thread_leak(self, test, leaked_threads, active_threads):
544
"""Display information on a test that leaked one or more threads"""
545
# GZ 2010-09-09: A leak summary reported separately from the general
546
# thread debugging would be nice. Tests under subunit
547
# need something not using stream, perhaps adding a
548
# testtools details object would be fitting.
549
if 'threads' in selftest_debug_flags:
550
self.stream.write('%s is leaking, active is now %d\n' %
551
(test.id(), len(active_threads)))
553
def startTestRun(self):
554
self.startTime = time.time()
277
def addSuccess(self, test):
278
self.extractBenchmarkTime(test)
279
if self._bench_history is not None:
280
if self._benchmarkTime is not None:
281
self._bench_history.write("%s %s\n" % (
282
self._formatTime(self._benchmarkTime),
284
self.report_success(test)
285
unittest.TestResult.addSuccess(self, test)
287
def addSkipped(self, test, skip_excinfo):
288
self.report_skip(test, skip_excinfo)
289
# seems best to treat this as success from point-of-view of unittest
290
# -- it actually does nothing so it barely matters :)
293
except KeyboardInterrupt:
296
self.addError(test, test.__exc_info())
298
unittest.TestResult.addSuccess(self, test)
300
def printErrorList(self, flavour, errors):
301
for test, err in errors:
302
self.stream.writeln(self.separator1)
303
self.stream.write("%s: " % flavour)
304
self.stream.writeln(self.getDescription(test))
305
if getattr(test, '_get_log', None) is not None:
307
print >>self.stream, \
308
('vvvv[log from %s]' % test.id()).ljust(78,'-')
309
print >>self.stream, test._get_log()
310
print >>self.stream, \
311
('^^^^[log from %s]' % test.id()).ljust(78,'-')
312
self.stream.writeln(self.separator2)
313
self.stream.writeln("%s" % err)
318
def report_cleaning_up(self):
556
321
def report_success(self, test):
559
def wasStrictlySuccessful(self):
560
if self.unsupported or self.known_failure_count:
562
return self.wasSuccessful()
565
325
class TextTestResult(ExtendedTestResult):
566
326
"""Displays progress and results of tests in text form"""
568
328
def __init__(self, stream, descriptions, verbosity,
569
329
bench_history=None,
573
333
ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
574
bench_history, strict)
575
# We no longer pass them around, but just rely on the UIFactory stack
578
warnings.warn("Passing pb to TextTestResult is deprecated")
579
self.pb = self.ui.nested_progress_bar()
334
bench_history, num_tests)
336
self.pb = self.ui.nested_progress_bar()
337
self._supplied_pb = False
340
self._supplied_pb = True
580
341
self.pb.show_pct = False
581
342
self.pb.show_spinner = False
582
343
self.pb.show_eta = False,
583
344
self.pb.show_count = False
584
345
self.pb.show_bar = False
585
self.pb.update_latency = 0
586
self.pb.show_transport_activity = False
588
def stopTestRun(self):
589
# called when the tests that are going to run have run
592
super(TextTestResult, self).stopTestRun()
594
def report_tests_starting(self):
595
super(TextTestResult, self).report_tests_starting()
596
self.pb.update('[test 0/%d] Starting' % (self.num_tests))
347
def report_starting(self):
348
self.pb.update('[test 0/%d] starting...' % (self.num_tests))
598
350
def _progress_prefix_text(self):
599
# the longer this text, the less space we have to show the test
601
a = '[%d' % self.count # total that have been run
602
# tests skipped as known not to be relevant are not important enough
604
## if self.skip_count:
605
## a += ', %d skip' % self.skip_count
606
## if self.known_failure_count:
607
## a += '+%dX' % self.known_failure_count
351
a = '[%d' % self.count
352
if self.num_tests is not None:
609
353
a +='/%d' % self.num_tests
611
runtime = time.time() - self._overall_start_time
613
a += '%dm%ds' % (runtime / 60, runtime % 60)
616
total_fail_count = self.error_count + self.failure_count
618
a += ', %d failed' % total_fail_count
619
# if self.unsupported:
620
# a += ', %d missing' % len(self.unsupported)
354
a += ' in %ds' % (time.time() - self._overall_start_time)
356
a += ', %d errors' % self.error_count
357
if self.failure_count:
358
a += ', %d failed' % self.failure_count
359
if self.known_failure_count:
360
a += ', %d known failures' % self.known_failure_count
362
a += ', %d skipped' % self.skip_count
364
a += ', %d missing features' % len(self.unsupported)
624
368
def report_test_start(self, test):
626
371
self._progress_prefix_text()
628
373
+ self._shortened_test_description(test))
630
375
def _test_description(self, test):
631
376
return self._shortened_test_description(test)
633
378
def report_error(self, test, err):
634
self.stream.write('ERROR: %s\n %s\n' % (
379
self.pb.note('ERROR: %s\n %s\n',
635
380
self._test_description(test),
639
384
def report_failure(self, test, err):
640
self.stream.write('FAIL: %s\n %s\n' % (
385
self.pb.note('FAIL: %s\n %s\n',
641
386
self._test_description(test),
645
390
def report_known_failure(self, test, err):
648
def report_unexpected_success(self, test, reason):
649
self.stream.write('FAIL: %s\n %s: %s\n' % (
650
self._test_description(test),
651
"Unexpected success. Should have failed",
655
def report_skip(self, test, reason):
658
def report_not_applicable(self, test, reason):
391
self.pb.note('XFAIL: %s\n%s\n',
392
self._test_description(test), err[1])
394
def report_skip(self, test, skip_excinfo):
397
# at the moment these are mostly not things we can fix
398
# and so they just produce stipple; use the verbose reporter
401
# show test and reason for skip
402
self.pb.note('SKIP: %s\n %s\n',
403
self._shortened_test_description(test),
406
# since the class name was left behind in the still-visible
408
self.pb.note('SKIP: %s', skip_excinfo[1])
661
410
def report_unsupported(self, test, feature):
662
411
"""test cannot be run because feature is missing."""
413
def report_cleaning_up(self):
414
self.pb.update('cleaning up...')
417
if not self._supplied_pb:
665
421
class VerboseTestResult(ExtendedTestResult):
956
704
retrieved by _get_log(). We use a real OS file, not an in-memory object,
957
705
so that it can also capture file IO. When the test completes this file
958
706
is read into memory and removed from disk.
960
708
There are also convenience functions to invoke bzr's command-line
961
709
routine, and to build and check bzr trees.
963
711
In addition to the usual method of overriding tearDown(), this class also
964
allows subclasses to register cleanup functions via addCleanup, which are
712
allows subclasses to register functions into the _cleanups list, which is
965
713
run in order as the object is torn down. It's less likely this will be
966
714
accidentally overlooked.
717
_log_file_name = None
719
_keep_log_file = False
970
720
# record lsprof data when performing benchmark calls.
971
721
_gather_lsprof_in_benchmarks = False
973
723
def __init__(self, methodName='testMethod'):
974
724
super(TestCase, self).__init__(methodName)
975
self._directory_isolation = True
976
self.exception_handlers.insert(0,
977
(UnavailableFeature, self._do_unsupported_or_skip))
978
self.exception_handlers.insert(0,
979
(TestNotApplicable, self._do_not_applicable))
982
super(TestCase, self).setUp()
983
for feature in getattr(self, '_test_needs_features', []):
984
self.requireFeature(feature)
728
unittest.TestCase.setUp(self)
985
729
self._cleanEnvironment()
730
bzrlib.trace.disable_default_logging()
986
731
self._silenceUI()
987
732
self._startLogFile()
988
733
self._benchcalls = []
989
734
self._benchtime = None
990
735
self._clear_hooks()
991
self._track_transports()
993
736
self._clear_debug_flags()
994
# Isolate global verbosity level, to make sure it's reproducible
995
# between tests. We should get rid of this altogether: bug 656694. --
997
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
998
# Isolate config option expansion until its default value for bzrlib is
999
# settled on or a the FIXME associated with _get_expand_default_value
1000
# is addressed -- vila 20110219
1001
self.overrideAttr(config, '_expand_default_value', None)
1002
self._log_files = set()
1003
# Each key in the ``_counters`` dict holds a value for a different
1004
# counter. When the test ends, addDetail() should be used to output the
1005
# counter values. This happens in install_counter_hook().
1007
if 'config_stats' in selftest_debug_flags:
1008
self._install_config_stats_hooks()
1009
# Do not use i18n for tests (unless the test reverses this)
1015
# The sys preserved stdin/stdout should allow blackbox tests debugging
1016
pdb.Pdb(stdin=sys.__stdin__, stdout=sys.__stdout__
1017
).set_trace(sys._getframe().f_back)
1019
def discardDetail(self, name):
1020
"""Extend the addDetail, getDetails api so we can remove a detail.
1022
eg. bzr always adds the 'log' detail at startup, but we don't want to
1023
include it for skipped, xfail, etc tests.
1025
It is safe to call this for a detail that doesn't exist, in case this
1026
gets called multiple times.
1028
# We cheat. details is stored in __details which means we shouldn't
1029
# touch it. but getDetails() returns the dict directly, so we can
1031
details = self.getDetails()
1035
def install_counter_hook(self, hooks, name, counter_name=None):
1036
"""Install a counting hook.
1038
Any hook can be counted as long as it doesn't need to return a value.
1040
:param hooks: Where the hook should be installed.
1042
:param name: The hook name that will be counted.
1044
:param counter_name: The counter identifier in ``_counters``, defaults
1047
_counters = self._counters # Avoid closing over self
1048
if counter_name is None:
1050
if _counters.has_key(counter_name):
1051
raise AssertionError('%s is already used as a counter name'
1053
_counters[counter_name] = 0
1054
self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1055
lambda: ['%d' % (_counters[counter_name],)]))
1056
def increment_counter(*args, **kwargs):
1057
_counters[counter_name] += 1
1058
label = 'count %s calls' % (counter_name,)
1059
hooks.install_named_hook(name, increment_counter, label)
1060
self.addCleanup(hooks.uninstall_named_hook, name, label)
1062
def _install_config_stats_hooks(self):
1063
"""Install config hooks to count hook calls.
1066
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1067
self.install_counter_hook(config.ConfigHooks, hook_name,
1068
'config.%s' % (hook_name,))
1070
# The OldConfigHooks are private and need special handling to protect
1071
# against recursive tests (tests that run other tests), so we just do
1072
# manually what registering them into _builtin_known_hooks will provide
1074
self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1075
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1076
self.install_counter_hook(config.OldConfigHooks, hook_name,
1077
'old_config.%s' % (hook_name,))
1079
738
def _clear_debug_flags(self):
1080
739
"""Prevent externally set debug flags affecting tests.
1082
741
Tests that want to use debug flags can just set them in the
1083
742
debug_flags set during setup/teardown.
1085
# Start with a copy of the current debug flags we can safely modify.
1086
self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
1087
if 'allow_debug' not in selftest_debug_flags:
1088
debug.debug_flags.clear()
1089
if 'disable_lock_checks' not in selftest_debug_flags:
1090
debug.debug_flags.add('strict_locks')
744
self._preserved_debug_flags = set(debug.debug_flags)
745
debug.debug_flags.clear()
746
self.addCleanup(self._restore_debug_flags)
1092
748
def _clear_hooks(self):
1093
749
# prevent hooks affecting tests
1094
known_hooks = hooks.known_hooks
1095
self._preserved_hooks = {}
1096
for key, (parent, name) in known_hooks.iter_parent_objects():
1097
current_hooks = getattr(parent, name)
1098
self._preserved_hooks[parent] = (name, current_hooks)
1099
self._preserved_lazy_hooks = hooks._lazy_hooks
1100
hooks._lazy_hooks = {}
751
import bzrlib.smart.server
752
self._preserved_hooks = {
753
bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
754
bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
1101
756
self.addCleanup(self._restoreHooks)
1102
for key, (parent, name) in known_hooks.iter_parent_objects():
1103
factory = known_hooks.get(key)
1104
setattr(parent, name, factory())
1105
# this hook should always be installed
1106
request._install_hook()
1108
def disable_directory_isolation(self):
1109
"""Turn off directory isolation checks."""
1110
self._directory_isolation = False
1112
def enable_directory_isolation(self):
1113
"""Enable directory isolation checks."""
1114
self._directory_isolation = True
757
# reset all hooks to an empty instance of the appropriate type
758
bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
759
bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
1116
761
def _silenceUI(self):
1117
762
"""Turn off UI for duration of test"""
1118
763
# by default the UI is off; tests can turn it on if they want it.
1119
self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
1121
def _check_locks(self):
1122
"""Check that all lock take/release actions have been paired."""
1123
# We always check for mismatched locks. If a mismatch is found, we
1124
# fail unless -Edisable_lock_checks is supplied to selftest, in which
1125
# case we just print a warning.
1127
acquired_locks = [lock for action, lock in self._lock_actions
1128
if action == 'acquired']
1129
released_locks = [lock for action, lock in self._lock_actions
1130
if action == 'released']
1131
broken_locks = [lock for action, lock in self._lock_actions
1132
if action == 'broken']
1133
# trivially, given the tests for lock acquistion and release, if we
1134
# have as many in each list, it should be ok. Some lock tests also
1135
# break some locks on purpose and should be taken into account by
1136
# considering that breaking a lock is just a dirty way of releasing it.
1137
if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1139
'Different number of acquired and '
1140
'released or broken locks.\n'
1144
(acquired_locks, released_locks, broken_locks))
1145
if not self._lock_check_thorough:
1146
# Rather than fail, just warn
1147
print "Broken test %s: %s" % (self, message)
1151
def _track_locks(self):
1152
"""Track lock activity during tests."""
1153
self._lock_actions = []
1154
if 'disable_lock_checks' in selftest_debug_flags:
1155
self._lock_check_thorough = False
1157
self._lock_check_thorough = True
1159
self.addCleanup(self._check_locks)
1160
_mod_lock.Lock.hooks.install_named_hook('lock_acquired',
1161
self._lock_acquired, None)
1162
_mod_lock.Lock.hooks.install_named_hook('lock_released',
1163
self._lock_released, None)
1164
_mod_lock.Lock.hooks.install_named_hook('lock_broken',
1165
self._lock_broken, None)
1167
def _lock_acquired(self, result):
1168
self._lock_actions.append(('acquired', result))
1170
def _lock_released(self, result):
1171
self._lock_actions.append(('released', result))
1173
def _lock_broken(self, result):
1174
self._lock_actions.append(('broken', result))
1176
def permit_dir(self, name):
1177
"""Permit a directory to be used by this test. See permit_url."""
1178
name_transport = _mod_transport.get_transport_from_path(name)
1179
self.permit_url(name)
1180
self.permit_url(name_transport.base)
1182
def permit_url(self, url):
1183
"""Declare that url is an ok url to use in this test.
1185
Do this for memory transports, temporary test directory etc.
1187
Do not do this for the current working directory, /tmp, or any other
1188
preexisting non isolated url.
1190
if not url.endswith('/'):
1192
self._bzr_selftest_roots.append(url)
1194
def permit_source_tree_branch_repo(self):
1195
"""Permit the source tree bzr is running from to be opened.
1197
Some code such as bzrlib.version attempts to read from the bzr branch
1198
that bzr is executing from (if any). This method permits that directory
1199
to be used in the test suite.
1201
path = self.get_source_path()
1202
self.record_directory_isolation()
1205
workingtree.WorkingTree.open(path)
1206
except (errors.NotBranchError, errors.NoWorkingTree):
1207
raise TestSkipped('Needs a working tree of bzr sources')
1209
self.enable_directory_isolation()
1211
def _preopen_isolate_transport(self, transport):
1212
"""Check that all transport openings are done in the test work area."""
1213
while isinstance(transport, pathfilter.PathFilteringTransport):
1214
# Unwrap pathfiltered transports
1215
transport = transport.server.backing_transport.clone(
1216
transport._filter('.'))
1217
url = transport.base
1218
# ReadonlySmartTCPServer_for_testing decorates the backing transport
1219
# urls it is given by prepending readonly+. This is appropriate as the
1220
# client shouldn't know that the server is readonly (or not readonly).
1221
# We could register all servers twice, with readonly+ prepending, but
1222
# that makes for a long list; this is about the same but easier to
1224
if url.startswith('readonly+'):
1225
url = url[len('readonly+'):]
1226
self._preopen_isolate_url(url)
1228
def _preopen_isolate_url(self, url):
1229
if not self._directory_isolation:
1231
if self._directory_isolation == 'record':
1232
self._bzr_selftest_roots.append(url)
1234
# This prevents all transports, including e.g. sftp ones backed on disk
1235
# from working unless they are explicitly granted permission. We then
1236
# depend on the code that sets up test transports to check that they are
1237
# appropriately isolated and enable their use by calling
1238
# self.permit_transport()
1239
if not osutils.is_inside_any(self._bzr_selftest_roots, url):
1240
raise errors.BzrError("Attempt to escape test isolation: %r %r"
1241
% (url, self._bzr_selftest_roots))
1243
def record_directory_isolation(self):
1244
"""Gather accessed directories to permit later access.
1246
This is used for tests that access the branch bzr is running from.
1248
self._directory_isolation = "record"
1250
def start_server(self, transport_server, backing_server=None):
1251
"""Start transport_server for this test.
1253
This starts the server, registers a cleanup for it and permits the
1254
server's urls to be used.
1256
if backing_server is None:
1257
transport_server.start_server()
1259
transport_server.start_server(backing_server)
1260
self.addCleanup(transport_server.stop_server)
1261
# Obtain a real transport because if the server supplies a password, it
1262
# will be hidden from the base on the client side.
1263
t = _mod_transport.get_transport_from_url(transport_server.get_url())
1264
# Some transport servers effectively chroot the backing transport;
1265
# others like SFTPServer don't - users of the transport can walk up the
1266
# transport to read the entire backing transport. This wouldn't matter
1267
# except that the workdir tests are given - and that they expect the
1268
# server's url to point at - is one directory under the safety net. So
1269
# Branch operations into the transport will attempt to walk up one
1270
# directory. Chrooting all servers would avoid this but also mean that
1271
# we wouldn't be testing directly against non-root urls. Alternatively
1272
# getting the test framework to start the server with a backing server
1273
# at the actual safety net directory would work too, but this then
1274
# means that the self.get_url/self.get_transport methods would need
1275
# to transform all their results. On balance its cleaner to handle it
1276
# here, and permit a higher url when we have one of these transports.
1277
if t.base.endswith('/work/'):
1278
# we have safety net/test root/work
1279
t = t.clone('../..')
1280
elif isinstance(transport_server,
1281
test_server.SmartTCPServer_for_testing):
1282
# The smart server adds a path similar to work, which is traversed
1283
# up from by the client. But the server is chrooted - the actual
1284
# backing transport is not escaped from, and VFS requests to the
1285
# root will error (because they try to escape the chroot).
1287
while t2.base != t.base:
1290
self.permit_url(t.base)
1292
def _track_transports(self):
1293
"""Install checks for transport usage."""
1294
# TestCase has no safe place it can write to.
1295
self._bzr_selftest_roots = []
1296
# Currently the easiest way to be sure that nothing is going on is to
1297
# hook into bzr dir opening. This leaves a small window of error for
1298
# transport tests, but they are well known, and we can improve on this
1300
bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1301
self._preopen_isolate_transport, "Check bzr directories are safe.")
764
saved = ui.ui_factory
766
ui.ui_factory = saved
767
ui.ui_factory = ui.SilentUIFactory()
768
self.addCleanup(_restore)
1303
770
def _ndiff_strings(self, a, b):
1304
771
"""Return ndiff between two strings containing lines.
1306
773
A trailing newline is added if missing to make the strings
1307
774
print properly."""
1308
775
if b and b[-1] != '\n':
1706
1038
The file is removed as the test is torn down.
1708
pseudo_log_file = StringIO()
1709
def _get_log_contents_for_weird_testtools_api():
1710
return [pseudo_log_file.getvalue().decode(
1711
"utf-8", "replace").encode("utf-8")]
1712
self.addDetail("log", content.Content(content.ContentType("text",
1713
"plain", {"charset": "utf8"}),
1714
_get_log_contents_for_weird_testtools_api))
1715
self._log_file = pseudo_log_file
1716
self._log_memento = trace.push_log_file(self._log_file)
1040
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1041
self._log_file = os.fdopen(fileno, 'w+')
1042
self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
1043
self._log_file_name = name
1717
1044
self.addCleanup(self._finishLogFile)
1719
1046
def _finishLogFile(self):
1720
1047
"""Finished with the log file.
1722
Close the file and delete it.
1724
if trace._trace_file:
1725
# flush the log file, to get all content
1726
trace._trace_file.flush()
1727
trace.pop_log_file(self._log_memento)
1729
def thisFailsStrictLockCheck(self):
1730
"""It is known that this test would fail with -Dstrict_locks.
1732
By default, all tests are run with strict lock checking unless
1733
-Edisable_lock_checks is supplied. However there are some tests which
1734
we know fail strict locks at this point that have not been fixed.
1735
They should call this function to disable the strict checking.
1737
This should be used sparingly, it is much better to fix the locking
1738
issues rather than papering over the problem by calling this function.
1740
debug.debug_flags.discard('strict_locks')
1742
def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1743
"""Overrides an object attribute restoring it after the test.
1745
:note: This should be used with discretion; you should think about
1746
whether it's better to make the code testable without monkey-patching.
1748
:param obj: The object that will be mutated.
1750
:param attr_name: The attribute name we want to preserve/override in
1753
:param new: The optional value we want to set the attribute to.
1755
:returns: The actual attr value.
1757
value = getattr(obj, attr_name)
1758
# The actual value is captured by the call below
1759
self.addCleanup(setattr, obj, attr_name, value)
1760
if new is not _unitialized_attr:
1761
setattr(obj, attr_name, new)
1764
def overrideEnv(self, name, new):
1765
"""Set an environment variable, and reset it after the test.
1767
:param name: The environment variable name.
1769
:param new: The value to set the variable to. If None, the
1770
variable is deleted from the environment.
1772
:returns: The actual variable value.
1774
value = osutils.set_or_unset_env(name, new)
1775
self.addCleanup(osutils.set_or_unset_env, name, value)
1778
def recordCalls(self, obj, attr_name):
1779
"""Monkeypatch in a wrapper that will record calls.
1781
The monkeypatch is automatically removed when the test concludes.
1783
:param obj: The namespace holding the reference to be replaced;
1784
typically a module, class, or object.
1785
:param attr_name: A string for the name of the attribute to
1787
:returns: A list that will be extended with one item every time the
1788
function is called, with a tuple of (args, kwargs).
1792
def decorator(*args, **kwargs):
1793
calls.append((args, kwargs))
1794
return orig(*args, **kwargs)
1795
orig = self.overrideAttr(obj, attr_name, decorator)
1049
Close the file and delete it, unless setKeepLogfile was called.
1051
if self._log_file is None:
1053
bzrlib.trace.disable_test_log(self._log_nonce)
1054
self._log_file.close()
1055
self._log_file = None
1056
if not self._keep_log_file:
1057
os.remove(self._log_file_name)
1058
self._log_file_name = None
1060
def setKeepLogfile(self):
1061
"""Make the logfile not be deleted when _finishLogFile is called."""
1062
self._keep_log_file = True
1064
def addCleanup(self, callable):
1065
"""Arrange to run a callable when this case is torn down.
1067
Callables are run in the reverse of the order they are registered,
1068
ie last-in first-out.
1070
if callable in self._cleanups:
1071
raise ValueError("cleanup function %r already registered on %s"
1073
self._cleanups.append(callable)
1798
1075
def _cleanEnvironment(self):
1799
for name, value in isolated_environ.iteritems():
1800
self.overrideEnv(name, value)
1077
'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1078
'HOME': os.getcwd(),
1079
'APPDATA': None, # bzr now use Win32 API and don't rely on APPDATA
1081
'BZREMAIL': None, # may still be present in the environment
1083
'BZR_PROGRESS_BAR': None,
1087
'https_proxy': None,
1088
'HTTPS_PROXY': None,
1093
# Nobody cares about these ones AFAIK. So far at
1094
# least. If you do (care), please update this comment
1098
'BZR_REMOTE_PATH': None,
1101
self.addCleanup(self._restoreEnvironment)
1102
for name, value in new_env.iteritems():
1103
self._captureVar(name, value)
1105
def _captureVar(self, name, newvalue):
1106
"""Set an environment variable, and reset it when finished."""
1107
self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1109
def _restore_debug_flags(self):
1110
debug.debug_flags.clear()
1111
debug.debug_flags.update(self._preserved_debug_flags)
1113
def _restoreEnvironment(self):
1114
for name, value in self.__old_env.iteritems():
1115
osutils.set_or_unset_env(name, value)
1802
1117
def _restoreHooks(self):
1803
for klass, (name, hooks) in self._preserved_hooks.items():
1804
setattr(klass, name, hooks)
1805
self._preserved_hooks.clear()
1806
bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1807
self._preserved_lazy_hooks.clear()
1118
for klass, hooks in self._preserved_hooks.items():
1119
setattr(klass, 'hooks', hooks)
1809
1121
def knownFailure(self, reason):
1810
"""Declare that this test fails for a known reason
1812
Tests that are known to fail should generally be using expectedFailure
1813
with an appropriate reverse assertion if a change could cause the test
1814
to start passing. Conversely if the test has no immediate prospect of
1815
succeeding then using skip is more suitable.
1817
When this method is called while an exception is being handled, that
1818
traceback will be used, otherwise a new exception will be thrown to
1819
provide one but won't be reported.
1821
self._add_reason(reason)
1823
exc_info = sys.exc_info()
1824
if exc_info != (None, None, None):
1825
self._report_traceback(exc_info)
1828
raise self.failureException(reason)
1829
except self.failureException:
1830
exc_info = sys.exc_info()
1831
# GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
1832
raise testtools.testcase._ExpectedFailure(exc_info)
1836
def _suppress_log(self):
1837
"""Remove the log info from details."""
1838
self.discardDetail('log')
1840
def _do_skip(self, result, reason):
1841
self._suppress_log()
1842
addSkip = getattr(result, 'addSkip', None)
1843
if not callable(addSkip):
1844
result.addSuccess(result)
1846
addSkip(self, reason)
1849
def _do_known_failure(self, result, e):
1850
self._suppress_log()
1851
err = sys.exc_info()
1852
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1853
if addExpectedFailure is not None:
1854
addExpectedFailure(self, err)
1856
result.addSuccess(self)
1859
def _do_not_applicable(self, result, e):
1861
reason = 'No reason given'
1864
self._suppress_log ()
1865
addNotApplicable = getattr(result, 'addNotApplicable', None)
1866
if addNotApplicable is not None:
1867
result.addNotApplicable(self, reason)
1869
self._do_skip(result, reason)
1872
def _report_skip(self, result, err):
1873
"""Override the default _report_skip.
1875
We want to strip the 'log' detail. If we waint until _do_skip, it has
1876
already been formatted into the 'reason' string, and we can't pull it
1879
self._suppress_log()
1880
super(TestCase, self)._report_skip(self, result, err)
1883
def _report_expected_failure(self, result, err):
1886
See _report_skip for motivation.
1888
self._suppress_log()
1889
super(TestCase, self)._report_expected_failure(self, result, err)
1892
def _do_unsupported_or_skip(self, result, e):
1894
self._suppress_log()
1895
addNotSupported = getattr(result, 'addNotSupported', None)
1896
if addNotSupported is not None:
1897
result.addNotSupported(self, reason)
1899
self._do_skip(result, reason)
1122
"""This test has failed for some known reason."""
1123
raise KnownFailure(reason)
1125
def run(self, result=None):
1126
if result is None: result = self.defaultTestResult()
1127
for feature in getattr(self, '_test_needs_features', []):
1128
if not feature.available():
1129
result.startTest(self)
1130
if getattr(result, 'addNotSupported', None):
1131
result.addNotSupported(self, feature)
1133
result.addSuccess(self)
1134
result.stopTest(self)
1136
return unittest.TestCase.run(self, result)
1140
unittest.TestCase.tearDown(self)
1901
1142
def time(self, callable, *args, **kwargs):
1902
1143
"""Run callable and accrue the time it takes to the benchmark time.
1904
1145
If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1905
1146
this will cause lsprofile statistics to be gathered and stored in
1906
1147
self._benchcalls.
1908
1149
if self._benchtime is None:
1909
self.addDetail('benchtime', content.Content(content.ContentType(
1910
"text", "plain"), lambda:[str(self._benchtime)]))
1911
1150
self._benchtime = 0
1912
1151
start = time.time()
2557
1772
base = self.get_vfs_only_server().get_url()
2558
1773
return self._adjust_url(base, relpath)
2560
def _create_safety_net(self):
2561
"""Make a fake bzr directory.
2563
This prevents any tests propagating up onto the TEST_ROOT directory's
2566
root = TestCaseWithMemoryTransport.TEST_ROOT
2568
# Make sure we get a readable and accessible home for .bzr.log
2569
# and/or config files, and not fallback to weird defaults (see
2570
# http://pad.lv/825027).
2571
self.assertIs(None, os.environ.get('BZR_HOME', None))
2572
os.environ['BZR_HOME'] = root
2573
wt = bzrdir.BzrDir.create_standalone_workingtree(root)
2574
del os.environ['BZR_HOME']
2575
except Exception, e:
2576
self.fail("Fail to initialize the safety net: %r\nExiting\n" % (e,))
2577
# Hack for speed: remember the raw bytes of the dirstate file so that
2578
# we don't need to re-open the wt to check it hasn't changed.
2579
TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2580
wt.control_transport.get_bytes('dirstate'))
2582
def _check_safety_net(self):
2583
"""Check that the safety .bzr directory have not been touched.
2585
_make_test_root have created a .bzr directory to prevent tests from
2586
propagating. This method ensures than a test did not leaked.
2588
root = TestCaseWithMemoryTransport.TEST_ROOT
2589
t = _mod_transport.get_transport_from_path(root)
2590
self.permit_url(t.base)
2591
if (t.get_bytes('.bzr/checkout/dirstate') !=
2592
TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE):
2593
# The current test have modified the /bzr directory, we need to
2594
# recreate a new one or all the followng tests will fail.
2595
# If you need to inspect its content uncomment the following line
2596
# import pdb; pdb.set_trace()
2597
_rmtree_temp_dir(root + '/.bzr', test_id=self.id())
2598
self._create_safety_net()
2599
raise AssertionError('%s/.bzr should not be modified' % root)
2601
1775
def _make_test_root(self):
2602
if TestCaseWithMemoryTransport.TEST_ROOT is None:
2603
# Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
2604
root = osutils.realpath(osutils.mkdtemp(prefix='testbzr-',
2606
TestCaseWithMemoryTransport.TEST_ROOT = root
2608
self._create_safety_net()
2610
# The same directory is used by all tests, and we're not
2611
# specifically told when all tests are finished. This will do.
2612
atexit.register(_rmtree_temp_dir, root)
2614
self.permit_dir(TestCaseWithMemoryTransport.TEST_ROOT)
2615
self.addCleanup(self._check_safety_net)
1776
if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1778
root = tempfile.mkdtemp(prefix='testbzr-', suffix='.tmp')
1779
TestCaseWithMemoryTransport.TEST_ROOT = root
1781
# make a fake bzr directory there to prevent any tests propagating
1782
# up onto the source directory's real branch
1783
bzrdir.BzrDir.create_standalone_workingtree(root)
1785
# The same directory is used by all tests, and we're not specifically
1786
# told when all tests are finished. This will do.
1787
atexit.register(_rmtree_temp_dir, root)
2617
1789
def makeAndChdirToTestDir(self):
2618
1790
"""Create a temporary directories for this one test.
2620
1792
This must set self.test_home_dir and self.test_dir and chdir to
2623
1795
For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
2625
1797
os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2626
1798
self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
2627
1799
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2628
self.permit_dir(self.test_dir)
2630
1801
def make_branch(self, relpath, format=None):
2631
1802
"""Create a branch on the transport at relpath."""
2632
1803
repo = self.make_repository(relpath, format=format)
2633
return repo.bzrdir.create_branch(append_revisions_only=False)
2635
def resolve_format(self, format):
2636
"""Resolve an object to a ControlDir format object.
2638
The initial format object can either already be
2639
a ControlDirFormat, None (for the default format),
2640
or a string with the name of the control dir format.
2642
:param format: Object to resolve
2643
:return A ControlDirFormat instance
2647
if isinstance(format, basestring):
2648
format = bzrdir.format_registry.make_bzrdir(format)
2651
def resolve_format(self, format):
2652
"""Resolve an object to a ControlDir format object.
2654
The initial format object can either already be
2655
a ControlDirFormat, None (for the default format),
2656
or a string with the name of the control dir format.
2658
:param format: Object to resolve
2659
:return A ControlDirFormat instance
2663
if isinstance(format, basestring):
2664
format = bzrdir.format_registry.make_bzrdir(format)
1804
return repo.bzrdir.create_branch()
2667
1806
def make_bzrdir(self, relpath, format=None):
2669
1808
# might be a relative or absolute path
2670
1809
maybe_a_url = self.get_url(relpath)
2671
1810
segments = maybe_a_url.rsplit('/', 1)
2672
t = _mod_transport.get_transport(maybe_a_url)
1811
t = get_transport(maybe_a_url)
2673
1812
if len(segments) > 1 and segments[-1] not in ('', '.'):
2674
1813
t.ensure_base()
2675
format = self.resolve_format(format)
1816
if isinstance(format, basestring):
1817
format = bzrdir.format_registry.make_bzrdir(format)
2676
1818
return format.initialize_on_transport(t)
2677
1819
except errors.UninitializableFormat:
2678
1820
raise TestSkipped("Format %s is not initializable." % format)
2680
def make_repository(self, relpath, shared=None, format=None):
1822
def make_repository(self, relpath, shared=False, format=None):
2681
1823
"""Create a repository on our default transport at relpath.
2683
1825
Note that relpath must be a relative path, not a full url.
2685
1827
# FIXME: If you create a remoterepository this returns the underlying
2686
# real format, which is incorrect. Actually we should make sure that
1828
# real format, which is incorrect. Actually we should make sure that
2687
1829
# RemoteBzrDir returns a RemoteRepository.
2688
1830
# maybe mbp 20070410
2689
1831
made_control = self.make_bzrdir(relpath, format=format)
2690
1832
return made_control.create_repository(shared=shared)
2692
def make_smart_server(self, path, backing_server=None):
2693
if backing_server is None:
2694
backing_server = self.get_server()
2695
smart_server = test_server.SmartTCPServer_for_testing()
2696
self.start_server(smart_server, backing_server)
2697
remote_transport = _mod_transport.get_transport_from_url(smart_server.get_url()
2699
return remote_transport
2701
1834
def make_branch_and_memory_tree(self, relpath, format=None):
2702
1835
"""Create a branch on the default transport and a MemoryTree for it."""
2703
1836
b = self.make_branch(relpath, format=format)
2704
1837
return memorytree.MemoryTree.create_on_branch(b)
2706
def make_branch_builder(self, relpath, format=None):
2707
branch = self.make_branch(relpath, format=format)
2708
return branchbuilder.BranchBuilder(branch=branch)
2710
1839
def overrideEnvironmentForTesting(self):
2711
test_home_dir = self.test_home_dir
2712
if isinstance(test_home_dir, unicode):
2713
test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2714
self.overrideEnv('HOME', test_home_dir)
2715
self.overrideEnv('BZR_HOME', test_home_dir)
1840
os.environ['HOME'] = self.test_home_dir
1841
os.environ['BZR_HOME'] = self.test_home_dir
2717
1843
def setUp(self):
2718
1844
super(TestCaseWithMemoryTransport, self).setUp()
2719
# Ensure that ConnectedTransport doesn't leak sockets
2720
def get_transport_from_url_with_cleanup(*args, **kwargs):
2721
t = orig_get_transport_from_url(*args, **kwargs)
2722
if isinstance(t, _mod_transport.ConnectedTransport):
2723
self.addCleanup(t.disconnect)
2726
orig_get_transport_from_url = self.overrideAttr(
2727
_mod_transport, 'get_transport_from_url',
2728
get_transport_from_url_with_cleanup)
2729
1845
self._make_test_root()
2730
self.addCleanup(os.chdir, os.getcwdu())
1846
_currentdir = os.getcwdu()
1847
def _leaveDirectory():
1848
os.chdir(_currentdir)
1849
self.addCleanup(_leaveDirectory)
2731
1850
self.makeAndChdirToTestDir()
2732
1851
self.overrideEnvironmentForTesting()
2733
1852
self.__readonly_server = None
2734
1853
self.__server = None
2735
1854
self.reduceLockdirTimeout()
2737
def setup_smart_server_with_call_log(self):
2738
"""Sets up a smart server as the transport server with a call log."""
2739
self.transport_server = test_server.SmartTCPServer_for_testing
2740
self.hpss_calls = []
2742
# Skip the current stack down to the caller of
2743
# setup_smart_server_with_call_log
2744
prefix_length = len(traceback.extract_stack()) - 2
2745
def capture_hpss_call(params):
2746
self.hpss_calls.append(
2747
CapturedCall(params, prefix_length))
2748
client._SmartClient.hooks.install_named_hook(
2749
'call', capture_hpss_call, None)
2751
def reset_smart_call_log(self):
2752
self.hpss_calls = []
2755
1857
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2756
1858
"""Derived class that runs a test within a temporary directory.
3024
2092
for readonly urls.
3026
2094
TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
3027
be used without needed to redo it when a different
2095
be used without needed to redo it when a different
3028
2096
subclass is in use ?
3031
2099
def setUp(self):
3032
from bzrlib.tests import http_server
3033
2100
super(ChrootedTestCase, self).setUp()
3034
if not self.vfs_transport_factory == memory.MemoryServer:
3035
self.transport_readonly_server = http_server.HttpServer
3038
def condition_id_re(pattern):
3039
"""Create a condition filter which performs a re check on a test's id.
3041
:param pattern: A regular expression string.
3042
:return: A callable that returns True if the re matches.
3044
filter_re = re.compile(pattern, 0)
3045
def condition(test):
2101
if not self.vfs_transport_factory == MemoryServer:
2102
self.transport_readonly_server = HttpServer
2105
def filter_suite_by_re(suite, pattern, exclude_pattern=None,
2106
random_order=False):
2107
"""Create a test suite by filtering another one.
2109
:param suite: the source suite
2110
:param pattern: pattern that names must match
2111
:param exclude_pattern: pattern that names must not match, if any
2112
:param random_order: if True, tests in the new suite will be put in
2114
:returns: the newly created suite
2116
return sort_suite_by_re(suite, pattern, exclude_pattern,
2117
random_order, False)
2120
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
2121
random_order=False, append_rest=True):
2122
"""Create a test suite by sorting another one.
2124
:param suite: the source suite
2125
:param pattern: pattern that names must match in order to go
2126
first in the new suite
2127
:param exclude_pattern: pattern that names must not match, if any
2128
:param random_order: if True, tests in the new suite will be put in
2130
:param append_rest: if False, pattern is a strict filter and not
2131
just an ordering directive
2132
:returns: the newly created suite
2136
filter_re = re.compile(pattern)
2137
if exclude_pattern is not None:
2138
exclude_re = re.compile(exclude_pattern)
2139
for test in iter_suite_tests(suite):
3046
2140
test_id = test.id()
3047
return filter_re.search(test_id)
3051
def condition_isinstance(klass_or_klass_list):
3052
"""Create a condition filter which returns isinstance(param, klass).
3054
:return: A callable which when called with one parameter obj return the
3055
result of isinstance(obj, klass_or_klass_list).
3058
return isinstance(obj, klass_or_klass_list)
3062
def condition_id_in_list(id_list):
3063
"""Create a condition filter which verify that test's id in a list.
3065
:param id_list: A TestIdList object.
3066
:return: A callable that returns True if the test's id appears in the list.
3068
def condition(test):
3069
return id_list.includes(test.id())
3073
def condition_id_startswith(starts):
3074
"""Create a condition filter verifying that test's id starts with a string.
3076
:param starts: A list of string.
3077
:return: A callable that returns True if the test's id starts with one of
3080
def condition(test):
3081
for start in starts:
3082
if test.id().startswith(start):
3088
def exclude_tests_by_condition(suite, condition):
3089
"""Create a test suite which excludes some tests from suite.
3091
:param suite: The suite to get tests from.
3092
:param condition: A callable whose result evaluates True when called with a
3093
test case which should be excluded from the result.
3094
:return: A suite which contains the tests found in suite that fail
3098
for test in iter_suite_tests(suite):
3099
if not condition(test):
3101
return TestUtil.TestSuite(result)
3104
def filter_suite_by_condition(suite, condition):
3105
"""Create a test suite by filtering another one.
3107
:param suite: The source suite.
3108
:param condition: A callable whose result evaluates True when called with a
3109
test case which should be included in the result.
3110
:return: A suite which contains the tests found in suite that pass
3114
for test in iter_suite_tests(suite):
3117
return TestUtil.TestSuite(result)
3120
def filter_suite_by_re(suite, pattern):
3121
"""Create a test suite by filtering another one.
3123
:param suite: the source suite
3124
:param pattern: pattern that names must match
3125
:returns: the newly created suite
3127
condition = condition_id_re(pattern)
3128
result_suite = filter_suite_by_condition(suite, condition)
3132
def filter_suite_by_id_list(suite, test_id_list):
3133
"""Create a test suite by filtering another one.
3135
:param suite: The source suite.
3136
:param test_id_list: A list of the test ids to keep as strings.
3137
:returns: the newly created suite
3139
condition = condition_id_in_list(test_id_list)
3140
result_suite = filter_suite_by_condition(suite, condition)
3144
def filter_suite_by_id_startswith(suite, start):
3145
"""Create a test suite by filtering another one.
3147
:param suite: The source suite.
3148
:param start: A list of string the test id must start with one of.
3149
:returns: the newly created suite
3151
condition = condition_id_startswith(start)
3152
result_suite = filter_suite_by_condition(suite, condition)
3156
def exclude_tests_by_re(suite, pattern):
3157
"""Create a test suite which excludes some tests from suite.
3159
:param suite: The suite to get tests from.
3160
:param pattern: A regular expression string. Test ids that match this
3161
pattern will be excluded from the result.
3162
:return: A TestSuite that contains all the tests from suite without the
3163
tests that matched pattern. The order of tests is the same as it was in
3166
return exclude_tests_by_condition(suite, condition_id_re(pattern))
3169
def preserve_input(something):
3170
"""A helper for performing test suite transformation chains.
3172
:param something: Anything you want to preserve.
3178
def randomize_suite(suite):
3179
"""Return a new TestSuite with suite's tests in random order.
3181
The tests in the input suite are flattened into a single suite in order to
3182
accomplish this. Any nested TestSuites are removed to provide global
3185
tests = list(iter_suite_tests(suite))
3186
random.shuffle(tests)
3187
return TestUtil.TestSuite(tests)
3190
def split_suite_by_condition(suite, condition):
3191
"""Split a test suite into two by a condition.
3193
:param suite: The suite to split.
3194
:param condition: The condition to match on. Tests that match this
3195
condition are returned in the first test suite, ones that do not match
3196
are in the second suite.
3197
:return: A tuple of two test suites, where the first contains tests from
3198
suite matching the condition, and the second contains the remainder
3199
from suite. The order within each output suite is the same as it was in
3204
for test in iter_suite_tests(suite):
3206
matched.append(test)
3208
did_not_match.append(test)
3209
return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
3212
def split_suite_by_re(suite, pattern):
3213
"""Split a test suite into two by a regular expression.
3215
:param suite: The suite to split.
3216
:param pattern: A regular expression string. Test ids that match this
3217
pattern will be in the first test suite returned, and the others in the
3218
second test suite returned.
3219
:return: A tuple of two test suites, where the first contains tests from
3220
suite matching pattern, and the second contains the remainder from
3221
suite. The order within each output suite is the same as it was in
3224
return split_suite_by_condition(suite, condition_id_re(pattern))
2141
if exclude_pattern is None or not exclude_re.search(test_id):
2142
if filter_re.search(test_id):
2147
random.shuffle(first)
2148
random.shuffle(second)
2149
return TestUtil.TestSuite(first + second)
3227
2152
def run_suite(suite, name='test', verbose=False, pattern=".*",
3231
2156
list_only=False,
3232
2157
random_seed=None,
3233
2158
exclude_pattern=None,
3236
suite_decorators=None,
3238
result_decorators=None,
3240
"""Run a test suite for bzr selftest.
3242
:param runner_class: The class of runner to use. Must support the
3243
constructor arguments passed by run_suite which are more than standard
3245
:return: A boolean indicating success.
3247
2160
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
3252
if runner_class is None:
3253
runner_class = TextTestRunner
3256
runner = runner_class(stream=stream,
2165
runner = TextTestRunner(stream=sys.stdout,
3257
2166
descriptions=0,
3258
2167
verbosity=verbosity,
3259
2168
bench_history=bench_history,
3261
result_decorators=result_decorators,
2169
list_only=list_only,
3263
2171
runner.stop_on_failure=stop_on_failure
3264
# built in decorator factories:
3266
random_order(random_seed, runner),
3267
exclude_tests(exclude_pattern),
3269
if matching_tests_first:
3270
decorators.append(tests_first(pattern))
3272
decorators.append(filter_tests(pattern))
3273
if suite_decorators:
3274
decorators.extend(suite_decorators)
3275
# tell the result object how many tests will be running: (except if
3276
# --parallel=fork is being used. Robert said he will provide a better
3277
# progress design later -- vila 20090817)
3278
if fork_decorator not in decorators:
3279
decorators.append(CountingDecorator)
3280
for decorator in decorators:
3281
suite = decorator(suite)
3283
# Done after test suite decoration to allow randomisation etc
3284
# to take effect, though that is of marginal benefit.
3286
stream.write("Listing tests only ...\n")
3287
for t in iter_suite_tests(suite):
3288
stream.write("%s\n" % (t.id()))
3290
result = runner.run(suite)
3292
return result.wasStrictlySuccessful()
3294
return result.wasSuccessful()
3297
# A registry where get() returns a suite decorator.
3298
parallel_registry = registry.Registry()
3301
def fork_decorator(suite):
3302
if getattr(os, "fork", None) is None:
3303
raise errors.BzrCommandError("platform does not support fork,"
3304
" try --parallel=subprocess instead.")
3305
concurrency = osutils.local_concurrency()
3306
if concurrency == 1:
3308
from testtools import ConcurrentTestSuite
3309
return ConcurrentTestSuite(suite, fork_for_tests)
3310
parallel_registry.register('fork', fork_decorator)
3313
def subprocess_decorator(suite):
3314
concurrency = osutils.local_concurrency()
3315
if concurrency == 1:
3317
from testtools import ConcurrentTestSuite
3318
return ConcurrentTestSuite(suite, reinvoke_for_tests)
3319
parallel_registry.register('subprocess', subprocess_decorator)
3322
def exclude_tests(exclude_pattern):
3323
"""Return a test suite decorator that excludes tests."""
3324
if exclude_pattern is None:
3325
return identity_decorator
3326
def decorator(suite):
3327
return ExcludeDecorator(suite, exclude_pattern)
3331
def filter_tests(pattern):
3333
return identity_decorator
3334
def decorator(suite):
3335
return FilterTestsDecorator(suite, pattern)
3339
def random_order(random_seed, runner):
3340
"""Return a test suite decorator factory for randomising tests order.
3342
:param random_seed: now, a string which casts to a long, or a long.
3343
:param runner: A test runner with a stream attribute to report on.
3345
if random_seed is None:
3346
return identity_decorator
3347
def decorator(suite):
3348
return RandomDecorator(suite, random_seed, runner.stream)
3352
def tests_first(pattern):
3354
return identity_decorator
3355
def decorator(suite):
3356
return TestFirstDecorator(suite, pattern)
3360
def identity_decorator(suite):
3365
class TestDecorator(TestUtil.TestSuite):
3366
"""A decorator for TestCase/TestSuite objects.
3368
Usually, subclasses should override __iter__(used when flattening test
3369
suites), which we do to filter, reorder, parallelise and so on, run() and
3373
def __init__(self, suite):
3374
TestUtil.TestSuite.__init__(self)
3377
def countTestCases(self):
3380
cases += test.countTestCases()
3387
def run(self, result):
3388
# Use iteration on self, not self._tests, to allow subclasses to hook
3391
if result.shouldStop:
3397
class CountingDecorator(TestDecorator):
3398
"""A decorator which calls result.progress(self.countTestCases)."""
3400
def run(self, result):
3401
progress_method = getattr(result, 'progress', None)
3402
if callable(progress_method):
3403
progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
3404
return super(CountingDecorator, self).run(result)
3407
class ExcludeDecorator(TestDecorator):
3408
"""A decorator which excludes test matching an exclude pattern."""
3410
def __init__(self, suite, exclude_pattern):
3411
TestDecorator.__init__(self, suite)
3412
self.exclude_pattern = exclude_pattern
3413
self.excluded = False
3417
return iter(self._tests)
3418
self.excluded = True
3419
suite = exclude_tests_by_re(self, self.exclude_pattern)
3421
self.addTests(suite)
3422
return iter(self._tests)
3425
class FilterTestsDecorator(TestDecorator):
3426
"""A decorator which filters tests to those matching a pattern."""
3428
def __init__(self, suite, pattern):
3429
TestDecorator.__init__(self, suite)
3430
self.pattern = pattern
3431
self.filtered = False
3435
return iter(self._tests)
3436
self.filtered = True
3437
suite = filter_suite_by_re(self, self.pattern)
3439
self.addTests(suite)
3440
return iter(self._tests)
3443
class RandomDecorator(TestDecorator):
3444
"""A decorator which randomises the order of its tests."""
3446
def __init__(self, suite, random_seed, stream):
3447
TestDecorator.__init__(self, suite)
3448
self.random_seed = random_seed
3449
self.randomised = False
3450
self.stream = stream
3454
return iter(self._tests)
3455
self.randomised = True
3456
self.stream.write("Randomizing test order using seed %s\n\n" %
3457
(self.actual_seed()))
3458
# Initialise the random number generator.
3459
random.seed(self.actual_seed())
3460
suite = randomize_suite(self)
3462
self.addTests(suite)
3463
return iter(self._tests)
3465
def actual_seed(self):
3466
if self.random_seed == "now":
3467
# We convert the seed to a long to make it reuseable across
3468
# invocations (because the user can reenter it).
3469
self.random_seed = long(time.time())
2172
# Initialise the random number generator and display the seed used.
2173
# We convert the seed to a long to make it reuseable across invocations.
2174
random_order = False
2175
if random_seed is not None:
2177
if random_seed == "now":
2178
random_seed = long(time.time())
3471
2180
# Convert the seed to a long if we can
3473
self.random_seed = long(self.random_seed)
2182
random_seed = long(random_seed)
3476
return self.random_seed
3479
class TestFirstDecorator(TestDecorator):
3480
"""A decorator which moves named tests to the front."""
3482
def __init__(self, suite, pattern):
3483
TestDecorator.__init__(self, suite)
3484
self.pattern = pattern
3485
self.filtered = False
3489
return iter(self._tests)
3490
self.filtered = True
3491
suites = split_suite_by_re(self, self.pattern)
3493
self.addTests(suites)
3494
return iter(self._tests)
3497
def partition_tests(suite, count):
3498
"""Partition suite into count lists of tests."""
3499
# This just assigns tests in a round-robin fashion. On one hand this
3500
# splits up blocks of related tests that might run faster if they shared
3501
# resources, but on the other it avoids assigning blocks of slow tests to
3502
# just one partition. So the slowest partition shouldn't be much slower
3504
partitions = [list() for i in range(count)]
3505
tests = iter_suite_tests(suite)
3506
for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3507
partition.append(test)
3511
def workaround_zealous_crypto_random():
3512
"""Crypto.Random want to help us being secure, but we don't care here.
3514
This workaround some test failure related to the sftp server. Once paramiko
3515
stop using the controversial API in Crypto.Random, we may get rid of it.
3518
from Crypto.Random import atfork
3524
def fork_for_tests(suite):
3525
"""Take suite and start up one runner per CPU by forking()
3527
:return: An iterable of TestCase-like objects which can each have
3528
run(result) called on them to feed tests to result.
3530
concurrency = osutils.local_concurrency()
3532
from subunit import TestProtocolClient, ProtocolTestCase
3533
from subunit.test_results import AutoTimingTestResultDecorator
3534
class TestInOtherProcess(ProtocolTestCase):
3535
# Should be in subunit, I think. RBC.
3536
def __init__(self, stream, pid):
3537
ProtocolTestCase.__init__(self, stream)
3540
def run(self, result):
3542
ProtocolTestCase.run(self, result)
3544
os.waitpid(self.pid, 0)
3546
test_blocks = partition_tests(suite, concurrency)
3547
for process_tests in test_blocks:
3548
process_suite = TestUtil.TestSuite()
3549
process_suite.addTests(process_tests)
3550
c2pread, c2pwrite = os.pipe()
3553
workaround_zealous_crypto_random()
3556
# Leave stderr and stdout open so we can see test noise
3557
# Close stdin so that the child goes away if it decides to
3558
# read from stdin (otherwise its a roulette to see what
3559
# child actually gets keystrokes for pdb etc).
3562
stream = os.fdopen(c2pwrite, 'wb', 1)
3563
subunit_result = AutoTimingTestResultDecorator(
3564
TestProtocolClient(stream))
3565
process_suite.run(subunit_result)
2185
runner.stream.writeln("Randomizing test order using seed %s\n" %
2187
random.seed(random_seed)
2188
# Customise the list of tests if requested
2189
if pattern != '.*' or exclude_pattern is not None or random_order:
2190
if matching_tests_first:
2191
suite = sort_suite_by_re(suite, pattern, exclude_pattern,
3570
stream = os.fdopen(c2pread, 'rb', 1)
3571
test = TestInOtherProcess(stream, pid)
3576
def reinvoke_for_tests(suite):
3577
"""Take suite and start up one runner per CPU using subprocess().
3579
:return: An iterable of TestCase-like objects which can each have
3580
run(result) called on them to feed tests to result.
3582
concurrency = osutils.local_concurrency()
3584
from subunit import ProtocolTestCase
3585
class TestInSubprocess(ProtocolTestCase):
3586
def __init__(self, process, name):
3587
ProtocolTestCase.__init__(self, process.stdout)
3588
self.process = process
3589
self.process.stdin.close()
3592
def run(self, result):
3594
ProtocolTestCase.run(self, result)
3597
os.unlink(self.name)
3598
# print "pid %d finished" % finished_process
3599
test_blocks = partition_tests(suite, concurrency)
3600
for process_tests in test_blocks:
3601
# ugly; currently reimplement rather than reuses TestCase methods.
3602
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
3603
if not os.path.isfile(bzr_path):
3604
# We are probably installed. Assume sys.argv is the right file
3605
bzr_path = sys.argv[0]
3606
bzr_path = [bzr_path]
3607
if sys.platform == "win32":
3608
# if we're on windows, we can't execute the bzr script directly
3609
bzr_path = [sys.executable] + bzr_path
3610
fd, test_list_file_name = tempfile.mkstemp()
3611
test_list_file = os.fdopen(fd, 'wb', 1)
3612
for test in process_tests:
3613
test_list_file.write(test.id() + '\n')
3614
test_list_file.close()
3616
argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
3618
if '--no-plugins' in sys.argv:
3619
argv.append('--no-plugins')
3620
# stderr=subprocess.STDOUT would be ideal, but until we prevent
3621
# noise on stderr it can interrupt the subunit protocol.
3622
process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3623
stdout=subprocess.PIPE,
3624
stderr=subprocess.PIPE,
3626
test = TestInSubprocess(process, test_list_file_name)
3629
os.unlink(test_list_file_name)
3634
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3635
"""Generate profiling data for all activity between start and success.
3637
The profile data is appended to the test's _benchcalls attribute and can
3638
be accessed by the forwarded-to TestResult.
3640
While it might be cleaner do accumulate this in stopTest, addSuccess is
3641
where our existing output support for lsprof is, and this class aims to
3642
fit in with that: while it could be moved it's not necessary to accomplish
3643
test profiling, nor would it be dramatically cleaner.
3646
def startTest(self, test):
3647
self.profiler = bzrlib.lsprof.BzrProfiler()
3648
# Prevent deadlocks in tests that use lsprof: those tests will
3650
bzrlib.lsprof.BzrProfiler.profiler_block = 0
3651
self.profiler.start()
3652
testtools.ExtendedToOriginalDecorator.startTest(self, test)
3654
def addSuccess(self, test):
3655
stats = self.profiler.stop()
3657
calls = test._benchcalls
3658
except AttributeError:
3659
test._benchcalls = []
3660
calls = test._benchcalls
3661
calls.append(((test.id(), "", ""), stats))
3662
testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
3664
def stopTest(self, test):
3665
testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3666
self.profiler = None
3669
# Controlled by "bzr selftest -E=..." option
3670
# Currently supported:
3671
# -Eallow_debug Will no longer clear debug.debug_flags() so it
3672
# preserves any flags supplied at the command line.
3673
# -Edisable_lock_checks Turns errors in mismatched locks into simple prints
3674
# rather than failing tests. And no longer raise
3675
# LockContention when fctnl locks are not being used
3676
# with proper exclusion rules.
3677
# -Ethreads Will display thread ident at creation/join time to
3678
# help track thread leaks
3680
# -Econfig_stats Will collect statistics using addDetail
3681
selftest_debug_flags = set()
2194
suite = filter_suite_by_re(suite, pattern, exclude_pattern,
2196
result = runner.run(suite)
2197
return result.wasSuccessful()
3684
2200
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
3743
2231
matching_tests_first=matching_tests_first,
3744
2232
list_only=list_only,
3745
2233
random_seed=random_seed,
3746
exclude_pattern=exclude_pattern,
3748
runner_class=runner_class,
3749
suite_decorators=suite_decorators,
3751
result_decorators=result_decorators,
2234
exclude_pattern=exclude_pattern)
3754
2236
default_transport = old_transport
3755
selftest_debug_flags = old_debug_flags
3758
def load_test_id_list(file_name):
3759
"""Load a test id list from a text file.
3761
The format is one test id by line. No special care is taken to impose
3762
strict rules, these test ids are used to filter the test suite so a test id
3763
that do not match an existing test will do no harm. This allows user to add
3764
comments, leave blank lines, etc.
3768
ftest = open(file_name, 'rt')
3770
if e.errno != errno.ENOENT:
3773
raise errors.NoSuchFile(file_name)
3775
for test_name in ftest.readlines():
3776
test_list.append(test_name.strip())
3781
def suite_matches_id_list(test_suite, id_list):
3782
"""Warns about tests not appearing or appearing more than once.
3784
:param test_suite: A TestSuite object.
3785
:param test_id_list: The list of test ids that should be found in
3788
:return: (absents, duplicates) absents is a list containing the test found
3789
in id_list but not in test_suite, duplicates is a list containing the
3790
test found multiple times in test_suite.
3792
When using a prefined test id list, it may occurs that some tests do not
3793
exist anymore or that some tests use the same id. This function warns the
3794
tester about potential problems in his workflow (test lists are volatile)
3795
or in the test suite itself (using the same id for several tests does not
3796
help to localize defects).
3798
# Build a dict counting id occurrences
3800
for test in iter_suite_tests(test_suite):
3802
tests[id] = tests.get(id, 0) + 1
3807
occurs = tests.get(id, 0)
3809
not_found.append(id)
3811
duplicates.append(id)
3813
return not_found, duplicates
3816
class TestIdList(object):
3817
"""Test id list to filter a test suite.
3819
Relying on the assumption that test ids are built as:
3820
<module>[.<class>.<method>][(<param>+)], <module> being in python dotted
3821
notation, this class offers methods to :
3822
- avoid building a test suite for modules not refered to in the test list,
3823
- keep only the tests listed from the module test suite.
3826
def __init__(self, test_id_list):
3827
# When a test suite needs to be filtered against us we compare test ids
3828
# for equality, so a simple dict offers a quick and simple solution.
3829
self.tests = dict().fromkeys(test_id_list, True)
3831
# While unittest.TestCase have ids like:
3832
# <module>.<class>.<method>[(<param+)],
3833
# doctest.DocTestCase can have ids like:
3836
# <module>.<function>
3837
# <module>.<class>.<method>
3839
# Since we can't predict a test class from its name only, we settle on
3840
# a simple constraint: a test id always begins with its module name.
3843
for test_id in test_id_list:
3844
parts = test_id.split('.')
3845
mod_name = parts.pop(0)
3846
modules[mod_name] = True
3848
mod_name += '.' + part
3849
modules[mod_name] = True
3850
self.modules = modules
3852
def refers_to(self, module_name):
3853
"""Is there tests for the module or one of its sub modules."""
3854
return self.modules.has_key(module_name)
3856
def includes(self, test_id):
3857
return self.tests.has_key(test_id)
3860
class TestPrefixAliasRegistry(registry.Registry):
3861
"""A registry for test prefix aliases.
3863
This helps implement shorcuts for the --starting-with selftest
3864
option. Overriding existing prefixes is not allowed but not fatal (a
3865
warning will be emitted).
3868
def register(self, key, obj, help=None, info=None,
3869
override_existing=False):
3870
"""See Registry.register.
3872
Trying to override an existing alias causes a warning to be emitted,
3873
not a fatal execption.
3876
super(TestPrefixAliasRegistry, self).register(
3877
key, obj, help=help, info=info, override_existing=False)
3879
actual = self.get(key)
3881
'Test prefix alias %s is already used for %s, ignoring %s'
3882
% (key, actual, obj))
3884
def resolve_alias(self, id_start):
3885
"""Replace the alias by the prefix in the given string.
3887
Using an unknown prefix is an error to help catching typos.
3889
parts = id_start.split('.')
3891
parts[0] = self.get(parts[0])
3893
raise errors.BzrCommandError(
3894
'%s is not a known test prefix alias' % parts[0])
3895
return '.'.join(parts)
3898
test_prefix_alias_registry = TestPrefixAliasRegistry()
3899
"""Registry of test prefix aliases."""
3902
# This alias allows to detect typos ('bzrlin.') by making all valid test ids
3903
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
3904
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
3906
# Obvious highest levels prefixes, feel free to add your own via a plugin
3907
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
3908
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
3909
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
3910
test_prefix_alias_registry.register('bb', 'bzrlib.tests.blackbox')
3911
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3914
def _test_suite_testmod_names():
3915
"""Return the standard list of test module names to test."""
3918
'bzrlib.tests.blackbox',
3919
'bzrlib.tests.commands',
3920
'bzrlib.tests.doc_generate',
3921
'bzrlib.tests.per_branch',
3922
'bzrlib.tests.per_bzrdir',
3923
'bzrlib.tests.per_controldir',
3924
'bzrlib.tests.per_controldir_colo',
3925
'bzrlib.tests.per_foreign_vcs',
3926
'bzrlib.tests.per_interrepository',
3927
'bzrlib.tests.per_intertree',
3928
'bzrlib.tests.per_inventory',
3929
'bzrlib.tests.per_interbranch',
3930
'bzrlib.tests.per_lock',
3931
'bzrlib.tests.per_merger',
3932
'bzrlib.tests.per_transport',
3933
'bzrlib.tests.per_tree',
3934
'bzrlib.tests.per_pack_repository',
3935
'bzrlib.tests.per_repository',
3936
'bzrlib.tests.per_repository_chk',
3937
'bzrlib.tests.per_repository_reference',
3938
'bzrlib.tests.per_repository_vf',
3939
'bzrlib.tests.per_uifactory',
3940
'bzrlib.tests.per_versionedfile',
3941
'bzrlib.tests.per_workingtree',
3942
'bzrlib.tests.test__annotator',
3943
'bzrlib.tests.test__bencode',
3944
'bzrlib.tests.test__btree_serializer',
3945
'bzrlib.tests.test__chk_map',
3946
'bzrlib.tests.test__dirstate_helpers',
3947
'bzrlib.tests.test__groupcompress',
3948
'bzrlib.tests.test__known_graph',
3949
'bzrlib.tests.test__rio',
3950
'bzrlib.tests.test__simple_set',
3951
'bzrlib.tests.test__static_tuple',
3952
'bzrlib.tests.test__walkdirs_win32',
3953
'bzrlib.tests.test_ancestry',
3954
'bzrlib.tests.test_annotate',
3955
'bzrlib.tests.test_api',
3956
'bzrlib.tests.test_atomicfile',
3957
'bzrlib.tests.test_bad_files',
3958
'bzrlib.tests.test_bisect_multi',
3959
'bzrlib.tests.test_branch',
3960
'bzrlib.tests.test_branchbuilder',
3961
'bzrlib.tests.test_btree_index',
3962
'bzrlib.tests.test_bugtracker',
3963
'bzrlib.tests.test_bundle',
3964
'bzrlib.tests.test_bzrdir',
3965
'bzrlib.tests.test__chunks_to_lines',
3966
'bzrlib.tests.test_cache_utf8',
3967
'bzrlib.tests.test_chk_map',
3968
'bzrlib.tests.test_chk_serializer',
3969
'bzrlib.tests.test_chunk_writer',
3970
'bzrlib.tests.test_clean_tree',
3971
'bzrlib.tests.test_cleanup',
3972
'bzrlib.tests.test_cmdline',
3973
'bzrlib.tests.test_commands',
3974
'bzrlib.tests.test_commit',
3975
'bzrlib.tests.test_commit_merge',
3976
'bzrlib.tests.test_config',
3977
'bzrlib.tests.test_conflicts',
3978
'bzrlib.tests.test_controldir',
3979
'bzrlib.tests.test_counted_lock',
3980
'bzrlib.tests.test_crash',
3981
'bzrlib.tests.test_decorators',
3982
'bzrlib.tests.test_delta',
3983
'bzrlib.tests.test_debug',
3984
'bzrlib.tests.test_diff',
3985
'bzrlib.tests.test_directory_service',
3986
'bzrlib.tests.test_dirstate',
3987
'bzrlib.tests.test_email_message',
3988
'bzrlib.tests.test_eol_filters',
3989
'bzrlib.tests.test_errors',
3990
'bzrlib.tests.test_estimate_compressed_size',
3991
'bzrlib.tests.test_export',
3992
'bzrlib.tests.test_export_pot',
3993
'bzrlib.tests.test_extract',
3994
'bzrlib.tests.test_features',
3995
'bzrlib.tests.test_fetch',
3996
'bzrlib.tests.test_fixtures',
3997
'bzrlib.tests.test_fifo_cache',
3998
'bzrlib.tests.test_filters',
3999
'bzrlib.tests.test_filter_tree',
4000
'bzrlib.tests.test_ftp_transport',
4001
'bzrlib.tests.test_foreign',
4002
'bzrlib.tests.test_generate_docs',
4003
'bzrlib.tests.test_generate_ids',
4004
'bzrlib.tests.test_globbing',
4005
'bzrlib.tests.test_gpg',
4006
'bzrlib.tests.test_graph',
4007
'bzrlib.tests.test_groupcompress',
4008
'bzrlib.tests.test_hashcache',
4009
'bzrlib.tests.test_help',
4010
'bzrlib.tests.test_hooks',
4011
'bzrlib.tests.test_http',
4012
'bzrlib.tests.test_http_response',
4013
'bzrlib.tests.test_https_ca_bundle',
4014
'bzrlib.tests.test_i18n',
4015
'bzrlib.tests.test_identitymap',
4016
'bzrlib.tests.test_ignores',
4017
'bzrlib.tests.test_index',
4018
'bzrlib.tests.test_import_tariff',
4019
'bzrlib.tests.test_info',
4020
'bzrlib.tests.test_inv',
4021
'bzrlib.tests.test_inventory_delta',
4022
'bzrlib.tests.test_knit',
4023
'bzrlib.tests.test_lazy_import',
4024
'bzrlib.tests.test_lazy_regex',
4025
'bzrlib.tests.test_library_state',
4026
'bzrlib.tests.test_lock',
4027
'bzrlib.tests.test_lockable_files',
4028
'bzrlib.tests.test_lockdir',
4029
'bzrlib.tests.test_log',
4030
'bzrlib.tests.test_lru_cache',
4031
'bzrlib.tests.test_lsprof',
4032
'bzrlib.tests.test_mail_client',
4033
'bzrlib.tests.test_matchers',
4034
'bzrlib.tests.test_memorytree',
4035
'bzrlib.tests.test_merge',
4036
'bzrlib.tests.test_merge3',
4037
'bzrlib.tests.test_merge_core',
4038
'bzrlib.tests.test_merge_directive',
4039
'bzrlib.tests.test_mergetools',
4040
'bzrlib.tests.test_missing',
4041
'bzrlib.tests.test_msgeditor',
4042
'bzrlib.tests.test_multiparent',
4043
'bzrlib.tests.test_mutabletree',
4044
'bzrlib.tests.test_nonascii',
4045
'bzrlib.tests.test_options',
4046
'bzrlib.tests.test_osutils',
4047
'bzrlib.tests.test_osutils_encodings',
4048
'bzrlib.tests.test_pack',
4049
'bzrlib.tests.test_patch',
4050
'bzrlib.tests.test_patches',
4051
'bzrlib.tests.test_permissions',
4052
'bzrlib.tests.test_plugins',
4053
'bzrlib.tests.test_progress',
4054
'bzrlib.tests.test_pyutils',
4055
'bzrlib.tests.test_read_bundle',
4056
'bzrlib.tests.test_reconcile',
4057
'bzrlib.tests.test_reconfigure',
4058
'bzrlib.tests.test_registry',
4059
'bzrlib.tests.test_remote',
4060
'bzrlib.tests.test_rename_map',
4061
'bzrlib.tests.test_repository',
4062
'bzrlib.tests.test_revert',
4063
'bzrlib.tests.test_revision',
4064
'bzrlib.tests.test_revisionspec',
4065
'bzrlib.tests.test_revisiontree',
4066
'bzrlib.tests.test_rio',
4067
'bzrlib.tests.test_rules',
4068
'bzrlib.tests.test_sampler',
4069
'bzrlib.tests.test_scenarios',
4070
'bzrlib.tests.test_script',
4071
'bzrlib.tests.test_selftest',
4072
'bzrlib.tests.test_serializer',
4073
'bzrlib.tests.test_setup',
4074
'bzrlib.tests.test_sftp_transport',
4075
'bzrlib.tests.test_shelf',
4076
'bzrlib.tests.test_shelf_ui',
4077
'bzrlib.tests.test_smart',
4078
'bzrlib.tests.test_smart_add',
4079
'bzrlib.tests.test_smart_request',
4080
'bzrlib.tests.test_smart_signals',
4081
'bzrlib.tests.test_smart_transport',
4082
'bzrlib.tests.test_smtp_connection',
4083
'bzrlib.tests.test_source',
4084
'bzrlib.tests.test_ssh_transport',
4085
'bzrlib.tests.test_status',
4086
'bzrlib.tests.test_store',
4087
'bzrlib.tests.test_strace',
4088
'bzrlib.tests.test_subsume',
4089
'bzrlib.tests.test_switch',
4090
'bzrlib.tests.test_symbol_versioning',
4091
'bzrlib.tests.test_tag',
4092
'bzrlib.tests.test_test_server',
4093
'bzrlib.tests.test_testament',
4094
'bzrlib.tests.test_textfile',
4095
'bzrlib.tests.test_textmerge',
4096
'bzrlib.tests.test_cethread',
4097
'bzrlib.tests.test_timestamp',
4098
'bzrlib.tests.test_trace',
4099
'bzrlib.tests.test_transactions',
4100
'bzrlib.tests.test_transform',
4101
'bzrlib.tests.test_transport',
4102
'bzrlib.tests.test_transport_log',
4103
'bzrlib.tests.test_tree',
4104
'bzrlib.tests.test_treebuilder',
4105
'bzrlib.tests.test_treeshape',
4106
'bzrlib.tests.test_tsort',
4107
'bzrlib.tests.test_tuned_gzip',
4108
'bzrlib.tests.test_ui',
4109
'bzrlib.tests.test_uncommit',
4110
'bzrlib.tests.test_upgrade',
4111
'bzrlib.tests.test_upgrade_stacked',
4112
'bzrlib.tests.test_urlutils',
4113
'bzrlib.tests.test_utextwrap',
4114
'bzrlib.tests.test_version',
4115
'bzrlib.tests.test_version_info',
4116
'bzrlib.tests.test_versionedfile',
4117
'bzrlib.tests.test_weave',
4118
'bzrlib.tests.test_whitebox',
4119
'bzrlib.tests.test_win32utils',
4120
'bzrlib.tests.test_workingtree',
4121
'bzrlib.tests.test_workingtree_4',
4122
'bzrlib.tests.test_wsgi',
4123
'bzrlib.tests.test_xml',
4127
def _test_suite_modules_to_doctest():
4128
"""Return the list of modules to doctest."""
4130
# GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
4134
'bzrlib.branchbuilder',
4135
'bzrlib.decorators',
4137
'bzrlib.iterablefile',
4142
'bzrlib.symbol_versioning',
4144
'bzrlib.tests.fixtures',
4146
'bzrlib.transport.http',
4147
'bzrlib.version_info_formats.format_custom',
4151
def test_suite(keep_only=None, starting_with=None):
4152
2240
"""Build and return TestSuite for the whole of bzrlib.
4154
:param keep_only: A list of test ids limiting the suite returned.
4156
:param starting_with: An id limiting the suite returned to the tests
4159
2242
This function can be replaced if you need to change the default test
4160
2243
suite on a global basis, but it is not encouraged.
2246
'bzrlib.util.tests.test_bencode',
2247
'bzrlib.tests.test_ancestry',
2248
'bzrlib.tests.test_annotate',
2249
'bzrlib.tests.test_api',
2250
'bzrlib.tests.test_atomicfile',
2251
'bzrlib.tests.test_bad_files',
2252
'bzrlib.tests.test_branch',
2253
'bzrlib.tests.test_branchbuilder',
2254
'bzrlib.tests.test_bugtracker',
2255
'bzrlib.tests.test_bundle',
2256
'bzrlib.tests.test_bzrdir',
2257
'bzrlib.tests.test_cache_utf8',
2258
'bzrlib.tests.test_commands',
2259
'bzrlib.tests.test_commit',
2260
'bzrlib.tests.test_commit_merge',
2261
'bzrlib.tests.test_config',
2262
'bzrlib.tests.test_conflicts',
2263
'bzrlib.tests.test_pack',
2264
'bzrlib.tests.test_counted_lock',
2265
'bzrlib.tests.test_decorators',
2266
'bzrlib.tests.test_delta',
2267
'bzrlib.tests.test_deprecated_graph',
2268
'bzrlib.tests.test_diff',
2269
'bzrlib.tests.test_dirstate',
2270
'bzrlib.tests.test_errors',
2271
'bzrlib.tests.test_escaped_store',
2272
'bzrlib.tests.test_extract',
2273
'bzrlib.tests.test_fetch',
2274
'bzrlib.tests.test_ftp_transport',
2275
'bzrlib.tests.test_generate_docs',
2276
'bzrlib.tests.test_generate_ids',
2277
'bzrlib.tests.test_globbing',
2278
'bzrlib.tests.test_gpg',
2279
'bzrlib.tests.test_graph',
2280
'bzrlib.tests.test_hashcache',
2281
'bzrlib.tests.test_help',
2282
'bzrlib.tests.test_hooks',
2283
'bzrlib.tests.test_http',
2284
'bzrlib.tests.test_http_response',
2285
'bzrlib.tests.test_https_ca_bundle',
2286
'bzrlib.tests.test_identitymap',
2287
'bzrlib.tests.test_ignores',
2288
'bzrlib.tests.test_index',
2289
'bzrlib.tests.test_info',
2290
'bzrlib.tests.test_inv',
2291
'bzrlib.tests.test_knit',
2292
'bzrlib.tests.test_lazy_import',
2293
'bzrlib.tests.test_lazy_regex',
2294
'bzrlib.tests.test_lockdir',
2295
'bzrlib.tests.test_lockable_files',
2296
'bzrlib.tests.test_log',
2297
'bzrlib.tests.test_lsprof',
2298
'bzrlib.tests.test_memorytree',
2299
'bzrlib.tests.test_merge',
2300
'bzrlib.tests.test_merge3',
2301
'bzrlib.tests.test_merge_core',
2302
'bzrlib.tests.test_merge_directive',
2303
'bzrlib.tests.test_missing',
2304
'bzrlib.tests.test_msgeditor',
2305
'bzrlib.tests.test_nonascii',
2306
'bzrlib.tests.test_options',
2307
'bzrlib.tests.test_osutils',
2308
'bzrlib.tests.test_osutils_encodings',
2309
'bzrlib.tests.test_patch',
2310
'bzrlib.tests.test_patches',
2311
'bzrlib.tests.test_permissions',
2312
'bzrlib.tests.test_plugins',
2313
'bzrlib.tests.test_progress',
2314
'bzrlib.tests.test_reconcile',
2315
'bzrlib.tests.test_registry',
2316
'bzrlib.tests.test_remote',
2317
'bzrlib.tests.test_repository',
2318
'bzrlib.tests.test_revert',
2319
'bzrlib.tests.test_revision',
2320
'bzrlib.tests.test_revisionnamespaces',
2321
'bzrlib.tests.test_revisiontree',
2322
'bzrlib.tests.test_rio',
2323
'bzrlib.tests.test_sampler',
2324
'bzrlib.tests.test_selftest',
2325
'bzrlib.tests.test_setup',
2326
'bzrlib.tests.test_sftp_transport',
2327
'bzrlib.tests.test_smart',
2328
'bzrlib.tests.test_smart_add',
2329
'bzrlib.tests.test_smart_transport',
2330
'bzrlib.tests.test_smtp_connection',
2331
'bzrlib.tests.test_source',
2332
'bzrlib.tests.test_ssh_transport',
2333
'bzrlib.tests.test_status',
2334
'bzrlib.tests.test_store',
2335
'bzrlib.tests.test_strace',
2336
'bzrlib.tests.test_subsume',
2337
'bzrlib.tests.test_symbol_versioning',
2338
'bzrlib.tests.test_tag',
2339
'bzrlib.tests.test_testament',
2340
'bzrlib.tests.test_textfile',
2341
'bzrlib.tests.test_textmerge',
2342
'bzrlib.tests.test_timestamp',
2343
'bzrlib.tests.test_trace',
2344
'bzrlib.tests.test_transactions',
2345
'bzrlib.tests.test_transform',
2346
'bzrlib.tests.test_transport',
2347
'bzrlib.tests.test_tree',
2348
'bzrlib.tests.test_treebuilder',
2349
'bzrlib.tests.test_tsort',
2350
'bzrlib.tests.test_tuned_gzip',
2351
'bzrlib.tests.test_ui',
2352
'bzrlib.tests.test_upgrade',
2353
'bzrlib.tests.test_urlutils',
2354
'bzrlib.tests.test_versionedfile',
2355
'bzrlib.tests.test_version',
2356
'bzrlib.tests.test_version_info',
2357
'bzrlib.tests.test_weave',
2358
'bzrlib.tests.test_whitebox',
2359
'bzrlib.tests.test_workingtree',
2360
'bzrlib.tests.test_workingtree_4',
2361
'bzrlib.tests.test_wsgi',
2362
'bzrlib.tests.test_xml',
2364
test_transport_implementations = [
2365
'bzrlib.tests.test_transport_implementations',
2366
'bzrlib.tests.test_read_bundle',
2368
suite = TestUtil.TestSuite()
4163
2369
loader = TestUtil.TestLoader()
4165
if keep_only is not None:
4166
id_filter = TestIdList(keep_only)
4168
# We take precedence over keep_only because *at loading time* using
4169
# both options means we will load less tests for the same final result.
4170
def interesting_module(name):
4171
for start in starting_with:
4173
# Either the module name starts with the specified string
4174
name.startswith(start)
4175
# or it may contain tests starting with the specified string
4176
or start.startswith(name)
4180
loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
4182
elif keep_only is not None:
4183
loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
4184
def interesting_module(name):
4185
return id_filter.refers_to(name)
4188
loader = TestUtil.TestLoader()
4189
def interesting_module(name):
4190
# No filtering, all modules are interesting
4193
suite = loader.suiteClass()
4195
# modules building their suite with loadTestsFromModuleNames
4196
suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
4198
for mod in _test_suite_modules_to_doctest():
4199
if not interesting_module(mod):
4200
# No tests to keep here, move along
2370
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2371
from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
2372
adapter = TransportTestProviderAdapter()
2373
adapt_modules(test_transport_implementations, adapter, loader, suite)
2374
for package in packages_to_test():
2375
suite.addTest(package.test_suite())
2376
for m in MODULES_TO_TEST:
2377
suite.addTest(loader.loadTestsFromModule(m))
2378
for m in MODULES_TO_DOCTEST:
4203
# note that this really does mean "report only" -- doctest
4204
# still runs the rest of the examples
4205
doc_suite = IsolatedDocTestSuite(
4206
mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
2380
suite.addTest(doctest.DocTestSuite(m))
4207
2381
except ValueError, e:
4208
print '**failed to get doctest for: %s\n%s' % (mod, e)
2382
print '**failed to get doctest for: %s\n%s' %(m,e)
4210
if len(doc_suite._tests) == 0:
4211
raise errors.BzrError("no doctests found in %s" % (mod,))
4212
suite.addTest(doc_suite)
4214
default_encoding = sys.getdefaultencoding()
4215
for name, plugin in _mod_plugin.plugins().items():
4216
if not interesting_module(plugin.module.__name__):
4218
plugin_suite = plugin.test_suite()
4219
# We used to catch ImportError here and turn it into just a warning,
4220
# but really if you don't have --no-plugins this should be a failure.
4221
# mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
4222
if plugin_suite is None:
4223
plugin_suite = plugin.load_plugin_tests(loader)
4224
if plugin_suite is not None:
4225
suite.addTest(plugin_suite)
4226
if default_encoding != sys.getdefaultencoding():
4228
'Plugin "%s" tried to reset default encoding to: %s', name,
4229
sys.getdefaultencoding())
4231
sys.setdefaultencoding(default_encoding)
4233
if keep_only is not None:
4234
# Now that the referred modules have loaded their tests, keep only the
4236
suite = filter_suite_by_id_list(suite, id_filter)
4237
# Do some sanity checks on the id_list filtering
4238
not_found, duplicates = suite_matches_id_list(suite, keep_only)
4240
# The tester has used both keep_only and starting_with, so he is
4241
# already aware that some tests are excluded from the list, there
4242
# is no need to tell him which.
4245
# Some tests mentioned in the list are not in the test suite. The
4246
# list may be out of date, report to the tester.
4247
for id in not_found:
4248
trace.warning('"%s" not found in the test suite', id)
4249
for id in duplicates:
4250
trace.warning('"%s" is used as an id by several tests', id)
2384
for name, plugin in bzrlib.plugin.all_plugins().items():
2385
if getattr(plugin, 'test_suite', None) is not None:
2386
default_encoding = sys.getdefaultencoding()
2388
plugin_suite = plugin.test_suite()
2389
except ImportError, e:
2390
bzrlib.trace.warning(
2391
'Unable to test plugin "%s": %s', name, e)
2393
suite.addTest(plugin_suite)
2394
if default_encoding != sys.getdefaultencoding():
2395
bzrlib.trace.warning(
2396
'Plugin "%s" tried to reset default encoding to: %s', name,
2397
sys.getdefaultencoding())
2399
sys.setdefaultencoding(default_encoding)
4255
def multiply_scenarios(*scenarios):
4256
"""Multiply two or more iterables of scenarios.
4258
It is safe to pass scenario generators or iterators.
4260
:returns: A list of compound scenarios: the cross-product of all
4261
scenarios, with the names concatenated and the parameters
4264
return reduce(_multiply_two_scenarios, map(list, scenarios))
4267
def _multiply_two_scenarios(scenarios_left, scenarios_right):
4268
"""Multiply two sets of scenarios.
4270
:returns: the cartesian product of the two sets of scenarios, that is
4271
a scenario for every possible combination of a left scenario and a
4275
('%s,%s' % (left_name, right_name),
4276
dict(left_dict.items() + right_dict.items()))
4277
for left_name, left_dict in scenarios_left
4278
for right_name, right_dict in scenarios_right]
4281
def multiply_tests(tests, scenarios, result):
4282
"""Multiply tests_list by scenarios into result.
4284
This is the core workhorse for test parameterisation.
4286
Typically the load_tests() method for a per-implementation test suite will
4287
call multiply_tests and return the result.
4289
:param tests: The tests to parameterise.
4290
:param scenarios: The scenarios to apply: pairs of (scenario_name,
4291
scenario_param_dict).
4292
:param result: A TestSuite to add created tests to.
4294
This returns the passed in result TestSuite with the cross product of all
4295
the tests repeated once for each scenario. Each test is adapted by adding
4296
the scenario name at the end of its id(), and updating the test object's
4297
__dict__ with the scenario_param_dict.
4299
>>> import bzrlib.tests.test_sampler
4300
>>> r = multiply_tests(
4301
... bzrlib.tests.test_sampler.DemoTest('test_nothing'),
4302
... [('one', dict(param=1)),
4303
... ('two', dict(param=2))],
4304
... TestUtil.TestSuite())
4305
>>> tests = list(iter_suite_tests(r))
4309
'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
4315
for test in iter_suite_tests(tests):
4316
apply_scenarios(test, scenarios, result)
4320
def apply_scenarios(test, scenarios, result):
4321
"""Apply the scenarios in scenarios to test and add to result.
4323
:param test: The test to apply scenarios to.
4324
:param scenarios: An iterable of scenarios to apply to test.
4326
:seealso: apply_scenario
4328
for scenario in scenarios:
4329
result.addTest(apply_scenario(test, scenario))
4333
def apply_scenario(test, scenario):
4334
"""Copy test and apply scenario to it.
4336
:param test: A test to adapt.
4337
:param scenario: A tuple describing the scenarion.
4338
The first element of the tuple is the new test id.
4339
The second element is a dict containing attributes to set on the
4341
:return: The adapted test.
4343
new_id = "%s(%s)" % (test.id(), scenario[0])
4344
new_test = clone_test(test, new_id)
4345
for name, value in scenario[1].items():
4346
setattr(new_test, name, value)
4350
def clone_test(test, new_id):
4351
"""Clone a test giving it a new id.
4353
:param test: The test to clone.
4354
:param new_id: The id to assign to it.
4355
:return: The new test.
4357
new_test = copy.copy(test)
4358
new_test.id = lambda: new_id
4359
# XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4360
# causes cloned tests to share the 'details' dict. This makes it hard to
4361
# read the test output for parameterized tests, because tracebacks will be
4362
# associated with irrelevant tests.
4364
details = new_test._TestCase__details
4365
except AttributeError:
4366
# must be a different version of testtools than expected. Do nothing.
4369
# Reset the '__details' dict.
4370
new_test._TestCase__details = {}
4374
def permute_tests_for_extension(standard_tests, loader, py_module_name,
4376
"""Helper for permutating tests against an extension module.
4378
This is meant to be used inside a modules 'load_tests()' function. It will
4379
create 2 scenarios, and cause all tests in the 'standard_tests' to be run
4380
against both implementations. Setting 'test.module' to the appropriate
4381
module. See bzrlib.tests.test__chk_map.load_tests as an example.
4383
:param standard_tests: A test suite to permute
4384
:param loader: A TestLoader
4385
:param py_module_name: The python path to a python module that can always
4386
be loaded, and will be considered the 'python' implementation. (eg
4387
'bzrlib._chk_map_py')
4388
:param ext_module_name: The python path to an extension module. If the
4389
module cannot be loaded, a single test will be added, which notes that
4390
the module is not available. If it can be loaded, all standard_tests
4391
will be run against that module.
4392
:return: (suite, feature) suite is a test-suite that has all the permuted
4393
tests. feature is the Feature object that can be used to determine if
4394
the module is available.
4397
from bzrlib.tests.features import ModuleAvailableFeature
4398
py_module = pyutils.get_named_object(py_module_name)
4400
('python', {'module': py_module}),
4402
suite = loader.suiteClass()
4403
feature = ModuleAvailableFeature(ext_module_name)
4404
if feature.available():
4405
scenarios.append(('C', {'module': feature.module}))
4407
# the compiled module isn't available, so we add a failing test
4408
class FailWithoutFeature(TestCase):
4409
def test_fail(self):
4410
self.requireFeature(feature)
4411
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4412
result = multiply_tests(standard_tests, scenarios, suite)
4413
return result, feature
4416
def _rmtree_temp_dir(dirname, test_id=None):
2403
def adapt_modules(mods_list, adapter, loader, suite):
2404
"""Adapt the modules in mods_list using adapter and add to suite."""
2405
for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
2406
suite.addTests(adapter.adapt(test))
2409
def _rmtree_temp_dir(dirname):
4417
2410
# If LANG=C we probably have created some bogus paths
4418
2411
# which rmtree(unicode) will fail to delete
4419
2412
# so make sure we are using rmtree(str) to delete everything