13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Testing framework extensions"""
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
# TODO: Perhaps there should be an API to find out if bzr running under the
19
# test suite -- some plugins might want to avoid making intrusive changes if
20
# this is the case. However, we want behaviour under to test to diverge as
21
# little as possible, so this should be used rarely if it's added at all.
22
# (Suggestion from j-a-meinel, 2005-11-24)
19
24
# NOTE: Some classes in here use camelCaseNaming() rather than
20
25
# underscore_naming(). That's for consistency with unittest; it's not the
21
26
# general style of bzrlib. Please continue that consistency when adding e.g.
22
27
# new assertFoo() methods.
27
30
from cStringIO import StringIO
36
from pprint import pformat
40
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
47
from bzrlib import (
62
commands as _mod_commands,
72
plugin as _mod_plugin,
79
transport as _mod_transport,
57
import bzrlib.commands
58
import bzrlib.bundle.serializer
60
import bzrlib.inventory
61
import bzrlib.iterablefile
83
64
import bzrlib.lsprof
84
65
except ImportError:
85
66
# lsprof not available
87
from bzrlib.smart import client, request
88
from bzrlib.transport import (
92
from bzrlib.symbol_versioning import (
96
from bzrlib.tests import (
101
from bzrlib.ui import NullProgressView
102
from bzrlib.ui.text import TextUIFactory
104
# Mark this python module as being part of the implementation
105
# of unittest: this gives us better tracebacks where the last
106
# 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):
68
from bzrlib.merge import merge_inner
72
from bzrlib.revision import common_ancestor
74
from bzrlib import symbol_versioning
76
from bzrlib.transport import get_transport
77
import bzrlib.transport
78
from bzrlib.transport.local import LocalURLServer
79
from bzrlib.transport.memory import MemoryServer
80
from bzrlib.transport.readonly import ReadonlyServer
81
from bzrlib.trace import mutter, note
82
from bzrlib.tests import TestUtil
83
from bzrlib.tests.HttpServer import HttpServer
84
from bzrlib.tests.TestUtil import (
88
from bzrlib.tests.treeshape import build_tree_contents
89
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
91
default_transport = LocalURLServer
94
MODULES_TO_DOCTEST = [
95
bzrlib.bundle.serializer,
107
def packages_to_test():
108
"""Return a list of packages to test.
110
The packages are not globally imported so that import failures are
111
triggered when running selftest, not when importing the command.
114
import bzrlib.tests.blackbox
115
import bzrlib.tests.branch_implementations
116
import bzrlib.tests.bzrdir_implementations
117
import bzrlib.tests.interrepository_implementations
118
import bzrlib.tests.interversionedfile_implementations
119
import bzrlib.tests.intertree_implementations
120
import bzrlib.tests.repository_implementations
121
import bzrlib.tests.revisionstore_implementations
122
import bzrlib.tests.tree_implementations
123
import bzrlib.tests.workingtree_implementations
126
bzrlib.tests.blackbox,
127
bzrlib.tests.branch_implementations,
128
bzrlib.tests.bzrdir_implementations,
129
bzrlib.tests.interrepository_implementations,
130
bzrlib.tests.interversionedfile_implementations,
131
bzrlib.tests.intertree_implementations,
132
bzrlib.tests.repository_implementations,
133
bzrlib.tests.revisionstore_implementations,
134
bzrlib.tests.tree_implementations,
135
bzrlib.tests.workingtree_implementations,
139
class ExtendedTestResult(unittest._TextTestResult):
216
140
"""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.
142
Compared to this unittest version this class adds support for profiling,
143
benchmarking, stopping as soon as a test fails, and skipping tests.
144
There are further-specialized subclasses for different types of display.
231
147
stop_early = False
233
149
def __init__(self, stream, descriptions, verbosity,
234
150
bench_history=None,
237
153
"""Construct new TestResult.
239
155
:param bench_history: Optionally, a writable file object to accumulate
240
156
benchmark results.
242
testtools.TextTestResult.__init__(self, stream)
158
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
243
159
if bench_history is not None:
244
160
from bzrlib.version import _get_bzr_source_tree
245
161
src_tree = _get_bzr_source_tree()
353
204
def _shortened_test_description(self, test):
355
what = re.sub(r'^bzrlib\.tests\.', '', what)
206
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
209
def startTest(self, test):
367
super(ExtendedTestResult, self).startTest(test)
210
unittest.TestResult.startTest(self, test)
371
211
self.report_test_start(test)
372
test.number = self.count
373
212
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
214
def _recordTestStartTime(self):
423
215
"""Record that a test has started."""
424
self._start_datetime = self._now()
216
self._start_time = time.time()
426
218
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)
434
self.error_count += 1
219
if isinstance(err[1], TestSkipped):
220
return self.addSkipped(test, err)
221
unittest.TestResult.addError(self, test, err)
222
# We can only do this if we have one of our TestCases, not if
224
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
225
if setKeepLogfile is not None:
227
self.extractBenchmarkTime(test)
435
228
self.report_error(test, err)
436
229
if self.stop_early:
439
232
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)
447
self.failure_count += 1
233
unittest.TestResult.addFailure(self, test, err)
234
# We can only do this if we have one of our TestCases, not if
236
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
237
if setKeepLogfile is not None:
239
self.extractBenchmarkTime(test)
448
240
self.report_failure(test, err)
449
241
if self.stop_early:
452
def addSuccess(self, test, details=None):
453
"""Tell result that test completed successfully.
455
Called from the TestCase run()
244
def addSuccess(self, test):
245
self.extractBenchmarkTime(test)
457
246
if self._bench_history is not None:
458
benchmark_time = self._extractBenchmarkTime(test, details)
459
if benchmark_time is not None:
247
if self._benchmarkTime is not None:
460
248
self._bench_history.write("%s %s\n" % (
461
self._formatTime(benchmark_time),
249
self._formatTime(self._benchmarkTime),
463
251
self.report_success(test)
464
super(ExtendedTestResult, self).addSuccess(test)
465
test._log_contents = ''
467
def addExpectedFailure(self, test, err):
468
self.known_failure_count += 1
469
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
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
self.unsupported.setdefault(str(feature), 0)
494
self.unsupported[str(feature)] += 1
495
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()
252
unittest.TestResult.addSuccess(self, test)
254
def addSkipped(self, test, skip_excinfo):
255
self.extractBenchmarkTime(test)
256
self.report_skip(test, skip_excinfo)
257
# seems best to treat this as success from point-of-view of unittest
258
# -- it actually does nothing so it barely matters :)
261
except KeyboardInterrupt:
264
self.addError(test, test.__exc_info())
266
unittest.TestResult.addSuccess(self, test)
268
def printErrorList(self, flavour, errors):
269
for test, err in errors:
270
self.stream.writeln(self.separator1)
271
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
272
if getattr(test, '_get_log', None) is not None:
274
print >>self.stream, \
275
('vvvv[log from %s]' % test.id()).ljust(78,'-')
276
print >>self.stream, test._get_log()
277
print >>self.stream, \
278
('^^^^[log from %s]' % test.id()).ljust(78,'-')
279
self.stream.writeln(self.separator2)
280
self.stream.writeln("%s" % err)
285
def report_cleaning_up(self):
556
288
def report_success(self, test):
559
def wasStrictlySuccessful(self):
560
if self.unsupported or self.known_failure_count:
562
return self.wasSuccessful()
565
292
class TextTestResult(ExtendedTestResult):
566
293
"""Displays progress and results of tests in text form"""
568
def __init__(self, stream, descriptions, verbosity,
573
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")
295
def __init__(self, *args, **kw):
296
ExtendedTestResult.__init__(self, *args, **kw)
579
297
self.pb = self.ui.nested_progress_bar()
580
298
self.pb.show_pct = False
581
299
self.pb.show_spinner = False
582
self.pb.show_eta = False,
300
self.pb.show_eta = False,
583
301
self.pb.show_count = False
584
302
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))
304
def report_starting(self):
305
self.pb.update('[test 0/%d] starting...' % (self.num_tests))
598
307
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
308
a = '[%d' % self.count
309
if self.num_tests is not None:
609
310
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)
311
a += ' in %ds' % (time.time() - self._overall_start_time)
313
a += ', %d errors' % self.error_count
314
if self.failure_count:
315
a += ', %d failed' % self.failure_count
317
a += ', %d skipped' % self.skip_count
624
321
def report_test_start(self, test):
626
324
self._progress_prefix_text()
628
326
+ self._shortened_test_description(test))
630
def _test_description(self, test):
631
return self._shortened_test_description(test)
633
328
def report_error(self, test, err):
634
self.stream.write('ERROR: %s\n %s\n' % (
635
self._test_description(test),
329
self.error_count += 1
330
self.pb.note('ERROR: %s\n %s\n',
331
self._shortened_test_description(test),
639
335
def report_failure(self, test, err):
640
self.stream.write('FAIL: %s\n %s\n' % (
641
self._test_description(test),
336
self.failure_count += 1
337
self.pb.note('FAIL: %s\n %s\n',
338
self._shortened_test_description(test),
645
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):
661
def report_unsupported(self, test, feature):
662
"""test cannot be run because feature is missing."""
342
def report_skip(self, test, skip_excinfo):
345
# at the moment these are mostly not things we can fix
346
# and so they just produce stipple; use the verbose reporter
349
# show test and reason for skip
350
self.pb.note('SKIP: %s\n %s\n',
351
self._shortened_test_description(test),
354
# since the class name was left behind in the still-visible
356
self.pb.note('SKIP: %s', skip_excinfo[1])
358
def report_cleaning_up(self):
359
self.pb.update('cleaning up...')
665
365
class VerboseTestResult(ExtendedTestResult):
956
542
retrieved by _get_log(). We use a real OS file, not an in-memory object,
957
543
so that it can also capture file IO. When the test completes this file
958
544
is read into memory and removed from disk.
960
546
There are also convenience functions to invoke bzr's command-line
961
547
routine, and to build and check bzr trees.
963
549
In addition to the usual method of overriding tearDown(), this class also
964
allows subclasses to register cleanup functions via addCleanup, which are
550
allows subclasses to register functions into the _cleanups list, which is
965
551
run in order as the object is torn down. It's less likely this will be
966
552
accidentally overlooked.
555
_log_file_name = None
557
_keep_log_file = False
970
558
# record lsprof data when performing benchmark calls.
971
559
_gather_lsprof_in_benchmarks = False
973
561
def __init__(self, methodName='testMethod'):
974
562
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)
566
unittest.TestCase.setUp(self)
985
567
self._cleanEnvironment()
568
bzrlib.trace.disable_default_logging()
986
569
self._silenceUI()
987
570
self._startLogFile()
988
571
self._benchcalls = []
989
572
self._benchtime = None
991
self._track_transports()
993
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
def _clear_debug_flags(self):
1080
"""Prevent externally set debug flags affecting tests.
1082
Tests that want to use debug flags can just set them in the
1083
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')
1092
def _clear_hooks(self):
1093
573
# 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 = {}
574
self._preserved_hooks = bzrlib.branch.Branch.hooks
1101
575
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
576
# this list of hooks must be kept in sync with the defaults
578
bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
1116
580
def _silenceUI(self):
1117
581
"""Turn off UI for duration of test"""
1118
582
# 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.")
583
saved = bzrlib.ui.ui_factory
585
bzrlib.ui.ui_factory = saved
586
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
587
self.addCleanup(_restore)
1303
589
def _ndiff_strings(self, a, b):
1304
590
"""Return ndiff between two strings containing lines.
1306
592
A trailing newline is added if missing to make the strings
1307
593
print properly."""
1308
594
if b and b[-1] != '\n':
1706
782
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)
784
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
785
self._log_file = os.fdopen(fileno, 'w+')
786
self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
787
self._log_file_name = name
1717
788
self.addCleanup(self._finishLogFile)
1719
790
def _finishLogFile(self):
1720
791
"""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)
793
Close the file and delete it, unless setKeepLogfile was called.
795
if self._log_file is None:
797
bzrlib.trace.disable_test_log(self._log_nonce)
798
self._log_file.close()
799
self._log_file = None
800
if not self._keep_log_file:
801
os.remove(self._log_file_name)
802
self._log_file_name = None
804
def setKeepLogfile(self):
805
"""Make the logfile not be deleted when _finishLogFile is called."""
806
self._keep_log_file = True
808
def addCleanup(self, callable):
809
"""Arrange to run a callable when this case is torn down.
811
Callables are run in the reverse of the order they are registered,
812
ie last-in first-out.
814
if callable in self._cleanups:
815
raise ValueError("cleanup function %r already registered on %s"
817
self._cleanups.append(callable)
1798
819
def _cleanEnvironment(self):
1799
for name, value in isolated_environ.iteritems():
1800
self.overrideEnv(name, value)
821
'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
823
'APPDATA': os.getcwd(),
825
'BZREMAIL': None, # may still be present in the environment
827
'BZR_PROGRESS_BAR': None,
837
# Nobody cares about these ones AFAIK. So far at
838
# least. If you do (care), please update this comment
844
self.addCleanup(self._restoreEnvironment)
845
for name, value in new_env.iteritems():
846
self._captureVar(name, value)
848
def _captureVar(self, name, newvalue):
849
"""Set an environment variable, and reset it when finished."""
850
self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
852
def _restoreEnvironment(self):
853
for name, value in self.__old_env.iteritems():
854
osutils.set_or_unset_env(name, value)
1802
856
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()
1809
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)
857
bzrlib.branch.Branch.hooks = self._preserved_hooks
861
unittest.TestCase.tearDown(self)
1901
863
def time(self, callable, *args, **kwargs):
1902
864
"""Run callable and accrue the time it takes to the benchmark time.
1904
866
If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1905
867
this will cause lsprofile statistics to be gathered and stored in
1906
868
self._benchcalls.
1908
870
if self._benchtime is None:
1909
self.addDetail('benchtime', content.Content(content.ContentType(
1910
"text", "plain"), lambda:[str(self._benchtime)]))
1911
871
self._benchtime = 0
1912
872
start = time.time()
2529
1388
base += urlutils.escape(relpath)
2532
def get_url(self, relpath=None):
2533
"""Get a URL (or maybe a path) for the readwrite transport.
2535
This will either be backed by '.' or to an equivalent non-file based
2537
relpath provides for clients to get a path relative to the base url.
2538
These should only be downwards relative, not upwards.
2540
base = self.get_server().get_url()
2541
return self._adjust_url(base, relpath)
2543
def get_vfs_only_url(self, relpath=None):
2544
"""Get a URL (or maybe a path for the plain old vfs transport.
2546
This will never be a smart protocol. It always has all the
2547
capabilities of the local filesystem, but it might actually be a
2548
MemoryTransport or some other similar virtual filesystem.
2550
This is the backing transport (if any) of the server returned by
2551
get_url and get_readonly_url.
2553
:param relpath: provides for clients to get a path relative to the base
2554
url. These should only be downwards relative, not upwards.
2557
base = self.get_vfs_only_server().get_url()
2558
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
1391
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)
1392
if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1396
root = u'test%04d.tmp' % i
1400
if e.errno == errno.EEXIST:
1405
# successfully created
1406
TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
1408
# make a fake bzr directory there to prevent any tests propagating
1409
# up onto the source directory's real branch
1410
bzrdir.BzrDir.create_standalone_workingtree(
1411
TestCaseWithMemoryTransport.TEST_ROOT)
2617
1413
def makeAndChdirToTestDir(self):
2618
1414
"""Create a temporary directories for this one test.
2620
1416
This must set self.test_home_dir and self.test_dir and chdir to
2623
1419
For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
2625
1421
os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2626
1422
self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
2627
1423
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2628
self.permit_dir(self.test_dir)
2630
1425
def make_branch(self, relpath, format=None):
2631
1426
"""Create a branch on the transport at relpath."""
2632
1427
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)
1428
return repo.bzrdir.create_branch()
2667
1430
def make_bzrdir(self, relpath, format=None):
2669
1432
# might be a relative or absolute path
2670
1433
maybe_a_url = self.get_url(relpath)
2671
1434
segments = maybe_a_url.rsplit('/', 1)
2672
t = _mod_transport.get_transport(maybe_a_url)
1435
t = get_transport(maybe_a_url)
2673
1436
if len(segments) > 1 and segments[-1] not in ('', '.'):
2675
format = self.resolve_format(format)
1439
except errors.FileExists:
1443
if isinstance(format, basestring):
1444
format = bzrdir.format_registry.make_bzrdir(format)
2676
1445
return format.initialize_on_transport(t)
2677
1446
except errors.UninitializableFormat:
2678
1447
raise TestSkipped("Format %s is not initializable." % format)
2680
def make_repository(self, relpath, shared=None, format=None):
2681
"""Create a repository on our default transport at relpath.
2683
Note that relpath must be a relative path, not a full url.
2685
# FIXME: If you create a remoterepository this returns the underlying
2686
# real format, which is incorrect. Actually we should make sure that
2687
# RemoteBzrDir returns a RemoteRepository.
2688
# maybe mbp 20070410
1449
def make_repository(self, relpath, shared=False, format=None):
1450
"""Create a repository on our default transport at relpath."""
2689
1451
made_control = self.make_bzrdir(relpath, format=format)
2690
1452
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
1454
def make_branch_and_memory_tree(self, relpath, format=None):
2702
1455
"""Create a branch on the default transport and a MemoryTree for it."""
2703
1456
b = self.make_branch(relpath, format=format)
2704
1457
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
1459
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)
1460
os.environ['HOME'] = self.test_home_dir
1461
os.environ['APPDATA'] = self.test_home_dir
2717
1463
def setUp(self):
2718
1464
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
1465
self._make_test_root()
2730
self.addCleanup(os.chdir, os.getcwdu())
1466
_currentdir = os.getcwdu()
1467
def _leaveDirectory():
1468
os.chdir(_currentdir)
1469
self.addCleanup(_leaveDirectory)
2731
1470
self.makeAndChdirToTestDir()
2732
1471
self.overrideEnvironmentForTesting()
2733
1472
self.__readonly_server = None
2734
1473
self.__server = None
2735
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
1476
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2756
1477
"""Derived class that runs a test within a temporary directory.
3024
1681
for readonly urls.
3026
1683
TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
3027
be used without needed to redo it when a different
1684
be used without needed to redo it when a different
3028
1685
subclass is in use ?
3031
1688
def setUp(self):
3032
from bzrlib.tests import http_server
3033
1689
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):
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)
1690
if not self.transport_server == MemoryServer:
1691
self.transport_readonly_server = HttpServer
3120
1694
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)
1695
result = TestUtil.TestSuite()
1696
filter_re = re.compile(pattern)
1697
for test in iter_suite_tests(suite):
1698
if filter_re.search(test.id()):
1699
result.addTest(test)
1703
def sort_suite_by_re(suite, pattern):
1706
filter_re = re.compile(pattern)
1707
for test in iter_suite_tests(suite):
1708
if filter_re.search(test.id()):
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))
1712
return TestUtil.TestSuite(first + second)
3227
1715
def run_suite(suite, name='test', verbose=False, pattern=".*",
3228
stop_on_failure=False,
1716
stop_on_failure=False, keep_output=False,
3229
1717
transport=None, lsprof_timed=None, bench_history=None,
3230
matching_tests_first=None,
3233
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.
1718
matching_tests_first=None):
3247
1719
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
3252
if runner_class is None:
3253
runner_class = TextTestRunner
3256
runner = runner_class(stream=stream,
1724
runner = TextTestRunner(stream=sys.stdout,
3257
1725
descriptions=0,
3258
1726
verbosity=verbosity,
3259
bench_history=bench_history,
3261
result_decorators=result_decorators,
1727
keep_output=keep_output,
1728
bench_history=bench_history)
3263
1729
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()))
1731
if matching_tests_first:
1732
suite = sort_suite_by_re(suite, pattern)
1734
suite = filter_suite_by_re(suite, pattern)
3290
1735
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())
3471
# Convert the seed to a long if we can
3473
self.random_seed = long(self.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)
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()
1736
return result.wasSuccessful()
3684
1739
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
3685
1741
transport=None,
3686
1742
test_suite_factory=None,
3687
1743
lsprof_timed=None,
3688
1744
bench_history=None,
3689
matching_tests_first=None,
3692
exclude_pattern=None,
3698
suite_decorators=None,
1745
matching_tests_first=None):
3702
1746
"""Run the whole test suite under the enhanced runner"""
3703
1747
# XXX: Very ugly way to do this...
3704
1748
# Disable warning about old formats because we don't want it to disturb
3711
1755
transport = default_transport
3712
1756
old_transport = default_transport
3713
1757
default_transport = transport
3714
global selftest_debug_flags
3715
old_debug_flags = selftest_debug_flags
3716
if debug_flags is not None:
3717
selftest_debug_flags = set(debug_flags)
3719
if load_list is None:
3722
keep_only = load_test_id_list(load_list)
3724
starting_with = [test_prefix_alias_registry.resolve_alias(start)
3725
for start in starting_with]
3726
1759
if test_suite_factory is None:
3727
# Reduce loading time by loading modules based on the starting_with
3729
suite = test_suite(keep_only, starting_with)
1760
suite = test_suite()
3731
1762
suite = test_suite_factory()
3733
# But always filter as requested.
3734
suite = filter_suite_by_id_startswith(suite, starting_with)
3735
result_decorators = []
3737
result_decorators.append(ProfileResult)
3738
1763
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
3739
stop_on_failure=stop_on_failure,
1764
stop_on_failure=stop_on_failure, keep_output=keep_output,
3740
1765
transport=transport,
3741
1766
lsprof_timed=lsprof_timed,
3742
1767
bench_history=bench_history,
3743
matching_tests_first=matching_tests_first,
3744
list_only=list_only,
3745
random_seed=random_seed,
3746
exclude_pattern=exclude_pattern,
3748
runner_class=runner_class,
3749
suite_decorators=suite_decorators,
3751
result_decorators=result_decorators,
1768
matching_tests_first=matching_tests_first)
3754
1770
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
1774
"""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
1776
This function can be replaced if you need to change the default test
4160
1777
suite on a global basis, but it is not encouraged.
1780
'bzrlib.tests.test_ancestry',
1781
'bzrlib.tests.test_annotate',
1782
'bzrlib.tests.test_api',
1783
'bzrlib.tests.test_atomicfile',
1784
'bzrlib.tests.test_bad_files',
1785
'bzrlib.tests.test_branch',
1786
'bzrlib.tests.test_bundle',
1787
'bzrlib.tests.test_bzrdir',
1788
'bzrlib.tests.test_cache_utf8',
1789
'bzrlib.tests.test_commands',
1790
'bzrlib.tests.test_commit',
1791
'bzrlib.tests.test_commit_merge',
1792
'bzrlib.tests.test_config',
1793
'bzrlib.tests.test_conflicts',
1794
'bzrlib.tests.test_decorators',
1795
'bzrlib.tests.test_delta',
1796
'bzrlib.tests.test_diff',
1797
'bzrlib.tests.test_dirstate',
1798
'bzrlib.tests.test_doc_generate',
1799
'bzrlib.tests.test_errors',
1800
'bzrlib.tests.test_escaped_store',
1801
'bzrlib.tests.test_extract',
1802
'bzrlib.tests.test_fetch',
1803
'bzrlib.tests.test_ftp_transport',
1804
'bzrlib.tests.test_generate_docs',
1805
'bzrlib.tests.test_generate_ids',
1806
'bzrlib.tests.test_globbing',
1807
'bzrlib.tests.test_gpg',
1808
'bzrlib.tests.test_graph',
1809
'bzrlib.tests.test_hashcache',
1810
'bzrlib.tests.test_http',
1811
'bzrlib.tests.test_http_response',
1812
'bzrlib.tests.test_https_ca_bundle',
1813
'bzrlib.tests.test_identitymap',
1814
'bzrlib.tests.test_ignores',
1815
'bzrlib.tests.test_inv',
1816
'bzrlib.tests.test_knit',
1817
'bzrlib.tests.test_lazy_import',
1818
'bzrlib.tests.test_lazy_regex',
1819
'bzrlib.tests.test_lockdir',
1820
'bzrlib.tests.test_lockable_files',
1821
'bzrlib.tests.test_log',
1822
'bzrlib.tests.test_memorytree',
1823
'bzrlib.tests.test_merge',
1824
'bzrlib.tests.test_merge3',
1825
'bzrlib.tests.test_merge_core',
1826
'bzrlib.tests.test_missing',
1827
'bzrlib.tests.test_msgeditor',
1828
'bzrlib.tests.test_nonascii',
1829
'bzrlib.tests.test_options',
1830
'bzrlib.tests.test_osutils',
1831
'bzrlib.tests.test_osutils_encodings',
1832
'bzrlib.tests.test_patch',
1833
'bzrlib.tests.test_patches',
1834
'bzrlib.tests.test_permissions',
1835
'bzrlib.tests.test_plugins',
1836
'bzrlib.tests.test_progress',
1837
'bzrlib.tests.test_reconcile',
1838
'bzrlib.tests.test_registry',
1839
'bzrlib.tests.test_repository',
1840
'bzrlib.tests.test_revert',
1841
'bzrlib.tests.test_revision',
1842
'bzrlib.tests.test_revisionnamespaces',
1843
'bzrlib.tests.test_revisiontree',
1844
'bzrlib.tests.test_rio',
1845
'bzrlib.tests.test_sampler',
1846
'bzrlib.tests.test_selftest',
1847
'bzrlib.tests.test_setup',
1848
'bzrlib.tests.test_sftp_transport',
1849
'bzrlib.tests.test_smart_add',
1850
'bzrlib.tests.test_smart_transport',
1851
'bzrlib.tests.test_source',
1852
'bzrlib.tests.test_status',
1853
'bzrlib.tests.test_store',
1854
'bzrlib.tests.test_subsume',
1855
'bzrlib.tests.test_symbol_versioning',
1856
'bzrlib.tests.test_tag',
1857
'bzrlib.tests.test_testament',
1858
'bzrlib.tests.test_textfile',
1859
'bzrlib.tests.test_textmerge',
1860
'bzrlib.tests.test_trace',
1861
'bzrlib.tests.test_transactions',
1862
'bzrlib.tests.test_transform',
1863
'bzrlib.tests.test_transport',
1864
'bzrlib.tests.test_tree',
1865
'bzrlib.tests.test_treebuilder',
1866
'bzrlib.tests.test_tsort',
1867
'bzrlib.tests.test_tuned_gzip',
1868
'bzrlib.tests.test_ui',
1869
'bzrlib.tests.test_upgrade',
1870
'bzrlib.tests.test_urlutils',
1871
'bzrlib.tests.test_versionedfile',
1872
'bzrlib.tests.test_version',
1873
'bzrlib.tests.test_version_info',
1874
'bzrlib.tests.test_weave',
1875
'bzrlib.tests.test_whitebox',
1876
'bzrlib.tests.test_workingtree',
1877
'bzrlib.tests.test_workingtree_4',
1878
'bzrlib.tests.test_wsgi',
1879
'bzrlib.tests.test_xml',
1881
test_transport_implementations = [
1882
'bzrlib.tests.test_transport_implementations',
1883
'bzrlib.tests.test_read_bundle',
1885
suite = TestUtil.TestSuite()
4163
1886
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
1887
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1888
from bzrlib.transport import TransportTestProviderAdapter
1889
adapter = TransportTestProviderAdapter()
1890
adapt_modules(test_transport_implementations, adapter, loader, suite)
1891
for package in packages_to_test():
1892
suite.addTest(package.test_suite())
1893
for m in MODULES_TO_TEST:
1894
suite.addTest(loader.loadTestsFromModule(m))
1895
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)
1897
suite.addTest(doctest.DocTestSuite(m))
4207
1898
except ValueError, e:
4208
print '**failed to get doctest for: %s\n%s' % (mod, e)
1899
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)
1901
for name, plugin in bzrlib.plugin.all_plugins().items():
1902
if getattr(plugin, 'test_suite', None) is not None:
1903
default_encoding = sys.getdefaultencoding()
1905
plugin_suite = plugin.test_suite()
1906
except ImportError, e:
1907
bzrlib.trace.warning(
1908
'Unable to test plugin "%s": %s', name, e)
1910
suite.addTest(plugin_suite)
1911
if default_encoding != sys.getdefaultencoding():
1912
bzrlib.trace.warning(
1913
'Plugin "%s" tried to reset default encoding to: %s', name,
1914
sys.getdefaultencoding())
1916
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):
4417
# If LANG=C we probably have created some bogus paths
4418
# which rmtree(unicode) will fail to delete
4419
# so make sure we are using rmtree(str) to delete everything
4420
# except on win32, where rmtree(str) will fail
4421
# since it doesn't have the property of byte-stream paths
4422
# (they are either ascii or mbcs)
4423
if sys.platform == 'win32':
4424
# make sure we are using the unicode win32 api
4425
dirname = unicode(dirname)
4427
dirname = dirname.encode(sys.getfilesystemencoding())
4429
osutils.rmtree(dirname)
4431
# We don't want to fail here because some useful display will be lost
4432
# otherwise. Polluting the tmp dir is bad, but not giving all the
4433
# possible info to the test runner is even worse.
4435
ui.ui_factory.clear_term()
4436
sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4437
# Ugly, but the last thing we want here is fail, so bear with it.
4438
printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4439
).encode('ascii', 'replace')
4440
sys.stderr.write('Unable to remove testing dir %s\n%s'
4441
% (os.path.basename(dirname), printable_e))
4444
def probe_unicode_in_user_encoding():
4445
"""Try to encode several unicode strings to use in unicode-aware tests.
4446
Return first successfull match.
4448
:return: (unicode value, encoded plain string value) or (None, None)
4450
possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
4451
for uni_val in possible_vals:
4453
str_val = uni_val.encode(osutils.get_user_encoding())
4454
except UnicodeEncodeError:
4455
# Try a different character
4458
return uni_val, str_val
4462
def probe_bad_non_ascii(encoding):
4463
"""Try to find [bad] character with code [128..255]
4464
that cannot be decoded to unicode in some encoding.
4465
Return None if all non-ascii characters is valid
4468
for i in xrange(128, 256):
4471
char.decode(encoding)
4472
except UnicodeDecodeError:
4477
# Only define SubUnitBzrRunner if subunit is available.
4479
from subunit import TestProtocolClient
4480
from subunit.test_results import AutoTimingTestResultDecorator
4481
class SubUnitBzrProtocolClient(TestProtocolClient):
4483
def addSuccess(self, test, details=None):
4484
# The subunit client always includes the details in the subunit
4485
# stream, but we don't want to include it in ours.
4486
if details is not None and 'log' in details:
4488
return super(SubUnitBzrProtocolClient, self).addSuccess(
4491
class SubUnitBzrRunner(TextTestRunner):
4492
def run(self, test):
4493
result = AutoTimingTestResultDecorator(
4494
SubUnitBzrProtocolClient(self.stream))
4501
@deprecated_function(deprecated_in((2, 5, 0)))
4502
def ModuleAvailableFeature(name):
4503
from bzrlib.tests import features
4504
return features.ModuleAvailableFeature(name)
1920
def adapt_modules(mods_list, adapter, loader, suite):
1921
"""Adapt the modules in mods_list using adapter and add to suite."""
1922
for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1923
suite.addTests(adapter.adapt(test))
1926
def clean_selftest_output(root=None, quiet=False):
1927
"""Remove all selftest output directories from root directory.
1929
:param root: root directory for clean
1930
(if ommitted or None then clean current directory).
1931
:param quiet: suppress report about deleting directories
1936
re_dir = re.compile(r'''test\d\d\d\d\.tmp''')
1939
for i in os.listdir(root):
1940
if os.path.isdir(i) and re_dir.match(i):
1942
print 'delete directory:', i