33
31
from cStringIO import StringIO
37
from pprint import pformat
42
from subprocess import Popen, PIPE
56
# nb: check this before importing anything else from within it
57
_testtools_version = getattr(testtools, '__version__', ())
58
if _testtools_version < (0, 9, 5):
59
raise ImportError("need at least testtools 0.9.5: %s is %r"
60
% (testtools.__file__, _testtools_version))
61
from testtools import content
64
51
from bzrlib import (
68
commands as _mod_commands,
77
plugin as _mod_plugin,
84
transport as _mod_transport,
63
import bzrlib.commands
64
import bzrlib.timestamp
66
import bzrlib.inventory
67
import bzrlib.iterablefile
88
70
import bzrlib.lsprof
89
71
except ImportError:
90
72
# lsprof not available
92
from bzrlib.smart import client, request
93
from bzrlib.transport import (
97
from bzrlib.tests import (
102
from bzrlib.ui import NullProgressView
103
from bzrlib.ui.text import TextUIFactory
74
from bzrlib.merge import merge_inner
78
from bzrlib import symbol_versioning
79
from bzrlib.symbol_versioning import (
86
from bzrlib.transport import get_transport
87
import bzrlib.transport
88
from bzrlib.transport.local import LocalURLServer
89
from bzrlib.transport.memory import MemoryServer
90
from bzrlib.transport.readonly import ReadonlyServer
91
from bzrlib.trace import mutter, note
92
from bzrlib.tests import TestUtil
93
from bzrlib.tests.http_server import HttpServer
94
from bzrlib.tests.TestUtil import (
98
from bzrlib.tests.treeshape import build_tree_contents
99
import bzrlib.version_info_formats.format_custom
100
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
105
102
# Mark this python module as being part of the implementation
106
103
# of unittest: this gives us better tracebacks where the last
107
104
# shown frame is the test code, not our assertXYZ.
110
default_transport = test_server.LocalURLServer
113
_unitialized_attr = object()
114
"""A sentinel needed to act as a default value in a method signature."""
117
# Subunit result codes, defined here to prevent a hard dependency on subunit.
121
# These are intentionally brought into this namespace. That way plugins, etc
122
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
123
TestSuite = TestUtil.TestSuite
124
TestLoader = TestUtil.TestLoader
126
# Tests should run in a clean and clearly defined environment. The goal is to
127
# keep them isolated from the running environment as mush as possible. The test
128
# framework ensures the variables defined below are set (or deleted if the
129
# value is None) before a test is run and reset to their original value after
130
# the test is run. Generally if some code depends on an environment variable,
131
# the tests should start without this variable in the environment. There are a
132
# few exceptions but you shouldn't violate this rule lightly.
136
# bzr now uses the Win32 API and doesn't rely on APPDATA, but the
137
# tests do check our impls match APPDATA
138
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
142
'BZREMAIL': None, # may still be present in the environment
143
'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
144
'BZR_PROGRESS_BAR': None,
146
'BZR_PLUGIN_PATH': None,
147
'BZR_DISABLE_PLUGINS': None,
148
'BZR_PLUGINS_AT': None,
149
'BZR_CONCURRENCY': None,
150
# Make sure that any text ui tests are consistent regardless of
151
# the environment the test case is run in; you may want tests that
152
# test other combinations. 'dumb' is a reasonable guess for tests
153
# going to a pipe or a StringIO.
159
'SSH_AUTH_SOCK': None,
169
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
170
# least. If you do (care), please update this comment
174
'BZR_REMOTE_PATH': None,
175
# Generally speaking, we don't want apport reporting on crashes in
176
# the test envirnoment unless we're specifically testing apport,
177
# so that it doesn't leak into the real system environment. We
178
# use an env var so it propagates to subprocesses.
179
'APPORT_DISABLE': '1',
183
def override_os_environ(test, env=None):
184
"""Modify os.environ keeping a copy.
186
:param test: A test instance
188
:param env: A dict containing variable definitions to be installed
191
env = isolated_environ
192
test._original_os_environ = dict([(var, value)
193
for var, value in os.environ.iteritems()])
194
for var, value in env.iteritems():
195
osutils.set_or_unset_env(var, value)
196
if var not in test._original_os_environ:
197
# The var is new, add it with a value of None, so
198
# restore_os_environ will delete it
199
test._original_os_environ[var] = None
202
def restore_os_environ(test):
203
"""Restore os.environ to its original state.
205
:param test: A test instance previously passed to override_os_environ.
207
for var, value in test._original_os_environ.iteritems():
208
# Restore the original value (or delete it if the value has been set to
209
# None in override_os_environ).
210
osutils.set_or_unset_env(var, value)
213
class ExtendedTestResult(testtools.TextTestResult):
107
default_transport = LocalURLServer
110
class ExtendedTestResult(unittest._TextTestResult):
214
111
"""Accepts, reports and accumulates the results of running tests.
216
113
Compared to the unittest version this class adds support for
263
160
self.unsupported = {}
265
162
self._overall_start_time = time.time()
266
self._strict = strict
267
self._first_thread_leaker_id = None
268
self._tests_leaking_threads_count = 0
269
self._traceback_from_test = None
271
def stopTestRun(self):
274
stopTime = time.time()
275
timeTaken = stopTime - self.startTime
276
# GZ 2010-07-19: Seems testtools has no printErrors method, and though
277
# the parent class method is similar have to duplicate
278
self._show_list('ERROR', self.errors)
279
self._show_list('FAIL', self.failures)
280
self.stream.write(self.sep2)
281
self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
282
run, run != 1 and "s" or "", timeTaken))
283
if not self.wasSuccessful():
284
self.stream.write("FAILED (")
285
failed, errored = map(len, (self.failures, self.errors))
287
self.stream.write("failures=%d" % failed)
289
if failed: self.stream.write(", ")
290
self.stream.write("errors=%d" % errored)
291
if self.known_failure_count:
292
if failed or errored: self.stream.write(", ")
293
self.stream.write("known_failure_count=%d" %
294
self.known_failure_count)
295
self.stream.write(")\n")
297
if self.known_failure_count:
298
self.stream.write("OK (known_failures=%d)\n" %
299
self.known_failure_count)
301
self.stream.write("OK\n")
302
if self.skip_count > 0:
303
skipped = self.skip_count
304
self.stream.write('%d test%s skipped\n' %
305
(skipped, skipped != 1 and "s" or ""))
307
for feature, count in sorted(self.unsupported.items()):
308
self.stream.write("Missing feature '%s' skipped %d tests.\n" %
311
ok = self.wasStrictlySuccessful()
313
ok = self.wasSuccessful()
314
if self._first_thread_leaker_id:
316
'%s is leaking threads among %d leaking tests.\n' % (
317
self._first_thread_leaker_id,
318
self._tests_leaking_threads_count))
319
# We don't report the main thread as an active one.
321
'%d non-main threads were left active in the end.\n'
322
% (len(self._active_threads) - 1))
324
def getDescription(self, test):
327
def _extractBenchmarkTime(self, testCase, details=None):
164
def _extractBenchmarkTime(self, testCase):
328
165
"""Add a benchmark time for the current test case."""
329
if details and 'benchtime' in details:
330
return float(''.join(details['benchtime'].iter_bytes()))
331
166
return getattr(testCase, "_benchtime", None)
333
168
def _elapsedTestTimeString(self):
334
169
"""Return a time string for the overall time the current test has taken."""
335
return self._formatTime(self._delta_to_float(
336
self._now() - self._start_datetime))
170
return self._formatTime(time.time() - self._start_time)
338
172
def _testTimeString(self, testCase):
339
173
benchmark_time = self._extractBenchmarkTime(testCase)
340
174
if benchmark_time is not None:
341
return self._formatTime(benchmark_time) + "*"
176
self._formatTime(benchmark_time),
177
self._elapsedTestTimeString())
343
return self._elapsedTestTimeString()
179
return " %s" % self._elapsedTestTimeString()
345
181
def _formatTime(self, seconds):
346
182
"""Format seconds as milliseconds with leading spaces."""
351
187
def _shortened_test_description(self, test):
353
what = re.sub(r'^bzrlib\.tests\.', '', what)
189
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
356
# GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
357
# multiple times in a row, because the handler is added for
358
# each test but the container list is shared between cases.
359
# See lp:498869 lp:625574 and lp:637725 for background.
360
def _record_traceback_from_test(self, exc_info):
361
"""Store the traceback from passed exc_info tuple till"""
362
self._traceback_from_test = exc_info[2]
364
192
def startTest(self, test):
365
super(ExtendedTestResult, self).startTest(test)
193
unittest.TestResult.startTest(self, test)
369
194
self.report_test_start(test)
370
195
test.number = self.count
371
196
self._recordTestStartTime()
372
# Make testtools cases give us the real traceback on failure
373
addOnException = getattr(test, "addOnException", None)
374
if addOnException is not None:
375
addOnException(self._record_traceback_from_test)
376
# Only check for thread leaks on bzrlib derived test cases
377
if isinstance(test, TestCase):
378
test.addCleanup(self._check_leaked_threads, test)
380
def startTests(self):
381
self.report_tests_starting()
382
self._active_threads = threading.enumerate()
384
def stopTest(self, test):
385
self._traceback_from_test = None
387
def _check_leaked_threads(self, test):
388
"""See if any threads have leaked since last call
390
A sample of live threads is stored in the _active_threads attribute,
391
when this method runs it compares the current live threads and any not
392
in the previous sample are treated as having leaked.
394
now_active_threads = set(threading.enumerate())
395
threads_leaked = now_active_threads.difference(self._active_threads)
397
self._report_thread_leak(test, threads_leaked, now_active_threads)
398
self._tests_leaking_threads_count += 1
399
if self._first_thread_leaker_id is None:
400
self._first_thread_leaker_id = test.id()
401
self._active_threads = now_active_threads
403
198
def _recordTestStartTime(self):
404
199
"""Record that a test has started."""
405
self._start_datetime = self._now()
200
self._start_time = time.time()
202
def _cleanupLogFile(self, test):
203
# We can only do this if we have one of our TestCases, not if
205
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
206
if setKeepLogfile is not None:
407
209
def addError(self, test, err):
408
210
"""Tell result that test finished with an error.
453
274
"""The test will not be run because of a missing feature.
455
276
# this can be called in two different ways: it may be that the
456
# test started running, and then raised (through requireFeature)
277
# test started running, and then raised (through addError)
457
278
# UnavailableFeature. Alternatively this method can be called
458
# while probing for features before running the test code proper; in
459
# that case we will see startTest and stopTest, but the test will
460
# never actually run.
279
# while probing for features before running the tests; in that
280
# case we will see startTest and stopTest, but the test will never
461
282
self.unsupported.setdefault(str(feature), 0)
462
283
self.unsupported[str(feature)] += 1
463
284
self.report_unsupported(test, feature)
465
def addSkip(self, test, reason):
466
"""A test has not run for 'reason'."""
468
self.report_skip(test, reason)
470
def addNotApplicable(self, test, reason):
471
self.not_applicable_count += 1
472
self.report_not_applicable(test, reason)
474
def _post_mortem(self, tb=None):
475
"""Start a PDB post mortem session."""
476
if os.environ.get('BZR_TEST_PDB', None):
480
def progress(self, offset, whence):
481
"""The test is adjusting the count of tests to run."""
482
if whence == SUBUNIT_SEEK_SET:
483
self.num_tests = offset
484
elif whence == SUBUNIT_SEEK_CUR:
485
self.num_tests += offset
487
raise errors.BzrError("Unknown whence %r" % whence)
489
def report_tests_starting(self):
490
"""Display information before the test run begins"""
491
if getattr(sys, 'frozen', None) is None:
492
bzr_path = osutils.realpath(sys.argv[0])
494
bzr_path = sys.executable
496
'bzr selftest: %s\n' % (bzr_path,))
499
bzrlib.__path__[0],))
501
' bzr-%s python-%s %s\n' % (
502
bzrlib.version_string,
503
bzrlib._format_version_tuple(sys.version_info),
504
platform.platform(aliased=1),
506
self.stream.write('\n')
508
def report_test_start(self, test):
509
"""Display information on the test just about to be run"""
511
def _report_thread_leak(self, test, leaked_threads, active_threads):
512
"""Display information on a test that leaked one or more threads"""
513
# GZ 2010-09-09: A leak summary reported separately from the general
514
# thread debugging would be nice. Tests under subunit
515
# need something not using stream, perhaps adding a
516
# testtools details object would be fitting.
517
if 'threads' in selftest_debug_flags:
518
self.stream.write('%s is leaking, active is now %d\n' %
519
(test.id(), len(active_threads)))
521
def startTestRun(self):
522
self.startTime = time.time()
286
def _addSkipped(self, test, skip_excinfo):
287
if isinstance(skip_excinfo[1], TestNotApplicable):
288
self.not_applicable_count += 1
289
self.report_not_applicable(test, skip_excinfo)
292
self.report_skip(test, skip_excinfo)
295
except KeyboardInterrupt:
298
self.addError(test, test._exc_info())
300
# seems best to treat this as success from point-of-view of unittest
301
# -- it actually does nothing so it barely matters :)
302
unittest.TestResult.addSuccess(self, test)
303
test._log_contents = ''
305
def printErrorList(self, flavour, errors):
306
for test, err in errors:
307
self.stream.writeln(self.separator1)
308
self.stream.write("%s: " % flavour)
309
self.stream.writeln(self.getDescription(test))
310
if getattr(test, '_get_log', None) is not None:
311
self.stream.write('\n')
313
('vvvv[log from %s]' % test.id()).ljust(78,'-'))
314
self.stream.write('\n')
315
self.stream.write(test._get_log())
316
self.stream.write('\n')
318
('^^^^[log from %s]' % test.id()).ljust(78,'-'))
319
self.stream.write('\n')
320
self.stream.writeln(self.separator2)
321
self.stream.writeln("%s" % err)
326
def report_cleaning_up(self):
524
329
def report_success(self, test):
703
508
bench_history=None,
705
result_decorators=None,
707
"""Create a TextTestRunner.
709
:param result_decorators: An optional list of decorators to apply
710
to the result object being used by the runner. Decorators are
711
applied left to right - the first element in the list is the
714
# stream may know claim to know to write unicode strings, but in older
715
# pythons this goes sufficiently wrong that it is a bad idea. (
716
# specifically a built in file with encoding 'UTF-8' will still try
717
# to encode using ascii.
718
new_encoding = osutils.get_terminal_encoding()
719
codec = codecs.lookup(new_encoding)
720
if type(codec) is tuple:
724
encode = codec.encode
725
# GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
726
# so should swap to the plain codecs.StreamWriter
727
stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
729
stream.encoding = new_encoding
511
self.stream = unittest._WritelnDecorator(stream)
731
512
self.descriptions = descriptions
732
513
self.verbosity = verbosity
733
514
self._bench_history = bench_history
734
self._strict = strict
735
self._result_decorators = result_decorators or []
515
self.list_only = list_only
737
517
def run(self, test):
738
518
"Run the given test case or test suite."
519
startTime = time.time()
739
520
if self.verbosity == 1:
740
521
result_class = TextTestResult
741
522
elif self.verbosity >= 2:
742
523
result_class = VerboseTestResult
743
original_result = result_class(self.stream,
524
result = result_class(self.stream,
744
525
self.descriptions,
746
527
bench_history=self._bench_history,
528
num_tests=test.countTestCases(),
749
# Signal to result objects that look at stop early policy to stop,
750
original_result.stop_early = self.stop_on_failure
751
result = original_result
752
for decorator in self._result_decorators:
753
result = decorator(result)
754
result.stop_early = self.stop_on_failure
755
result.startTestRun()
530
result.stop_early = self.stop_on_failure
531
result.report_starting()
533
if self.verbosity >= 2:
534
self.stream.writeln("Listing tests only ...\n")
536
for t in iter_suite_tests(test):
537
self.stream.writeln("%s" % (t.id()))
539
actionTaken = "Listed"
760
# higher level code uses our extended protocol to determine
761
# what exit code to give.
762
return original_result
542
run = result.testsRun
544
stopTime = time.time()
545
timeTaken = stopTime - startTime
547
self.stream.writeln(result.separator2)
548
self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
549
run, run != 1 and "s" or "", timeTaken))
550
self.stream.writeln()
551
if not result.wasSuccessful():
552
self.stream.write("FAILED (")
553
failed, errored = map(len, (result.failures, result.errors))
555
self.stream.write("failures=%d" % failed)
557
if failed: self.stream.write(", ")
558
self.stream.write("errors=%d" % errored)
559
if result.known_failure_count:
560
if failed or errored: self.stream.write(", ")
561
self.stream.write("known_failure_count=%d" %
562
result.known_failure_count)
563
self.stream.writeln(")")
565
if result.known_failure_count:
566
self.stream.writeln("OK (known_failures=%d)" %
567
result.known_failure_count)
569
self.stream.writeln("OK")
570
if result.skip_count > 0:
571
skipped = result.skip_count
572
self.stream.writeln('%d test%s skipped' %
573
(skipped, skipped != 1 and "s" or ""))
574
if result.unsupported:
575
for feature, count in sorted(result.unsupported.items()):
576
self.stream.writeln("Missing feature '%s' skipped %d tests." %
765
582
def iter_suite_tests(suite):
766
583
"""Return all tests in a suite, recursing through nested suites"""
767
if isinstance(suite, unittest.TestCase):
769
elif isinstance(suite, unittest.TestSuite):
584
for item in suite._tests:
585
if isinstance(item, unittest.TestCase):
587
elif isinstance(item, unittest.TestSuite):
771
588
for r in iter_suite_tests(item):
774
raise Exception('unknown type %r for object %r'
775
% (type(suite), suite))
778
TestSkipped = testtools.testcase.TestSkipped
591
raise Exception('unknown object %r inside test suite %r'
595
class TestSkipped(Exception):
596
"""Indicates that a test was intentionally skipped, rather than failing."""
781
599
class TestNotApplicable(TestSkipped):
782
600
"""A test is not applicable to the situation where it was run.
784
This is only normally raised by parameterized tests, if they find that
785
the instance they're constructed upon does not support one aspect
602
This is only normally raised by parameterized tests, if they find that
603
the instance they're constructed upon does not support one aspect
786
604
of its interface.
790
# traceback._some_str fails to format exceptions that have the default
791
# __str__ which does an implicit ascii conversion. However, repr() on those
792
# objects works, for all that its not quite what the doctor may have ordered.
793
def _clever_some_str(value):
798
return repr(value).replace('\\n', '\n')
800
return '<unprintable %s object>' % type(value).__name__
802
traceback._some_str = _clever_some_str
805
# deprecated - use self.knownFailure(), or self.expectFailure.
806
KnownFailure = testtools.testcase._ExpectedFailure
608
class KnownFailure(AssertionError):
609
"""Indicates that a test failed in a precisely expected manner.
611
Such failures dont block the whole test suite from passing because they are
612
indicators of partially completed code or of future work. We have an
613
explicit error for them so that we can ensure that they are always visible:
614
KnownFailures are always shown in the output of bzr selftest.
809
618
class UnavailableFeature(Exception):
810
619
"""A feature required for this test was not available.
812
This can be considered a specialised form of SkippedTest.
814
621
The feature should be used to construct the exception.
625
class CommandFailed(Exception):
818
629
class StringIOWrapper(object):
819
630
"""A wrapper around cStringIO which just adds an encoding attribute.
821
632
Internally we can check sys.stdout to see what the output encoding
822
633
should be. However, cStringIO has no encoding attribute that we can
823
634
set. So we wrap it instead.
911
734
retrieved by _get_log(). We use a real OS file, not an in-memory object,
912
735
so that it can also capture file IO. When the test completes this file
913
736
is read into memory and removed from disk.
915
738
There are also convenience functions to invoke bzr's command-line
916
739
routine, and to build and check bzr trees.
918
741
In addition to the usual method of overriding tearDown(), this class also
919
allows subclasses to register cleanup functions via addCleanup, which are
742
allows subclasses to register functions into the _cleanups list, which is
920
743
run in order as the object is torn down. It's less likely this will be
921
744
accidentally overlooked.
747
_active_threads = None
748
_leaking_threads_tests = 0
749
_first_thread_leaker_id = None
750
_log_file_name = None
752
_keep_log_file = False
925
753
# record lsprof data when performing benchmark calls.
926
754
_gather_lsprof_in_benchmarks = False
755
attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
756
'_log_contents', '_log_file_name', '_benchtime',
757
'_TestCase__testMethodName')
928
759
def __init__(self, methodName='testMethod'):
929
760
super(TestCase, self).__init__(methodName)
930
self._directory_isolation = True
931
self.exception_handlers.insert(0,
932
(UnavailableFeature, self._do_unsupported_or_skip))
933
self.exception_handlers.insert(0,
934
(TestNotApplicable, self._do_not_applicable))
937
super(TestCase, self).setUp()
938
for feature in getattr(self, '_test_needs_features', []):
939
self.requireFeature(feature)
940
self._log_contents = None
941
self.addDetail("log", content.Content(content.ContentType("text",
942
"plain", {"charset": "utf8"}),
943
lambda:[self._get_log(keep_log_file=True)]))
764
unittest.TestCase.setUp(self)
944
765
self._cleanEnvironment()
945
766
self._silenceUI()
946
767
self._startLogFile()
947
768
self._benchcalls = []
948
769
self._benchtime = None
949
770
self._clear_hooks()
950
self._track_transports()
952
771
self._clear_debug_flags()
953
# Isolate global verbosity level, to make sure it's reproducible
954
# between tests. We should get rid of this altogether: bug 656694. --
956
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
957
# Isolate config option expansion until its default value for bzrlib is
958
# settled on or a the FIXME associated with _get_expand_default_value
959
# is addressed -- vila 20110219
960
self.overrideAttr(config, '_expand_default_value', None)
965
pdb.Pdb().set_trace(sys._getframe().f_back)
967
def discardDetail(self, name):
968
"""Extend the addDetail, getDetails api so we can remove a detail.
970
eg. bzr always adds the 'log' detail at startup, but we don't want to
971
include it for skipped, xfail, etc tests.
973
It is safe to call this for a detail that doesn't exist, in case this
974
gets called multiple times.
976
# We cheat. details is stored in __details which means we shouldn't
977
# touch it. but getDetails() returns the dict directly, so we can
979
details = self.getDetails()
772
TestCase._active_threads = threading.activeCount()
773
self.addCleanup(self._check_leaked_threads)
775
def _check_leaked_threads(self):
776
active = threading.activeCount()
777
leaked_threads = active - TestCase._active_threads
778
TestCase._active_threads = active
780
TestCase._leaking_threads_tests += 1
781
if TestCase._first_thread_leaker_id is None:
782
TestCase._first_thread_leaker_id = self.id()
783
# we're not specifically told when all tests are finished.
784
# This will do. We use a function to avoid keeping a reference
785
# to a TestCase object.
786
atexit.register(_report_leaked_threads)
983
788
def _clear_debug_flags(self):
984
789
"""Prevent externally set debug flags affecting tests.
986
791
Tests that want to use debug flags can just set them in the
987
792
debug_flags set during setup/teardown.
989
# Start with a copy of the current debug flags we can safely modify.
990
self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
991
794
if 'allow_debug' not in selftest_debug_flags:
795
self._preserved_debug_flags = set(debug.debug_flags)
992
796
debug.debug_flags.clear()
993
if 'disable_lock_checks' not in selftest_debug_flags:
994
debug.debug_flags.add('strict_locks')
797
self.addCleanup(self._restore_debug_flags)
996
799
def _clear_hooks(self):
997
800
# prevent hooks affecting tests
998
known_hooks = hooks.known_hooks
999
self._preserved_hooks = {}
1000
for key, (parent, name) in known_hooks.iter_parent_objects():
1001
current_hooks = getattr(parent, name)
1002
self._preserved_hooks[parent] = (name, current_hooks)
1003
self._preserved_lazy_hooks = hooks._lazy_hooks
1004
hooks._lazy_hooks = {}
802
import bzrlib.smart.server
803
self._preserved_hooks = {
804
bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
805
bzrlib.mutabletree.MutableTree: bzrlib.mutabletree.MutableTree.hooks,
806
bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
1005
808
self.addCleanup(self._restoreHooks)
1006
for key, (parent, name) in known_hooks.iter_parent_objects():
1007
factory = known_hooks.get(key)
1008
setattr(parent, name, factory())
1009
# this hook should always be installed
1010
request._install_hook()
1012
def disable_directory_isolation(self):
1013
"""Turn off directory isolation checks."""
1014
self._directory_isolation = False
1016
def enable_directory_isolation(self):
1017
"""Enable directory isolation checks."""
1018
self._directory_isolation = True
809
# reset all hooks to an empty instance of the appropriate type
810
bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
811
bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
1020
813
def _silenceUI(self):
1021
814
"""Turn off UI for duration of test"""
1022
815
# by default the UI is off; tests can turn it on if they want it.
1023
self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
1025
def _check_locks(self):
1026
"""Check that all lock take/release actions have been paired."""
1027
# We always check for mismatched locks. If a mismatch is found, we
1028
# fail unless -Edisable_lock_checks is supplied to selftest, in which
1029
# case we just print a warning.
1031
acquired_locks = [lock for action, lock in self._lock_actions
1032
if action == 'acquired']
1033
released_locks = [lock for action, lock in self._lock_actions
1034
if action == 'released']
1035
broken_locks = [lock for action, lock in self._lock_actions
1036
if action == 'broken']
1037
# trivially, given the tests for lock acquistion and release, if we
1038
# have as many in each list, it should be ok. Some lock tests also
1039
# break some locks on purpose and should be taken into account by
1040
# considering that breaking a lock is just a dirty way of releasing it.
1041
if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1042
message = ('Different number of acquired and '
1043
'released or broken locks. (%s, %s + %s)' %
1044
(acquired_locks, released_locks, broken_locks))
1045
if not self._lock_check_thorough:
1046
# Rather than fail, just warn
1047
print "Broken test %s: %s" % (self, message)
1051
def _track_locks(self):
1052
"""Track lock activity during tests."""
1053
self._lock_actions = []
1054
if 'disable_lock_checks' in selftest_debug_flags:
1055
self._lock_check_thorough = False
1057
self._lock_check_thorough = True
1059
self.addCleanup(self._check_locks)
1060
_mod_lock.Lock.hooks.install_named_hook('lock_acquired',
1061
self._lock_acquired, None)
1062
_mod_lock.Lock.hooks.install_named_hook('lock_released',
1063
self._lock_released, None)
1064
_mod_lock.Lock.hooks.install_named_hook('lock_broken',
1065
self._lock_broken, None)
1067
def _lock_acquired(self, result):
1068
self._lock_actions.append(('acquired', result))
1070
def _lock_released(self, result):
1071
self._lock_actions.append(('released', result))
1073
def _lock_broken(self, result):
1074
self._lock_actions.append(('broken', result))
1076
def permit_dir(self, name):
1077
"""Permit a directory to be used by this test. See permit_url."""
1078
name_transport = _mod_transport.get_transport(name)
1079
self.permit_url(name)
1080
self.permit_url(name_transport.base)
1082
def permit_url(self, url):
1083
"""Declare that url is an ok url to use in this test.
1085
Do this for memory transports, temporary test directory etc.
1087
Do not do this for the current working directory, /tmp, or any other
1088
preexisting non isolated url.
1090
if not url.endswith('/'):
1092
self._bzr_selftest_roots.append(url)
1094
def permit_source_tree_branch_repo(self):
1095
"""Permit the source tree bzr is running from to be opened.
1097
Some code such as bzrlib.version attempts to read from the bzr branch
1098
that bzr is executing from (if any). This method permits that directory
1099
to be used in the test suite.
1101
path = self.get_source_path()
1102
self.record_directory_isolation()
1105
workingtree.WorkingTree.open(path)
1106
except (errors.NotBranchError, errors.NoWorkingTree):
1107
raise TestSkipped('Needs a working tree of bzr sources')
1109
self.enable_directory_isolation()
1111
def _preopen_isolate_transport(self, transport):
1112
"""Check that all transport openings are done in the test work area."""
1113
while isinstance(transport, pathfilter.PathFilteringTransport):
1114
# Unwrap pathfiltered transports
1115
transport = transport.server.backing_transport.clone(
1116
transport._filter('.'))
1117
url = transport.base
1118
# ReadonlySmartTCPServer_for_testing decorates the backing transport
1119
# urls it is given by prepending readonly+. This is appropriate as the
1120
# client shouldn't know that the server is readonly (or not readonly).
1121
# We could register all servers twice, with readonly+ prepending, but
1122
# that makes for a long list; this is about the same but easier to
1124
if url.startswith('readonly+'):
1125
url = url[len('readonly+'):]
1126
self._preopen_isolate_url(url)
1128
def _preopen_isolate_url(self, url):
1129
if not self._directory_isolation:
1131
if self._directory_isolation == 'record':
1132
self._bzr_selftest_roots.append(url)
1134
# This prevents all transports, including e.g. sftp ones backed on disk
1135
# from working unless they are explicitly granted permission. We then
1136
# depend on the code that sets up test transports to check that they are
1137
# appropriately isolated and enable their use by calling
1138
# self.permit_transport()
1139
if not osutils.is_inside_any(self._bzr_selftest_roots, url):
1140
raise errors.BzrError("Attempt to escape test isolation: %r %r"
1141
% (url, self._bzr_selftest_roots))
1143
def record_directory_isolation(self):
1144
"""Gather accessed directories to permit later access.
1146
This is used for tests that access the branch bzr is running from.
1148
self._directory_isolation = "record"
1150
def start_server(self, transport_server, backing_server=None):
1151
"""Start transport_server for this test.
1153
This starts the server, registers a cleanup for it and permits the
1154
server's urls to be used.
1156
if backing_server is None:
1157
transport_server.start_server()
1159
transport_server.start_server(backing_server)
1160
self.addCleanup(transport_server.stop_server)
1161
# Obtain a real transport because if the server supplies a password, it
1162
# will be hidden from the base on the client side.
1163
t = _mod_transport.get_transport(transport_server.get_url())
1164
# Some transport servers effectively chroot the backing transport;
1165
# others like SFTPServer don't - users of the transport can walk up the
1166
# transport to read the entire backing transport. This wouldn't matter
1167
# except that the workdir tests are given - and that they expect the
1168
# server's url to point at - is one directory under the safety net. So
1169
# Branch operations into the transport will attempt to walk up one
1170
# directory. Chrooting all servers would avoid this but also mean that
1171
# we wouldn't be testing directly against non-root urls. Alternatively
1172
# getting the test framework to start the server with a backing server
1173
# at the actual safety net directory would work too, but this then
1174
# means that the self.get_url/self.get_transport methods would need
1175
# to transform all their results. On balance its cleaner to handle it
1176
# here, and permit a higher url when we have one of these transports.
1177
if t.base.endswith('/work/'):
1178
# we have safety net/test root/work
1179
t = t.clone('../..')
1180
elif isinstance(transport_server,
1181
test_server.SmartTCPServer_for_testing):
1182
# The smart server adds a path similar to work, which is traversed
1183
# up from by the client. But the server is chrooted - the actual
1184
# backing transport is not escaped from, and VFS requests to the
1185
# root will error (because they try to escape the chroot).
1187
while t2.base != t.base:
1190
self.permit_url(t.base)
1192
def _track_transports(self):
1193
"""Install checks for transport usage."""
1194
# TestCase has no safe place it can write to.
1195
self._bzr_selftest_roots = []
1196
# Currently the easiest way to be sure that nothing is going on is to
1197
# hook into bzr dir opening. This leaves a small window of error for
1198
# transport tests, but they are well known, and we can improve on this
1200
bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1201
self._preopen_isolate_transport, "Check bzr directories are safe.")
816
saved = ui.ui_factory
818
ui.ui_factory = saved
819
ui.ui_factory = ui.SilentUIFactory()
820
self.addCleanup(_restore)
1203
822
def _ndiff_strings(self, a, b):
1204
823
"""Return ndiff between two strings containing lines.
1206
825
A trailing newline is added if missing to make the strings
1207
826
print properly."""
1208
827
if b and b[-1] != '\n':
1243
862
if message is None:
1244
863
message = "texts not equal:\n"
865
message = 'first string is missing a final newline.\n'
1245
866
if a + '\n' == b:
1246
message = 'first string is missing a final newline.\n'
1248
867
message = 'second string is missing a final newline.\n'
1249
868
raise AssertionError(message +
1250
869
self._ndiff_strings(a, b))
1252
871
def assertEqualMode(self, mode, mode_test):
1253
872
self.assertEqual(mode, mode_test,
1254
873
'mode mismatch %o != %o' % (mode, mode_test))
1256
def assertEqualStat(self, expected, actual):
1257
"""assert that expected and actual are the same stat result.
1259
:param expected: A stat result.
1260
:param actual: A stat result.
1261
:raises AssertionError: If the expected and actual stat values differ
1262
other than by atime.
1264
self.assertEqual(expected.st_size, actual.st_size,
1265
'st_size did not match')
1266
self.assertEqual(expected.st_mtime, actual.st_mtime,
1267
'st_mtime did not match')
1268
self.assertEqual(expected.st_ctime, actual.st_ctime,
1269
'st_ctime did not match')
1270
if sys.platform == 'win32':
1271
# On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
1272
# is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
1273
# odd. We just force it to always be 0 to avoid any problems.
1274
self.assertEqual(0, expected.st_dev)
1275
self.assertEqual(0, actual.st_dev)
1276
self.assertEqual(0, expected.st_ino)
1277
self.assertEqual(0, actual.st_ino)
1279
self.assertEqual(expected.st_dev, actual.st_dev,
1280
'st_dev did not match')
1281
self.assertEqual(expected.st_ino, actual.st_ino,
1282
'st_ino did not match')
1283
self.assertEqual(expected.st_mode, actual.st_mode,
1284
'st_mode did not match')
1286
def assertLength(self, length, obj_with_len):
1287
"""Assert that obj_with_len is of length length."""
1288
if len(obj_with_len) != length:
1289
self.fail("Incorrect length: wanted %d, got %d for %r" % (
1290
length, len(obj_with_len), obj_with_len))
1292
def assertLogsError(self, exception_class, func, *args, **kwargs):
1293
"""Assert that func(*args, **kwargs) quietly logs a specific exception.
1296
orig_log_exception_quietly = trace.log_exception_quietly
1299
orig_log_exception_quietly()
1300
captured.append(sys.exc_info())
1301
trace.log_exception_quietly = capture
1302
func(*args, **kwargs)
1304
trace.log_exception_quietly = orig_log_exception_quietly
1305
self.assertLength(1, captured)
1306
err = captured[0][1]
1307
self.assertIsInstance(err, exception_class)
1310
875
def assertPositive(self, val):
1311
876
"""Assert that val is greater than 0."""
1312
877
self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
1614
1183
Close the file and delete it, unless setKeepLogfile was called.
1616
if trace._trace_file:
1617
# flush the log file, to get all content
1618
trace._trace_file.flush()
1619
trace.pop_log_file(self._log_memento)
1620
# Cache the log result and delete the file on disk
1621
self._get_log(False)
1623
def thisFailsStrictLockCheck(self):
1624
"""It is known that this test would fail with -Dstrict_locks.
1626
By default, all tests are run with strict lock checking unless
1627
-Edisable_lock_checks is supplied. However there are some tests which
1628
we know fail strict locks at this point that have not been fixed.
1629
They should call this function to disable the strict checking.
1631
This should be used sparingly, it is much better to fix the locking
1632
issues rather than papering over the problem by calling this function.
1634
debug.debug_flags.discard('strict_locks')
1636
def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1637
"""Overrides an object attribute restoring it after the test.
1639
:param obj: The object that will be mutated.
1641
:param attr_name: The attribute name we want to preserve/override in
1644
:param new: The optional value we want to set the attribute to.
1646
:returns: The actual attr value.
1648
value = getattr(obj, attr_name)
1649
# The actual value is captured by the call below
1650
self.addCleanup(setattr, obj, attr_name, value)
1651
if new is not _unitialized_attr:
1652
setattr(obj, attr_name, new)
1655
def overrideEnv(self, name, new):
1656
"""Set an environment variable, and reset it after the test.
1658
:param name: The environment variable name.
1660
:param new: The value to set the variable to. If None, the
1661
variable is deleted from the environment.
1663
:returns: The actual variable value.
1665
value = osutils.set_or_unset_env(name, new)
1666
self.addCleanup(osutils.set_or_unset_env, name, value)
1185
if self._log_file is None:
1187
bzrlib.trace.pop_log_file(self._log_memento)
1188
self._log_file.close()
1189
self._log_file = None
1190
if not self._keep_log_file:
1191
os.remove(self._log_file_name)
1192
self._log_file_name = None
1194
def setKeepLogfile(self):
1195
"""Make the logfile not be deleted when _finishLogFile is called."""
1196
self._keep_log_file = True
1198
def addCleanup(self, callable):
1199
"""Arrange to run a callable when this case is torn down.
1201
Callables are run in the reverse of the order they are registered,
1202
ie last-in first-out.
1204
if callable in self._cleanups:
1205
raise ValueError("cleanup function %r already registered on %s"
1207
self._cleanups.append(callable)
1669
1209
def _cleanEnvironment(self):
1670
for name, value in isolated_environ.iteritems():
1671
self.overrideEnv(name, value)
1211
'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1212
'HOME': os.getcwd(),
1213
'APPDATA': None, # bzr now use Win32 API and don't rely on APPDATA
1214
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
1216
'BZREMAIL': None, # may still be present in the environment
1218
'BZR_PROGRESS_BAR': None,
1221
'SSH_AUTH_SOCK': None,
1225
'https_proxy': None,
1226
'HTTPS_PROXY': None,
1231
# Nobody cares about these ones AFAIK. So far at
1232
# least. If you do (care), please update this comment
1236
'BZR_REMOTE_PATH': None,
1239
self.addCleanup(self._restoreEnvironment)
1240
for name, value in new_env.iteritems():
1241
self._captureVar(name, value)
1243
def _captureVar(self, name, newvalue):
1244
"""Set an environment variable, and reset it when finished."""
1245
self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1247
def _restore_debug_flags(self):
1248
debug.debug_flags.clear()
1249
debug.debug_flags.update(self._preserved_debug_flags)
1251
def _restoreEnvironment(self):
1252
for name, value in self.__old_env.iteritems():
1253
osutils.set_or_unset_env(name, value)
1673
1255
def _restoreHooks(self):
1674
for klass, (name, hooks) in self._preserved_hooks.items():
1675
setattr(klass, name, hooks)
1676
hooks._lazy_hooks = self._preserved_lazy_hooks
1256
for klass, hooks in self._preserved_hooks.items():
1257
setattr(klass, 'hooks', hooks)
1678
1259
def knownFailure(self, reason):
1679
1260
"""This test has failed for some known reason."""
1680
1261
raise KnownFailure(reason)
1682
def _suppress_log(self):
1683
"""Remove the log info from details."""
1684
self.discardDetail('log')
1686
def _do_skip(self, result, reason):
1687
self._suppress_log()
1688
addSkip = getattr(result, 'addSkip', None)
1689
if not callable(addSkip):
1690
result.addSuccess(result)
1692
addSkip(self, reason)
1695
def _do_known_failure(self, result, e):
1696
self._suppress_log()
1697
err = sys.exc_info()
1698
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1699
if addExpectedFailure is not None:
1700
addExpectedFailure(self, err)
1702
result.addSuccess(self)
1705
def _do_not_applicable(self, result, e):
1707
reason = 'No reason given'
1710
self._suppress_log ()
1711
addNotApplicable = getattr(result, 'addNotApplicable', None)
1712
if addNotApplicable is not None:
1713
result.addNotApplicable(self, reason)
1715
self._do_skip(result, reason)
1718
def _report_skip(self, result, err):
1719
"""Override the default _report_skip.
1721
We want to strip the 'log' detail. If we waint until _do_skip, it has
1722
already been formatted into the 'reason' string, and we can't pull it
1725
self._suppress_log()
1726
super(TestCase, self)._report_skip(self, result, err)
1729
def _report_expected_failure(self, result, err):
1732
See _report_skip for motivation.
1734
self._suppress_log()
1735
super(TestCase, self)._report_expected_failure(self, result, err)
1738
def _do_unsupported_or_skip(self, result, e):
1740
self._suppress_log()
1741
addNotSupported = getattr(result, 'addNotSupported', None)
1742
if addNotSupported is not None:
1743
result.addNotSupported(self, reason)
1745
self._do_skip(result, reason)
1263
def run(self, result=None):
1264
if result is None: result = self.defaultTestResult()
1265
for feature in getattr(self, '_test_needs_features', []):
1266
if not feature.available():
1267
result.startTest(self)
1268
if getattr(result, 'addNotSupported', None):
1269
result.addNotSupported(self, feature)
1271
result.addSuccess(self)
1272
result.stopTest(self)
1275
return unittest.TestCase.run(self, result)
1278
absent_attr = object()
1279
for attr_name in self.attrs_to_keep:
1280
attr = getattr(self, attr_name, absent_attr)
1281
if attr is not absent_attr:
1282
saved_attrs[attr_name] = attr
1283
self.__dict__ = saved_attrs
1287
unittest.TestCase.tearDown(self)
1747
1289
def time(self, callable, *args, **kwargs):
1748
1290
"""Run callable and accrue the time it takes to the benchmark time.
1750
1292
If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1751
1293
this will cause lsprofile statistics to be gathered and stored in
1752
1294
self._benchcalls.
1754
1296
if self._benchtime is None:
1755
self.addDetail('benchtime', content.Content(content.ContentType(
1756
"text", "plain"), lambda:[str(self._benchtime)]))
1757
1297
self._benchtime = 0
1758
1298
start = time.time()
2484
1979
def make_repository(self, relpath, shared=False, format=None):
2485
1980
"""Create a repository on our default transport at relpath.
2487
1982
Note that relpath must be a relative path, not a full url.
2489
1984
# FIXME: If you create a remoterepository this returns the underlying
2490
# real format, which is incorrect. Actually we should make sure that
1985
# real format, which is incorrect. Actually we should make sure that
2491
1986
# RemoteBzrDir returns a RemoteRepository.
2492
1987
# maybe mbp 20070410
2493
1988
made_control = self.make_bzrdir(relpath, format=format)
2494
1989
return made_control.create_repository(shared=shared)
2496
def make_smart_server(self, path, backing_server=None):
2497
if backing_server is None:
2498
backing_server = self.get_server()
2499
smart_server = test_server.SmartTCPServer_for_testing()
2500
self.start_server(smart_server, backing_server)
2501
remote_transport = _mod_transport.get_transport(smart_server.get_url()
2503
return remote_transport
2505
1991
def make_branch_and_memory_tree(self, relpath, format=None):
2506
1992
"""Create a branch on the default transport and a MemoryTree for it."""
2507
1993
b = self.make_branch(relpath, format=format)
2508
1994
return memorytree.MemoryTree.create_on_branch(b)
2510
def make_branch_builder(self, relpath, format=None):
2511
branch = self.make_branch(relpath, format=format)
2512
return branchbuilder.BranchBuilder(branch=branch)
2514
1996
def overrideEnvironmentForTesting(self):
2515
test_home_dir = self.test_home_dir
2516
if isinstance(test_home_dir, unicode):
2517
test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2518
self.overrideEnv('HOME', test_home_dir)
2519
self.overrideEnv('BZR_HOME', test_home_dir)
1997
os.environ['HOME'] = self.test_home_dir
1998
os.environ['BZR_HOME'] = self.test_home_dir
2521
2000
def setUp(self):
2522
2001
super(TestCaseWithMemoryTransport, self).setUp()
2523
# Ensure that ConnectedTransport doesn't leak sockets
2524
def get_transport_with_cleanup(*args, **kwargs):
2525
t = orig_get_transport(*args, **kwargs)
2526
if isinstance(t, _mod_transport.ConnectedTransport):
2527
self.addCleanup(t.disconnect)
2530
orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
2531
get_transport_with_cleanup)
2532
2002
self._make_test_root()
2533
self.addCleanup(os.chdir, os.getcwdu())
2003
_currentdir = os.getcwdu()
2004
def _leaveDirectory():
2005
os.chdir(_currentdir)
2006
self.addCleanup(_leaveDirectory)
2534
2007
self.makeAndChdirToTestDir()
2535
2008
self.overrideEnvironmentForTesting()
2536
2009
self.__readonly_server = None
2537
2010
self.__server = None
2538
2011
self.reduceLockdirTimeout()
2540
def setup_smart_server_with_call_log(self):
2541
"""Sets up a smart server as the transport server with a call log."""
2542
self.transport_server = test_server.SmartTCPServer_for_testing
2543
self.hpss_calls = []
2545
# Skip the current stack down to the caller of
2546
# setup_smart_server_with_call_log
2547
prefix_length = len(traceback.extract_stack()) - 2
2548
def capture_hpss_call(params):
2549
self.hpss_calls.append(
2550
CapturedCall(params, prefix_length))
2551
client._SmartClient.hooks.install_named_hook(
2552
'call', capture_hpss_call, None)
2554
def reset_smart_call_log(self):
2555
self.hpss_calls = []
2558
2014
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2559
2015
"""Derived class that runs a test within a temporary directory.
3028
2437
list_only=False,
3029
2438
random_seed=None,
3030
2439
exclude_pattern=None,
3033
suite_decorators=None,
3035
result_decorators=None,
3037
"""Run a test suite for bzr selftest.
3039
:param runner_class: The class of runner to use. Must support the
3040
constructor arguments passed by run_suite which are more than standard
3042
:return: A boolean indicating success.
3044
2441
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
3049
if runner_class is None:
3050
runner_class = TextTestRunner
3053
runner = runner_class(stream=stream,
2446
runner = TextTestRunner(stream=sys.stdout,
3054
2447
descriptions=0,
3055
2448
verbosity=verbosity,
3056
2449
bench_history=bench_history,
3058
result_decorators=result_decorators,
2450
list_only=list_only,
3060
2452
runner.stop_on_failure=stop_on_failure
3061
# built in decorator factories:
3063
random_order(random_seed, runner),
3064
exclude_tests(exclude_pattern),
3066
if matching_tests_first:
3067
decorators.append(tests_first(pattern))
2453
# Initialise the random number generator and display the seed used.
2454
# We convert the seed to a long to make it reuseable across invocations.
2455
random_order = False
2456
if random_seed is not None:
2458
if random_seed == "now":
2459
random_seed = long(time.time())
2461
# Convert the seed to a long if we can
2463
random_seed = long(random_seed)
2466
runner.stream.writeln("Randomizing test order using seed %s\n" %
2468
random.seed(random_seed)
2469
# Customise the list of tests if requested
2470
if exclude_pattern is not None:
2471
suite = exclude_tests_by_re(suite, exclude_pattern)
2473
order_changer = randomize_suite
3069
decorators.append(filter_tests(pattern))
3070
if suite_decorators:
3071
decorators.extend(suite_decorators)
3072
# tell the result object how many tests will be running: (except if
3073
# --parallel=fork is being used. Robert said he will provide a better
3074
# progress design later -- vila 20090817)
3075
if fork_decorator not in decorators:
3076
decorators.append(CountingDecorator)
3077
for decorator in decorators:
3078
suite = decorator(suite)
3080
# Done after test suite decoration to allow randomisation etc
3081
# to take effect, though that is of marginal benefit.
3083
stream.write("Listing tests only ...\n")
3084
for t in iter_suite_tests(suite):
3085
stream.write("%s\n" % (t.id()))
2475
order_changer = preserve_input
2476
if pattern != '.*' or random_order:
2477
if matching_tests_first:
2478
suites = map(order_changer, split_suite_by_re(suite, pattern))
2479
suite = TestUtil.TestSuite(suites)
2481
suite = order_changer(filter_suite_by_re(suite, pattern))
3087
2483
result = runner.run(suite)
3089
2486
return result.wasStrictlySuccessful()
3091
return result.wasSuccessful()
3094
# A registry where get() returns a suite decorator.
3095
parallel_registry = registry.Registry()
3098
def fork_decorator(suite):
3099
if getattr(os, "fork", None) is None:
3100
raise errors.BzrCommandError("platform does not support fork,"
3101
" try --parallel=subprocess instead.")
3102
concurrency = osutils.local_concurrency()
3103
if concurrency == 1:
3105
from testtools import ConcurrentTestSuite
3106
return ConcurrentTestSuite(suite, fork_for_tests)
3107
parallel_registry.register('fork', fork_decorator)
3110
def subprocess_decorator(suite):
3111
concurrency = osutils.local_concurrency()
3112
if concurrency == 1:
3114
from testtools import ConcurrentTestSuite
3115
return ConcurrentTestSuite(suite, reinvoke_for_tests)
3116
parallel_registry.register('subprocess', subprocess_decorator)
3119
def exclude_tests(exclude_pattern):
3120
"""Return a test suite decorator that excludes tests."""
3121
if exclude_pattern is None:
3122
return identity_decorator
3123
def decorator(suite):
3124
return ExcludeDecorator(suite, exclude_pattern)
3128
def filter_tests(pattern):
3130
return identity_decorator
3131
def decorator(suite):
3132
return FilterTestsDecorator(suite, pattern)
3136
def random_order(random_seed, runner):
3137
"""Return a test suite decorator factory for randomising tests order.
3139
:param random_seed: now, a string which casts to a long, or a long.
3140
:param runner: A test runner with a stream attribute to report on.
3142
if random_seed is None:
3143
return identity_decorator
3144
def decorator(suite):
3145
return RandomDecorator(suite, random_seed, runner.stream)
3149
def tests_first(pattern):
3151
return identity_decorator
3152
def decorator(suite):
3153
return TestFirstDecorator(suite, pattern)
3157
def identity_decorator(suite):
3162
class TestDecorator(TestUtil.TestSuite):
3163
"""A decorator for TestCase/TestSuite objects.
3165
Usually, subclasses should override __iter__(used when flattening test
3166
suites), which we do to filter, reorder, parallelise and so on, run() and
3170
def __init__(self, suite):
3171
TestUtil.TestSuite.__init__(self)
3174
def countTestCases(self):
3177
cases += test.countTestCases()
3184
def run(self, result):
3185
# Use iteration on self, not self._tests, to allow subclasses to hook
3188
if result.shouldStop:
3194
class CountingDecorator(TestDecorator):
3195
"""A decorator which calls result.progress(self.countTestCases)."""
3197
def run(self, result):
3198
progress_method = getattr(result, 'progress', None)
3199
if callable(progress_method):
3200
progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
3201
return super(CountingDecorator, self).run(result)
3204
class ExcludeDecorator(TestDecorator):
3205
"""A decorator which excludes test matching an exclude pattern."""
3207
def __init__(self, suite, exclude_pattern):
3208
TestDecorator.__init__(self, suite)
3209
self.exclude_pattern = exclude_pattern
3210
self.excluded = False
3214
return iter(self._tests)
3215
self.excluded = True
3216
suite = exclude_tests_by_re(self, self.exclude_pattern)
3218
self.addTests(suite)
3219
return iter(self._tests)
3222
class FilterTestsDecorator(TestDecorator):
3223
"""A decorator which filters tests to those matching a pattern."""
3225
def __init__(self, suite, pattern):
3226
TestDecorator.__init__(self, suite)
3227
self.pattern = pattern
3228
self.filtered = False
3232
return iter(self._tests)
3233
self.filtered = True
3234
suite = filter_suite_by_re(self, self.pattern)
3236
self.addTests(suite)
3237
return iter(self._tests)
3240
class RandomDecorator(TestDecorator):
3241
"""A decorator which randomises the order of its tests."""
3243
def __init__(self, suite, random_seed, stream):
3244
TestDecorator.__init__(self, suite)
3245
self.random_seed = random_seed
3246
self.randomised = False
3247
self.stream = stream
3251
return iter(self._tests)
3252
self.randomised = True
3253
self.stream.write("Randomizing test order using seed %s\n\n" %
3254
(self.actual_seed()))
3255
# Initialise the random number generator.
3256
random.seed(self.actual_seed())
3257
suite = randomize_suite(self)
3259
self.addTests(suite)
3260
return iter(self._tests)
3262
def actual_seed(self):
3263
if self.random_seed == "now":
3264
# We convert the seed to a long to make it reuseable across
3265
# invocations (because the user can reenter it).
3266
self.random_seed = long(time.time())
3268
# Convert the seed to a long if we can
3270
self.random_seed = long(self.random_seed)
3273
return self.random_seed
3276
class TestFirstDecorator(TestDecorator):
3277
"""A decorator which moves named tests to the front."""
3279
def __init__(self, suite, pattern):
3280
TestDecorator.__init__(self, suite)
3281
self.pattern = pattern
3282
self.filtered = False
3286
return iter(self._tests)
3287
self.filtered = True
3288
suites = split_suite_by_re(self, self.pattern)
3290
self.addTests(suites)
3291
return iter(self._tests)
3294
def partition_tests(suite, count):
3295
"""Partition suite into count lists of tests."""
3296
# This just assigns tests in a round-robin fashion. On one hand this
3297
# splits up blocks of related tests that might run faster if they shared
3298
# resources, but on the other it avoids assigning blocks of slow tests to
3299
# just one partition. So the slowest partition shouldn't be much slower
3301
partitions = [list() for i in range(count)]
3302
tests = iter_suite_tests(suite)
3303
for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3304
partition.append(test)
3308
def workaround_zealous_crypto_random():
3309
"""Crypto.Random want to help us being secure, but we don't care here.
3311
This workaround some test failure related to the sftp server. Once paramiko
3312
stop using the controversial API in Crypto.Random, we may get rid of it.
3315
from Crypto.Random import atfork
3321
def fork_for_tests(suite):
3322
"""Take suite and start up one runner per CPU by forking()
3324
:return: An iterable of TestCase-like objects which can each have
3325
run(result) called on them to feed tests to result.
3327
concurrency = osutils.local_concurrency()
3329
from subunit import TestProtocolClient, ProtocolTestCase
3330
from subunit.test_results import AutoTimingTestResultDecorator
3331
class TestInOtherProcess(ProtocolTestCase):
3332
# Should be in subunit, I think. RBC.
3333
def __init__(self, stream, pid):
3334
ProtocolTestCase.__init__(self, stream)
3337
def run(self, result):
3339
ProtocolTestCase.run(self, result)
3341
os.waitpid(self.pid, 0)
3343
test_blocks = partition_tests(suite, concurrency)
3344
for process_tests in test_blocks:
3345
process_suite = TestUtil.TestSuite()
3346
process_suite.addTests(process_tests)
3347
c2pread, c2pwrite = os.pipe()
3350
workaround_zealous_crypto_random()
3353
# Leave stderr and stdout open so we can see test noise
3354
# Close stdin so that the child goes away if it decides to
3355
# read from stdin (otherwise its a roulette to see what
3356
# child actually gets keystrokes for pdb etc).
3359
stream = os.fdopen(c2pwrite, 'wb', 1)
3360
subunit_result = AutoTimingTestResultDecorator(
3361
TestProtocolClient(stream))
3362
process_suite.run(subunit_result)
3367
stream = os.fdopen(c2pread, 'rb', 1)
3368
test = TestInOtherProcess(stream, pid)
3373
def reinvoke_for_tests(suite):
3374
"""Take suite and start up one runner per CPU using subprocess().
3376
:return: An iterable of TestCase-like objects which can each have
3377
run(result) called on them to feed tests to result.
3379
concurrency = osutils.local_concurrency()
3381
from subunit import ProtocolTestCase
3382
class TestInSubprocess(ProtocolTestCase):
3383
def __init__(self, process, name):
3384
ProtocolTestCase.__init__(self, process.stdout)
3385
self.process = process
3386
self.process.stdin.close()
3389
def run(self, result):
3391
ProtocolTestCase.run(self, result)
3394
os.unlink(self.name)
3395
# print "pid %d finished" % finished_process
3396
test_blocks = partition_tests(suite, concurrency)
3397
for process_tests in test_blocks:
3398
# ugly; currently reimplement rather than reuses TestCase methods.
3399
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
3400
if not os.path.isfile(bzr_path):
3401
# We are probably installed. Assume sys.argv is the right file
3402
bzr_path = sys.argv[0]
3403
bzr_path = [bzr_path]
3404
if sys.platform == "win32":
3405
# if we're on windows, we can't execute the bzr script directly
3406
bzr_path = [sys.executable] + bzr_path
3407
fd, test_list_file_name = tempfile.mkstemp()
3408
test_list_file = os.fdopen(fd, 'wb', 1)
3409
for test in process_tests:
3410
test_list_file.write(test.id() + '\n')
3411
test_list_file.close()
3413
argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
3415
if '--no-plugins' in sys.argv:
3416
argv.append('--no-plugins')
3417
# stderr=subprocess.STDOUT would be ideal, but until we prevent
3418
# noise on stderr it can interrupt the subunit protocol.
3419
process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3420
stdout=subprocess.PIPE,
3421
stderr=subprocess.PIPE,
3423
test = TestInSubprocess(process, test_list_file_name)
3426
os.unlink(test_list_file_name)
3431
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3432
"""Generate profiling data for all activity between start and success.
3434
The profile data is appended to the test's _benchcalls attribute and can
3435
be accessed by the forwarded-to TestResult.
3437
While it might be cleaner do accumulate this in stopTest, addSuccess is
3438
where our existing output support for lsprof is, and this class aims to
3439
fit in with that: while it could be moved it's not necessary to accomplish
3440
test profiling, nor would it be dramatically cleaner.
3443
def startTest(self, test):
3444
self.profiler = bzrlib.lsprof.BzrProfiler()
3445
# Prevent deadlocks in tests that use lsprof: those tests will
3447
bzrlib.lsprof.BzrProfiler.profiler_block = 0
3448
self.profiler.start()
3449
testtools.ExtendedToOriginalDecorator.startTest(self, test)
3451
def addSuccess(self, test):
3452
stats = self.profiler.stop()
3454
calls = test._benchcalls
3455
except AttributeError:
3456
test._benchcalls = []
3457
calls = test._benchcalls
3458
calls.append(((test.id(), "", ""), stats))
3459
testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
3461
def stopTest(self, test):
3462
testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3463
self.profiler = None
2488
return result.wasSuccessful()
3466
2491
# Controlled by "bzr selftest -E=..." option
3467
# Currently supported:
3468
# -Eallow_debug Will no longer clear debug.debug_flags() so it
3469
# preserves any flags supplied at the command line.
3470
# -Edisable_lock_checks Turns errors in mismatched locks into simple prints
3471
# rather than failing tests. And no longer raise
3472
# LockContention when fctnl locks are not being used
3473
# with proper exclusion rules.
3474
# -Ethreads Will display thread ident at creation/join time to
3475
# help track thread leaks
3476
2492
selftest_debug_flags = set()
3652
2648
return self.tests.has_key(test_id)
3655
class TestPrefixAliasRegistry(registry.Registry):
3656
"""A registry for test prefix aliases.
3658
This helps implement shorcuts for the --starting-with selftest
3659
option. Overriding existing prefixes is not allowed but not fatal (a
3660
warning will be emitted).
3663
def register(self, key, obj, help=None, info=None,
3664
override_existing=False):
3665
"""See Registry.register.
3667
Trying to override an existing alias causes a warning to be emitted,
3668
not a fatal execption.
3671
super(TestPrefixAliasRegistry, self).register(
3672
key, obj, help=help, info=info, override_existing=False)
3674
actual = self.get(key)
3676
'Test prefix alias %s is already used for %s, ignoring %s'
3677
% (key, actual, obj))
3679
def resolve_alias(self, id_start):
3680
"""Replace the alias by the prefix in the given string.
3682
Using an unknown prefix is an error to help catching typos.
3684
parts = id_start.split('.')
3686
parts[0] = self.get(parts[0])
3688
raise errors.BzrCommandError(
3689
'%s is not a known test prefix alias' % parts[0])
3690
return '.'.join(parts)
3693
test_prefix_alias_registry = TestPrefixAliasRegistry()
3694
"""Registry of test prefix aliases."""
3697
# This alias allows to detect typos ('bzrlin.') by making all valid test ids
3698
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
3699
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
3701
# Obvious highest levels prefixes, feel free to add your own via a plugin
3702
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
3703
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
3704
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
3705
test_prefix_alias_registry.register('bb', 'bzrlib.tests.blackbox')
3706
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3709
def _test_suite_testmod_names():
3710
"""Return the standard list of test module names to test."""
3713
'bzrlib.tests.blackbox',
3714
'bzrlib.tests.commands',
3715
'bzrlib.tests.doc_generate',
3716
'bzrlib.tests.per_branch',
3717
'bzrlib.tests.per_bzrdir',
3718
'bzrlib.tests.per_controldir',
3719
'bzrlib.tests.per_controldir_colo',
3720
'bzrlib.tests.per_foreign_vcs',
3721
'bzrlib.tests.per_interrepository',
3722
'bzrlib.tests.per_intertree',
3723
'bzrlib.tests.per_inventory',
3724
'bzrlib.tests.per_interbranch',
3725
'bzrlib.tests.per_lock',
3726
'bzrlib.tests.per_merger',
3727
'bzrlib.tests.per_transport',
3728
'bzrlib.tests.per_tree',
3729
'bzrlib.tests.per_pack_repository',
3730
'bzrlib.tests.per_repository',
3731
'bzrlib.tests.per_repository_chk',
3732
'bzrlib.tests.per_repository_reference',
3733
'bzrlib.tests.per_repository_vf',
3734
'bzrlib.tests.per_uifactory',
3735
'bzrlib.tests.per_versionedfile',
3736
'bzrlib.tests.per_workingtree',
3737
'bzrlib.tests.test__annotator',
3738
'bzrlib.tests.test__bencode',
3739
'bzrlib.tests.test__btree_serializer',
3740
'bzrlib.tests.test__chk_map',
3741
'bzrlib.tests.test__dirstate_helpers',
3742
'bzrlib.tests.test__groupcompress',
3743
'bzrlib.tests.test__known_graph',
3744
'bzrlib.tests.test__rio',
3745
'bzrlib.tests.test__simple_set',
3746
'bzrlib.tests.test__static_tuple',
3747
'bzrlib.tests.test__walkdirs_win32',
3748
'bzrlib.tests.test_ancestry',
3749
'bzrlib.tests.test_annotate',
3750
'bzrlib.tests.test_api',
3751
'bzrlib.tests.test_atomicfile',
3752
'bzrlib.tests.test_bad_files',
3753
'bzrlib.tests.test_bisect_multi',
3754
'bzrlib.tests.test_branch',
3755
'bzrlib.tests.test_branchbuilder',
3756
'bzrlib.tests.test_btree_index',
3757
'bzrlib.tests.test_bugtracker',
3758
'bzrlib.tests.test_bundle',
3759
'bzrlib.tests.test_bzrdir',
3760
'bzrlib.tests.test__chunks_to_lines',
3761
'bzrlib.tests.test_cache_utf8',
3762
'bzrlib.tests.test_chk_map',
3763
'bzrlib.tests.test_chk_serializer',
3764
'bzrlib.tests.test_chunk_writer',
3765
'bzrlib.tests.test_clean_tree',
3766
'bzrlib.tests.test_cleanup',
3767
'bzrlib.tests.test_cmdline',
3768
'bzrlib.tests.test_commands',
3769
'bzrlib.tests.test_commit',
3770
'bzrlib.tests.test_commit_merge',
3771
'bzrlib.tests.test_config',
3772
'bzrlib.tests.test_conflicts',
3773
'bzrlib.tests.test_controldir',
3774
'bzrlib.tests.test_counted_lock',
3775
'bzrlib.tests.test_crash',
3776
'bzrlib.tests.test_decorators',
3777
'bzrlib.tests.test_delta',
3778
'bzrlib.tests.test_debug',
3779
'bzrlib.tests.test_deprecated_graph',
3780
'bzrlib.tests.test_diff',
3781
'bzrlib.tests.test_directory_service',
3782
'bzrlib.tests.test_dirstate',
3783
'bzrlib.tests.test_email_message',
3784
'bzrlib.tests.test_eol_filters',
3785
'bzrlib.tests.test_errors',
3786
'bzrlib.tests.test_export',
3787
'bzrlib.tests.test_extract',
3788
'bzrlib.tests.test_fetch',
3789
'bzrlib.tests.test_fixtures',
3790
'bzrlib.tests.test_fifo_cache',
3791
'bzrlib.tests.test_filters',
3792
'bzrlib.tests.test_ftp_transport',
3793
'bzrlib.tests.test_foreign',
3794
'bzrlib.tests.test_generate_docs',
3795
'bzrlib.tests.test_generate_ids',
3796
'bzrlib.tests.test_globbing',
3797
'bzrlib.tests.test_gpg',
3798
'bzrlib.tests.test_graph',
3799
'bzrlib.tests.test_groupcompress',
3800
'bzrlib.tests.test_hashcache',
3801
'bzrlib.tests.test_help',
3802
'bzrlib.tests.test_hooks',
3803
'bzrlib.tests.test_http',
3804
'bzrlib.tests.test_http_response',
3805
'bzrlib.tests.test_https_ca_bundle',
3806
'bzrlib.tests.test_identitymap',
3807
'bzrlib.tests.test_ignores',
3808
'bzrlib.tests.test_index',
3809
'bzrlib.tests.test_import_tariff',
3810
'bzrlib.tests.test_info',
3811
'bzrlib.tests.test_inv',
3812
'bzrlib.tests.test_inventory_delta',
3813
'bzrlib.tests.test_knit',
3814
'bzrlib.tests.test_lazy_import',
3815
'bzrlib.tests.test_lazy_regex',
3816
'bzrlib.tests.test_library_state',
3817
'bzrlib.tests.test_lock',
3818
'bzrlib.tests.test_lockable_files',
3819
'bzrlib.tests.test_lockdir',
3820
'bzrlib.tests.test_log',
3821
'bzrlib.tests.test_lru_cache',
3822
'bzrlib.tests.test_lsprof',
3823
'bzrlib.tests.test_mail_client',
3824
'bzrlib.tests.test_matchers',
3825
'bzrlib.tests.test_memorytree',
3826
'bzrlib.tests.test_merge',
3827
'bzrlib.tests.test_merge3',
3828
'bzrlib.tests.test_merge_core',
3829
'bzrlib.tests.test_merge_directive',
3830
'bzrlib.tests.test_mergetools',
3831
'bzrlib.tests.test_missing',
3832
'bzrlib.tests.test_msgeditor',
3833
'bzrlib.tests.test_multiparent',
3834
'bzrlib.tests.test_mutabletree',
3835
'bzrlib.tests.test_nonascii',
3836
'bzrlib.tests.test_options',
3837
'bzrlib.tests.test_osutils',
3838
'bzrlib.tests.test_osutils_encodings',
3839
'bzrlib.tests.test_pack',
3840
'bzrlib.tests.test_patch',
3841
'bzrlib.tests.test_patches',
3842
'bzrlib.tests.test_permissions',
3843
'bzrlib.tests.test_plugins',
3844
'bzrlib.tests.test_progress',
3845
'bzrlib.tests.test_pyutils',
3846
'bzrlib.tests.test_read_bundle',
3847
'bzrlib.tests.test_reconcile',
3848
'bzrlib.tests.test_reconfigure',
3849
'bzrlib.tests.test_registry',
3850
'bzrlib.tests.test_remote',
3851
'bzrlib.tests.test_rename_map',
3852
'bzrlib.tests.test_repository',
3853
'bzrlib.tests.test_revert',
3854
'bzrlib.tests.test_revision',
3855
'bzrlib.tests.test_revisionspec',
3856
'bzrlib.tests.test_revisiontree',
3857
'bzrlib.tests.test_rio',
3858
'bzrlib.tests.test_rules',
3859
'bzrlib.tests.test_sampler',
3860
'bzrlib.tests.test_scenarios',
3861
'bzrlib.tests.test_script',
3862
'bzrlib.tests.test_selftest',
3863
'bzrlib.tests.test_serializer',
3864
'bzrlib.tests.test_setup',
3865
'bzrlib.tests.test_sftp_transport',
3866
'bzrlib.tests.test_shelf',
3867
'bzrlib.tests.test_shelf_ui',
3868
'bzrlib.tests.test_smart',
3869
'bzrlib.tests.test_smart_add',
3870
'bzrlib.tests.test_smart_request',
3871
'bzrlib.tests.test_smart_transport',
3872
'bzrlib.tests.test_smtp_connection',
3873
'bzrlib.tests.test_source',
3874
'bzrlib.tests.test_ssh_transport',
3875
'bzrlib.tests.test_status',
3876
'bzrlib.tests.test_store',
3877
'bzrlib.tests.test_strace',
3878
'bzrlib.tests.test_subsume',
3879
'bzrlib.tests.test_switch',
3880
'bzrlib.tests.test_symbol_versioning',
3881
'bzrlib.tests.test_tag',
3882
'bzrlib.tests.test_test_server',
3883
'bzrlib.tests.test_testament',
3884
'bzrlib.tests.test_textfile',
3885
'bzrlib.tests.test_textmerge',
3886
'bzrlib.tests.test_cethread',
3887
'bzrlib.tests.test_timestamp',
3888
'bzrlib.tests.test_trace',
3889
'bzrlib.tests.test_transactions',
3890
'bzrlib.tests.test_transform',
3891
'bzrlib.tests.test_transport',
3892
'bzrlib.tests.test_transport_log',
3893
'bzrlib.tests.test_tree',
3894
'bzrlib.tests.test_treebuilder',
3895
'bzrlib.tests.test_treeshape',
3896
'bzrlib.tests.test_tsort',
3897
'bzrlib.tests.test_tuned_gzip',
3898
'bzrlib.tests.test_ui',
3899
'bzrlib.tests.test_uncommit',
3900
'bzrlib.tests.test_upgrade',
3901
'bzrlib.tests.test_upgrade_stacked',
3902
'bzrlib.tests.test_urlutils',
3903
'bzrlib.tests.test_version',
3904
'bzrlib.tests.test_version_info',
3905
'bzrlib.tests.test_versionedfile',
3906
'bzrlib.tests.test_weave',
3907
'bzrlib.tests.test_whitebox',
3908
'bzrlib.tests.test_win32utils',
3909
'bzrlib.tests.test_workingtree',
3910
'bzrlib.tests.test_workingtree_4',
3911
'bzrlib.tests.test_wsgi',
3912
'bzrlib.tests.test_xml',
3916
def _test_suite_modules_to_doctest():
3917
"""Return the list of modules to doctest."""
3919
# GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
3923
'bzrlib.branchbuilder',
3924
'bzrlib.decorators',
3926
'bzrlib.iterablefile',
3931
'bzrlib.symbol_versioning',
3933
'bzrlib.tests.fixtures',
3935
'bzrlib.transport.http',
3936
'bzrlib.version_info_formats.format_custom',
3940
2651
def test_suite(keep_only=None, starting_with=None):
3941
2652
"""Build and return TestSuite for the whole of bzrlib.
3948
2659
This function can be replaced if you need to change the default test
3949
2660
suite on a global basis, but it is not encouraged.
2664
'bzrlib.util.tests.test_bencode',
2665
'bzrlib.tests.blackbox',
2666
'bzrlib.tests.branch_implementations',
2667
'bzrlib.tests.bzrdir_implementations',
2668
'bzrlib.tests.commands',
2669
'bzrlib.tests.inventory_implementations',
2670
'bzrlib.tests.interrepository_implementations',
2671
'bzrlib.tests.intertree_implementations',
2672
'bzrlib.tests.per_lock',
2673
'bzrlib.tests.repository_implementations',
2674
'bzrlib.tests.test__dirstate_helpers',
2675
'bzrlib.tests.test_ancestry',
2676
'bzrlib.tests.test_annotate',
2677
'bzrlib.tests.test_api',
2678
'bzrlib.tests.test_atomicfile',
2679
'bzrlib.tests.test_bad_files',
2680
'bzrlib.tests.test_bisect_multi',
2681
'bzrlib.tests.test_branch',
2682
'bzrlib.tests.test_branchbuilder',
2683
'bzrlib.tests.test_bugtracker',
2684
'bzrlib.tests.test_bundle',
2685
'bzrlib.tests.test_bzrdir',
2686
'bzrlib.tests.test_cache_utf8',
2687
'bzrlib.tests.test_commands',
2688
'bzrlib.tests.test_commit',
2689
'bzrlib.tests.test_commit_merge',
2690
'bzrlib.tests.test_config',
2691
'bzrlib.tests.test_conflicts',
2692
'bzrlib.tests.test_counted_lock',
2693
'bzrlib.tests.test_decorators',
2694
'bzrlib.tests.test_delta',
2695
'bzrlib.tests.test_deprecated_graph',
2696
'bzrlib.tests.test_diff',
2697
'bzrlib.tests.test_dirstate',
2698
'bzrlib.tests.test_directory_service',
2699
'bzrlib.tests.test_email_message',
2700
'bzrlib.tests.test_errors',
2701
'bzrlib.tests.test_extract',
2702
'bzrlib.tests.test_fetch',
2703
'bzrlib.tests.test_ftp_transport',
2704
'bzrlib.tests.test_generate_docs',
2705
'bzrlib.tests.test_generate_ids',
2706
'bzrlib.tests.test_globbing',
2707
'bzrlib.tests.test_gpg',
2708
'bzrlib.tests.test_graph',
2709
'bzrlib.tests.test_hashcache',
2710
'bzrlib.tests.test_help',
2711
'bzrlib.tests.test_hooks',
2712
'bzrlib.tests.test_http',
2713
'bzrlib.tests.test_http_implementations',
2714
'bzrlib.tests.test_http_response',
2715
'bzrlib.tests.test_https_ca_bundle',
2716
'bzrlib.tests.test_identitymap',
2717
'bzrlib.tests.test_ignores',
2718
'bzrlib.tests.test_index',
2719
'bzrlib.tests.test_info',
2720
'bzrlib.tests.test_inv',
2721
'bzrlib.tests.test_knit',
2722
'bzrlib.tests.test_lazy_import',
2723
'bzrlib.tests.test_lazy_regex',
2724
'bzrlib.tests.test_lockdir',
2725
'bzrlib.tests.test_lockable_files',
2726
'bzrlib.tests.test_log',
2727
'bzrlib.tests.test_lsprof',
2728
'bzrlib.tests.test_lru_cache',
2729
'bzrlib.tests.test_mail_client',
2730
'bzrlib.tests.test_memorytree',
2731
'bzrlib.tests.test_merge',
2732
'bzrlib.tests.test_merge3',
2733
'bzrlib.tests.test_merge_core',
2734
'bzrlib.tests.test_merge_directive',
2735
'bzrlib.tests.test_missing',
2736
'bzrlib.tests.test_msgeditor',
2737
'bzrlib.tests.test_multiparent',
2738
'bzrlib.tests.test_mutabletree',
2739
'bzrlib.tests.test_nonascii',
2740
'bzrlib.tests.test_options',
2741
'bzrlib.tests.test_osutils',
2742
'bzrlib.tests.test_osutils_encodings',
2743
'bzrlib.tests.test_pack',
2744
'bzrlib.tests.test_patch',
2745
'bzrlib.tests.test_patches',
2746
'bzrlib.tests.test_permissions',
2747
'bzrlib.tests.test_plugins',
2748
'bzrlib.tests.test_progress',
2749
'bzrlib.tests.test_read_bundle',
2750
'bzrlib.tests.test_reconfigure',
2751
'bzrlib.tests.test_reconcile',
2752
'bzrlib.tests.test_registry',
2753
'bzrlib.tests.test_remote',
2754
'bzrlib.tests.test_repository',
2755
'bzrlib.tests.per_repository_reference',
2756
'bzrlib.tests.test_revert',
2757
'bzrlib.tests.test_revision',
2758
'bzrlib.tests.test_revisionspec',
2759
'bzrlib.tests.test_revisiontree',
2760
'bzrlib.tests.test_rio',
2761
'bzrlib.tests.test_rules',
2762
'bzrlib.tests.test_sampler',
2763
'bzrlib.tests.test_selftest',
2764
'bzrlib.tests.test_setup',
2765
'bzrlib.tests.test_sftp_transport',
2766
'bzrlib.tests.test_smart',
2767
'bzrlib.tests.test_smart_add',
2768
'bzrlib.tests.test_smart_transport',
2769
'bzrlib.tests.test_smtp_connection',
2770
'bzrlib.tests.test_source',
2771
'bzrlib.tests.test_ssh_transport',
2772
'bzrlib.tests.test_status',
2773
'bzrlib.tests.test_store',
2774
'bzrlib.tests.test_strace',
2775
'bzrlib.tests.test_subsume',
2776
'bzrlib.tests.test_switch',
2777
'bzrlib.tests.test_symbol_versioning',
2778
'bzrlib.tests.test_tag',
2779
'bzrlib.tests.test_testament',
2780
'bzrlib.tests.test_textfile',
2781
'bzrlib.tests.test_textmerge',
2782
'bzrlib.tests.test_timestamp',
2783
'bzrlib.tests.test_trace',
2784
'bzrlib.tests.test_transactions',
2785
'bzrlib.tests.test_transform',
2786
'bzrlib.tests.test_transport',
2787
'bzrlib.tests.test_transport_implementations',
2788
'bzrlib.tests.test_tree',
2789
'bzrlib.tests.test_treebuilder',
2790
'bzrlib.tests.test_tsort',
2791
'bzrlib.tests.test_tuned_gzip',
2792
'bzrlib.tests.test_ui',
2793
'bzrlib.tests.test_uncommit',
2794
'bzrlib.tests.test_upgrade',
2795
'bzrlib.tests.test_urlutils',
2796
'bzrlib.tests.test_versionedfile',
2797
'bzrlib.tests.test_version',
2798
'bzrlib.tests.test_version_info',
2799
'bzrlib.tests.test_weave',
2800
'bzrlib.tests.test_whitebox',
2801
'bzrlib.tests.test_win32utils',
2802
'bzrlib.tests.test_workingtree',
2803
'bzrlib.tests.test_workingtree_4',
2804
'bzrlib.tests.test_wsgi',
2805
'bzrlib.tests.test_xml',
2806
'bzrlib.tests.tree_implementations',
2807
'bzrlib.tests.workingtree_implementations',
3952
2810
loader = TestUtil.TestLoader()
3954
if keep_only is not None:
3955
id_filter = TestIdList(keep_only)
2812
if starting_with is not None:
3957
2813
# We take precedence over keep_only because *at loading time* using
3958
2814
# both options means we will load less tests for the same final result.
3959
2815
def interesting_module(name):
3960
for start in starting_with:
3962
# Either the module name starts with the specified string
3963
name.startswith(start)
3964
# or it may contain tests starting with the specified string
3965
or start.startswith(name)
2817
# Either the module name starts with the specified string
2818
name.startswith(starting_with)
2819
# or it may contain tests starting with the specified string
2820
or starting_with.startswith(name)
3969
2822
loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
3971
2824
elif keep_only is not None:
2825
id_filter = TestIdList(keep_only)
3972
2826
loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
3973
2827
def interesting_module(name):
3974
2828
return id_filter.refers_to(name)
4067
2971
for right_name, right_dict in scenarios_right]
4070
def multiply_tests(tests, scenarios, result):
4071
"""Multiply tests_list by scenarios into result.
4073
This is the core workhorse for test parameterisation.
4075
Typically the load_tests() method for a per-implementation test suite will
4076
call multiply_tests and return the result.
4078
:param tests: The tests to parameterise.
4079
:param scenarios: The scenarios to apply: pairs of (scenario_name,
4080
scenario_param_dict).
4081
:param result: A TestSuite to add created tests to.
4083
This returns the passed in result TestSuite with the cross product of all
4084
the tests repeated once for each scenario. Each test is adapted by adding
4085
the scenario name at the end of its id(), and updating the test object's
4086
__dict__ with the scenario_param_dict.
4088
>>> import bzrlib.tests.test_sampler
4089
>>> r = multiply_tests(
4090
... bzrlib.tests.test_sampler.DemoTest('test_nothing'),
4091
... [('one', dict(param=1)),
4092
... ('two', dict(param=2))],
4093
... TestUtil.TestSuite())
4094
>>> tests = list(iter_suite_tests(r))
4098
'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
4104
for test in iter_suite_tests(tests):
4105
apply_scenarios(test, scenarios, result)
4109
def apply_scenarios(test, scenarios, result):
4110
"""Apply the scenarios in scenarios to test and add to result.
4112
:param test: The test to apply scenarios to.
4113
:param scenarios: An iterable of scenarios to apply to test.
4115
:seealso: apply_scenario
4117
for scenario in scenarios:
4118
result.addTest(apply_scenario(test, scenario))
4122
def apply_scenario(test, scenario):
4123
"""Copy test and apply scenario to it.
4125
:param test: A test to adapt.
4126
:param scenario: A tuple describing the scenarion.
4127
The first element of the tuple is the new test id.
4128
The second element is a dict containing attributes to set on the
4130
:return: The adapted test.
4132
new_id = "%s(%s)" % (test.id(), scenario[0])
4133
new_test = clone_test(test, new_id)
4134
for name, value in scenario[1].items():
4135
setattr(new_test, name, value)
4139
def clone_test(test, new_id):
4140
"""Clone a test giving it a new id.
4142
:param test: The test to clone.
4143
:param new_id: The id to assign to it.
4144
:return: The new test.
4146
new_test = copy.copy(test)
4147
new_test.id = lambda: new_id
4148
# XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4149
# causes cloned tests to share the 'details' dict. This makes it hard to
4150
# read the test output for parameterized tests, because tracebacks will be
4151
# associated with irrelevant tests.
4153
details = new_test._TestCase__details
4154
except AttributeError:
4155
# must be a different version of testtools than expected. Do nothing.
4158
# Reset the '__details' dict.
4159
new_test._TestCase__details = {}
4163
def permute_tests_for_extension(standard_tests, loader, py_module_name,
4165
"""Helper for permutating tests against an extension module.
4167
This is meant to be used inside a modules 'load_tests()' function. It will
4168
create 2 scenarios, and cause all tests in the 'standard_tests' to be run
4169
against both implementations. Setting 'test.module' to the appropriate
4170
module. See bzrlib.tests.test__chk_map.load_tests as an example.
4172
:param standard_tests: A test suite to permute
4173
:param loader: A TestLoader
4174
:param py_module_name: The python path to a python module that can always
4175
be loaded, and will be considered the 'python' implementation. (eg
4176
'bzrlib._chk_map_py')
4177
:param ext_module_name: The python path to an extension module. If the
4178
module cannot be loaded, a single test will be added, which notes that
4179
the module is not available. If it can be loaded, all standard_tests
4180
will be run against that module.
4181
:return: (suite, feature) suite is a test-suite that has all the permuted
4182
tests. feature is the Feature object that can be used to determine if
4183
the module is available.
4186
py_module = pyutils.get_named_object(py_module_name)
4188
('python', {'module': py_module}),
4190
suite = loader.suiteClass()
4191
feature = ModuleAvailableFeature(ext_module_name)
4192
if feature.available():
4193
scenarios.append(('C', {'module': feature.module}))
4195
# the compiled module isn't available, so we add a failing test
4196
class FailWithoutFeature(TestCase):
4197
def test_fail(self):
4198
self.requireFeature(feature)
4199
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4200
result = multiply_tests(standard_tests, scenarios, suite)
4201
return result, feature
4204
def _rmtree_temp_dir(dirname, test_id=None):
2975
def adapt_modules(mods_list, adapter, loader, suite):
2976
"""Adapt the modules in mods_list using adapter and add to suite."""
2977
tests = loader.loadTestsFromModuleNames(mods_list)
2978
adapt_tests(tests, adapter, suite)
2981
def adapt_tests(tests_list, adapter, suite):
2982
"""Adapt the tests in tests_list using adapter and add to suite."""
2983
for test in iter_suite_tests(tests_list):
2984
suite.addTests(adapter.adapt(test))
2987
def _rmtree_temp_dir(dirname):
4205
2988
# If LANG=C we probably have created some bogus paths
4206
2989
# which rmtree(unicode) will fail to delete
4207
2990
# so make sure we are using rmtree(str) to delete everything
4314
3088
UnicodeFilenameFeature = _UnicodeFilenameFeature()
4317
class _CompatabilityThunkFeature(Feature):
4318
"""This feature is just a thunk to another feature.
4320
It issues a deprecation warning if it is accessed, to let you know that you
4321
should really use a different feature.
4324
def __init__(self, dep_version, module, name,
4325
replacement_name, replacement_module=None):
4326
super(_CompatabilityThunkFeature, self).__init__()
4327
self._module = module
4328
if replacement_module is None:
4329
replacement_module = module
4330
self._replacement_module = replacement_module
4332
self._replacement_name = replacement_name
4333
self._dep_version = dep_version
4334
self._feature = None
4337
if self._feature is None:
4338
depr_msg = self._dep_version % ('%s.%s'
4339
% (self._module, self._name))
4340
use_msg = ' Use %s.%s instead.' % (self._replacement_module,
4341
self._replacement_name)
4342
symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
4343
# Import the new feature and use it as a replacement for the
4345
self._feature = pyutils.get_named_object(
4346
self._replacement_module, self._replacement_name)
4350
return self._feature._probe()
4353
class ModuleAvailableFeature(Feature):
4354
"""This is a feature than describes a module we want to be available.
4356
Declare the name of the module in __init__(), and then after probing, the
4357
module will be available as 'self.module'.
4359
:ivar module: The module if it is available, else None.
4362
def __init__(self, module_name):
4363
super(ModuleAvailableFeature, self).__init__()
4364
self.module_name = module_name
4368
self._module = __import__(self.module_name, {}, {}, [''])
4375
if self.available(): # Make sure the probe has been done
4379
def feature_name(self):
4380
return self.module_name
3091
class TestScenarioApplier(object):
3092
"""A tool to apply scenarios to tests."""
3094
def adapt(self, test):
3095
"""Return a TestSuite containing a copy of test for each scenario."""
3096
result = unittest.TestSuite()
3097
for scenario in self.scenarios:
3098
result.addTest(self.adapt_test_to_scenario(test, scenario))
3101
def adapt_test_to_scenario(self, test, scenario):
3102
"""Copy test and apply scenario to it.
3104
:param test: A test to adapt.
3105
:param scenario: A tuple describing the scenarion.
3106
The first element of the tuple is the new test id.
3107
The second element is a dict containing attributes to set on the
3109
:return: The adapted test.
3111
from copy import deepcopy
3112
new_test = deepcopy(test)
3113
for name, value in scenario[1].items():
3114
setattr(new_test, name, value)
3115
new_id = "%s(%s)" % (new_test.id(), scenario[0])
3116
new_test.id = lambda: new_id
4383
3120
def probe_unicode_in_user_encoding():
4416
class _HTTPSServerFeature(Feature):
4417
"""Some tests want an https Server, check if one is available.
3153
class _FTPServerFeature(Feature):
3154
"""Some tests want an FTP Server, check if one is available.
4419
Right now, the only way this is available is under python2.6 which provides
3156
Right now, the only way this is available is if 'medusa' is installed.
3157
http://www.amk.ca/python/code/medusa.html
4423
3160
def _probe(self):
3162
import bzrlib.tests.ftp_server
4427
3164
except ImportError:
4430
3167
def feature_name(self):
4431
return 'HTTPSServer'
4434
HTTPSServerFeature = _HTTPSServerFeature()
4437
class _UnicodeFilename(Feature):
4438
"""Does the filesystem support Unicode filenames?"""
4443
except UnicodeEncodeError:
4445
except (IOError, OSError):
4446
# The filesystem allows the Unicode filename but the file doesn't
4450
# The filesystem allows the Unicode filename and the file exists,
4454
UnicodeFilename = _UnicodeFilename()
4457
class _ByteStringNamedFilesystem(Feature):
4458
"""Is the filesystem based on bytes?"""
4461
if os.name == "posix":
4465
ByteStringNamedFilesystem = _ByteStringNamedFilesystem()
4468
class _UTF8Filesystem(Feature):
4469
"""Is the filesystem UTF-8?"""
4472
if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
4476
UTF8Filesystem = _UTF8Filesystem()
4479
class _BreakinFeature(Feature):
4480
"""Does this platform support the breakin feature?"""
4483
from bzrlib import breakin
4484
if breakin.determine_signal() is None:
4486
if sys.platform == 'win32':
4487
# Windows doesn't have os.kill, and we catch the SIGBREAK signal.
4488
# We trigger SIGBREAK via a Console api so we need ctypes to
4489
# access the function
4496
def feature_name(self):
4497
return "SIGQUIT or SIGBREAK w/ctypes on win32"
4500
BreakinFeature = _BreakinFeature()
4503
class _CaseInsCasePresFilenameFeature(Feature):
4504
"""Is the file-system case insensitive, but case-preserving?"""
4507
fileno, name = tempfile.mkstemp(prefix='MixedCase')
4509
# first check truly case-preserving for created files, then check
4510
# case insensitive when opening existing files.
4511
name = osutils.normpath(name)
4512
base, rel = osutils.split(name)
4513
found_rel = osutils.canonical_relpath(base, name)
4514
return (found_rel == rel
4515
and os.path.isfile(name.upper())
4516
and os.path.isfile(name.lower()))
4521
def feature_name(self):
4522
return "case-insensitive case-preserving filesystem"
4524
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
3170
FTPServerFeature = _FTPServerFeature()
4527
3173
class _CaseInsensitiveFilesystemFeature(Feature):
4528
"""Check if underlying filesystem is case-insensitive but *not* case
3174
"""Check if underlined filesystem is case-insensitive
3175
(e.g. on Windows, Cygwin, MacOS)
4531
# Note that on Windows, Cygwin, MacOS etc, the file-systems are far
4532
# more likely to be case preserving, so this case is rare.
4534
3178
def _probe(self):
4535
if CaseInsCasePresFilenameFeature.available():
4538
3179
if TestCaseWithMemoryTransport.TEST_ROOT is None:
4539
3180
root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
4540
3181
TestCaseWithMemoryTransport.TEST_ROOT = root