27
26
# general style of bzrlib. Please continue that consistency when adding e.g.
28
27
# new assertFoo() methods.
33
30
from cStringIO import StringIO
36
from pprint import pformat
40
from subprocess import Popen, PIPE
56
# nb: check this before importing anything else from within it
57
_testtools_version = getattr(testtools, '__version__', ())
58
if _testtools_version < (0, 9, 5):
59
raise ImportError("need at least testtools 0.9.5: %s is %r"
60
% (testtools.__file__, _testtools_version))
61
from testtools import content
64
47
from bzrlib import (
68
commands as _mod_commands,
77
plugin as _mod_plugin,
84
transport as _mod_transport,
58
import bzrlib.commands
59
import bzrlib.timestamp
61
import bzrlib.inventory
62
import bzrlib.iterablefile
88
65
import bzrlib.lsprof
89
66
except ImportError:
90
67
# lsprof not available
92
from bzrlib.smart import client, request
93
from bzrlib.transport import (
97
from bzrlib.tests import (
102
from bzrlib.ui import NullProgressView
103
from bzrlib.ui.text import TextUIFactory
105
# Mark this python module as being part of the implementation
106
# of unittest: this gives us better tracebacks where the last
107
# shown frame is the test code, not our assertXYZ.
110
default_transport = test_server.LocalURLServer
113
_unitialized_attr = object()
114
"""A sentinel needed to act as a default value in a method signature."""
117
# Subunit result codes, defined here to prevent a hard dependency on subunit.
121
# These are intentionally brought into this namespace. That way plugins, etc
122
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
123
TestSuite = TestUtil.TestSuite
124
TestLoader = TestUtil.TestLoader
126
# Tests should run in a clean and clearly defined environment. The goal is to
127
# keep them isolated from the running environment as mush as possible. The test
128
# framework ensures the variables defined below are set (or deleted if the
129
# value is None) before a test is run and reset to their original value after
130
# the test is run. Generally if some code depends on an environment variable,
131
# the tests should start without this variable in the environment. There are a
132
# few exceptions but you shouldn't violate this rule lightly.
136
# bzr now uses the Win32 API and doesn't rely on APPDATA, but the
137
# tests do check our impls match APPDATA
138
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
142
'BZREMAIL': None, # may still be present in the environment
143
'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
144
'BZR_PROGRESS_BAR': None,
146
'BZR_PLUGIN_PATH': None,
147
'BZR_DISABLE_PLUGINS': None,
148
'BZR_PLUGINS_AT': None,
149
'BZR_CONCURRENCY': None,
150
# Make sure that any text ui tests are consistent regardless of
151
# the environment the test case is run in; you may want tests that
152
# test other combinations. 'dumb' is a reasonable guess for tests
153
# going to a pipe or a StringIO.
159
'SSH_AUTH_SOCK': None,
169
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
170
# least. If you do (care), please update this comment
174
'BZR_REMOTE_PATH': None,
175
# Generally speaking, we don't want apport reporting on crashes in
176
# the test envirnoment unless we're specifically testing apport,
177
# so that it doesn't leak into the real system environment. We
178
# use an env var so it propagates to subprocesses.
179
'APPORT_DISABLE': '1',
183
def override_os_environ(test, env=None):
184
"""Modify os.environ keeping a copy.
186
:param test: A test instance
188
:param env: A dict containing variable definitions to be installed
191
env = isolated_environ
192
test._original_os_environ = dict([(var, value)
193
for var, value in os.environ.iteritems()])
194
for var, value in env.iteritems():
195
osutils.set_or_unset_env(var, value)
196
if var not in test._original_os_environ:
197
# The var is new, add it with a value of None, so
198
# restore_os_environ will delete it
199
test._original_os_environ[var] = None
202
def restore_os_environ(test):
203
"""Restore os.environ to its original state.
205
:param test: A test instance previously passed to override_os_environ.
207
for var, value in test._original_os_environ.iteritems():
208
# Restore the original value (or delete it if the value has been set to
209
# None in override_os_environ).
210
osutils.set_or_unset_env(var, value)
213
class ExtendedTestResult(testtools.TextTestResult):
69
from bzrlib.merge import merge_inner
73
from bzrlib.revision import common_ancestor
75
from bzrlib import symbol_versioning
77
from bzrlib.transport import get_transport
78
import bzrlib.transport
79
from bzrlib.transport.local import LocalURLServer
80
from bzrlib.transport.memory import MemoryServer
81
from bzrlib.transport.readonly import ReadonlyServer
82
from bzrlib.trace import mutter, note
83
from bzrlib.tests import TestUtil
84
from bzrlib.tests.HttpServer import HttpServer
85
from bzrlib.tests.TestUtil import (
89
from bzrlib.tests.treeshape import build_tree_contents
90
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
92
default_transport = LocalURLServer
95
MODULES_TO_DOCTEST = [
108
def packages_to_test():
109
"""Return a list of packages to test.
111
The packages are not globally imported so that import failures are
112
triggered when running selftest, not when importing the command.
115
import bzrlib.tests.blackbox
116
import bzrlib.tests.branch_implementations
117
import bzrlib.tests.bzrdir_implementations
118
import bzrlib.tests.interrepository_implementations
119
import bzrlib.tests.interversionedfile_implementations
120
import bzrlib.tests.intertree_implementations
121
import bzrlib.tests.per_lock
122
import bzrlib.tests.repository_implementations
123
import bzrlib.tests.revisionstore_implementations
124
import bzrlib.tests.tree_implementations
125
import bzrlib.tests.workingtree_implementations
128
bzrlib.tests.blackbox,
129
bzrlib.tests.branch_implementations,
130
bzrlib.tests.bzrdir_implementations,
131
bzrlib.tests.interrepository_implementations,
132
bzrlib.tests.interversionedfile_implementations,
133
bzrlib.tests.intertree_implementations,
134
bzrlib.tests.per_lock,
135
bzrlib.tests.repository_implementations,
136
bzrlib.tests.revisionstore_implementations,
137
bzrlib.tests.tree_implementations,
138
bzrlib.tests.workingtree_implementations,
142
class ExtendedTestResult(unittest._TextTestResult):
214
143
"""Accepts, reports and accumulates the results of running tests.
216
Compared to the unittest version this class adds support for
217
profiling, benchmarking, stopping as soon as a test fails, and
218
skipping tests. There are further-specialized subclasses for
219
different types of display.
221
When a test finishes, in whatever way, it calls one of the addSuccess,
222
addFailure or addError classes. These in turn may redirect to a more
223
specific case for the special test results supported by our extended
226
Note that just one of these objects is fed the results from many tests.
145
Compared to this unittest version this class adds support for profiling,
146
benchmarking, stopping as soon as a test fails, and skipping tests.
147
There are further-specialized subclasses for different types of display.
229
150
stop_early = False
231
152
def __init__(self, stream, descriptions, verbosity,
232
153
bench_history=None,
155
use_numbered_dirs=False,
235
157
"""Construct new TestResult.
237
159
:param bench_history: Optionally, a writable file object to accumulate
238
160
benchmark results.
240
testtools.TextTestResult.__init__(self, stream)
162
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
241
163
if bench_history is not None:
242
164
from bzrlib.version import _get_bzr_source_tree
243
165
src_tree = _get_bzr_source_tree()
351
211
def _shortened_test_description(self, test):
353
what = re.sub(r'^bzrlib\.tests\.', '', what)
213
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
356
# GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
357
# multiple times in a row, because the handler is added for
358
# each test but the container list is shared between cases.
359
# See lp:498869 lp:625574 and lp:637725 for background.
360
def _record_traceback_from_test(self, exc_info):
361
"""Store the traceback from passed exc_info tuple till"""
362
self._traceback_from_test = exc_info[2]
364
216
def startTest(self, test):
365
super(ExtendedTestResult, self).startTest(test)
217
unittest.TestResult.startTest(self, test)
369
218
self.report_test_start(test)
370
219
test.number = self.count
371
220
self._recordTestStartTime()
372
# Make testtools cases give us the real traceback on failure
373
addOnException = getattr(test, "addOnException", None)
374
if addOnException is not None:
375
addOnException(self._record_traceback_from_test)
376
# Only check for thread leaks on bzrlib derived test cases
377
if isinstance(test, TestCase):
378
test.addCleanup(self._check_leaked_threads, test)
380
def startTests(self):
381
self.report_tests_starting()
382
self._active_threads = threading.enumerate()
384
def stopTest(self, test):
385
self._traceback_from_test = None
387
def _check_leaked_threads(self, test):
388
"""See if any threads have leaked since last call
390
A sample of live threads is stored in the _active_threads attribute,
391
when this method runs it compares the current live threads and any not
392
in the previous sample are treated as having leaked.
394
now_active_threads = set(threading.enumerate())
395
threads_leaked = now_active_threads.difference(self._active_threads)
397
self._report_thread_leak(test, threads_leaked, now_active_threads)
398
self._tests_leaking_threads_count += 1
399
if self._first_thread_leaker_id is None:
400
self._first_thread_leaker_id = test.id()
401
self._active_threads = now_active_threads
403
222
def _recordTestStartTime(self):
404
223
"""Record that a test has started."""
405
self._start_datetime = self._now()
224
self._start_time = time.time()
226
def _cleanupLogFile(self, test):
227
# We can only do this if we have one of our TestCases, not if
229
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
230
if setKeepLogfile is not None:
407
233
def addError(self, test, err):
408
"""Tell result that test finished with an error.
410
Called from the TestCase run() method when the test
411
fails with an unexpected error.
413
self._post_mortem(self._traceback_from_test)
414
super(ExtendedTestResult, self).addError(test, err)
234
self.extractBenchmarkTime(test)
235
self._cleanupLogFile(test)
236
if isinstance(err[1], TestSkipped):
237
return self.addSkipped(test, err)
238
elif isinstance(err[1], UnavailableFeature):
239
return self.addNotSupported(test, err[1].args[0])
240
unittest.TestResult.addError(self, test, err)
415
241
self.error_count += 1
416
242
self.report_error(test, err)
417
243
if self.stop_early:
420
246
def addFailure(self, test, err):
421
"""Tell result that test failed.
423
Called from the TestCase run() method when the test
424
fails because e.g. an assert() method failed.
426
self._post_mortem(self._traceback_from_test)
427
super(ExtendedTestResult, self).addFailure(test, err)
247
self._cleanupLogFile(test)
248
self.extractBenchmarkTime(test)
249
if isinstance(err[1], KnownFailure):
250
return self.addKnownFailure(test, err)
251
unittest.TestResult.addFailure(self, test, err)
428
252
self.failure_count += 1
429
253
self.report_failure(test, err)
430
254
if self.stop_early:
433
def addSuccess(self, test, details=None):
434
"""Tell result that test completed successfully.
436
Called from the TestCase run()
438
if self._bench_history is not None:
439
benchmark_time = self._extractBenchmarkTime(test, details)
440
if benchmark_time is not None:
441
self._bench_history.write("%s %s\n" % (
442
self._formatTime(benchmark_time),
444
self.report_success(test)
445
super(ExtendedTestResult, self).addSuccess(test)
446
test._log_contents = ''
448
def addExpectedFailure(self, test, err):
257
def addKnownFailure(self, test, err):
449
258
self.known_failure_count += 1
450
259
self.report_known_failure(test, err)
452
261
def addNotSupported(self, test, feature):
453
"""The test will not be run because of a missing feature.
455
# this can be called in two different ways: it may be that the
456
# test started running, and then raised (through requireFeature)
457
# UnavailableFeature. Alternatively this method can be called
458
# while probing for features before running the test code proper; in
459
# that case we will see startTest and stopTest, but the test will
460
# never actually run.
461
262
self.unsupported.setdefault(str(feature), 0)
462
263
self.unsupported[str(feature)] += 1
463
264
self.report_unsupported(test, feature)
465
def addSkip(self, test, reason):
466
"""A test has not run for 'reason'."""
468
self.report_skip(test, reason)
470
def addNotApplicable(self, test, reason):
471
self.not_applicable_count += 1
472
self.report_not_applicable(test, reason)
474
def _post_mortem(self, tb=None):
475
"""Start a PDB post mortem session."""
476
if os.environ.get('BZR_TEST_PDB', None):
480
def progress(self, offset, whence):
481
"""The test is adjusting the count of tests to run."""
482
if whence == SUBUNIT_SEEK_SET:
483
self.num_tests = offset
484
elif whence == SUBUNIT_SEEK_CUR:
485
self.num_tests += offset
487
raise errors.BzrError("Unknown whence %r" % whence)
489
def report_tests_starting(self):
490
"""Display information before the test run begins"""
491
if getattr(sys, 'frozen', None) is None:
492
bzr_path = osutils.realpath(sys.argv[0])
494
bzr_path = sys.executable
496
'bzr selftest: %s\n' % (bzr_path,))
499
bzrlib.__path__[0],))
501
' bzr-%s python-%s %s\n' % (
502
bzrlib.version_string,
503
bzrlib._format_version_tuple(sys.version_info),
504
platform.platform(aliased=1),
506
self.stream.write('\n')
508
def report_test_start(self, test):
509
"""Display information on the test just about to be run"""
511
def _report_thread_leak(self, test, leaked_threads, active_threads):
512
"""Display information on a test that leaked one or more threads"""
513
# GZ 2010-09-09: A leak summary reported separately from the general
514
# thread debugging would be nice. Tests under subunit
515
# need something not using stream, perhaps adding a
516
# testtools details object would be fitting.
517
if 'threads' in selftest_debug_flags:
518
self.stream.write('%s is leaking, active is now %d\n' %
519
(test.id(), len(active_threads)))
521
def startTestRun(self):
522
self.startTime = time.time()
266
def addSuccess(self, test):
267
self.extractBenchmarkTime(test)
268
if self._bench_history is not None:
269
if self._benchmarkTime is not None:
270
self._bench_history.write("%s %s\n" % (
271
self._formatTime(self._benchmarkTime),
273
self.report_success(test)
274
unittest.TestResult.addSuccess(self, test)
276
def addSkipped(self, test, skip_excinfo):
277
self.report_skip(test, skip_excinfo)
278
# seems best to treat this as success from point-of-view of unittest
279
# -- it actually does nothing so it barely matters :)
282
except KeyboardInterrupt:
285
self.addError(test, test.__exc_info())
287
unittest.TestResult.addSuccess(self, test)
289
def printErrorList(self, flavour, errors):
290
for test, err in errors:
291
self.stream.writeln(self.separator1)
292
self.stream.write("%s: " % flavour)
293
if self.use_numbered_dirs:
294
self.stream.write('#%d ' % test.number)
295
self.stream.writeln(self.getDescription(test))
296
if getattr(test, '_get_log', None) is not None:
298
print >>self.stream, \
299
('vvvv[log from %s]' % test.id()).ljust(78,'-')
300
print >>self.stream, test._get_log()
301
print >>self.stream, \
302
('^^^^[log from %s]' % test.id()).ljust(78,'-')
303
self.stream.writeln(self.separator2)
304
self.stream.writeln("%s" % err)
309
def report_cleaning_up(self):
524
312
def report_success(self, test):
527
def wasStrictlySuccessful(self):
528
if self.unsupported or self.known_failure_count:
530
return self.wasSuccessful()
533
316
class TextTestResult(ExtendedTestResult):
534
317
"""Displays progress and results of tests in text form"""
536
319
def __init__(self, stream, descriptions, verbosity,
537
320
bench_history=None,
323
use_numbered_dirs=False,
541
325
ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
542
bench_history, strict)
543
# We no longer pass them around, but just rely on the UIFactory stack
546
warnings.warn("Passing pb to TextTestResult is deprecated")
547
self.pb = self.ui.nested_progress_bar()
326
bench_history, num_tests, use_numbered_dirs)
328
self.pb = self.ui.nested_progress_bar()
329
self._supplied_pb = False
332
self._supplied_pb = True
548
333
self.pb.show_pct = False
549
334
self.pb.show_spinner = False
550
335
self.pb.show_eta = False,
551
336
self.pb.show_count = False
552
337
self.pb.show_bar = False
553
self.pb.update_latency = 0
554
self.pb.show_transport_activity = False
556
def stopTestRun(self):
557
# called when the tests that are going to run have run
560
super(TextTestResult, self).stopTestRun()
562
def report_tests_starting(self):
563
super(TextTestResult, self).report_tests_starting()
564
self.pb.update('[test 0/%d] Starting' % (self.num_tests))
339
def report_starting(self):
340
self.pb.update('[test 0/%d] starting...' % (self.num_tests))
566
342
def _progress_prefix_text(self):
567
# the longer this text, the less space we have to show the test
569
a = '[%d' % self.count # total that have been run
570
# tests skipped as known not to be relevant are not important enough
572
## if self.skip_count:
573
## a += ', %d skip' % self.skip_count
574
## if self.known_failure_count:
575
## a += '+%dX' % self.known_failure_count
343
a = '[%d' % self.count
344
if self.num_tests is not None:
577
345
a +='/%d' % self.num_tests
579
runtime = time.time() - self._overall_start_time
581
a += '%dm%ds' % (runtime / 60, runtime % 60)
584
total_fail_count = self.error_count + self.failure_count
586
a += ', %d failed' % total_fail_count
587
# if self.unsupported:
588
# a += ', %d missing' % len(self.unsupported)
346
a += ' in %ds' % (time.time() - self._overall_start_time)
348
a += ', %d errors' % self.error_count
349
if self.failure_count:
350
a += ', %d failed' % self.failure_count
351
if self.known_failure_count:
352
a += ', %d known failures' % self.known_failure_count
354
a += ', %d skipped' % self.skip_count
356
a += ', %d missing features' % len(self.unsupported)
592
360
def report_test_start(self, test):
594
363
self._progress_prefix_text()
596
365
+ self._shortened_test_description(test))
598
367
def _test_description(self, test):
599
return self._shortened_test_description(test)
368
if self.use_numbered_dirs:
369
return '#%d %s' % (self.count,
370
self._shortened_test_description(test))
372
return self._shortened_test_description(test)
601
374
def report_error(self, test, err):
602
self.stream.write('ERROR: %s\n %s\n' % (
375
self.pb.note('ERROR: %s\n %s\n',
603
376
self._test_description(test),
607
380
def report_failure(self, test, err):
608
self.stream.write('FAIL: %s\n %s\n' % (
381
self.pb.note('FAIL: %s\n %s\n',
609
382
self._test_description(test),
613
386
def report_known_failure(self, test, err):
616
def report_skip(self, test, reason):
619
def report_not_applicable(self, test, reason):
387
self.pb.note('XFAIL: %s\n%s\n',
388
self._test_description(test), err[1])
390
def report_skip(self, test, skip_excinfo):
393
# at the moment these are mostly not things we can fix
394
# and so they just produce stipple; use the verbose reporter
397
# show test and reason for skip
398
self.pb.note('SKIP: %s\n %s\n',
399
self._shortened_test_description(test),
402
# since the class name was left behind in the still-visible
404
self.pb.note('SKIP: %s', skip_excinfo[1])
622
406
def report_unsupported(self, test, feature):
623
407
"""test cannot be run because feature is missing."""
409
def report_cleaning_up(self):
410
self.pb.update('cleaning up...')
413
if not self._supplied_pb:
626
417
class VerboseTestResult(ExtendedTestResult):
911
723
retrieved by _get_log(). We use a real OS file, not an in-memory object,
912
724
so that it can also capture file IO. When the test completes this file
913
725
is read into memory and removed from disk.
915
727
There are also convenience functions to invoke bzr's command-line
916
728
routine, and to build and check bzr trees.
918
730
In addition to the usual method of overriding tearDown(), this class also
919
allows subclasses to register cleanup functions via addCleanup, which are
731
allows subclasses to register functions into the _cleanups list, which is
920
732
run in order as the object is torn down. It's less likely this will be
921
733
accidentally overlooked.
736
_log_file_name = None
738
_keep_log_file = False
925
739
# record lsprof data when performing benchmark calls.
926
740
_gather_lsprof_in_benchmarks = False
928
742
def __init__(self, methodName='testMethod'):
929
743
super(TestCase, self).__init__(methodName)
930
self._directory_isolation = True
931
self.exception_handlers.insert(0,
932
(UnavailableFeature, self._do_unsupported_or_skip))
933
self.exception_handlers.insert(0,
934
(TestNotApplicable, self._do_not_applicable))
937
super(TestCase, self).setUp()
938
for feature in getattr(self, '_test_needs_features', []):
939
self.requireFeature(feature)
940
self._log_contents = None
941
self.addDetail("log", content.Content(content.ContentType("text",
942
"plain", {"charset": "utf8"}),
943
lambda:[self._get_log(keep_log_file=True)]))
747
unittest.TestCase.setUp(self)
944
748
self._cleanEnvironment()
749
bzrlib.trace.disable_default_logging()
945
750
self._silenceUI()
946
751
self._startLogFile()
947
752
self._benchcalls = []
948
753
self._benchtime = None
949
754
self._clear_hooks()
950
self._track_transports()
952
self._clear_debug_flags()
953
# Isolate global verbosity level, to make sure it's reproducible
954
# between tests. We should get rid of this altogether: bug 656694. --
956
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
961
pdb.Pdb().set_trace(sys._getframe().f_back)
963
def discardDetail(self, name):
964
"""Extend the addDetail, getDetails api so we can remove a detail.
966
eg. bzr always adds the 'log' detail at startup, but we don't want to
967
include it for skipped, xfail, etc tests.
969
It is safe to call this for a detail that doesn't exist, in case this
970
gets called multiple times.
972
# We cheat. details is stored in __details which means we shouldn't
973
# touch it. but getDetails() returns the dict directly, so we can
975
details = self.getDetails()
979
def _clear_debug_flags(self):
980
"""Prevent externally set debug flags affecting tests.
982
Tests that want to use debug flags can just set them in the
983
debug_flags set during setup/teardown.
985
# Start with a copy of the current debug flags we can safely modify.
986
self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
987
if 'allow_debug' not in selftest_debug_flags:
988
debug.debug_flags.clear()
989
if 'disable_lock_checks' not in selftest_debug_flags:
990
debug.debug_flags.add('strict_locks')
992
756
def _clear_hooks(self):
993
757
# prevent hooks affecting tests
994
known_hooks = hooks.known_hooks
995
self._preserved_hooks = {}
996
for key, (parent, name) in known_hooks.iter_parent_objects():
997
current_hooks = getattr(parent, name)
998
self._preserved_hooks[parent] = (name, current_hooks)
759
import bzrlib.smart.server
760
self._preserved_hooks = {
761
bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
762
bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
999
764
self.addCleanup(self._restoreHooks)
1000
for key, (parent, name) in known_hooks.iter_parent_objects():
1001
factory = known_hooks.get(key)
1002
setattr(parent, name, factory())
1003
# this hook should always be installed
1004
request._install_hook()
1006
def disable_directory_isolation(self):
1007
"""Turn off directory isolation checks."""
1008
self._directory_isolation = False
1010
def enable_directory_isolation(self):
1011
"""Enable directory isolation checks."""
1012
self._directory_isolation = True
765
# this list of hooks must be kept in sync with the defaults
767
bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
768
bzrlib.smart.server.SmartTCPServer.hooks = \
769
bzrlib.smart.server.SmartServerHooks()
1014
771
def _silenceUI(self):
1015
772
"""Turn off UI for duration of test"""
1016
773
# by default the UI is off; tests can turn it on if they want it.
1017
self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
1019
def _check_locks(self):
1020
"""Check that all lock take/release actions have been paired."""
1021
# We always check for mismatched locks. If a mismatch is found, we
1022
# fail unless -Edisable_lock_checks is supplied to selftest, in which
1023
# case we just print a warning.
1025
acquired_locks = [lock for action, lock in self._lock_actions
1026
if action == 'acquired']
1027
released_locks = [lock for action, lock in self._lock_actions
1028
if action == 'released']
1029
broken_locks = [lock for action, lock in self._lock_actions
1030
if action == 'broken']
1031
# trivially, given the tests for lock acquistion and release, if we
1032
# have as many in each list, it should be ok. Some lock tests also
1033
# break some locks on purpose and should be taken into account by
1034
# considering that breaking a lock is just a dirty way of releasing it.
1035
if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1036
message = ('Different number of acquired and '
1037
'released or broken locks. (%s, %s + %s)' %
1038
(acquired_locks, released_locks, broken_locks))
1039
if not self._lock_check_thorough:
1040
# Rather than fail, just warn
1041
print "Broken test %s: %s" % (self, message)
1045
def _track_locks(self):
1046
"""Track lock activity during tests."""
1047
self._lock_actions = []
1048
if 'disable_lock_checks' in selftest_debug_flags:
1049
self._lock_check_thorough = False
1051
self._lock_check_thorough = True
1053
self.addCleanup(self._check_locks)
1054
_mod_lock.Lock.hooks.install_named_hook('lock_acquired',
1055
self._lock_acquired, None)
1056
_mod_lock.Lock.hooks.install_named_hook('lock_released',
1057
self._lock_released, None)
1058
_mod_lock.Lock.hooks.install_named_hook('lock_broken',
1059
self._lock_broken, None)
1061
def _lock_acquired(self, result):
1062
self._lock_actions.append(('acquired', result))
1064
def _lock_released(self, result):
1065
self._lock_actions.append(('released', result))
1067
def _lock_broken(self, result):
1068
self._lock_actions.append(('broken', result))
1070
def permit_dir(self, name):
1071
"""Permit a directory to be used by this test. See permit_url."""
1072
name_transport = _mod_transport.get_transport(name)
1073
self.permit_url(name)
1074
self.permit_url(name_transport.base)
1076
def permit_url(self, url):
1077
"""Declare that url is an ok url to use in this test.
1079
Do this for memory transports, temporary test directory etc.
1081
Do not do this for the current working directory, /tmp, or any other
1082
preexisting non isolated url.
1084
if not url.endswith('/'):
1086
self._bzr_selftest_roots.append(url)
1088
def permit_source_tree_branch_repo(self):
1089
"""Permit the source tree bzr is running from to be opened.
1091
Some code such as bzrlib.version attempts to read from the bzr branch
1092
that bzr is executing from (if any). This method permits that directory
1093
to be used in the test suite.
1095
path = self.get_source_path()
1096
self.record_directory_isolation()
1099
workingtree.WorkingTree.open(path)
1100
except (errors.NotBranchError, errors.NoWorkingTree):
1101
raise TestSkipped('Needs a working tree of bzr sources')
1103
self.enable_directory_isolation()
1105
def _preopen_isolate_transport(self, transport):
1106
"""Check that all transport openings are done in the test work area."""
1107
while isinstance(transport, pathfilter.PathFilteringTransport):
1108
# Unwrap pathfiltered transports
1109
transport = transport.server.backing_transport.clone(
1110
transport._filter('.'))
1111
url = transport.base
1112
# ReadonlySmartTCPServer_for_testing decorates the backing transport
1113
# urls it is given by prepending readonly+. This is appropriate as the
1114
# client shouldn't know that the server is readonly (or not readonly).
1115
# We could register all servers twice, with readonly+ prepending, but
1116
# that makes for a long list; this is about the same but easier to
1118
if url.startswith('readonly+'):
1119
url = url[len('readonly+'):]
1120
self._preopen_isolate_url(url)
1122
def _preopen_isolate_url(self, url):
1123
if not self._directory_isolation:
1125
if self._directory_isolation == 'record':
1126
self._bzr_selftest_roots.append(url)
1128
# This prevents all transports, including e.g. sftp ones backed on disk
1129
# from working unless they are explicitly granted permission. We then
1130
# depend on the code that sets up test transports to check that they are
1131
# appropriately isolated and enable their use by calling
1132
# self.permit_transport()
1133
if not osutils.is_inside_any(self._bzr_selftest_roots, url):
1134
raise errors.BzrError("Attempt to escape test isolation: %r %r"
1135
% (url, self._bzr_selftest_roots))
1137
def record_directory_isolation(self):
1138
"""Gather accessed directories to permit later access.
1140
This is used for tests that access the branch bzr is running from.
1142
self._directory_isolation = "record"
1144
def start_server(self, transport_server, backing_server=None):
1145
"""Start transport_server for this test.
1147
This starts the server, registers a cleanup for it and permits the
1148
server's urls to be used.
1150
if backing_server is None:
1151
transport_server.start_server()
1153
transport_server.start_server(backing_server)
1154
self.addCleanup(transport_server.stop_server)
1155
# Obtain a real transport because if the server supplies a password, it
1156
# will be hidden from the base on the client side.
1157
t = _mod_transport.get_transport(transport_server.get_url())
1158
# Some transport servers effectively chroot the backing transport;
1159
# others like SFTPServer don't - users of the transport can walk up the
1160
# transport to read the entire backing transport. This wouldn't matter
1161
# except that the workdir tests are given - and that they expect the
1162
# server's url to point at - is one directory under the safety net. So
1163
# Branch operations into the transport will attempt to walk up one
1164
# directory. Chrooting all servers would avoid this but also mean that
1165
# we wouldn't be testing directly against non-root urls. Alternatively
1166
# getting the test framework to start the server with a backing server
1167
# at the actual safety net directory would work too, but this then
1168
# means that the self.get_url/self.get_transport methods would need
1169
# to transform all their results. On balance its cleaner to handle it
1170
# here, and permit a higher url when we have one of these transports.
1171
if t.base.endswith('/work/'):
1172
# we have safety net/test root/work
1173
t = t.clone('../..')
1174
elif isinstance(transport_server,
1175
test_server.SmartTCPServer_for_testing):
1176
# The smart server adds a path similar to work, which is traversed
1177
# up from by the client. But the server is chrooted - the actual
1178
# backing transport is not escaped from, and VFS requests to the
1179
# root will error (because they try to escape the chroot).
1181
while t2.base != t.base:
1184
self.permit_url(t.base)
1186
def _track_transports(self):
1187
"""Install checks for transport usage."""
1188
# TestCase has no safe place it can write to.
1189
self._bzr_selftest_roots = []
1190
# Currently the easiest way to be sure that nothing is going on is to
1191
# hook into bzr dir opening. This leaves a small window of error for
1192
# transport tests, but they are well known, and we can improve on this
1194
bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1195
self._preopen_isolate_transport, "Check bzr directories are safe.")
774
saved = ui.ui_factory
776
ui.ui_factory = saved
777
ui.ui_factory = ui.SilentUIFactory()
778
self.addCleanup(_restore)
1197
780
def _ndiff_strings(self, a, b):
1198
781
"""Return ndiff between two strings containing lines.
1200
783
A trailing newline is added if missing to make the strings
1201
784
print properly."""
1202
785
if b and b[-1] != '\n':
2798
2038
for readonly urls.
2800
2040
TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
2801
be used without needed to redo it when a different
2041
be used without needed to redo it when a different
2802
2042
subclass is in use ?
2805
2045
def setUp(self):
2806
from bzrlib.tests import http_server
2807
2046
super(ChrootedTestCase, self).setUp()
2808
if not self.vfs_transport_factory == memory.MemoryServer:
2809
self.transport_readonly_server = http_server.HttpServer
2812
def condition_id_re(pattern):
2813
"""Create a condition filter which performs a re check on a test's id.
2815
:param pattern: A regular expression string.
2816
:return: A callable that returns True if the re matches.
2818
filter_re = re.compile(pattern, 0)
2819
def condition(test):
2821
return filter_re.search(test_id)
2825
def condition_isinstance(klass_or_klass_list):
2826
"""Create a condition filter which returns isinstance(param, klass).
2828
:return: A callable which when called with one parameter obj return the
2829
result of isinstance(obj, klass_or_klass_list).
2832
return isinstance(obj, klass_or_klass_list)
2836
def condition_id_in_list(id_list):
2837
"""Create a condition filter which verify that test's id in a list.
2839
:param id_list: A TestIdList object.
2840
:return: A callable that returns True if the test's id appears in the list.
2842
def condition(test):
2843
return id_list.includes(test.id())
2847
def condition_id_startswith(starts):
2848
"""Create a condition filter verifying that test's id starts with a string.
2850
:param starts: A list of string.
2851
:return: A callable that returns True if the test's id starts with one of
2854
def condition(test):
2855
for start in starts:
2856
if test.id().startswith(start):
2862
def exclude_tests_by_condition(suite, condition):
2863
"""Create a test suite which excludes some tests from suite.
2865
:param suite: The suite to get tests from.
2866
:param condition: A callable whose result evaluates True when called with a
2867
test case which should be excluded from the result.
2868
:return: A suite which contains the tests found in suite that fail
2872
for test in iter_suite_tests(suite):
2873
if not condition(test):
2875
return TestUtil.TestSuite(result)
2878
def filter_suite_by_condition(suite, condition):
2879
"""Create a test suite by filtering another one.
2881
:param suite: The source suite.
2882
:param condition: A callable whose result evaluates True when called with a
2883
test case which should be included in the result.
2884
:return: A suite which contains the tests found in suite that pass
2888
for test in iter_suite_tests(suite):
2891
return TestUtil.TestSuite(result)
2047
if not self.vfs_transport_factory == MemoryServer:
2048
self.transport_readonly_server = HttpServer
2894
2051
def filter_suite_by_re(suite, pattern):
2895
"""Create a test suite by filtering another one.
2897
:param suite: the source suite
2898
:param pattern: pattern that names must match
2899
:returns: the newly created suite
2901
condition = condition_id_re(pattern)
2902
result_suite = filter_suite_by_condition(suite, condition)
2906
def filter_suite_by_id_list(suite, test_id_list):
2907
"""Create a test suite by filtering another one.
2909
:param suite: The source suite.
2910
:param test_id_list: A list of the test ids to keep as strings.
2911
:returns: the newly created suite
2913
condition = condition_id_in_list(test_id_list)
2914
result_suite = filter_suite_by_condition(suite, condition)
2918
def filter_suite_by_id_startswith(suite, start):
2919
"""Create a test suite by filtering another one.
2921
:param suite: The source suite.
2922
:param start: A list of string the test id must start with one of.
2923
:returns: the newly created suite
2925
condition = condition_id_startswith(start)
2926
result_suite = filter_suite_by_condition(suite, condition)
2930
def exclude_tests_by_re(suite, pattern):
2931
"""Create a test suite which excludes some tests from suite.
2933
:param suite: The suite to get tests from.
2934
:param pattern: A regular expression string. Test ids that match this
2935
pattern will be excluded from the result.
2936
:return: A TestSuite that contains all the tests from suite without the
2937
tests that matched pattern. The order of tests is the same as it was in
2940
return exclude_tests_by_condition(suite, condition_id_re(pattern))
2943
def preserve_input(something):
2944
"""A helper for performing test suite transformation chains.
2946
:param something: Anything you want to preserve.
2952
def randomize_suite(suite):
2953
"""Return a new TestSuite with suite's tests in random order.
2955
The tests in the input suite are flattened into a single suite in order to
2956
accomplish this. Any nested TestSuites are removed to provide global
2959
tests = list(iter_suite_tests(suite))
2960
random.shuffle(tests)
2961
return TestUtil.TestSuite(tests)
2964
def split_suite_by_condition(suite, condition):
2965
"""Split a test suite into two by a condition.
2967
:param suite: The suite to split.
2968
:param condition: The condition to match on. Tests that match this
2969
condition are returned in the first test suite, ones that do not match
2970
are in the second suite.
2971
:return: A tuple of two test suites, where the first contains tests from
2972
suite matching the condition, and the second contains the remainder
2973
from suite. The order within each output suite is the same as it was in
2978
for test in iter_suite_tests(suite):
2980
matched.append(test)
2052
result = TestUtil.TestSuite()
2053
filter_re = re.compile(pattern)
2054
for test in iter_suite_tests(suite):
2055
if filter_re.search(test.id()):
2056
result.addTest(test)
2060
def sort_suite_by_re(suite, pattern):
2063
filter_re = re.compile(pattern)
2064
for test in iter_suite_tests(suite):
2065
if filter_re.search(test.id()):
2982
did_not_match.append(test)
2983
return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
2986
def split_suite_by_re(suite, pattern):
2987
"""Split a test suite into two by a regular expression.
2989
:param suite: The suite to split.
2990
:param pattern: A regular expression string. Test ids that match this
2991
pattern will be in the first test suite returned, and the others in the
2992
second test suite returned.
2993
:return: A tuple of two test suites, where the first contains tests from
2994
suite matching pattern, and the second contains the remainder from
2995
suite. The order within each output suite is the same as it was in
2998
return split_suite_by_condition(suite, condition_id_re(pattern))
2069
return TestUtil.TestSuite(first + second)
3001
2072
def run_suite(suite, name='test', verbose=False, pattern=".*",
3002
stop_on_failure=False,
2073
stop_on_failure=False, keep_output=False,
3003
2074
transport=None, lsprof_timed=None, bench_history=None,
3004
2075
matching_tests_first=None,
3007
exclude_pattern=None,
3010
suite_decorators=None,
3012
result_decorators=None,
3014
"""Run a test suite for bzr selftest.
2076
numbered_dirs=None):
2077
use_numbered_dirs = bool(numbered_dirs)
3016
:param runner_class: The class of runner to use. Must support the
3017
constructor arguments passed by run_suite which are more than standard
3019
:return: A boolean indicating success.
3021
2079
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2080
if numbered_dirs is not None:
2081
TestCaseInTempDir.use_numbered_dirs = use_numbered_dirs
3026
if runner_class is None:
3027
runner_class = TextTestRunner
3030
runner = runner_class(stream=stream,
2086
runner = TextTestRunner(stream=sys.stdout,
3031
2087
descriptions=0,
3032
2088
verbosity=verbosity,
2089
keep_output=keep_output,
3033
2090
bench_history=bench_history,
3035
result_decorators=result_decorators,
2091
use_numbered_dirs=use_numbered_dirs,
3037
2093
runner.stop_on_failure=stop_on_failure
3038
# built in decorator factories:
3040
random_order(random_seed, runner),
3041
exclude_tests(exclude_pattern),
3043
if matching_tests_first:
3044
decorators.append(tests_first(pattern))
3046
decorators.append(filter_tests(pattern))
3047
if suite_decorators:
3048
decorators.extend(suite_decorators)
3049
# tell the result object how many tests will be running: (except if
3050
# --parallel=fork is being used. Robert said he will provide a better
3051
# progress design later -- vila 20090817)
3052
if fork_decorator not in decorators:
3053
decorators.append(CountingDecorator)
3054
for decorator in decorators:
3055
suite = decorator(suite)
3057
# Done after test suite decoration to allow randomisation etc
3058
# to take effect, though that is of marginal benefit.
3060
stream.write("Listing tests only ...\n")
3061
for t in iter_suite_tests(suite):
3062
stream.write("%s\n" % (t.id()))
2095
if matching_tests_first:
2096
suite = sort_suite_by_re(suite, pattern)
2098
suite = filter_suite_by_re(suite, pattern)
3064
2099
result = runner.run(suite)
3066
return result.wasStrictlySuccessful()
3068
return result.wasSuccessful()
3071
# A registry where get() returns a suite decorator.
3072
parallel_registry = registry.Registry()
3075
def fork_decorator(suite):
3076
if getattr(os, "fork", None) is None:
3077
raise errors.BzrCommandError("platform does not support fork,"
3078
" try --parallel=subprocess instead.")
3079
concurrency = osutils.local_concurrency()
3080
if concurrency == 1:
3082
from testtools import ConcurrentTestSuite
3083
return ConcurrentTestSuite(suite, fork_for_tests)
3084
parallel_registry.register('fork', fork_decorator)
3087
def subprocess_decorator(suite):
3088
concurrency = osutils.local_concurrency()
3089
if concurrency == 1:
3091
from testtools import ConcurrentTestSuite
3092
return ConcurrentTestSuite(suite, reinvoke_for_tests)
3093
parallel_registry.register('subprocess', subprocess_decorator)
3096
def exclude_tests(exclude_pattern):
3097
"""Return a test suite decorator that excludes tests."""
3098
if exclude_pattern is None:
3099
return identity_decorator
3100
def decorator(suite):
3101
return ExcludeDecorator(suite, exclude_pattern)
3105
def filter_tests(pattern):
3107
return identity_decorator
3108
def decorator(suite):
3109
return FilterTestsDecorator(suite, pattern)
3113
def random_order(random_seed, runner):
3114
"""Return a test suite decorator factory for randomising tests order.
3116
:param random_seed: now, a string which casts to a long, or a long.
3117
:param runner: A test runner with a stream attribute to report on.
3119
if random_seed is None:
3120
return identity_decorator
3121
def decorator(suite):
3122
return RandomDecorator(suite, random_seed, runner.stream)
3126
def tests_first(pattern):
3128
return identity_decorator
3129
def decorator(suite):
3130
return TestFirstDecorator(suite, pattern)
3134
def identity_decorator(suite):
3139
class TestDecorator(TestUtil.TestSuite):
3140
"""A decorator for TestCase/TestSuite objects.
3142
Usually, subclasses should override __iter__(used when flattening test
3143
suites), which we do to filter, reorder, parallelise and so on, run() and
3147
def __init__(self, suite):
3148
TestUtil.TestSuite.__init__(self)
3151
def countTestCases(self):
3154
cases += test.countTestCases()
3161
def run(self, result):
3162
# Use iteration on self, not self._tests, to allow subclasses to hook
3165
if result.shouldStop:
3171
class CountingDecorator(TestDecorator):
3172
"""A decorator which calls result.progress(self.countTestCases)."""
3174
def run(self, result):
3175
progress_method = getattr(result, 'progress', None)
3176
if callable(progress_method):
3177
progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
3178
return super(CountingDecorator, self).run(result)
3181
class ExcludeDecorator(TestDecorator):
3182
"""A decorator which excludes test matching an exclude pattern."""
3184
def __init__(self, suite, exclude_pattern):
3185
TestDecorator.__init__(self, suite)
3186
self.exclude_pattern = exclude_pattern
3187
self.excluded = False
3191
return iter(self._tests)
3192
self.excluded = True
3193
suite = exclude_tests_by_re(self, self.exclude_pattern)
3195
self.addTests(suite)
3196
return iter(self._tests)
3199
class FilterTestsDecorator(TestDecorator):
3200
"""A decorator which filters tests to those matching a pattern."""
3202
def __init__(self, suite, pattern):
3203
TestDecorator.__init__(self, suite)
3204
self.pattern = pattern
3205
self.filtered = False
3209
return iter(self._tests)
3210
self.filtered = True
3211
suite = filter_suite_by_re(self, self.pattern)
3213
self.addTests(suite)
3214
return iter(self._tests)
3217
class RandomDecorator(TestDecorator):
3218
"""A decorator which randomises the order of its tests."""
3220
def __init__(self, suite, random_seed, stream):
3221
TestDecorator.__init__(self, suite)
3222
self.random_seed = random_seed
3223
self.randomised = False
3224
self.stream = stream
3228
return iter(self._tests)
3229
self.randomised = True
3230
self.stream.write("Randomizing test order using seed %s\n\n" %
3231
(self.actual_seed()))
3232
# Initialise the random number generator.
3233
random.seed(self.actual_seed())
3234
suite = randomize_suite(self)
3236
self.addTests(suite)
3237
return iter(self._tests)
3239
def actual_seed(self):
3240
if self.random_seed == "now":
3241
# We convert the seed to a long to make it reuseable across
3242
# invocations (because the user can reenter it).
3243
self.random_seed = long(time.time())
3245
# Convert the seed to a long if we can
3247
self.random_seed = long(self.random_seed)
3250
return self.random_seed
3253
class TestFirstDecorator(TestDecorator):
3254
"""A decorator which moves named tests to the front."""
3256
def __init__(self, suite, pattern):
3257
TestDecorator.__init__(self, suite)
3258
self.pattern = pattern
3259
self.filtered = False
3263
return iter(self._tests)
3264
self.filtered = True
3265
suites = split_suite_by_re(self, self.pattern)
3267
self.addTests(suites)
3268
return iter(self._tests)
3271
def partition_tests(suite, count):
3272
"""Partition suite into count lists of tests."""
3273
# This just assigns tests in a round-robin fashion. On one hand this
3274
# splits up blocks of related tests that might run faster if they shared
3275
# resources, but on the other it avoids assigning blocks of slow tests to
3276
# just one partition. So the slowest partition shouldn't be much slower
3278
partitions = [list() for i in range(count)]
3279
tests = iter_suite_tests(suite)
3280
for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3281
partition.append(test)
3285
def workaround_zealous_crypto_random():
3286
"""Crypto.Random want to help us being secure, but we don't care here.
3288
This workaround some test failure related to the sftp server. Once paramiko
3289
stop using the controversial API in Crypto.Random, we may get rid of it.
3292
from Crypto.Random import atfork
3298
def fork_for_tests(suite):
3299
"""Take suite and start up one runner per CPU by forking()
3301
:return: An iterable of TestCase-like objects which can each have
3302
run(result) called on them to feed tests to result.
3304
concurrency = osutils.local_concurrency()
3306
from subunit import TestProtocolClient, ProtocolTestCase
3307
from subunit.test_results import AutoTimingTestResultDecorator
3308
class TestInOtherProcess(ProtocolTestCase):
3309
# Should be in subunit, I think. RBC.
3310
def __init__(self, stream, pid):
3311
ProtocolTestCase.__init__(self, stream)
3314
def run(self, result):
3316
ProtocolTestCase.run(self, result)
3318
os.waitpid(self.pid, 0)
3320
test_blocks = partition_tests(suite, concurrency)
3321
for process_tests in test_blocks:
3322
process_suite = TestUtil.TestSuite()
3323
process_suite.addTests(process_tests)
3324
c2pread, c2pwrite = os.pipe()
3327
workaround_zealous_crypto_random()
3330
# Leave stderr and stdout open so we can see test noise
3331
# Close stdin so that the child goes away if it decides to
3332
# read from stdin (otherwise its a roulette to see what
3333
# child actually gets keystrokes for pdb etc).
3336
stream = os.fdopen(c2pwrite, 'wb', 1)
3337
subunit_result = AutoTimingTestResultDecorator(
3338
TestProtocolClient(stream))
3339
process_suite.run(subunit_result)
3344
stream = os.fdopen(c2pread, 'rb', 1)
3345
test = TestInOtherProcess(stream, pid)
3350
def reinvoke_for_tests(suite):
3351
"""Take suite and start up one runner per CPU using subprocess().
3353
:return: An iterable of TestCase-like objects which can each have
3354
run(result) called on them to feed tests to result.
3356
concurrency = osutils.local_concurrency()
3358
from subunit import ProtocolTestCase
3359
class TestInSubprocess(ProtocolTestCase):
3360
def __init__(self, process, name):
3361
ProtocolTestCase.__init__(self, process.stdout)
3362
self.process = process
3363
self.process.stdin.close()
3366
def run(self, result):
3368
ProtocolTestCase.run(self, result)
3371
os.unlink(self.name)
3372
# print "pid %d finished" % finished_process
3373
test_blocks = partition_tests(suite, concurrency)
3374
for process_tests in test_blocks:
3375
# ugly; currently reimplement rather than reuses TestCase methods.
3376
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
3377
if not os.path.isfile(bzr_path):
3378
# We are probably installed. Assume sys.argv is the right file
3379
bzr_path = sys.argv[0]
3380
bzr_path = [bzr_path]
3381
if sys.platform == "win32":
3382
# if we're on windows, we can't execute the bzr script directly
3383
bzr_path = [sys.executable] + bzr_path
3384
fd, test_list_file_name = tempfile.mkstemp()
3385
test_list_file = os.fdopen(fd, 'wb', 1)
3386
for test in process_tests:
3387
test_list_file.write(test.id() + '\n')
3388
test_list_file.close()
3390
argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
3392
if '--no-plugins' in sys.argv:
3393
argv.append('--no-plugins')
3394
# stderr=subprocess.STDOUT would be ideal, but until we prevent
3395
# noise on stderr it can interrupt the subunit protocol.
3396
process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3397
stdout=subprocess.PIPE,
3398
stderr=subprocess.PIPE,
3400
test = TestInSubprocess(process, test_list_file_name)
3403
os.unlink(test_list_file_name)
3408
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3409
"""Generate profiling data for all activity between start and success.
3411
The profile data is appended to the test's _benchcalls attribute and can
3412
be accessed by the forwarded-to TestResult.
3414
While it might be cleaner do accumulate this in stopTest, addSuccess is
3415
where our existing output support for lsprof is, and this class aims to
3416
fit in with that: while it could be moved it's not necessary to accomplish
3417
test profiling, nor would it be dramatically cleaner.
3420
def startTest(self, test):
3421
self.profiler = bzrlib.lsprof.BzrProfiler()
3422
# Prevent deadlocks in tests that use lsprof: those tests will
3424
bzrlib.lsprof.BzrProfiler.profiler_block = 0
3425
self.profiler.start()
3426
testtools.ExtendedToOriginalDecorator.startTest(self, test)
3428
def addSuccess(self, test):
3429
stats = self.profiler.stop()
3431
calls = test._benchcalls
3432
except AttributeError:
3433
test._benchcalls = []
3434
calls = test._benchcalls
3435
calls.append(((test.id(), "", ""), stats))
3436
testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
3438
def stopTest(self, test):
3439
testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3440
self.profiler = None
3443
# Controlled by "bzr selftest -E=..." option
3444
# Currently supported:
3445
# -Eallow_debug Will no longer clear debug.debug_flags() so it
3446
# preserves any flags supplied at the command line.
3447
# -Edisable_lock_checks Turns errors in mismatched locks into simple prints
3448
# rather than failing tests. And no longer raise
3449
# LockContention when fctnl locks are not being used
3450
# with proper exclusion rules.
3451
# -Ethreads Will display thread ident at creation/join time to
3452
# help track thread leaks
3453
selftest_debug_flags = set()
2100
return result.wasSuccessful()
3456
2103
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
3457
2105
transport=None,
3458
2106
test_suite_factory=None,
3459
2107
lsprof_timed=None,
3460
2108
bench_history=None,
3461
2109
matching_tests_first=None,
3464
exclude_pattern=None,
3470
suite_decorators=None,
2110
numbered_dirs=None):
3474
2111
"""Run the whole test suite under the enhanced runner"""
3475
2112
# XXX: Very ugly way to do this...
3476
2113
# Disable warning about old formats because we don't want it to disturb
3483
2120
transport = default_transport
3484
2121
old_transport = default_transport
3485
2122
default_transport = transport
3486
global selftest_debug_flags
3487
old_debug_flags = selftest_debug_flags
3488
if debug_flags is not None:
3489
selftest_debug_flags = set(debug_flags)
3491
if load_list is None:
3494
keep_only = load_test_id_list(load_list)
3496
starting_with = [test_prefix_alias_registry.resolve_alias(start)
3497
for start in starting_with]
3498
2124
if test_suite_factory is None:
3499
# Reduce loading time by loading modules based on the starting_with
3501
suite = test_suite(keep_only, starting_with)
2125
suite = test_suite()
3503
2127
suite = test_suite_factory()
3505
# But always filter as requested.
3506
suite = filter_suite_by_id_startswith(suite, starting_with)
3507
result_decorators = []
3509
result_decorators.append(ProfileResult)
3510
2128
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
3511
stop_on_failure=stop_on_failure,
2129
stop_on_failure=stop_on_failure, keep_output=keep_output,
3512
2130
transport=transport,
3513
2131
lsprof_timed=lsprof_timed,
3514
2132
bench_history=bench_history,
3515
2133
matching_tests_first=matching_tests_first,
3516
list_only=list_only,
3517
random_seed=random_seed,
3518
exclude_pattern=exclude_pattern,
3520
runner_class=runner_class,
3521
suite_decorators=suite_decorators,
3523
result_decorators=result_decorators,
2134
numbered_dirs=numbered_dirs)
3526
2136
default_transport = old_transport
3527
selftest_debug_flags = old_debug_flags
3530
def load_test_id_list(file_name):
3531
"""Load a test id list from a text file.
3533
The format is one test id by line. No special care is taken to impose
3534
strict rules, these test ids are used to filter the test suite so a test id
3535
that do not match an existing test will do no harm. This allows user to add
3536
comments, leave blank lines, etc.
3540
ftest = open(file_name, 'rt')
3542
if e.errno != errno.ENOENT:
3545
raise errors.NoSuchFile(file_name)
3547
for test_name in ftest.readlines():
3548
test_list.append(test_name.strip())
3553
def suite_matches_id_list(test_suite, id_list):
3554
"""Warns about tests not appearing or appearing more than once.
3556
:param test_suite: A TestSuite object.
3557
:param test_id_list: The list of test ids that should be found in
3560
:return: (absents, duplicates) absents is a list containing the test found
3561
in id_list but not in test_suite, duplicates is a list containing the
3562
test found multiple times in test_suite.
3564
When using a prefined test id list, it may occurs that some tests do not
3565
exist anymore or that some tests use the same id. This function warns the
3566
tester about potential problems in his workflow (test lists are volatile)
3567
or in the test suite itself (using the same id for several tests does not
3568
help to localize defects).
3570
# Build a dict counting id occurrences
3572
for test in iter_suite_tests(test_suite):
3574
tests[id] = tests.get(id, 0) + 1
3579
occurs = tests.get(id, 0)
3581
not_found.append(id)
3583
duplicates.append(id)
3585
return not_found, duplicates
3588
class TestIdList(object):
3589
"""Test id list to filter a test suite.
3591
Relying on the assumption that test ids are built as:
3592
<module>[.<class>.<method>][(<param>+)], <module> being in python dotted
3593
notation, this class offers methods to :
3594
- avoid building a test suite for modules not refered to in the test list,
3595
- keep only the tests listed from the module test suite.
3598
def __init__(self, test_id_list):
3599
# When a test suite needs to be filtered against us we compare test ids
3600
# for equality, so a simple dict offers a quick and simple solution.
3601
self.tests = dict().fromkeys(test_id_list, True)
3603
# While unittest.TestCase have ids like:
3604
# <module>.<class>.<method>[(<param+)],
3605
# doctest.DocTestCase can have ids like:
3608
# <module>.<function>
3609
# <module>.<class>.<method>
3611
# Since we can't predict a test class from its name only, we settle on
3612
# a simple constraint: a test id always begins with its module name.
3615
for test_id in test_id_list:
3616
parts = test_id.split('.')
3617
mod_name = parts.pop(0)
3618
modules[mod_name] = True
3620
mod_name += '.' + part
3621
modules[mod_name] = True
3622
self.modules = modules
3624
def refers_to(self, module_name):
3625
"""Is there tests for the module or one of its sub modules."""
3626
return self.modules.has_key(module_name)
3628
def includes(self, test_id):
3629
return self.tests.has_key(test_id)
3632
class TestPrefixAliasRegistry(registry.Registry):
3633
"""A registry for test prefix aliases.
3635
This helps implement shorcuts for the --starting-with selftest
3636
option. Overriding existing prefixes is not allowed but not fatal (a
3637
warning will be emitted).
3640
def register(self, key, obj, help=None, info=None,
3641
override_existing=False):
3642
"""See Registry.register.
3644
Trying to override an existing alias causes a warning to be emitted,
3645
not a fatal execption.
3648
super(TestPrefixAliasRegistry, self).register(
3649
key, obj, help=help, info=info, override_existing=False)
3651
actual = self.get(key)
3653
'Test prefix alias %s is already used for %s, ignoring %s'
3654
% (key, actual, obj))
3656
def resolve_alias(self, id_start):
3657
"""Replace the alias by the prefix in the given string.
3659
Using an unknown prefix is an error to help catching typos.
3661
parts = id_start.split('.')
3663
parts[0] = self.get(parts[0])
3665
raise errors.BzrCommandError(
3666
'%s is not a known test prefix alias' % parts[0])
3667
return '.'.join(parts)
3670
test_prefix_alias_registry = TestPrefixAliasRegistry()
3671
"""Registry of test prefix aliases."""
3674
# This alias allows to detect typos ('bzrlin.') by making all valid test ids
3675
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
3676
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
3678
# Obvious highest levels prefixes, feel free to add your own via a plugin
3679
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
3680
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
3681
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
3682
test_prefix_alias_registry.register('bb', 'bzrlib.tests.blackbox')
3683
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3686
def _test_suite_testmod_names():
3687
"""Return the standard list of test module names to test."""
3690
'bzrlib.tests.blackbox',
3691
'bzrlib.tests.commands',
3692
'bzrlib.tests.doc_generate',
3693
'bzrlib.tests.per_branch',
3694
'bzrlib.tests.per_bzrdir',
3695
'bzrlib.tests.per_controldir',
3696
'bzrlib.tests.per_controldir_colo',
3697
'bzrlib.tests.per_foreign_vcs',
3698
'bzrlib.tests.per_interrepository',
3699
'bzrlib.tests.per_intertree',
3700
'bzrlib.tests.per_inventory',
3701
'bzrlib.tests.per_interbranch',
3702
'bzrlib.tests.per_lock',
3703
'bzrlib.tests.per_merger',
3704
'bzrlib.tests.per_transport',
3705
'bzrlib.tests.per_tree',
3706
'bzrlib.tests.per_pack_repository',
3707
'bzrlib.tests.per_repository',
3708
'bzrlib.tests.per_repository_chk',
3709
'bzrlib.tests.per_repository_reference',
3710
'bzrlib.tests.per_uifactory',
3711
'bzrlib.tests.per_versionedfile',
3712
'bzrlib.tests.per_workingtree',
3713
'bzrlib.tests.test__annotator',
3714
'bzrlib.tests.test__bencode',
3715
'bzrlib.tests.test__btree_serializer',
3716
'bzrlib.tests.test__chk_map',
3717
'bzrlib.tests.test__dirstate_helpers',
3718
'bzrlib.tests.test__groupcompress',
3719
'bzrlib.tests.test__known_graph',
3720
'bzrlib.tests.test__rio',
3721
'bzrlib.tests.test__simple_set',
3722
'bzrlib.tests.test__static_tuple',
3723
'bzrlib.tests.test__walkdirs_win32',
3724
'bzrlib.tests.test_ancestry',
3725
'bzrlib.tests.test_annotate',
3726
'bzrlib.tests.test_api',
3727
'bzrlib.tests.test_atomicfile',
3728
'bzrlib.tests.test_bad_files',
3729
'bzrlib.tests.test_bisect_multi',
3730
'bzrlib.tests.test_branch',
3731
'bzrlib.tests.test_branchbuilder',
3732
'bzrlib.tests.test_btree_index',
3733
'bzrlib.tests.test_bugtracker',
3734
'bzrlib.tests.test_bundle',
3735
'bzrlib.tests.test_bzrdir',
3736
'bzrlib.tests.test__chunks_to_lines',
3737
'bzrlib.tests.test_cache_utf8',
3738
'bzrlib.tests.test_chk_map',
3739
'bzrlib.tests.test_chk_serializer',
3740
'bzrlib.tests.test_chunk_writer',
3741
'bzrlib.tests.test_clean_tree',
3742
'bzrlib.tests.test_cleanup',
3743
'bzrlib.tests.test_cmdline',
3744
'bzrlib.tests.test_commands',
3745
'bzrlib.tests.test_commit',
3746
'bzrlib.tests.test_commit_merge',
3747
'bzrlib.tests.test_config',
3748
'bzrlib.tests.test_conflicts',
3749
'bzrlib.tests.test_counted_lock',
3750
'bzrlib.tests.test_crash',
3751
'bzrlib.tests.test_decorators',
3752
'bzrlib.tests.test_delta',
3753
'bzrlib.tests.test_debug',
3754
'bzrlib.tests.test_deprecated_graph',
3755
'bzrlib.tests.test_diff',
3756
'bzrlib.tests.test_directory_service',
3757
'bzrlib.tests.test_dirstate',
3758
'bzrlib.tests.test_email_message',
3759
'bzrlib.tests.test_eol_filters',
3760
'bzrlib.tests.test_errors',
3761
'bzrlib.tests.test_export',
3762
'bzrlib.tests.test_extract',
3763
'bzrlib.tests.test_fetch',
3764
'bzrlib.tests.test_fixtures',
3765
'bzrlib.tests.test_fifo_cache',
3766
'bzrlib.tests.test_filters',
3767
'bzrlib.tests.test_ftp_transport',
3768
'bzrlib.tests.test_foreign',
3769
'bzrlib.tests.test_generate_docs',
3770
'bzrlib.tests.test_generate_ids',
3771
'bzrlib.tests.test_globbing',
3772
'bzrlib.tests.test_gpg',
3773
'bzrlib.tests.test_graph',
3774
'bzrlib.tests.test_groupcompress',
3775
'bzrlib.tests.test_hashcache',
3776
'bzrlib.tests.test_help',
3777
'bzrlib.tests.test_hooks',
3778
'bzrlib.tests.test_http',
3779
'bzrlib.tests.test_http_response',
3780
'bzrlib.tests.test_https_ca_bundle',
3781
'bzrlib.tests.test_identitymap',
3782
'bzrlib.tests.test_ignores',
3783
'bzrlib.tests.test_index',
3784
'bzrlib.tests.test_import_tariff',
3785
'bzrlib.tests.test_info',
3786
'bzrlib.tests.test_inv',
3787
'bzrlib.tests.test_inventory_delta',
3788
'bzrlib.tests.test_knit',
3789
'bzrlib.tests.test_lazy_import',
3790
'bzrlib.tests.test_lazy_regex',
3791
'bzrlib.tests.test_library_state',
3792
'bzrlib.tests.test_lock',
3793
'bzrlib.tests.test_lockable_files',
3794
'bzrlib.tests.test_lockdir',
3795
'bzrlib.tests.test_log',
3796
'bzrlib.tests.test_lru_cache',
3797
'bzrlib.tests.test_lsprof',
3798
'bzrlib.tests.test_mail_client',
3799
'bzrlib.tests.test_matchers',
3800
'bzrlib.tests.test_memorytree',
3801
'bzrlib.tests.test_merge',
3802
'bzrlib.tests.test_merge3',
3803
'bzrlib.tests.test_merge_core',
3804
'bzrlib.tests.test_merge_directive',
3805
'bzrlib.tests.test_mergetools',
3806
'bzrlib.tests.test_missing',
3807
'bzrlib.tests.test_msgeditor',
3808
'bzrlib.tests.test_multiparent',
3809
'bzrlib.tests.test_mutabletree',
3810
'bzrlib.tests.test_nonascii',
3811
'bzrlib.tests.test_options',
3812
'bzrlib.tests.test_osutils',
3813
'bzrlib.tests.test_osutils_encodings',
3814
'bzrlib.tests.test_pack',
3815
'bzrlib.tests.test_patch',
3816
'bzrlib.tests.test_patches',
3817
'bzrlib.tests.test_permissions',
3818
'bzrlib.tests.test_plugins',
3819
'bzrlib.tests.test_progress',
3820
'bzrlib.tests.test_pyutils',
3821
'bzrlib.tests.test_read_bundle',
3822
'bzrlib.tests.test_reconcile',
3823
'bzrlib.tests.test_reconfigure',
3824
'bzrlib.tests.test_registry',
3825
'bzrlib.tests.test_remote',
3826
'bzrlib.tests.test_rename_map',
3827
'bzrlib.tests.test_repository',
3828
'bzrlib.tests.test_revert',
3829
'bzrlib.tests.test_revision',
3830
'bzrlib.tests.test_revisionspec',
3831
'bzrlib.tests.test_revisiontree',
3832
'bzrlib.tests.test_rio',
3833
'bzrlib.tests.test_rules',
3834
'bzrlib.tests.test_sampler',
3835
'bzrlib.tests.test_scenarios',
3836
'bzrlib.tests.test_script',
3837
'bzrlib.tests.test_selftest',
3838
'bzrlib.tests.test_serializer',
3839
'bzrlib.tests.test_setup',
3840
'bzrlib.tests.test_sftp_transport',
3841
'bzrlib.tests.test_shelf',
3842
'bzrlib.tests.test_shelf_ui',
3843
'bzrlib.tests.test_smart',
3844
'bzrlib.tests.test_smart_add',
3845
'bzrlib.tests.test_smart_request',
3846
'bzrlib.tests.test_smart_transport',
3847
'bzrlib.tests.test_smtp_connection',
3848
'bzrlib.tests.test_source',
3849
'bzrlib.tests.test_ssh_transport',
3850
'bzrlib.tests.test_status',
3851
'bzrlib.tests.test_store',
3852
'bzrlib.tests.test_strace',
3853
'bzrlib.tests.test_subsume',
3854
'bzrlib.tests.test_switch',
3855
'bzrlib.tests.test_symbol_versioning',
3856
'bzrlib.tests.test_tag',
3857
'bzrlib.tests.test_test_server',
3858
'bzrlib.tests.test_testament',
3859
'bzrlib.tests.test_textfile',
3860
'bzrlib.tests.test_textmerge',
3861
'bzrlib.tests.test_cethread',
3862
'bzrlib.tests.test_timestamp',
3863
'bzrlib.tests.test_trace',
3864
'bzrlib.tests.test_transactions',
3865
'bzrlib.tests.test_transform',
3866
'bzrlib.tests.test_transport',
3867
'bzrlib.tests.test_transport_log',
3868
'bzrlib.tests.test_tree',
3869
'bzrlib.tests.test_treebuilder',
3870
'bzrlib.tests.test_treeshape',
3871
'bzrlib.tests.test_tsort',
3872
'bzrlib.tests.test_tuned_gzip',
3873
'bzrlib.tests.test_ui',
3874
'bzrlib.tests.test_uncommit',
3875
'bzrlib.tests.test_upgrade',
3876
'bzrlib.tests.test_upgrade_stacked',
3877
'bzrlib.tests.test_urlutils',
3878
'bzrlib.tests.test_version',
3879
'bzrlib.tests.test_version_info',
3880
'bzrlib.tests.test_versionedfile',
3881
'bzrlib.tests.test_weave',
3882
'bzrlib.tests.test_whitebox',
3883
'bzrlib.tests.test_win32utils',
3884
'bzrlib.tests.test_workingtree',
3885
'bzrlib.tests.test_workingtree_4',
3886
'bzrlib.tests.test_wsgi',
3887
'bzrlib.tests.test_xml',
3891
def _test_suite_modules_to_doctest():
3892
"""Return the list of modules to doctest."""
3894
# GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
3898
'bzrlib.branchbuilder',
3899
'bzrlib.decorators',
3902
'bzrlib.iterablefile',
3907
'bzrlib.symbol_versioning',
3909
'bzrlib.tests.fixtures',
3911
'bzrlib.transport.http',
3912
'bzrlib.version_info_formats.format_custom',
3916
def test_suite(keep_only=None, starting_with=None):
3917
2140
"""Build and return TestSuite for the whole of bzrlib.
3919
:param keep_only: A list of test ids limiting the suite returned.
3921
:param starting_with: An id limiting the suite returned to the tests
3924
2142
This function can be replaced if you need to change the default test
3925
2143
suite on a global basis, but it is not encouraged.
2146
'bzrlib.tests.test_ancestry',
2147
'bzrlib.tests.test_annotate',
2148
'bzrlib.tests.test_api',
2149
'bzrlib.tests.test_atomicfile',
2150
'bzrlib.tests.test_bad_files',
2151
'bzrlib.tests.test_branch',
2152
'bzrlib.tests.test_bundle',
2153
'bzrlib.tests.test_bzrdir',
2154
'bzrlib.tests.test_cache_utf8',
2155
'bzrlib.tests.test_commands',
2156
'bzrlib.tests.test_commit',
2157
'bzrlib.tests.test_commit_merge',
2158
'bzrlib.tests.test_config',
2159
'bzrlib.tests.test_conflicts',
2160
'bzrlib.tests.test_decorators',
2161
'bzrlib.tests.test_delta',
2162
'bzrlib.tests.test_diff',
2163
'bzrlib.tests.test_dirstate',
2164
'bzrlib.tests.test_doc_generate',
2165
'bzrlib.tests.test_errors',
2166
'bzrlib.tests.test_escaped_store',
2167
'bzrlib.tests.test_extract',
2168
'bzrlib.tests.test_fetch',
2169
'bzrlib.tests.test_ftp_transport',
2170
'bzrlib.tests.test_generate_docs',
2171
'bzrlib.tests.test_generate_ids',
2172
'bzrlib.tests.test_globbing',
2173
'bzrlib.tests.test_gpg',
2174
'bzrlib.tests.test_graph',
2175
'bzrlib.tests.test_hashcache',
2176
'bzrlib.tests.test_http',
2177
'bzrlib.tests.test_http_response',
2178
'bzrlib.tests.test_https_ca_bundle',
2179
'bzrlib.tests.test_identitymap',
2180
'bzrlib.tests.test_ignores',
2181
'bzrlib.tests.test_inv',
2182
'bzrlib.tests.test_knit',
2183
'bzrlib.tests.test_lazy_import',
2184
'bzrlib.tests.test_lazy_regex',
2185
'bzrlib.tests.test_lockdir',
2186
'bzrlib.tests.test_lockable_files',
2187
'bzrlib.tests.test_log',
2188
'bzrlib.tests.test_memorytree',
2189
'bzrlib.tests.test_merge',
2190
'bzrlib.tests.test_merge3',
2191
'bzrlib.tests.test_merge_core',
2192
'bzrlib.tests.test_merge_directive',
2193
'bzrlib.tests.test_missing',
2194
'bzrlib.tests.test_msgeditor',
2195
'bzrlib.tests.test_nonascii',
2196
'bzrlib.tests.test_options',
2197
'bzrlib.tests.test_osutils',
2198
'bzrlib.tests.test_osutils_encodings',
2199
'bzrlib.tests.test_patch',
2200
'bzrlib.tests.test_patches',
2201
'bzrlib.tests.test_permissions',
2202
'bzrlib.tests.test_plugins',
2203
'bzrlib.tests.test_progress',
2204
'bzrlib.tests.test_reconcile',
2205
'bzrlib.tests.test_registry',
2206
'bzrlib.tests.test_repository',
2207
'bzrlib.tests.test_revert',
2208
'bzrlib.tests.test_revision',
2209
'bzrlib.tests.test_revisionnamespaces',
2210
'bzrlib.tests.test_revisiontree',
2211
'bzrlib.tests.test_rio',
2212
'bzrlib.tests.test_sampler',
2213
'bzrlib.tests.test_selftest',
2214
'bzrlib.tests.test_setup',
2215
'bzrlib.tests.test_sftp_transport',
2216
'bzrlib.tests.test_smart_add',
2217
'bzrlib.tests.test_smart_transport',
2218
'bzrlib.tests.test_source',
2219
'bzrlib.tests.test_ssh_transport',
2220
'bzrlib.tests.test_status',
2221
'bzrlib.tests.test_store',
2222
'bzrlib.tests.test_strace',
2223
'bzrlib.tests.test_subsume',
2224
'bzrlib.tests.test_symbol_versioning',
2225
'bzrlib.tests.test_tag',
2226
'bzrlib.tests.test_testament',
2227
'bzrlib.tests.test_textfile',
2228
'bzrlib.tests.test_textmerge',
2229
'bzrlib.tests.test_timestamp',
2230
'bzrlib.tests.test_trace',
2231
'bzrlib.tests.test_transactions',
2232
'bzrlib.tests.test_transform',
2233
'bzrlib.tests.test_transport',
2234
'bzrlib.tests.test_tree',
2235
'bzrlib.tests.test_treebuilder',
2236
'bzrlib.tests.test_tsort',
2237
'bzrlib.tests.test_tuned_gzip',
2238
'bzrlib.tests.test_ui',
2239
'bzrlib.tests.test_upgrade',
2240
'bzrlib.tests.test_urlutils',
2241
'bzrlib.tests.test_versionedfile',
2242
'bzrlib.tests.test_version',
2243
'bzrlib.tests.test_version_info',
2244
'bzrlib.tests.test_weave',
2245
'bzrlib.tests.test_whitebox',
2246
'bzrlib.tests.test_workingtree',
2247
'bzrlib.tests.test_workingtree_4',
2248
'bzrlib.tests.test_wsgi',
2249
'bzrlib.tests.test_xml',
2251
test_transport_implementations = [
2252
'bzrlib.tests.test_transport_implementations',
2253
'bzrlib.tests.test_read_bundle',
2255
suite = TestUtil.TestSuite()
3928
2256
loader = TestUtil.TestLoader()
3930
if keep_only is not None:
3931
id_filter = TestIdList(keep_only)
3933
# We take precedence over keep_only because *at loading time* using
3934
# both options means we will load less tests for the same final result.
3935
def interesting_module(name):
3936
for start in starting_with:
3938
# Either the module name starts with the specified string
3939
name.startswith(start)
3940
# or it may contain tests starting with the specified string
3941
or start.startswith(name)
3945
loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
3947
elif keep_only is not None:
3948
loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
3949
def interesting_module(name):
3950
return id_filter.refers_to(name)
3953
loader = TestUtil.TestLoader()
3954
def interesting_module(name):
3955
# No filtering, all modules are interesting
3958
suite = loader.suiteClass()
3960
# modules building their suite with loadTestsFromModuleNames
3961
suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
3963
for mod in _test_suite_modules_to_doctest():
3964
if not interesting_module(mod):
3965
# No tests to keep here, move along
2257
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2258
from bzrlib.transport import TransportTestProviderAdapter
2259
adapter = TransportTestProviderAdapter()
2260
adapt_modules(test_transport_implementations, adapter, loader, suite)
2261
for package in packages_to_test():
2262
suite.addTest(package.test_suite())
2263
for m in MODULES_TO_TEST:
2264
suite.addTest(loader.loadTestsFromModule(m))
2265
for m in MODULES_TO_DOCTEST:
3968
# note that this really does mean "report only" -- doctest
3969
# still runs the rest of the examples
3970
doc_suite = IsolatedDocTestSuite(
3971
mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
2267
suite.addTest(doctest.DocTestSuite(m))
3972
2268
except ValueError, e:
3973
print '**failed to get doctest for: %s\n%s' % (mod, e)
2269
print '**failed to get doctest for: %s\n%s' %(m,e)
3975
if len(doc_suite._tests) == 0:
3976
raise errors.BzrError("no doctests found in %s" % (mod,))
3977
suite.addTest(doc_suite)
3979
default_encoding = sys.getdefaultencoding()
3980
for name, plugin in _mod_plugin.plugins().items():
3981
if not interesting_module(plugin.module.__name__):
3983
plugin_suite = plugin.test_suite()
3984
# We used to catch ImportError here and turn it into just a warning,
3985
# but really if you don't have --no-plugins this should be a failure.
3986
# mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
3987
if plugin_suite is None:
3988
plugin_suite = plugin.load_plugin_tests(loader)
3989
if plugin_suite is not None:
3990
suite.addTest(plugin_suite)
3991
if default_encoding != sys.getdefaultencoding():
3993
'Plugin "%s" tried to reset default encoding to: %s', name,
3994
sys.getdefaultencoding())
3996
sys.setdefaultencoding(default_encoding)
3998
if keep_only is not None:
3999
# Now that the referred modules have loaded their tests, keep only the
4001
suite = filter_suite_by_id_list(suite, id_filter)
4002
# Do some sanity checks on the id_list filtering
4003
not_found, duplicates = suite_matches_id_list(suite, keep_only)
4005
# The tester has used both keep_only and starting_with, so he is
4006
# already aware that some tests are excluded from the list, there
4007
# is no need to tell him which.
4010
# Some tests mentioned in the list are not in the test suite. The
4011
# list may be out of date, report to the tester.
4012
for id in not_found:
4013
trace.warning('"%s" not found in the test suite', id)
4014
for id in duplicates:
4015
trace.warning('"%s" is used as an id by several tests', id)
2271
for name, plugin in bzrlib.plugin.all_plugins().items():
2272
if getattr(plugin, 'test_suite', None) is not None:
2273
default_encoding = sys.getdefaultencoding()
2275
plugin_suite = plugin.test_suite()
2276
except ImportError, e:
2277
bzrlib.trace.warning(
2278
'Unable to test plugin "%s": %s', name, e)
2280
suite.addTest(plugin_suite)
2281
if default_encoding != sys.getdefaultencoding():
2282
bzrlib.trace.warning(
2283
'Plugin "%s" tried to reset default encoding to: %s', name,
2284
sys.getdefaultencoding())
2286
sys.setdefaultencoding(default_encoding)
4020
def multiply_scenarios(*scenarios):
4021
"""Multiply two or more iterables of scenarios.
4023
It is safe to pass scenario generators or iterators.
4025
:returns: A list of compound scenarios: the cross-product of all
4026
scenarios, with the names concatenated and the parameters
4029
return reduce(_multiply_two_scenarios, map(list, scenarios))
4032
def _multiply_two_scenarios(scenarios_left, scenarios_right):
4033
"""Multiply two sets of scenarios.
4035
:returns: the cartesian product of the two sets of scenarios, that is
4036
a scenario for every possible combination of a left scenario and a
4040
('%s,%s' % (left_name, right_name),
4041
dict(left_dict.items() + right_dict.items()))
4042
for left_name, left_dict in scenarios_left
4043
for right_name, right_dict in scenarios_right]
4046
def multiply_tests(tests, scenarios, result):
4047
"""Multiply tests_list by scenarios into result.
4049
This is the core workhorse for test parameterisation.
4051
Typically the load_tests() method for a per-implementation test suite will
4052
call multiply_tests and return the result.
4054
:param tests: The tests to parameterise.
4055
:param scenarios: The scenarios to apply: pairs of (scenario_name,
4056
scenario_param_dict).
4057
:param result: A TestSuite to add created tests to.
4059
This returns the passed in result TestSuite with the cross product of all
4060
the tests repeated once for each scenario. Each test is adapted by adding
4061
the scenario name at the end of its id(), and updating the test object's
4062
__dict__ with the scenario_param_dict.
4064
>>> import bzrlib.tests.test_sampler
4065
>>> r = multiply_tests(
4066
... bzrlib.tests.test_sampler.DemoTest('test_nothing'),
4067
... [('one', dict(param=1)),
4068
... ('two', dict(param=2))],
4069
... TestUtil.TestSuite())
4070
>>> tests = list(iter_suite_tests(r))
4074
'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
4080
for test in iter_suite_tests(tests):
4081
apply_scenarios(test, scenarios, result)
4085
def apply_scenarios(test, scenarios, result):
4086
"""Apply the scenarios in scenarios to test and add to result.
4088
:param test: The test to apply scenarios to.
4089
:param scenarios: An iterable of scenarios to apply to test.
4091
:seealso: apply_scenario
4093
for scenario in scenarios:
4094
result.addTest(apply_scenario(test, scenario))
4098
def apply_scenario(test, scenario):
4099
"""Copy test and apply scenario to it.
4101
:param test: A test to adapt.
4102
:param scenario: A tuple describing the scenarion.
4103
The first element of the tuple is the new test id.
4104
The second element is a dict containing attributes to set on the
4106
:return: The adapted test.
4108
new_id = "%s(%s)" % (test.id(), scenario[0])
4109
new_test = clone_test(test, new_id)
4110
for name, value in scenario[1].items():
4111
setattr(new_test, name, value)
4115
def clone_test(test, new_id):
4116
"""Clone a test giving it a new id.
4118
:param test: The test to clone.
4119
:param new_id: The id to assign to it.
4120
:return: The new test.
4122
new_test = copy.copy(test)
4123
new_test.id = lambda: new_id
4124
# XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4125
# causes cloned tests to share the 'details' dict. This makes it hard to
4126
# read the test output for parameterized tests, because tracebacks will be
4127
# associated with irrelevant tests.
4129
details = new_test._TestCase__details
4130
except AttributeError:
4131
# must be a different version of testtools than expected. Do nothing.
4134
# Reset the '__details' dict.
4135
new_test._TestCase__details = {}
4139
def permute_tests_for_extension(standard_tests, loader, py_module_name,
4141
"""Helper for permutating tests against an extension module.
4143
This is meant to be used inside a modules 'load_tests()' function. It will
4144
create 2 scenarios, and cause all tests in the 'standard_tests' to be run
4145
against both implementations. Setting 'test.module' to the appropriate
4146
module. See bzrlib.tests.test__chk_map.load_tests as an example.
4148
:param standard_tests: A test suite to permute
4149
:param loader: A TestLoader
4150
:param py_module_name: The python path to a python module that can always
4151
be loaded, and will be considered the 'python' implementation. (eg
4152
'bzrlib._chk_map_py')
4153
:param ext_module_name: The python path to an extension module. If the
4154
module cannot be loaded, a single test will be added, which notes that
4155
the module is not available. If it can be loaded, all standard_tests
4156
will be run against that module.
4157
:return: (suite, feature) suite is a test-suite that has all the permuted
4158
tests. feature is the Feature object that can be used to determine if
4159
the module is available.
4162
py_module = pyutils.get_named_object(py_module_name)
4164
('python', {'module': py_module}),
4166
suite = loader.suiteClass()
4167
feature = ModuleAvailableFeature(ext_module_name)
4168
if feature.available():
4169
scenarios.append(('C', {'module': feature.module}))
4171
# the compiled module isn't available, so we add a failing test
4172
class FailWithoutFeature(TestCase):
4173
def test_fail(self):
4174
self.requireFeature(feature)
4175
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4176
result = multiply_tests(standard_tests, scenarios, suite)
4177
return result, feature
4180
def _rmtree_temp_dir(dirname, test_id=None):
4181
# If LANG=C we probably have created some bogus paths
4182
# which rmtree(unicode) will fail to delete
4183
# so make sure we are using rmtree(str) to delete everything
4184
# except on win32, where rmtree(str) will fail
4185
# since it doesn't have the property of byte-stream paths
4186
# (they are either ascii or mbcs)
4187
if sys.platform == 'win32':
4188
# make sure we are using the unicode win32 api
4189
dirname = unicode(dirname)
4191
dirname = dirname.encode(sys.getfilesystemencoding())
2290
def adapt_modules(mods_list, adapter, loader, suite):
2291
"""Adapt the modules in mods_list using adapter and add to suite."""
2292
for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
2293
suite.addTests(adapter.adapt(test))
2296
def _rmtree_temp_dir(dirname):
4193
2298
osutils.rmtree(dirname)
4194
2299
except OSError, e:
4195
# We don't want to fail here because some useful display will be lost
4196
# otherwise. Polluting the tmp dir is bad, but not giving all the
4197
# possible info to the test runner is even worse.
4199
ui.ui_factory.clear_term()
4200
sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4201
# Ugly, but the last thing we want here is fail, so bear with it.
4202
printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4203
).encode('ascii', 'replace')
4204
sys.stderr.write('Unable to remove testing dir %s\n%s'
4205
% (os.path.basename(dirname), printable_e))
2300
if sys.platform == 'win32' and e.errno == errno.EACCES:
2301
print >>sys.stderr, ('Permission denied: '
2302
'unable to remove testing dir '
2303
'%s' % os.path.basename(dirname))
2308
def clean_selftest_output(root=None, quiet=False):
2309
"""Remove all selftest output directories from root directory.
2311
:param root: root directory for clean
2312
(if ommitted or None then clean current directory).
2313
:param quiet: suppress report about deleting directories
2318
re_dir = re.compile(r'''test\d\d\d\d\.tmp''')
2321
for i in os.listdir(root):
2322
if os.path.isdir(i) and re_dir.match(i):
2324
print 'delete directory:', i
4208
2328
class Feature(object):
4231
2351
if getattr(self, 'feature_name', None):
4232
2352
return self.feature_name()
4233
2353
return self.__class__.__name__
4236
class _SymlinkFeature(Feature):
4239
return osutils.has_symlinks()
4241
def feature_name(self):
4244
SymlinkFeature = _SymlinkFeature()
4247
class _HardlinkFeature(Feature):
4250
return osutils.has_hardlinks()
4252
def feature_name(self):
4255
HardlinkFeature = _HardlinkFeature()
4258
class _OsFifoFeature(Feature):
4261
return getattr(os, 'mkfifo', None)
4263
def feature_name(self):
4264
return 'filesystem fifos'
4266
OsFifoFeature = _OsFifoFeature()
4269
class _UnicodeFilenameFeature(Feature):
4270
"""Does the filesystem support Unicode filenames?"""
4274
# Check for character combinations unlikely to be covered by any
4275
# single non-unicode encoding. We use the characters
4276
# - greek small letter alpha (U+03B1) and
4277
# - braille pattern dots-123456 (U+283F).
4278
os.stat(u'\u03b1\u283f')
4279
except UnicodeEncodeError:
4281
except (IOError, OSError):
4282
# The filesystem allows the Unicode filename but the file doesn't
4286
# The filesystem allows the Unicode filename and the file exists,
4290
UnicodeFilenameFeature = _UnicodeFilenameFeature()
4293
class _CompatabilityThunkFeature(Feature):
4294
"""This feature is just a thunk to another feature.
4296
It issues a deprecation warning if it is accessed, to let you know that you
4297
should really use a different feature.
4300
def __init__(self, dep_version, module, name,
4301
replacement_name, replacement_module=None):
4302
super(_CompatabilityThunkFeature, self).__init__()
4303
self._module = module
4304
if replacement_module is None:
4305
replacement_module = module
4306
self._replacement_module = replacement_module
4308
self._replacement_name = replacement_name
4309
self._dep_version = dep_version
4310
self._feature = None
4313
if self._feature is None:
4314
depr_msg = self._dep_version % ('%s.%s'
4315
% (self._module, self._name))
4316
use_msg = ' Use %s.%s instead.' % (self._replacement_module,
4317
self._replacement_name)
4318
symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
4319
# Import the new feature and use it as a replacement for the
4321
self._feature = pyutils.get_named_object(
4322
self._replacement_module, self._replacement_name)
4326
return self._feature._probe()
4329
class ModuleAvailableFeature(Feature):
4330
"""This is a feature than describes a module we want to be available.
4332
Declare the name of the module in __init__(), and then after probing, the
4333
module will be available as 'self.module'.
4335
:ivar module: The module if it is available, else None.
4338
def __init__(self, module_name):
4339
super(ModuleAvailableFeature, self).__init__()
4340
self.module_name = module_name
4344
self._module = __import__(self.module_name, {}, {}, [''])
4351
if self.available(): # Make sure the probe has been done
4355
def feature_name(self):
4356
return self.module_name
4359
def probe_unicode_in_user_encoding():
4360
"""Try to encode several unicode strings to use in unicode-aware tests.
4361
Return first successfull match.
4363
:return: (unicode value, encoded plain string value) or (None, None)
4365
possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
4366
for uni_val in possible_vals:
4368
str_val = uni_val.encode(osutils.get_user_encoding())
4369
except UnicodeEncodeError:
4370
# Try a different character
4373
return uni_val, str_val
4377
def probe_bad_non_ascii(encoding):
4378
"""Try to find [bad] character with code [128..255]
4379
that cannot be decoded to unicode in some encoding.
4380
Return None if all non-ascii characters is valid
4383
for i in xrange(128, 256):
4386
char.decode(encoding)
4387
except UnicodeDecodeError:
4392
class _HTTPSServerFeature(Feature):
4393
"""Some tests want an https Server, check if one is available.
4395
Right now, the only way this is available is under python2.6 which provides
4406
def feature_name(self):
4407
return 'HTTPSServer'
4410
HTTPSServerFeature = _HTTPSServerFeature()
4413
class _UnicodeFilename(Feature):
4414
"""Does the filesystem support Unicode filenames?"""
4419
except UnicodeEncodeError:
4421
except (IOError, OSError):
4422
# The filesystem allows the Unicode filename but the file doesn't
4426
# The filesystem allows the Unicode filename and the file exists,
4430
UnicodeFilename = _UnicodeFilename()
4433
class _ByteStringNamedFilesystem(Feature):
4434
"""Is the filesystem based on bytes?"""
4437
if os.name == "posix":
4441
ByteStringNamedFilesystem = _ByteStringNamedFilesystem()
4444
class _UTF8Filesystem(Feature):
4445
"""Is the filesystem UTF-8?"""
4448
if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
4452
UTF8Filesystem = _UTF8Filesystem()
4455
class _BreakinFeature(Feature):
4456
"""Does this platform support the breakin feature?"""
4459
from bzrlib import breakin
4460
if breakin.determine_signal() is None:
4462
if sys.platform == 'win32':
4463
# Windows doesn't have os.kill, and we catch the SIGBREAK signal.
4464
# We trigger SIGBREAK via a Console api so we need ctypes to
4465
# access the function
4472
def feature_name(self):
4473
return "SIGQUIT or SIGBREAK w/ctypes on win32"
4476
BreakinFeature = _BreakinFeature()
4479
class _CaseInsCasePresFilenameFeature(Feature):
4480
"""Is the file-system case insensitive, but case-preserving?"""
4483
fileno, name = tempfile.mkstemp(prefix='MixedCase')
4485
# first check truly case-preserving for created files, then check
4486
# case insensitive when opening existing files.
4487
name = osutils.normpath(name)
4488
base, rel = osutils.split(name)
4489
found_rel = osutils.canonical_relpath(base, name)
4490
return (found_rel == rel
4491
and os.path.isfile(name.upper())
4492
and os.path.isfile(name.lower()))
4497
def feature_name(self):
4498
return "case-insensitive case-preserving filesystem"
4500
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
4503
class _CaseInsensitiveFilesystemFeature(Feature):
4504
"""Check if underlying filesystem is case-insensitive but *not* case
4507
# Note that on Windows, Cygwin, MacOS etc, the file-systems are far
4508
# more likely to be case preserving, so this case is rare.
4511
if CaseInsCasePresFilenameFeature.available():
4514
if TestCaseWithMemoryTransport.TEST_ROOT is None:
4515
root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
4516
TestCaseWithMemoryTransport.TEST_ROOT = root
4518
root = TestCaseWithMemoryTransport.TEST_ROOT
4519
tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
4521
name_a = osutils.pathjoin(tdir, 'a')
4522
name_A = osutils.pathjoin(tdir, 'A')
4524
result = osutils.isdir(name_A)
4525
_rmtree_temp_dir(tdir)
4528
def feature_name(self):
4529
return 'case-insensitive filesystem'
4531
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
4534
class _CaseSensitiveFilesystemFeature(Feature):
4537
if CaseInsCasePresFilenameFeature.available():
4539
elif CaseInsensitiveFilesystemFeature.available():
4544
def feature_name(self):
4545
return 'case-sensitive filesystem'
4547
# new coding style is for feature instances to be lowercase
4548
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
4551
# Only define SubUnitBzrRunner if subunit is available.
4553
from subunit import TestProtocolClient
4554
from subunit.test_results import AutoTimingTestResultDecorator
4555
class SubUnitBzrProtocolClient(TestProtocolClient):
4557
def addSuccess(self, test, details=None):
4558
# The subunit client always includes the details in the subunit
4559
# stream, but we don't want to include it in ours.
4560
if details is not None and 'log' in details:
4562
return super(SubUnitBzrProtocolClient, self).addSuccess(
4565
class SubUnitBzrRunner(TextTestRunner):
4566
def run(self, test):
4567
result = AutoTimingTestResultDecorator(
4568
SubUnitBzrProtocolClient(self.stream))
4574
class _PosixPermissionsFeature(Feature):
4578
# create temporary file and check if specified perms are maintained.
4581
write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
4582
f = tempfile.mkstemp(prefix='bzr_perms_chk_')
4585
os.chmod(name, write_perms)
4587
read_perms = os.stat(name).st_mode & 0777
4589
return (write_perms == read_perms)
4591
return (os.name == 'posix') and has_perms()
4593
def feature_name(self):
4594
return 'POSIX permissions support'
4596
posix_permissions_feature = _PosixPermissionsFeature()