31
29
from cStringIO import StringIO
37
from pprint import pformat
42
from subprocess import Popen, PIPE
54
# nb: check this before importing anything else from within it
55
_testtools_version = getattr(testtools, '__version__', ())
56
if _testtools_version < (0, 9, 5):
57
raise ImportError("need at least testtools 0.9.5: %s is %r"
58
% (testtools.__file__, _testtools_version))
59
from testtools import content
51
62
from bzrlib import (
66
commands as _mod_commands,
76
plugin as _mod_plugin,
83
transport as _mod_transport,
65
import bzrlib.commands
66
import bzrlib.timestamp
68
import bzrlib.inventory
69
import bzrlib.iterablefile
72
87
import bzrlib.lsprof
73
88
except ImportError:
74
89
# lsprof not available
76
from bzrlib.merge import merge_inner
80
from bzrlib import symbol_versioning
91
from bzrlib.smart import client, request
92
from bzrlib.transport import (
81
96
from bzrlib.symbol_versioning import (
83
97
deprecated_function,
88
from bzrlib.transport import get_transport
89
import bzrlib.transport
90
from bzrlib.transport.local import LocalURLServer
91
from bzrlib.transport.memory import MemoryServer
92
from bzrlib.transport.readonly import ReadonlyServer
93
from bzrlib.trace import mutter, note
94
from bzrlib.tests import TestUtil
95
from bzrlib.tests.http_server import HttpServer
96
from bzrlib.tests.TestUtil import (
100
from bzrlib.tests.treeshape import build_tree_contents
101
import bzrlib.version_info_formats.format_custom
102
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
100
from bzrlib.tests import (
106
from bzrlib.ui import NullProgressView
107
from bzrlib.ui.text import TextUIFactory
108
from bzrlib.tests.features import _CompatabilityThunkFeature
104
110
# Mark this python module as being part of the implementation
105
111
# of unittest: this gives us better tracebacks where the last
106
112
# shown frame is the test code, not our assertXYZ.
109
default_transport = LocalURLServer
112
class ExtendedTestResult(unittest._TextTestResult):
115
default_transport = test_server.LocalURLServer
118
_unitialized_attr = object()
119
"""A sentinel needed to act as a default value in a method signature."""
122
# Subunit result codes, defined here to prevent a hard dependency on subunit.
126
# These are intentionally brought into this namespace. That way plugins, etc
127
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
128
TestSuite = TestUtil.TestSuite
129
TestLoader = TestUtil.TestLoader
131
# Tests should run in a clean and clearly defined environment. The goal is to
132
# keep them isolated from the running environment as mush as possible. The test
133
# framework ensures the variables defined below are set (or deleted if the
134
# value is None) before a test is run and reset to their original value after
135
# the test is run. Generally if some code depends on an environment variable,
136
# the tests should start without this variable in the environment. There are a
137
# few exceptions but you shouldn't violate this rule lightly.
141
'XDG_CONFIG_HOME': None,
142
# bzr now uses the Win32 API and doesn't rely on APPDATA, but the
143
# tests do check our impls match APPDATA
144
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
148
'BZREMAIL': None, # may still be present in the environment
149
'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
150
'BZR_PROGRESS_BAR': None,
151
# This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
152
# as a base class instead of TestCaseInTempDir. Tests inheriting from
153
# TestCase should not use disk resources, BZR_LOG is one.
154
'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
155
'BZR_PLUGIN_PATH': None,
156
'BZR_DISABLE_PLUGINS': None,
157
'BZR_PLUGINS_AT': None,
158
'BZR_CONCURRENCY': None,
159
# Make sure that any text ui tests are consistent regardless of
160
# the environment the test case is run in; you may want tests that
161
# test other combinations. 'dumb' is a reasonable guess for tests
162
# going to a pipe or a StringIO.
168
'SSH_AUTH_SOCK': None,
178
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
179
# least. If you do (care), please update this comment
183
'BZR_REMOTE_PATH': None,
184
# Generally speaking, we don't want apport reporting on crashes in
185
# the test envirnoment unless we're specifically testing apport,
186
# so that it doesn't leak into the real system environment. We
187
# use an env var so it propagates to subprocesses.
188
'APPORT_DISABLE': '1',
192
def override_os_environ(test, env=None):
193
"""Modify os.environ keeping a copy.
195
:param test: A test instance
197
:param env: A dict containing variable definitions to be installed
200
env = isolated_environ
201
test._original_os_environ = dict([(var, value)
202
for var, value in os.environ.iteritems()])
203
for var, value in env.iteritems():
204
osutils.set_or_unset_env(var, value)
205
if var not in test._original_os_environ:
206
# The var is new, add it with a value of None, so
207
# restore_os_environ will delete it
208
test._original_os_environ[var] = None
211
def restore_os_environ(test):
212
"""Restore os.environ to its original state.
214
:param test: A test instance previously passed to override_os_environ.
216
for var, value in test._original_os_environ.iteritems():
217
# Restore the original value (or delete it if the value has been set to
218
# None in override_os_environ).
219
osutils.set_or_unset_env(var, value)
222
def _clear__type_equality_funcs(test):
223
"""Cleanup bound methods stored on TestCase instances
225
Clear the dict breaking a few (mostly) harmless cycles in the affected
226
unittests released with Python 2.6 and initial Python 2.7 versions.
228
For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
229
shipped in Oneiric, an object with no clear method was used, hence the
230
extra complications, see bug 809048 for details.
232
type_equality_funcs = getattr(test, "_type_equality_funcs", None)
233
if type_equality_funcs is not None:
234
tef_clear = getattr(type_equality_funcs, "clear", None)
235
if tef_clear is None:
236
tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
237
if tef_instance_dict is not None:
238
tef_clear = tef_instance_dict.clear
239
if tef_clear is not None:
243
class ExtendedTestResult(testtools.TextTestResult):
113
244
"""Accepts, reports and accumulates the results of running tests.
115
246
Compared to the unittest version this class adds support for
162
293
self.unsupported = {}
164
295
self._overall_start_time = time.time()
166
def _extractBenchmarkTime(self, testCase):
296
self._strict = strict
297
self._first_thread_leaker_id = None
298
self._tests_leaking_threads_count = 0
299
self._traceback_from_test = None
301
def stopTestRun(self):
304
stopTime = time.time()
305
timeTaken = stopTime - self.startTime
306
# GZ 2010-07-19: Seems testtools has no printErrors method, and though
307
# the parent class method is similar have to duplicate
308
self._show_list('ERROR', self.errors)
309
self._show_list('FAIL', self.failures)
310
self.stream.write(self.sep2)
311
self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
312
run, run != 1 and "s" or "", timeTaken))
313
if not self.wasSuccessful():
314
self.stream.write("FAILED (")
315
failed, errored = map(len, (self.failures, self.errors))
317
self.stream.write("failures=%d" % failed)
319
if failed: self.stream.write(", ")
320
self.stream.write("errors=%d" % errored)
321
if self.known_failure_count:
322
if failed or errored: self.stream.write(", ")
323
self.stream.write("known_failure_count=%d" %
324
self.known_failure_count)
325
self.stream.write(")\n")
327
if self.known_failure_count:
328
self.stream.write("OK (known_failures=%d)\n" %
329
self.known_failure_count)
331
self.stream.write("OK\n")
332
if self.skip_count > 0:
333
skipped = self.skip_count
334
self.stream.write('%d test%s skipped\n' %
335
(skipped, skipped != 1 and "s" or ""))
337
for feature, count in sorted(self.unsupported.items()):
338
self.stream.write("Missing feature '%s' skipped %d tests.\n" %
341
ok = self.wasStrictlySuccessful()
343
ok = self.wasSuccessful()
344
if self._first_thread_leaker_id:
346
'%s is leaking threads among %d leaking tests.\n' % (
347
self._first_thread_leaker_id,
348
self._tests_leaking_threads_count))
349
# We don't report the main thread as an active one.
351
'%d non-main threads were left active in the end.\n'
352
% (len(self._active_threads) - 1))
354
def getDescription(self, test):
357
def _extractBenchmarkTime(self, testCase, details=None):
167
358
"""Add a benchmark time for the current test case."""
359
if details and 'benchtime' in details:
360
return float(''.join(details['benchtime'].iter_bytes()))
168
361
return getattr(testCase, "_benchtime", None)
363
def _delta_to_float(self, a_timedelta, precision):
364
# This calls ceiling to ensure that the most pessimistic view of time
365
# taken is shown (rather than leaving it to the Python %f operator
366
# to decide whether to round/floor/ceiling. This was added when we
367
# had pyp3 test failures that suggest a floor was happening.
368
shift = 10 ** precision
369
return math.ceil((a_timedelta.days * 86400.0 + a_timedelta.seconds +
370
a_timedelta.microseconds / 1000000.0) * shift) / shift
170
372
def _elapsedTestTimeString(self):
171
373
"""Return a time string for the overall time the current test has taken."""
172
return self._formatTime(time.time() - self._start_time)
374
return self._formatTime(self._delta_to_float(
375
self._now() - self._start_datetime, 3))
174
377
def _testTimeString(self, testCase):
175
378
benchmark_time = self._extractBenchmarkTime(testCase)
176
379
if benchmark_time is not None:
178
self._formatTime(benchmark_time),
179
self._elapsedTestTimeString())
380
return self._formatTime(benchmark_time) + "*"
181
return " %s" % self._elapsedTestTimeString()
382
return self._elapsedTestTimeString()
183
384
def _formatTime(self, seconds):
184
385
"""Format seconds as milliseconds with leading spaces."""
189
390
def _shortened_test_description(self, test):
191
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
392
what = re.sub(r'^bzrlib\.tests\.', '', what)
395
# GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
396
# multiple times in a row, because the handler is added for
397
# each test but the container list is shared between cases.
398
# See lp:498869 lp:625574 and lp:637725 for background.
399
def _record_traceback_from_test(self, exc_info):
400
"""Store the traceback from passed exc_info tuple till"""
401
self._traceback_from_test = exc_info[2]
194
403
def startTest(self, test):
195
unittest.TestResult.startTest(self, test)
404
super(ExtendedTestResult, self).startTest(test)
196
408
self.report_test_start(test)
197
409
test.number = self.count
198
410
self._recordTestStartTime()
411
# Make testtools cases give us the real traceback on failure
412
addOnException = getattr(test, "addOnException", None)
413
if addOnException is not None:
414
addOnException(self._record_traceback_from_test)
415
# Only check for thread leaks on bzrlib derived test cases
416
if isinstance(test, TestCase):
417
test.addCleanup(self._check_leaked_threads, test)
419
def stopTest(self, test):
420
super(ExtendedTestResult, self).stopTest(test)
421
# Manually break cycles, means touching various private things but hey
422
getDetails = getattr(test, "getDetails", None)
423
if getDetails is not None:
425
_clear__type_equality_funcs(test)
426
self._traceback_from_test = None
428
def startTests(self):
429
self.report_tests_starting()
430
self._active_threads = threading.enumerate()
432
def _check_leaked_threads(self, test):
433
"""See if any threads have leaked since last call
435
A sample of live threads is stored in the _active_threads attribute,
436
when this method runs it compares the current live threads and any not
437
in the previous sample are treated as having leaked.
439
now_active_threads = set(threading.enumerate())
440
threads_leaked = now_active_threads.difference(self._active_threads)
442
self._report_thread_leak(test, threads_leaked, now_active_threads)
443
self._tests_leaking_threads_count += 1
444
if self._first_thread_leaker_id is None:
445
self._first_thread_leaker_id = test.id()
446
self._active_threads = now_active_threads
200
448
def _recordTestStartTime(self):
201
449
"""Record that a test has started."""
202
self._start_time = time.time()
204
def _cleanupLogFile(self, test):
205
# We can only do this if we have one of our TestCases, not if
207
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
208
if setKeepLogfile is not None:
450
self._start_datetime = self._now()
211
452
def addError(self, test, err):
212
453
"""Tell result that test finished with an error.
233
468
Called from the TestCase run() method when the test
234
469
fails because e.g. an assert() method failed.
236
self._testConcluded(test)
237
if isinstance(err[1], KnownFailure):
238
return self._addKnownFailure(test, err)
240
unittest.TestResult.addFailure(self, test, err)
241
self.failure_count += 1
242
self.report_failure(test, err)
245
self._cleanupLogFile(test)
471
self._post_mortem(self._traceback_from_test)
472
super(ExtendedTestResult, self).addFailure(test, err)
473
self.failure_count += 1
474
self.report_failure(test, err)
247
def addSuccess(self, test):
478
def addSuccess(self, test, details=None):
248
479
"""Tell result that test completed successfully.
250
481
Called from the TestCase run()
252
self._testConcluded(test)
253
483
if self._bench_history is not None:
254
benchmark_time = self._extractBenchmarkTime(test)
484
benchmark_time = self._extractBenchmarkTime(test, details)
255
485
if benchmark_time is not None:
256
486
self._bench_history.write("%s %s\n" % (
257
487
self._formatTime(benchmark_time),
259
489
self.report_success(test)
260
self._cleanupLogFile(test)
261
unittest.TestResult.addSuccess(self, test)
490
super(ExtendedTestResult, self).addSuccess(test)
262
491
test._log_contents = ''
264
def _testConcluded(self, test):
265
"""Common code when a test has finished.
267
Called regardless of whether it succeded, failed, etc.
271
def _addKnownFailure(self, test, err):
493
def addExpectedFailure(self, test, err):
272
494
self.known_failure_count += 1
273
495
self.report_known_failure(test, err)
497
def addUnexpectedSuccess(self, test, details=None):
498
"""Tell result the test unexpectedly passed, counting as a failure
500
When the minimum version of testtools required becomes 0.9.8 this
501
can be updated to use the new handling there.
503
super(ExtendedTestResult, self).addFailure(test, details=details)
504
self.failure_count += 1
505
self.report_unexpected_success(test,
506
"".join(details["reason"].iter_text()))
275
510
def addNotSupported(self, test, feature):
276
511
"""The test will not be run because of a missing feature.
278
513
# this can be called in two different ways: it may be that the
279
# test started running, and then raised (through addError)
514
# test started running, and then raised (through requireFeature)
280
515
# UnavailableFeature. Alternatively this method can be called
281
# while probing for features before running the tests; in that
282
# case we will see startTest and stopTest, but the test will never
516
# while probing for features before running the test code proper; in
517
# that case we will see startTest and stopTest, but the test will
518
# never actually run.
284
519
self.unsupported.setdefault(str(feature), 0)
285
520
self.unsupported[str(feature)] += 1
286
521
self.report_unsupported(test, feature)
288
def _addSkipped(self, test, skip_excinfo):
289
if isinstance(skip_excinfo[1], TestNotApplicable):
290
self.not_applicable_count += 1
291
self.report_not_applicable(test, skip_excinfo)
294
self.report_skip(test, skip_excinfo)
297
except KeyboardInterrupt:
300
self.addError(test, test._exc_info())
302
# seems best to treat this as success from point-of-view of unittest
303
# -- it actually does nothing so it barely matters :)
304
unittest.TestResult.addSuccess(self, test)
305
test._log_contents = ''
307
def printErrorList(self, flavour, errors):
308
for test, err in errors:
309
self.stream.writeln(self.separator1)
310
self.stream.write("%s: " % flavour)
311
self.stream.writeln(self.getDescription(test))
312
if getattr(test, '_get_log', None) is not None:
313
self.stream.write('\n')
315
('vvvv[log from %s]' % test.id()).ljust(78,'-'))
316
self.stream.write('\n')
317
self.stream.write(test._get_log())
318
self.stream.write('\n')
320
('^^^^[log from %s]' % test.id()).ljust(78,'-'))
321
self.stream.write('\n')
322
self.stream.writeln(self.separator2)
323
self.stream.writeln("%s" % err)
328
def report_cleaning_up(self):
523
def addSkip(self, test, reason):
524
"""A test has not run for 'reason'."""
526
self.report_skip(test, reason)
528
def addNotApplicable(self, test, reason):
529
self.not_applicable_count += 1
530
self.report_not_applicable(test, reason)
532
def _count_stored_tests(self):
533
"""Count of tests instances kept alive due to not succeeding"""
534
return self.error_count + self.failure_count + self.known_failure_count
536
def _post_mortem(self, tb=None):
537
"""Start a PDB post mortem session."""
538
if os.environ.get('BZR_TEST_PDB', None):
542
def progress(self, offset, whence):
543
"""The test is adjusting the count of tests to run."""
544
if whence == SUBUNIT_SEEK_SET:
545
self.num_tests = offset
546
elif whence == SUBUNIT_SEEK_CUR:
547
self.num_tests += offset
549
raise errors.BzrError("Unknown whence %r" % whence)
551
def report_tests_starting(self):
552
"""Display information before the test run begins"""
553
if getattr(sys, 'frozen', None) is None:
554
bzr_path = osutils.realpath(sys.argv[0])
556
bzr_path = sys.executable
558
'bzr selftest: %s\n' % (bzr_path,))
561
bzrlib.__path__[0],))
563
' bzr-%s python-%s %s\n' % (
564
bzrlib.version_string,
565
bzrlib._format_version_tuple(sys.version_info),
566
platform.platform(aliased=1),
568
self.stream.write('\n')
570
def report_test_start(self, test):
571
"""Display information on the test just about to be run"""
573
def _report_thread_leak(self, test, leaked_threads, active_threads):
574
"""Display information on a test that leaked one or more threads"""
575
# GZ 2010-09-09: A leak summary reported separately from the general
576
# thread debugging would be nice. Tests under subunit
577
# need something not using stream, perhaps adding a
578
# testtools details object would be fitting.
579
if 'threads' in selftest_debug_flags:
580
self.stream.write('%s is leaking, active is now %d\n' %
581
(test.id(), len(active_threads)))
583
def startTestRun(self):
584
self.startTime = time.time()
331
586
def report_success(self, test):
510
778
bench_history=None,
780
result_decorators=None,
513
self.stream = unittest._WritelnDecorator(stream)
782
"""Create a TextTestRunner.
784
:param result_decorators: An optional list of decorators to apply
785
to the result object being used by the runner. Decorators are
786
applied left to right - the first element in the list is the
789
# stream may know claim to know to write unicode strings, but in older
790
# pythons this goes sufficiently wrong that it is a bad idea. (
791
# specifically a built in file with encoding 'UTF-8' will still try
792
# to encode using ascii.
793
new_encoding = osutils.get_terminal_encoding()
794
codec = codecs.lookup(new_encoding)
795
if type(codec) is tuple:
799
encode = codec.encode
800
# GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
801
# so should swap to the plain codecs.StreamWriter
802
stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
804
stream.encoding = new_encoding
514
806
self.descriptions = descriptions
515
807
self.verbosity = verbosity
516
808
self._bench_history = bench_history
517
self.list_only = list_only
809
self._strict = strict
810
self._result_decorators = result_decorators or []
519
812
def run(self, test):
520
813
"Run the given test case or test suite."
521
startTime = time.time()
522
814
if self.verbosity == 1:
523
815
result_class = TextTestResult
524
816
elif self.verbosity >= 2:
525
817
result_class = VerboseTestResult
526
result = result_class(self.stream,
818
original_result = result_class(self.stream,
527
819
self.descriptions,
529
821
bench_history=self._bench_history,
530
num_tests=test.countTestCases(),
532
result.stop_early = self.stop_on_failure
533
result.report_starting()
535
if self.verbosity >= 2:
536
self.stream.writeln("Listing tests only ...\n")
538
for t in iter_suite_tests(test):
539
self.stream.writeln("%s" % (t.id()))
541
actionTaken = "Listed"
824
# Signal to result objects that look at stop early policy to stop,
825
original_result.stop_early = self.stop_on_failure
826
result = original_result
827
for decorator in self._result_decorators:
828
result = decorator(result)
829
result.stop_early = self.stop_on_failure
830
result.startTestRun()
544
run = result.testsRun
546
stopTime = time.time()
547
timeTaken = stopTime - startTime
549
self.stream.writeln(result.separator2)
550
self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
551
run, run != 1 and "s" or "", timeTaken))
552
self.stream.writeln()
553
if not result.wasSuccessful():
554
self.stream.write("FAILED (")
555
failed, errored = map(len, (result.failures, result.errors))
557
self.stream.write("failures=%d" % failed)
559
if failed: self.stream.write(", ")
560
self.stream.write("errors=%d" % errored)
561
if result.known_failure_count:
562
if failed or errored: self.stream.write(", ")
563
self.stream.write("known_failure_count=%d" %
564
result.known_failure_count)
565
self.stream.writeln(")")
567
if result.known_failure_count:
568
self.stream.writeln("OK (known_failures=%d)" %
569
result.known_failure_count)
571
self.stream.writeln("OK")
572
if result.skip_count > 0:
573
skipped = result.skip_count
574
self.stream.writeln('%d test%s skipped' %
575
(skipped, skipped != 1 and "s" or ""))
576
if result.unsupported:
577
for feature, count in sorted(result.unsupported.items()):
578
self.stream.writeln("Missing feature '%s' skipped %d tests." %
835
# higher level code uses our extended protocol to determine
836
# what exit code to give.
837
return original_result
584
840
def iter_suite_tests(suite):
585
841
"""Return all tests in a suite, recursing through nested suites"""
586
for item in suite._tests:
587
if isinstance(item, unittest.TestCase):
589
elif isinstance(item, unittest.TestSuite):
842
if isinstance(suite, unittest.TestCase):
844
elif isinstance(suite, unittest.TestSuite):
590
846
for r in iter_suite_tests(item):
593
raise Exception('unknown object %r inside test suite %r'
597
class TestSkipped(Exception):
598
"""Indicates that a test was intentionally skipped, rather than failing."""
849
raise Exception('unknown type %r for object %r'
850
% (type(suite), suite))
853
TestSkipped = testtools.testcase.TestSkipped
601
856
class TestNotApplicable(TestSkipped):
602
857
"""A test is not applicable to the situation where it was run.
604
This is only normally raised by parameterized tests, if they find that
605
the instance they're constructed upon does not support one aspect
859
This is only normally raised by parameterized tests, if they find that
860
the instance they're constructed upon does not support one aspect
606
861
of its interface.
610
class KnownFailure(AssertionError):
611
"""Indicates that a test failed in a precisely expected manner.
613
Such failures dont block the whole test suite from passing because they are
614
indicators of partially completed code or of future work. We have an
615
explicit error for them so that we can ensure that they are always visible:
616
KnownFailures are always shown in the output of bzr selftest.
865
# traceback._some_str fails to format exceptions that have the default
866
# __str__ which does an implicit ascii conversion. However, repr() on those
867
# objects works, for all that its not quite what the doctor may have ordered.
868
def _clever_some_str(value):
873
return repr(value).replace('\\n', '\n')
875
return '<unprintable %s object>' % type(value).__name__
877
traceback._some_str = _clever_some_str
880
# deprecated - use self.knownFailure(), or self.expectFailure.
881
KnownFailure = testtools.testcase._ExpectedFailure
620
884
class UnavailableFeature(Exception):
621
885
"""A feature required for this test was not available.
887
This can be considered a specialised form of SkippedTest.
623
889
The feature should be used to construct the exception.
627
class CommandFailed(Exception):
631
893
class StringIOWrapper(object):
632
894
"""A wrapper around cStringIO which just adds an encoding attribute.
634
896
Internally we can check sys.stdout to see what the output encoding
635
897
should be. However, cStringIO has no encoding attribute that we can
636
898
set. So we wrap it instead.
736
986
retrieved by _get_log(). We use a real OS file, not an in-memory object,
737
987
so that it can also capture file IO. When the test completes this file
738
988
is read into memory and removed from disk.
740
990
There are also convenience functions to invoke bzr's command-line
741
991
routine, and to build and check bzr trees.
743
993
In addition to the usual method of overriding tearDown(), this class also
744
allows subclasses to register functions into the _cleanups list, which is
994
allows subclasses to register cleanup functions via addCleanup, which are
745
995
run in order as the object is torn down. It's less likely this will be
746
996
accidentally overlooked.
749
_active_threads = None
750
_leaking_threads_tests = 0
751
_first_thread_leaker_id = None
752
_log_file_name = None
754
_keep_log_file = False
755
1000
# record lsprof data when performing benchmark calls.
756
1001
_gather_lsprof_in_benchmarks = False
757
attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
758
'_log_contents', '_log_file_name', '_benchtime',
759
'_TestCase__testMethodName')
761
1003
def __init__(self, methodName='testMethod'):
762
1004
super(TestCase, self).__init__(methodName)
1005
self._directory_isolation = True
1006
self.exception_handlers.insert(0,
1007
(UnavailableFeature, self._do_unsupported_or_skip))
1008
self.exception_handlers.insert(0,
1009
(TestNotApplicable, self._do_not_applicable))
765
1011
def setUp(self):
766
unittest.TestCase.setUp(self)
1012
super(TestCase, self).setUp()
1014
# At this point we're still accessing the config files in $BZR_HOME (as
1015
# set by the user running selftest).
1016
timeout = config.GlobalStack().get('selftest.timeout')
1018
timeout_fixture = fixtures.TimeoutFixture(timeout)
1019
timeout_fixture.setUp()
1020
self.addCleanup(timeout_fixture.cleanUp)
1022
for feature in getattr(self, '_test_needs_features', []):
1023
self.requireFeature(feature)
767
1024
self._cleanEnvironment()
1026
if bzrlib.global_state is not None:
1027
self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1028
config.CommandLineStore())
768
1030
self._silenceUI()
769
1031
self._startLogFile()
770
1032
self._benchcalls = []
771
1033
self._benchtime = None
772
1034
self._clear_hooks()
1035
self._track_transports()
773
1037
self._clear_debug_flags()
774
TestCase._active_threads = threading.activeCount()
775
self.addCleanup(self._check_leaked_threads)
777
def _check_leaked_threads(self):
778
active = threading.activeCount()
779
leaked_threads = active - TestCase._active_threads
780
TestCase._active_threads = active
782
TestCase._leaking_threads_tests += 1
783
if TestCase._first_thread_leaker_id is None:
784
TestCase._first_thread_leaker_id = self.id()
785
# we're not specifically told when all tests are finished.
786
# This will do. We use a function to avoid keeping a reference
787
# to a TestCase object.
788
atexit.register(_report_leaked_threads)
1038
# Isolate global verbosity level, to make sure it's reproducible
1039
# between tests. We should get rid of this altogether: bug 656694. --
1041
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
1042
self._log_files = set()
1043
# Each key in the ``_counters`` dict holds a value for a different
1044
# counter. When the test ends, addDetail() should be used to output the
1045
# counter values. This happens in install_counter_hook().
1047
if 'config_stats' in selftest_debug_flags:
1048
self._install_config_stats_hooks()
1049
# Do not use i18n for tests (unless the test reverses this)
1055
# The sys preserved stdin/stdout should allow blackbox tests debugging
1056
pdb.Pdb(stdin=sys.__stdin__, stdout=sys.__stdout__
1057
).set_trace(sys._getframe().f_back)
1059
def discardDetail(self, name):
1060
"""Extend the addDetail, getDetails api so we can remove a detail.
1062
eg. bzr always adds the 'log' detail at startup, but we don't want to
1063
include it for skipped, xfail, etc tests.
1065
It is safe to call this for a detail that doesn't exist, in case this
1066
gets called multiple times.
1068
# We cheat. details is stored in __details which means we shouldn't
1069
# touch it. but getDetails() returns the dict directly, so we can
1071
details = self.getDetails()
1075
def install_counter_hook(self, hooks, name, counter_name=None):
1076
"""Install a counting hook.
1078
Any hook can be counted as long as it doesn't need to return a value.
1080
:param hooks: Where the hook should be installed.
1082
:param name: The hook name that will be counted.
1084
:param counter_name: The counter identifier in ``_counters``, defaults
1087
_counters = self._counters # Avoid closing over self
1088
if counter_name is None:
1090
if _counters.has_key(counter_name):
1091
raise AssertionError('%s is already used as a counter name'
1093
_counters[counter_name] = 0
1094
self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1095
lambda: ['%d' % (_counters[counter_name],)]))
1096
def increment_counter(*args, **kwargs):
1097
_counters[counter_name] += 1
1098
label = 'count %s calls' % (counter_name,)
1099
hooks.install_named_hook(name, increment_counter, label)
1100
self.addCleanup(hooks.uninstall_named_hook, name, label)
1102
def _install_config_stats_hooks(self):
1103
"""Install config hooks to count hook calls.
1106
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1107
self.install_counter_hook(config.ConfigHooks, hook_name,
1108
'config.%s' % (hook_name,))
1110
# The OldConfigHooks are private and need special handling to protect
1111
# against recursive tests (tests that run other tests), so we just do
1112
# manually what registering them into _builtin_known_hooks will provide
1114
self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1115
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1116
self.install_counter_hook(config.OldConfigHooks, hook_name,
1117
'old_config.%s' % (hook_name,))
790
1119
def _clear_debug_flags(self):
791
1120
"""Prevent externally set debug flags affecting tests.
793
1122
Tests that want to use debug flags can just set them in the
794
1123
debug_flags set during setup/teardown.
1125
# Start with a copy of the current debug flags we can safely modify.
1126
self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
796
1127
if 'allow_debug' not in selftest_debug_flags:
797
self._preserved_debug_flags = set(debug.debug_flags)
798
1128
debug.debug_flags.clear()
799
self.addCleanup(self._restore_debug_flags)
1129
if 'disable_lock_checks' not in selftest_debug_flags:
1130
debug.debug_flags.add('strict_locks')
801
1132
def _clear_hooks(self):
802
1133
# prevent hooks affecting tests
804
import bzrlib.smart.server
805
self._preserved_hooks = {
806
bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
807
bzrlib.mutabletree.MutableTree: bzrlib.mutabletree.MutableTree.hooks,
808
bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
1134
known_hooks = hooks.known_hooks
1135
self._preserved_hooks = {}
1136
for key, (parent, name) in known_hooks.iter_parent_objects():
1137
current_hooks = getattr(parent, name)
1138
self._preserved_hooks[parent] = (name, current_hooks)
1139
self._preserved_lazy_hooks = hooks._lazy_hooks
1140
hooks._lazy_hooks = {}
810
1141
self.addCleanup(self._restoreHooks)
811
# reset all hooks to an empty instance of the appropriate type
812
bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
813
bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
1142
for key, (parent, name) in known_hooks.iter_parent_objects():
1143
factory = known_hooks.get(key)
1144
setattr(parent, name, factory())
1145
# this hook should always be installed
1146
request._install_hook()
1148
def disable_directory_isolation(self):
1149
"""Turn off directory isolation checks."""
1150
self._directory_isolation = False
1152
def enable_directory_isolation(self):
1153
"""Enable directory isolation checks."""
1154
self._directory_isolation = True
815
1156
def _silenceUI(self):
816
1157
"""Turn off UI for duration of test"""
817
1158
# by default the UI is off; tests can turn it on if they want it.
818
saved = ui.ui_factory
820
ui.ui_factory = saved
821
ui.ui_factory = ui.SilentUIFactory()
822
self.addCleanup(_restore)
1159
self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
1161
def _check_locks(self):
1162
"""Check that all lock take/release actions have been paired."""
1163
# We always check for mismatched locks. If a mismatch is found, we
1164
# fail unless -Edisable_lock_checks is supplied to selftest, in which
1165
# case we just print a warning.
1167
acquired_locks = [lock for action, lock in self._lock_actions
1168
if action == 'acquired']
1169
released_locks = [lock for action, lock in self._lock_actions
1170
if action == 'released']
1171
broken_locks = [lock for action, lock in self._lock_actions
1172
if action == 'broken']
1173
# trivially, given the tests for lock acquistion and release, if we
1174
# have as many in each list, it should be ok. Some lock tests also
1175
# break some locks on purpose and should be taken into account by
1176
# considering that breaking a lock is just a dirty way of releasing it.
1177
if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1179
'Different number of acquired and '
1180
'released or broken locks.\n'
1184
(acquired_locks, released_locks, broken_locks))
1185
if not self._lock_check_thorough:
1186
# Rather than fail, just warn
1187
print "Broken test %s: %s" % (self, message)
1191
def _track_locks(self):
1192
"""Track lock activity during tests."""
1193
self._lock_actions = []
1194
if 'disable_lock_checks' in selftest_debug_flags:
1195
self._lock_check_thorough = False
1197
self._lock_check_thorough = True
1199
self.addCleanup(self._check_locks)
1200
_mod_lock.Lock.hooks.install_named_hook('lock_acquired',
1201
self._lock_acquired, None)
1202
_mod_lock.Lock.hooks.install_named_hook('lock_released',
1203
self._lock_released, None)
1204
_mod_lock.Lock.hooks.install_named_hook('lock_broken',
1205
self._lock_broken, None)
1207
def _lock_acquired(self, result):
1208
self._lock_actions.append(('acquired', result))
1210
def _lock_released(self, result):
1211
self._lock_actions.append(('released', result))
1213
def _lock_broken(self, result):
1214
self._lock_actions.append(('broken', result))
1216
def permit_dir(self, name):
1217
"""Permit a directory to be used by this test. See permit_url."""
1218
name_transport = _mod_transport.get_transport_from_path(name)
1219
self.permit_url(name)
1220
self.permit_url(name_transport.base)
1222
def permit_url(self, url):
1223
"""Declare that url is an ok url to use in this test.
1225
Do this for memory transports, temporary test directory etc.
1227
Do not do this for the current working directory, /tmp, or any other
1228
preexisting non isolated url.
1230
if not url.endswith('/'):
1232
self._bzr_selftest_roots.append(url)
1234
def permit_source_tree_branch_repo(self):
1235
"""Permit the source tree bzr is running from to be opened.
1237
Some code such as bzrlib.version attempts to read from the bzr branch
1238
that bzr is executing from (if any). This method permits that directory
1239
to be used in the test suite.
1241
path = self.get_source_path()
1242
self.record_directory_isolation()
1245
workingtree.WorkingTree.open(path)
1246
except (errors.NotBranchError, errors.NoWorkingTree):
1247
raise TestSkipped('Needs a working tree of bzr sources')
1249
self.enable_directory_isolation()
1251
def _preopen_isolate_transport(self, transport):
1252
"""Check that all transport openings are done in the test work area."""
1253
while isinstance(transport, pathfilter.PathFilteringTransport):
1254
# Unwrap pathfiltered transports
1255
transport = transport.server.backing_transport.clone(
1256
transport._filter('.'))
1257
url = transport.base
1258
# ReadonlySmartTCPServer_for_testing decorates the backing transport
1259
# urls it is given by prepending readonly+. This is appropriate as the
1260
# client shouldn't know that the server is readonly (or not readonly).
1261
# We could register all servers twice, with readonly+ prepending, but
1262
# that makes for a long list; this is about the same but easier to
1264
if url.startswith('readonly+'):
1265
url = url[len('readonly+'):]
1266
self._preopen_isolate_url(url)
1268
def _preopen_isolate_url(self, url):
1269
if not self._directory_isolation:
1271
if self._directory_isolation == 'record':
1272
self._bzr_selftest_roots.append(url)
1274
# This prevents all transports, including e.g. sftp ones backed on disk
1275
# from working unless they are explicitly granted permission. We then
1276
# depend on the code that sets up test transports to check that they are
1277
# appropriately isolated and enable their use by calling
1278
# self.permit_transport()
1279
if not osutils.is_inside_any(self._bzr_selftest_roots, url):
1280
raise errors.BzrError("Attempt to escape test isolation: %r %r"
1281
% (url, self._bzr_selftest_roots))
1283
def record_directory_isolation(self):
1284
"""Gather accessed directories to permit later access.
1286
This is used for tests that access the branch bzr is running from.
1288
self._directory_isolation = "record"
1290
def start_server(self, transport_server, backing_server=None):
1291
"""Start transport_server for this test.
1293
This starts the server, registers a cleanup for it and permits the
1294
server's urls to be used.
1296
if backing_server is None:
1297
transport_server.start_server()
1299
transport_server.start_server(backing_server)
1300
self.addCleanup(transport_server.stop_server)
1301
# Obtain a real transport because if the server supplies a password, it
1302
# will be hidden from the base on the client side.
1303
t = _mod_transport.get_transport_from_url(transport_server.get_url())
1304
# Some transport servers effectively chroot the backing transport;
1305
# others like SFTPServer don't - users of the transport can walk up the
1306
# transport to read the entire backing transport. This wouldn't matter
1307
# except that the workdir tests are given - and that they expect the
1308
# server's url to point at - is one directory under the safety net. So
1309
# Branch operations into the transport will attempt to walk up one
1310
# directory. Chrooting all servers would avoid this but also mean that
1311
# we wouldn't be testing directly against non-root urls. Alternatively
1312
# getting the test framework to start the server with a backing server
1313
# at the actual safety net directory would work too, but this then
1314
# means that the self.get_url/self.get_transport methods would need
1315
# to transform all their results. On balance its cleaner to handle it
1316
# here, and permit a higher url when we have one of these transports.
1317
if t.base.endswith('/work/'):
1318
# we have safety net/test root/work
1319
t = t.clone('../..')
1320
elif isinstance(transport_server,
1321
test_server.SmartTCPServer_for_testing):
1322
# The smart server adds a path similar to work, which is traversed
1323
# up from by the client. But the server is chrooted - the actual
1324
# backing transport is not escaped from, and VFS requests to the
1325
# root will error (because they try to escape the chroot).
1327
while t2.base != t.base:
1330
self.permit_url(t.base)
1332
def _track_transports(self):
1333
"""Install checks for transport usage."""
1334
# TestCase has no safe place it can write to.
1335
self._bzr_selftest_roots = []
1336
# Currently the easiest way to be sure that nothing is going on is to
1337
# hook into bzr dir opening. This leaves a small window of error for
1338
# transport tests, but they are well known, and we can improve on this
1340
controldir.ControlDir.hooks.install_named_hook("pre_open",
1341
self._preopen_isolate_transport, "Check bzr directories are safe.")
824
1343
def _ndiff_strings(self, a, b):
825
1344
"""Return ndiff between two strings containing lines.
827
1346
A trailing newline is added if missing to make the strings
828
1347
print properly."""
829
1348
if b and b[-1] != '\n':
864
1383
if message is None:
865
1384
message = "texts not equal:\n"
1386
message = 'first string is missing a final newline.\n'
866
1387
if a == b + '\n':
867
message = 'first string is missing a final newline.\n'
869
1388
message = 'second string is missing a final newline.\n'
870
1389
raise AssertionError(message +
871
1390
self._ndiff_strings(a, b))
873
1392
def assertEqualMode(self, mode, mode_test):
874
1393
self.assertEqual(mode, mode_test,
875
1394
'mode mismatch %o != %o' % (mode, mode_test))
1396
def assertEqualStat(self, expected, actual):
1397
"""assert that expected and actual are the same stat result.
1399
:param expected: A stat result.
1400
:param actual: A stat result.
1401
:raises AssertionError: If the expected and actual stat values differ
1402
other than by atime.
1404
self.assertEqual(expected.st_size, actual.st_size,
1405
'st_size did not match')
1406
self.assertEqual(expected.st_mtime, actual.st_mtime,
1407
'st_mtime did not match')
1408
self.assertEqual(expected.st_ctime, actual.st_ctime,
1409
'st_ctime did not match')
1410
if sys.platform == 'win32':
1411
# On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
1412
# is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
1413
# odd. We just force it to always be 0 to avoid any problems.
1414
self.assertEqual(0, expected.st_dev)
1415
self.assertEqual(0, actual.st_dev)
1416
self.assertEqual(0, expected.st_ino)
1417
self.assertEqual(0, actual.st_ino)
1419
self.assertEqual(expected.st_dev, actual.st_dev,
1420
'st_dev did not match')
1421
self.assertEqual(expected.st_ino, actual.st_ino,
1422
'st_ino did not match')
1423
self.assertEqual(expected.st_mode, actual.st_mode,
1424
'st_mode did not match')
1426
def assertLength(self, length, obj_with_len):
1427
"""Assert that obj_with_len is of length length."""
1428
if len(obj_with_len) != length:
1429
self.fail("Incorrect length: wanted %d, got %d for %r" % (
1430
length, len(obj_with_len), obj_with_len))
1432
def assertLogsError(self, exception_class, func, *args, **kwargs):
1433
"""Assert that `func(*args, **kwargs)` quietly logs a specific error.
1436
orig_log_exception_quietly = trace.log_exception_quietly
1439
orig_log_exception_quietly()
1440
captured.append(sys.exc_info()[1])
1441
trace.log_exception_quietly = capture
1442
func(*args, **kwargs)
1444
trace.log_exception_quietly = orig_log_exception_quietly
1445
self.assertLength(1, captured)
1447
self.assertIsInstance(err, exception_class)
877
1450
def assertPositive(self, val):
878
1451
"""Assert that val is greater than 0."""
879
1452
self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
1171
1743
def _startLogFile(self):
1172
"""Send bzr and test log messages to a temporary file.
1174
The file is removed as the test is torn down.
1176
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1177
self._log_file = os.fdopen(fileno, 'w+')
1178
self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1179
self._log_file_name = name
1744
"""Setup a in-memory target for bzr and testcase log messages"""
1745
pseudo_log_file = StringIO()
1746
def _get_log_contents_for_weird_testtools_api():
1747
return [pseudo_log_file.getvalue().decode(
1748
"utf-8", "replace").encode("utf-8")]
1749
self.addDetail("log", content.Content(content.ContentType("text",
1750
"plain", {"charset": "utf8"}),
1751
_get_log_contents_for_weird_testtools_api))
1752
self._log_file = pseudo_log_file
1753
self._log_memento = trace.push_log_file(self._log_file)
1180
1754
self.addCleanup(self._finishLogFile)
1182
1756
def _finishLogFile(self):
1183
"""Finished with the log file.
1185
Close the file and delete it, unless setKeepLogfile was called.
1187
if self._log_file is None:
1189
bzrlib.trace.pop_log_file(self._log_memento)
1190
self._log_file.close()
1191
self._log_file = None
1192
if not self._keep_log_file:
1193
os.remove(self._log_file_name)
1194
self._log_file_name = None
1196
def setKeepLogfile(self):
1197
"""Make the logfile not be deleted when _finishLogFile is called."""
1198
self._keep_log_file = True
1200
def addCleanup(self, callable, *args, **kwargs):
1201
"""Arrange to run a callable when this case is torn down.
1203
Callables are run in the reverse of the order they are registered,
1204
ie last-in first-out.
1206
self._cleanups.append((callable, args, kwargs))
1757
"""Flush and dereference the in-memory log for this testcase"""
1758
if trace._trace_file:
1759
# flush the log file, to get all content
1760
trace._trace_file.flush()
1761
trace.pop_log_file(self._log_memento)
1762
# The logging module now tracks references for cleanup so discard ours
1763
del self._log_memento
1765
def thisFailsStrictLockCheck(self):
1766
"""It is known that this test would fail with -Dstrict_locks.
1768
By default, all tests are run with strict lock checking unless
1769
-Edisable_lock_checks is supplied. However there are some tests which
1770
we know fail strict locks at this point that have not been fixed.
1771
They should call this function to disable the strict checking.
1773
This should be used sparingly, it is much better to fix the locking
1774
issues rather than papering over the problem by calling this function.
1776
debug.debug_flags.discard('strict_locks')
1778
def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1779
"""Overrides an object attribute restoring it after the test.
1781
:note: This should be used with discretion; you should think about
1782
whether it's better to make the code testable without monkey-patching.
1784
:param obj: The object that will be mutated.
1786
:param attr_name: The attribute name we want to preserve/override in
1789
:param new: The optional value we want to set the attribute to.
1791
:returns: The actual attr value.
1793
# The actual value is captured by the call below
1794
value = getattr(obj, attr_name, _unitialized_attr)
1795
if value is _unitialized_attr:
1796
# When the test completes, the attribute should not exist, but if
1797
# we aren't setting a value, we don't need to do anything.
1798
if new is not _unitialized_attr:
1799
self.addCleanup(delattr, obj, attr_name)
1801
self.addCleanup(setattr, obj, attr_name, value)
1802
if new is not _unitialized_attr:
1803
setattr(obj, attr_name, new)
1806
def overrideEnv(self, name, new):
1807
"""Set an environment variable, and reset it after the test.
1809
:param name: The environment variable name.
1811
:param new: The value to set the variable to. If None, the
1812
variable is deleted from the environment.
1814
:returns: The actual variable value.
1816
value = osutils.set_or_unset_env(name, new)
1817
self.addCleanup(osutils.set_or_unset_env, name, value)
1820
def recordCalls(self, obj, attr_name):
1821
"""Monkeypatch in a wrapper that will record calls.
1823
The monkeypatch is automatically removed when the test concludes.
1825
:param obj: The namespace holding the reference to be replaced;
1826
typically a module, class, or object.
1827
:param attr_name: A string for the name of the attribute to
1829
:returns: A list that will be extended with one item every time the
1830
function is called, with a tuple of (args, kwargs).
1834
def decorator(*args, **kwargs):
1835
calls.append((args, kwargs))
1836
return orig(*args, **kwargs)
1837
orig = self.overrideAttr(obj, attr_name, decorator)
1208
1840
def _cleanEnvironment(self):
1210
'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1211
'HOME': os.getcwd(),
1212
'APPDATA': None, # bzr now use Win32 API and don't rely on APPDATA
1213
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
1215
'BZREMAIL': None, # may still be present in the environment
1217
'BZR_PROGRESS_BAR': None,
1220
'SSH_AUTH_SOCK': None,
1224
'https_proxy': None,
1225
'HTTPS_PROXY': None,
1230
# Nobody cares about these ones AFAIK. So far at
1231
# least. If you do (care), please update this comment
1235
'BZR_REMOTE_PATH': None,
1238
self.addCleanup(self._restoreEnvironment)
1239
for name, value in new_env.iteritems():
1240
self._captureVar(name, value)
1242
def _captureVar(self, name, newvalue):
1243
"""Set an environment variable, and reset it when finished."""
1244
self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1246
def _restore_debug_flags(self):
1247
debug.debug_flags.clear()
1248
debug.debug_flags.update(self._preserved_debug_flags)
1250
def _restoreEnvironment(self):
1251
for name, value in self.__old_env.iteritems():
1252
osutils.set_or_unset_env(name, value)
1841
for name, value in isolated_environ.iteritems():
1842
self.overrideEnv(name, value)
1254
1844
def _restoreHooks(self):
1255
for klass, hooks in self._preserved_hooks.items():
1256
setattr(klass, 'hooks', hooks)
1845
for klass, (name, hooks) in self._preserved_hooks.items():
1846
setattr(klass, name, hooks)
1847
self._preserved_hooks.clear()
1848
bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1849
self._preserved_lazy_hooks.clear()
1258
1851
def knownFailure(self, reason):
1259
"""This test has failed for some known reason."""
1260
raise KnownFailure(reason)
1262
def run(self, result=None):
1263
if result is None: result = self.defaultTestResult()
1264
for feature in getattr(self, '_test_needs_features', []):
1265
if not feature.available():
1266
result.startTest(self)
1267
if getattr(result, 'addNotSupported', None):
1268
result.addNotSupported(self, feature)
1270
result.addSuccess(self)
1271
result.stopTest(self)
1852
"""Declare that this test fails for a known reason
1854
Tests that are known to fail should generally be using expectedFailure
1855
with an appropriate reverse assertion if a change could cause the test
1856
to start passing. Conversely if the test has no immediate prospect of
1857
succeeding then using skip is more suitable.
1859
When this method is called while an exception is being handled, that
1860
traceback will be used, otherwise a new exception will be thrown to
1861
provide one but won't be reported.
1863
self._add_reason(reason)
1274
return unittest.TestCase.run(self, result)
1865
exc_info = sys.exc_info()
1866
if exc_info != (None, None, None):
1867
self._report_traceback(exc_info)
1870
raise self.failureException(reason)
1871
except self.failureException:
1872
exc_info = sys.exc_info()
1873
# GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
1874
raise testtools.testcase._ExpectedFailure(exc_info)
1277
absent_attr = object()
1278
for attr_name in self.attrs_to_keep:
1279
attr = getattr(self, attr_name, absent_attr)
1280
if attr is not absent_attr:
1281
saved_attrs[attr_name] = attr
1282
self.__dict__ = saved_attrs
1286
unittest.TestCase.tearDown(self)
1878
def _suppress_log(self):
1879
"""Remove the log info from details."""
1880
self.discardDetail('log')
1882
def _do_skip(self, result, reason):
1883
self._suppress_log()
1884
addSkip = getattr(result, 'addSkip', None)
1885
if not callable(addSkip):
1886
result.addSuccess(result)
1888
addSkip(self, reason)
1891
def _do_known_failure(self, result, e):
1892
self._suppress_log()
1893
err = sys.exc_info()
1894
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1895
if addExpectedFailure is not None:
1896
addExpectedFailure(self, err)
1898
result.addSuccess(self)
1901
def _do_not_applicable(self, result, e):
1903
reason = 'No reason given'
1906
self._suppress_log ()
1907
addNotApplicable = getattr(result, 'addNotApplicable', None)
1908
if addNotApplicable is not None:
1909
result.addNotApplicable(self, reason)
1911
self._do_skip(result, reason)
1914
def _report_skip(self, result, err):
1915
"""Override the default _report_skip.
1917
We want to strip the 'log' detail. If we waint until _do_skip, it has
1918
already been formatted into the 'reason' string, and we can't pull it
1921
self._suppress_log()
1922
super(TestCase, self)._report_skip(self, result, err)
1925
def _report_expected_failure(self, result, err):
1928
See _report_skip for motivation.
1930
self._suppress_log()
1931
super(TestCase, self)._report_expected_failure(self, result, err)
1934
def _do_unsupported_or_skip(self, result, e):
1936
self._suppress_log()
1937
addNotSupported = getattr(result, 'addNotSupported', None)
1938
if addNotSupported is not None:
1939
result.addNotSupported(self, reason)
1941
self._do_skip(result, reason)
1288
1943
def time(self, callable, *args, **kwargs):
1289
1944
"""Run callable and accrue the time it takes to the benchmark time.
1291
1946
If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1292
1947
this will cause lsprofile statistics to be gathered and stored in
1293
1948
self._benchcalls.
1295
1950
if self._benchtime is None:
1951
self.addDetail('benchtime', content.Content(content.ContentType(
1952
"text", "plain"), lambda:[str(self._benchtime)]))
1296
1953
self._benchtime = 0
1297
1954
start = time.time()
1944
2688
# specifically told when all tests are finished. This will do.
1945
2689
atexit.register(_rmtree_temp_dir, root)
2691
self.permit_dir(TestCaseWithMemoryTransport.TEST_ROOT)
1947
2692
self.addCleanup(self._check_safety_net)
1949
2694
def makeAndChdirToTestDir(self):
1950
2695
"""Create a temporary directories for this one test.
1952
2697
This must set self.test_home_dir and self.test_dir and chdir to
1955
2700
For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1957
2702
os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1958
2703
self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1959
2704
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1961
def make_branch(self, relpath, format=None):
2705
self.permit_dir(self.test_dir)
2707
def make_branch(self, relpath, format=None, name=None):
1962
2708
"""Create a branch on the transport at relpath."""
1963
2709
repo = self.make_repository(relpath, format=format)
1964
return repo.bzrdir.create_branch()
2710
return repo.bzrdir.create_branch(append_revisions_only=False,
2713
def get_default_format(self):
2716
def resolve_format(self, format):
2717
"""Resolve an object to a ControlDir format object.
2719
The initial format object can either already be
2720
a ControlDirFormat, None (for the default format),
2721
or a string with the name of the control dir format.
2723
:param format: Object to resolve
2724
:return A ControlDirFormat instance
2727
format = self.get_default_format()
2728
if isinstance(format, basestring):
2729
format = controldir.format_registry.make_bzrdir(format)
1966
2732
def make_bzrdir(self, relpath, format=None):
1968
2734
# might be a relative or absolute path
1969
2735
maybe_a_url = self.get_url(relpath)
1970
2736
segments = maybe_a_url.rsplit('/', 1)
1971
t = get_transport(maybe_a_url)
2737
t = _mod_transport.get_transport(maybe_a_url)
1972
2738
if len(segments) > 1 and segments[-1] not in ('', '.'):
1973
2739
t.ensure_base()
1976
if isinstance(format, basestring):
1977
format = bzrdir.format_registry.make_bzrdir(format)
2740
format = self.resolve_format(format)
1978
2741
return format.initialize_on_transport(t)
1979
2742
except errors.UninitializableFormat:
1980
2743
raise TestSkipped("Format %s is not initializable." % format)
1982
def make_repository(self, relpath, shared=False, format=None):
2745
def make_repository(self, relpath, shared=None, format=None):
1983
2746
"""Create a repository on our default transport at relpath.
1985
2748
Note that relpath must be a relative path, not a full url.
1987
2750
# FIXME: If you create a remoterepository this returns the underlying
1988
# real format, which is incorrect. Actually we should make sure that
2751
# real format, which is incorrect. Actually we should make sure that
1989
2752
# RemoteBzrDir returns a RemoteRepository.
1990
2753
# maybe mbp 20070410
1991
2754
made_control = self.make_bzrdir(relpath, format=format)
1992
2755
return made_control.create_repository(shared=shared)
2757
def make_smart_server(self, path, backing_server=None):
2758
if backing_server is None:
2759
backing_server = self.get_server()
2760
smart_server = test_server.SmartTCPServer_for_testing()
2761
self.start_server(smart_server, backing_server)
2762
remote_transport = _mod_transport.get_transport_from_url(smart_server.get_url()
2764
return remote_transport
1994
2766
def make_branch_and_memory_tree(self, relpath, format=None):
1995
2767
"""Create a branch on the default transport and a MemoryTree for it."""
1996
2768
b = self.make_branch(relpath, format=format)
1997
2769
return memorytree.MemoryTree.create_on_branch(b)
1999
2771
def make_branch_builder(self, relpath, format=None):
2000
url = self.get_url(relpath)
2001
tran = get_transport(url)
2002
return branchbuilder.BranchBuilder(get_transport(url), format=format)
2772
branch = self.make_branch(relpath, format=format)
2773
return branchbuilder.BranchBuilder(branch=branch)
2004
2775
def overrideEnvironmentForTesting(self):
2005
os.environ['HOME'] = self.test_home_dir
2006
os.environ['BZR_HOME'] = self.test_home_dir
2009
super(TestCaseWithMemoryTransport, self).setUp()
2010
self._make_test_root()
2011
_currentdir = os.getcwdu()
2012
def _leaveDirectory():
2013
os.chdir(_currentdir)
2014
self.addCleanup(_leaveDirectory)
2015
self.makeAndChdirToTestDir()
2016
self.overrideEnvironmentForTesting()
2017
self.__readonly_server = None
2018
self.__server = None
2019
self.reduceLockdirTimeout()
2776
test_home_dir = self.test_home_dir
2777
if isinstance(test_home_dir, unicode):
2778
test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2779
self.overrideEnv('HOME', test_home_dir)
2780
self.overrideEnv('BZR_HOME', test_home_dir)
2782
def setup_smart_server_with_call_log(self):
2783
"""Sets up a smart server as the transport server with a call log."""
2784
self.transport_server = test_server.SmartTCPServer_for_testing
2785
self.hpss_connections = []
2786
self.hpss_calls = []
2788
# Skip the current stack down to the caller of
2789
# setup_smart_server_with_call_log
2790
prefix_length = len(traceback.extract_stack()) - 2
2791
def capture_hpss_call(params):
2792
self.hpss_calls.append(
2793
CapturedCall(params, prefix_length))
2794
def capture_connect(transport):
2795
self.hpss_connections.append(transport)
2796
client._SmartClient.hooks.install_named_hook(
2797
'call', capture_hpss_call, None)
2798
_mod_transport.Transport.hooks.install_named_hook(
2799
'post_connect', capture_connect, None)
2801
def reset_smart_call_log(self):
2802
self.hpss_calls = []
2803
self.hpss_connections = []
2022
2806
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2023
2807
"""Derived class that runs a test within a temporary directory.
2464
3287
list_only=False,
2465
3288
random_seed=None,
2466
3289
exclude_pattern=None,
3292
suite_decorators=None,
3294
result_decorators=None,
3296
"""Run a test suite for bzr selftest.
3298
:param runner_class: The class of runner to use. Must support the
3299
constructor arguments passed by run_suite which are more than standard
3301
:return: A boolean indicating success.
2468
3303
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2473
runner = TextTestRunner(stream=sys.stdout,
3308
if runner_class is None:
3309
runner_class = TextTestRunner
3312
runner = runner_class(stream=stream,
2474
3313
descriptions=0,
2475
3314
verbosity=verbosity,
2476
3315
bench_history=bench_history,
2477
list_only=list_only,
3317
result_decorators=result_decorators,
2479
3319
runner.stop_on_failure=stop_on_failure
2480
# Initialise the random number generator and display the seed used.
2481
# We convert the seed to a long to make it reuseable across invocations.
2482
random_order = False
2483
if random_seed is not None:
2485
if random_seed == "now":
2486
random_seed = long(time.time())
2488
# Convert the seed to a long if we can
2490
random_seed = long(random_seed)
2493
runner.stream.writeln("Randomizing test order using seed %s\n" %
2495
random.seed(random_seed)
2496
# Customise the list of tests if requested
2497
if exclude_pattern is not None:
2498
suite = exclude_tests_by_re(suite, exclude_pattern)
2500
order_changer = randomize_suite
3320
if isinstance(suite, unittest.TestSuite):
3321
# Empty out _tests list of passed suite and populate new TestSuite
3322
suite._tests[:], suite = [], TestSuite(suite)
3323
# built in decorator factories:
3325
random_order(random_seed, runner),
3326
exclude_tests(exclude_pattern),
3328
if matching_tests_first:
3329
decorators.append(tests_first(pattern))
2502
order_changer = preserve_input
2503
if pattern != '.*' or random_order:
2504
if matching_tests_first:
2505
suites = map(order_changer, split_suite_by_re(suite, pattern))
2506
suite = TestUtil.TestSuite(suites)
2508
suite = order_changer(filter_suite_by_re(suite, pattern))
3331
decorators.append(filter_tests(pattern))
3332
if suite_decorators:
3333
decorators.extend(suite_decorators)
3334
# tell the result object how many tests will be running: (except if
3335
# --parallel=fork is being used. Robert said he will provide a better
3336
# progress design later -- vila 20090817)
3337
if fork_decorator not in decorators:
3338
decorators.append(CountingDecorator)
3339
for decorator in decorators:
3340
suite = decorator(suite)
3342
# Done after test suite decoration to allow randomisation etc
3343
# to take effect, though that is of marginal benefit.
3345
stream.write("Listing tests only ...\n")
3346
for t in iter_suite_tests(suite):
3347
stream.write("%s\n" % (t.id()))
2510
3349
result = runner.run(suite)
2513
3351
return result.wasStrictlySuccessful()
2515
return result.wasSuccessful()
3353
return result.wasSuccessful()
3356
# A registry where get() returns a suite decorator.
3357
parallel_registry = registry.Registry()
3360
def fork_decorator(suite):
3361
if getattr(os, "fork", None) is None:
3362
raise errors.BzrCommandError("platform does not support fork,"
3363
" try --parallel=subprocess instead.")
3364
concurrency = osutils.local_concurrency()
3365
if concurrency == 1:
3367
from testtools import ConcurrentTestSuite
3368
return ConcurrentTestSuite(suite, fork_for_tests)
3369
parallel_registry.register('fork', fork_decorator)
3372
def subprocess_decorator(suite):
3373
concurrency = osutils.local_concurrency()
3374
if concurrency == 1:
3376
from testtools import ConcurrentTestSuite
3377
return ConcurrentTestSuite(suite, reinvoke_for_tests)
3378
parallel_registry.register('subprocess', subprocess_decorator)
3381
def exclude_tests(exclude_pattern):
3382
"""Return a test suite decorator that excludes tests."""
3383
if exclude_pattern is None:
3384
return identity_decorator
3385
def decorator(suite):
3386
return ExcludeDecorator(suite, exclude_pattern)
3390
def filter_tests(pattern):
3392
return identity_decorator
3393
def decorator(suite):
3394
return FilterTestsDecorator(suite, pattern)
3398
def random_order(random_seed, runner):
3399
"""Return a test suite decorator factory for randomising tests order.
3401
:param random_seed: now, a string which casts to a long, or a long.
3402
:param runner: A test runner with a stream attribute to report on.
3404
if random_seed is None:
3405
return identity_decorator
3406
def decorator(suite):
3407
return RandomDecorator(suite, random_seed, runner.stream)
3411
def tests_first(pattern):
3413
return identity_decorator
3414
def decorator(suite):
3415
return TestFirstDecorator(suite, pattern)
3419
def identity_decorator(suite):
3424
class TestDecorator(TestUtil.TestSuite):
3425
"""A decorator for TestCase/TestSuite objects.
3427
Contains rather than flattening suite passed on construction
3430
def __init__(self, suite=None):
3431
super(TestDecorator, self).__init__()
3432
if suite is not None:
3435
# Don't need subclass run method with suite emptying
3436
run = unittest.TestSuite.run
3439
class CountingDecorator(TestDecorator):
3440
"""A decorator which calls result.progress(self.countTestCases)."""
3442
def run(self, result):
3443
progress_method = getattr(result, 'progress', None)
3444
if callable(progress_method):
3445
progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
3446
return super(CountingDecorator, self).run(result)
3449
class ExcludeDecorator(TestDecorator):
3450
"""A decorator which excludes test matching an exclude pattern."""
3452
def __init__(self, suite, exclude_pattern):
3453
super(ExcludeDecorator, self).__init__(
3454
exclude_tests_by_re(suite, exclude_pattern))
3457
class FilterTestsDecorator(TestDecorator):
3458
"""A decorator which filters tests to those matching a pattern."""
3460
def __init__(self, suite, pattern):
3461
super(FilterTestsDecorator, self).__init__(
3462
filter_suite_by_re(suite, pattern))
3465
class RandomDecorator(TestDecorator):
3466
"""A decorator which randomises the order of its tests."""
3468
def __init__(self, suite, random_seed, stream):
3469
random_seed = self.actual_seed(random_seed)
3470
stream.write("Randomizing test order using seed %s\n\n" %
3472
# Initialise the random number generator.
3473
random.seed(random_seed)
3474
super(RandomDecorator, self).__init__(randomize_suite(suite))
3477
def actual_seed(seed):
3479
# We convert the seed to a long to make it reuseable across
3480
# invocations (because the user can reenter it).
3481
return long(time.time())
3483
# Convert the seed to a long if we can
3486
except (TypeError, ValueError):
3491
class TestFirstDecorator(TestDecorator):
3492
"""A decorator which moves named tests to the front."""
3494
def __init__(self, suite, pattern):
3495
super(TestFirstDecorator, self).__init__()
3496
self.addTests(split_suite_by_re(suite, pattern))
3499
def partition_tests(suite, count):
3500
"""Partition suite into count lists of tests."""
3501
# This just assigns tests in a round-robin fashion. On one hand this
3502
# splits up blocks of related tests that might run faster if they shared
3503
# resources, but on the other it avoids assigning blocks of slow tests to
3504
# just one partition. So the slowest partition shouldn't be much slower
3506
partitions = [list() for i in range(count)]
3507
tests = iter_suite_tests(suite)
3508
for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3509
partition.append(test)
3513
def workaround_zealous_crypto_random():
3514
"""Crypto.Random want to help us being secure, but we don't care here.
3516
This workaround some test failure related to the sftp server. Once paramiko
3517
stop using the controversial API in Crypto.Random, we may get rid of it.
3520
from Crypto.Random import atfork
3526
def fork_for_tests(suite):
3527
"""Take suite and start up one runner per CPU by forking()
3529
:return: An iterable of TestCase-like objects which can each have
3530
run(result) called on them to feed tests to result.
3532
concurrency = osutils.local_concurrency()
3534
from subunit import ProtocolTestCase
3535
from subunit.test_results import AutoTimingTestResultDecorator
3536
class TestInOtherProcess(ProtocolTestCase):
3537
# Should be in subunit, I think. RBC.
3538
def __init__(self, stream, pid):
3539
ProtocolTestCase.__init__(self, stream)
3542
def run(self, result):
3544
ProtocolTestCase.run(self, result)
3546
pid, status = os.waitpid(self.pid, 0)
3547
# GZ 2011-10-18: If status is nonzero, should report to the result
3548
# that something went wrong.
3550
test_blocks = partition_tests(suite, concurrency)
3551
# Clear the tests from the original suite so it doesn't keep them alive
3552
suite._tests[:] = []
3553
for process_tests in test_blocks:
3554
process_suite = TestUtil.TestSuite(process_tests)
3555
# Also clear each split list so new suite has only reference
3556
process_tests[:] = []
3557
c2pread, c2pwrite = os.pipe()
3561
stream = os.fdopen(c2pwrite, 'wb', 1)
3562
workaround_zealous_crypto_random()
3564
# Leave stderr and stdout open so we can see test noise
3565
# Close stdin so that the child goes away if it decides to
3566
# read from stdin (otherwise its a roulette to see what
3567
# child actually gets keystrokes for pdb etc).
3569
subunit_result = AutoTimingTestResultDecorator(
3570
SubUnitBzrProtocolClient(stream))
3571
process_suite.run(subunit_result)
3573
# Try and report traceback on stream, but exit with error even
3574
# if stream couldn't be created or something else goes wrong.
3575
# The traceback is formatted to a string and written in one go
3576
# to avoid interleaving lines from multiple failing children.
3578
stream.write(traceback.format_exc())
3584
stream = os.fdopen(c2pread, 'rb', 1)
3585
test = TestInOtherProcess(stream, pid)
3590
def reinvoke_for_tests(suite):
3591
"""Take suite and start up one runner per CPU using subprocess().
3593
:return: An iterable of TestCase-like objects which can each have
3594
run(result) called on them to feed tests to result.
3596
concurrency = osutils.local_concurrency()
3598
from subunit import ProtocolTestCase
3599
class TestInSubprocess(ProtocolTestCase):
3600
def __init__(self, process, name):
3601
ProtocolTestCase.__init__(self, process.stdout)
3602
self.process = process
3603
self.process.stdin.close()
3606
def run(self, result):
3608
ProtocolTestCase.run(self, result)
3611
os.unlink(self.name)
3612
# print "pid %d finished" % finished_process
3613
test_blocks = partition_tests(suite, concurrency)
3614
for process_tests in test_blocks:
3615
# ugly; currently reimplement rather than reuses TestCase methods.
3616
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
3617
if not os.path.isfile(bzr_path):
3618
# We are probably installed. Assume sys.argv is the right file
3619
bzr_path = sys.argv[0]
3620
bzr_path = [bzr_path]
3621
if sys.platform == "win32":
3622
# if we're on windows, we can't execute the bzr script directly
3623
bzr_path = [sys.executable] + bzr_path
3624
fd, test_list_file_name = tempfile.mkstemp()
3625
test_list_file = os.fdopen(fd, 'wb', 1)
3626
for test in process_tests:
3627
test_list_file.write(test.id() + '\n')
3628
test_list_file.close()
3630
argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
3632
if '--no-plugins' in sys.argv:
3633
argv.append('--no-plugins')
3634
# stderr=subprocess.STDOUT would be ideal, but until we prevent
3635
# noise on stderr it can interrupt the subunit protocol.
3636
process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3637
stdout=subprocess.PIPE,
3638
stderr=subprocess.PIPE,
3640
test = TestInSubprocess(process, test_list_file_name)
3643
os.unlink(test_list_file_name)
3648
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3649
"""Generate profiling data for all activity between start and success.
3651
The profile data is appended to the test's _benchcalls attribute and can
3652
be accessed by the forwarded-to TestResult.
3654
While it might be cleaner do accumulate this in stopTest, addSuccess is
3655
where our existing output support for lsprof is, and this class aims to
3656
fit in with that: while it could be moved it's not necessary to accomplish
3657
test profiling, nor would it be dramatically cleaner.
3660
def startTest(self, test):
3661
self.profiler = bzrlib.lsprof.BzrProfiler()
3662
# Prevent deadlocks in tests that use lsprof: those tests will
3664
bzrlib.lsprof.BzrProfiler.profiler_block = 0
3665
self.profiler.start()
3666
testtools.ExtendedToOriginalDecorator.startTest(self, test)
3668
def addSuccess(self, test):
3669
stats = self.profiler.stop()
3671
calls = test._benchcalls
3672
except AttributeError:
3673
test._benchcalls = []
3674
calls = test._benchcalls
3675
calls.append(((test.id(), "", ""), stats))
3676
testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
3678
def stopTest(self, test):
3679
testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3680
self.profiler = None
2518
3683
# Controlled by "bzr selftest -E=..." option
3684
# Currently supported:
3685
# -Eallow_debug Will no longer clear debug.debug_flags() so it
3686
# preserves any flags supplied at the command line.
3687
# -Edisable_lock_checks Turns errors in mismatched locks into simple prints
3688
# rather than failing tests. And no longer raise
3689
# LockContention when fctnl locks are not being used
3690
# with proper exclusion rules.
3691
# -Ethreads Will display thread ident at creation/join time to
3692
# help track thread leaks
3693
# -Euncollected_cases Display the identity of any test cases that weren't
3694
# deallocated after being completed.
3695
# -Econfig_stats Will collect statistics using addDetail
2519
3696
selftest_debug_flags = set()
2728
3926
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3929
def _test_suite_testmod_names():
3930
"""Return the standard list of test module names to test."""
3933
'bzrlib.tests.blackbox',
3934
'bzrlib.tests.commands',
3935
'bzrlib.tests.per_branch',
3936
'bzrlib.tests.per_bzrdir',
3937
'bzrlib.tests.per_controldir',
3938
'bzrlib.tests.per_controldir_colo',
3939
'bzrlib.tests.per_foreign_vcs',
3940
'bzrlib.tests.per_interrepository',
3941
'bzrlib.tests.per_intertree',
3942
'bzrlib.tests.per_inventory',
3943
'bzrlib.tests.per_interbranch',
3944
'bzrlib.tests.per_lock',
3945
'bzrlib.tests.per_merger',
3946
'bzrlib.tests.per_transport',
3947
'bzrlib.tests.per_tree',
3948
'bzrlib.tests.per_pack_repository',
3949
'bzrlib.tests.per_repository',
3950
'bzrlib.tests.per_repository_chk',
3951
'bzrlib.tests.per_repository_reference',
3952
'bzrlib.tests.per_repository_vf',
3953
'bzrlib.tests.per_uifactory',
3954
'bzrlib.tests.per_versionedfile',
3955
'bzrlib.tests.per_workingtree',
3956
'bzrlib.tests.test__annotator',
3957
'bzrlib.tests.test__bencode',
3958
'bzrlib.tests.test__btree_serializer',
3959
'bzrlib.tests.test__chk_map',
3960
'bzrlib.tests.test__dirstate_helpers',
3961
'bzrlib.tests.test__groupcompress',
3962
'bzrlib.tests.test__known_graph',
3963
'bzrlib.tests.test__rio',
3964
'bzrlib.tests.test__simple_set',
3965
'bzrlib.tests.test__static_tuple',
3966
'bzrlib.tests.test__walkdirs_win32',
3967
'bzrlib.tests.test_ancestry',
3968
'bzrlib.tests.test_annotate',
3969
'bzrlib.tests.test_api',
3970
'bzrlib.tests.test_atomicfile',
3971
'bzrlib.tests.test_bad_files',
3972
'bzrlib.tests.test_bisect_multi',
3973
'bzrlib.tests.test_branch',
3974
'bzrlib.tests.test_branchbuilder',
3975
'bzrlib.tests.test_btree_index',
3976
'bzrlib.tests.test_bugtracker',
3977
'bzrlib.tests.test_bundle',
3978
'bzrlib.tests.test_bzrdir',
3979
'bzrlib.tests.test__chunks_to_lines',
3980
'bzrlib.tests.test_cache_utf8',
3981
'bzrlib.tests.test_chk_map',
3982
'bzrlib.tests.test_chk_serializer',
3983
'bzrlib.tests.test_chunk_writer',
3984
'bzrlib.tests.test_clean_tree',
3985
'bzrlib.tests.test_cleanup',
3986
'bzrlib.tests.test_cmdline',
3987
'bzrlib.tests.test_commands',
3988
'bzrlib.tests.test_commit',
3989
'bzrlib.tests.test_commit_merge',
3990
'bzrlib.tests.test_config',
3991
'bzrlib.tests.test_conflicts',
3992
'bzrlib.tests.test_controldir',
3993
'bzrlib.tests.test_counted_lock',
3994
'bzrlib.tests.test_crash',
3995
'bzrlib.tests.test_decorators',
3996
'bzrlib.tests.test_delta',
3997
'bzrlib.tests.test_debug',
3998
'bzrlib.tests.test_diff',
3999
'bzrlib.tests.test_directory_service',
4000
'bzrlib.tests.test_dirstate',
4001
'bzrlib.tests.test_email_message',
4002
'bzrlib.tests.test_eol_filters',
4003
'bzrlib.tests.test_errors',
4004
'bzrlib.tests.test_estimate_compressed_size',
4005
'bzrlib.tests.test_export',
4006
'bzrlib.tests.test_export_pot',
4007
'bzrlib.tests.test_extract',
4008
'bzrlib.tests.test_features',
4009
'bzrlib.tests.test_fetch',
4010
'bzrlib.tests.test_fixtures',
4011
'bzrlib.tests.test_fifo_cache',
4012
'bzrlib.tests.test_filters',
4013
'bzrlib.tests.test_filter_tree',
4014
'bzrlib.tests.test_ftp_transport',
4015
'bzrlib.tests.test_foreign',
4016
'bzrlib.tests.test_generate_docs',
4017
'bzrlib.tests.test_generate_ids',
4018
'bzrlib.tests.test_globbing',
4019
'bzrlib.tests.test_gpg',
4020
'bzrlib.tests.test_graph',
4021
'bzrlib.tests.test_groupcompress',
4022
'bzrlib.tests.test_hashcache',
4023
'bzrlib.tests.test_help',
4024
'bzrlib.tests.test_hooks',
4025
'bzrlib.tests.test_http',
4026
'bzrlib.tests.test_http_response',
4027
'bzrlib.tests.test_https_ca_bundle',
4028
'bzrlib.tests.test_https_urllib',
4029
'bzrlib.tests.test_i18n',
4030
'bzrlib.tests.test_identitymap',
4031
'bzrlib.tests.test_ignores',
4032
'bzrlib.tests.test_index',
4033
'bzrlib.tests.test_import_tariff',
4034
'bzrlib.tests.test_info',
4035
'bzrlib.tests.test_inv',
4036
'bzrlib.tests.test_inventory_delta',
4037
'bzrlib.tests.test_knit',
4038
'bzrlib.tests.test_lazy_import',
4039
'bzrlib.tests.test_lazy_regex',
4040
'bzrlib.tests.test_library_state',
4041
'bzrlib.tests.test_lock',
4042
'bzrlib.tests.test_lockable_files',
4043
'bzrlib.tests.test_lockdir',
4044
'bzrlib.tests.test_log',
4045
'bzrlib.tests.test_lru_cache',
4046
'bzrlib.tests.test_lsprof',
4047
'bzrlib.tests.test_mail_client',
4048
'bzrlib.tests.test_matchers',
4049
'bzrlib.tests.test_memorytree',
4050
'bzrlib.tests.test_merge',
4051
'bzrlib.tests.test_merge3',
4052
'bzrlib.tests.test_merge_core',
4053
'bzrlib.tests.test_merge_directive',
4054
'bzrlib.tests.test_mergetools',
4055
'bzrlib.tests.test_missing',
4056
'bzrlib.tests.test_msgeditor',
4057
'bzrlib.tests.test_multiparent',
4058
'bzrlib.tests.test_mutabletree',
4059
'bzrlib.tests.test_nonascii',
4060
'bzrlib.tests.test_options',
4061
'bzrlib.tests.test_osutils',
4062
'bzrlib.tests.test_osutils_encodings',
4063
'bzrlib.tests.test_pack',
4064
'bzrlib.tests.test_patch',
4065
'bzrlib.tests.test_patches',
4066
'bzrlib.tests.test_permissions',
4067
'bzrlib.tests.test_plugins',
4068
'bzrlib.tests.test_progress',
4069
'bzrlib.tests.test_pyutils',
4070
'bzrlib.tests.test_read_bundle',
4071
'bzrlib.tests.test_reconcile',
4072
'bzrlib.tests.test_reconfigure',
4073
'bzrlib.tests.test_registry',
4074
'bzrlib.tests.test_remote',
4075
'bzrlib.tests.test_rename_map',
4076
'bzrlib.tests.test_repository',
4077
'bzrlib.tests.test_revert',
4078
'bzrlib.tests.test_revision',
4079
'bzrlib.tests.test_revisionspec',
4080
'bzrlib.tests.test_revisiontree',
4081
'bzrlib.tests.test_rio',
4082
'bzrlib.tests.test_rules',
4083
'bzrlib.tests.test_url_policy_open',
4084
'bzrlib.tests.test_sampler',
4085
'bzrlib.tests.test_scenarios',
4086
'bzrlib.tests.test_script',
4087
'bzrlib.tests.test_selftest',
4088
'bzrlib.tests.test_serializer',
4089
'bzrlib.tests.test_setup',
4090
'bzrlib.tests.test_sftp_transport',
4091
'bzrlib.tests.test_shelf',
4092
'bzrlib.tests.test_shelf_ui',
4093
'bzrlib.tests.test_smart',
4094
'bzrlib.tests.test_smart_add',
4095
'bzrlib.tests.test_smart_request',
4096
'bzrlib.tests.test_smart_signals',
4097
'bzrlib.tests.test_smart_transport',
4098
'bzrlib.tests.test_smtp_connection',
4099
'bzrlib.tests.test_source',
4100
'bzrlib.tests.test_ssh_transport',
4101
'bzrlib.tests.test_status',
4102
'bzrlib.tests.test_store',
4103
'bzrlib.tests.test_strace',
4104
'bzrlib.tests.test_subsume',
4105
'bzrlib.tests.test_switch',
4106
'bzrlib.tests.test_symbol_versioning',
4107
'bzrlib.tests.test_tag',
4108
'bzrlib.tests.test_test_server',
4109
'bzrlib.tests.test_testament',
4110
'bzrlib.tests.test_textfile',
4111
'bzrlib.tests.test_textmerge',
4112
'bzrlib.tests.test_cethread',
4113
'bzrlib.tests.test_timestamp',
4114
'bzrlib.tests.test_trace',
4115
'bzrlib.tests.test_transactions',
4116
'bzrlib.tests.test_transform',
4117
'bzrlib.tests.test_transport',
4118
'bzrlib.tests.test_transport_log',
4119
'bzrlib.tests.test_tree',
4120
'bzrlib.tests.test_treebuilder',
4121
'bzrlib.tests.test_treeshape',
4122
'bzrlib.tests.test_tsort',
4123
'bzrlib.tests.test_tuned_gzip',
4124
'bzrlib.tests.test_ui',
4125
'bzrlib.tests.test_uncommit',
4126
'bzrlib.tests.test_upgrade',
4127
'bzrlib.tests.test_upgrade_stacked',
4128
'bzrlib.tests.test_urlutils',
4129
'bzrlib.tests.test_utextwrap',
4130
'bzrlib.tests.test_version',
4131
'bzrlib.tests.test_version_info',
4132
'bzrlib.tests.test_versionedfile',
4133
'bzrlib.tests.test_vf_search',
4134
'bzrlib.tests.test_weave',
4135
'bzrlib.tests.test_whitebox',
4136
'bzrlib.tests.test_win32utils',
4137
'bzrlib.tests.test_workingtree',
4138
'bzrlib.tests.test_workingtree_4',
4139
'bzrlib.tests.test_wsgi',
4140
'bzrlib.tests.test_xml',
4144
def _test_suite_modules_to_doctest():
4145
"""Return the list of modules to doctest."""
4147
# GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
4151
'bzrlib.branchbuilder',
4152
'bzrlib.decorators',
4154
'bzrlib.iterablefile',
4159
'bzrlib.symbol_versioning',
4161
'bzrlib.tests.fixtures',
4163
'bzrlib.transport.http',
4164
'bzrlib.version_info_formats.format_custom',
2731
4168
def test_suite(keep_only=None, starting_with=None):
2732
4169
"""Build and return TestSuite for the whole of bzrlib.
2739
4176
This function can be replaced if you need to change the default test
2740
4177
suite on a global basis, but it is not encouraged.
2744
'bzrlib.util.tests.test_bencode',
2745
'bzrlib.tests.blackbox',
2746
'bzrlib.tests.branch_implementations',
2747
'bzrlib.tests.bzrdir_implementations',
2748
'bzrlib.tests.commands',
2749
'bzrlib.tests.inventory_implementations',
2750
'bzrlib.tests.interrepository_implementations',
2751
'bzrlib.tests.intertree_implementations',
2752
'bzrlib.tests.per_lock',
2753
'bzrlib.tests.repository_implementations',
2754
'bzrlib.tests.test__dirstate_helpers',
2755
'bzrlib.tests.test_ancestry',
2756
'bzrlib.tests.test_annotate',
2757
'bzrlib.tests.test_api',
2758
'bzrlib.tests.test_atomicfile',
2759
'bzrlib.tests.test_bad_files',
2760
'bzrlib.tests.test_bisect_multi',
2761
'bzrlib.tests.test_branch',
2762
'bzrlib.tests.test_branchbuilder',
2763
'bzrlib.tests.test_btree_index',
2764
'bzrlib.tests.test_bugtracker',
2765
'bzrlib.tests.test_bundle',
2766
'bzrlib.tests.test_bzrdir',
2767
'bzrlib.tests.test_cache_utf8',
2768
'bzrlib.tests.test_chunk_writer',
2769
'bzrlib.tests.test_commands',
2770
'bzrlib.tests.test_commit',
2771
'bzrlib.tests.test_commit_merge',
2772
'bzrlib.tests.test_config',
2773
'bzrlib.tests.test_conflicts',
2774
'bzrlib.tests.test_counted_lock',
2775
'bzrlib.tests.test_decorators',
2776
'bzrlib.tests.test_delta',
2777
'bzrlib.tests.test_deprecated_graph',
2778
'bzrlib.tests.test_diff',
2779
'bzrlib.tests.test_dirstate',
2780
'bzrlib.tests.test_directory_service',
2781
'bzrlib.tests.test_email_message',
2782
'bzrlib.tests.test_errors',
2783
'bzrlib.tests.test_extract',
2784
'bzrlib.tests.test_fetch',
2785
'bzrlib.tests.test_ftp_transport',
2786
'bzrlib.tests.test_generate_docs',
2787
'bzrlib.tests.test_generate_ids',
2788
'bzrlib.tests.test_globbing',
2789
'bzrlib.tests.test_gpg',
2790
'bzrlib.tests.test_graph',
2791
'bzrlib.tests.test_hashcache',
2792
'bzrlib.tests.test_help',
2793
'bzrlib.tests.test_hooks',
2794
'bzrlib.tests.test_http',
2795
'bzrlib.tests.test_http_implementations',
2796
'bzrlib.tests.test_http_response',
2797
'bzrlib.tests.test_https_ca_bundle',
2798
'bzrlib.tests.test_identitymap',
2799
'bzrlib.tests.test_ignores',
2800
'bzrlib.tests.test_index',
2801
'bzrlib.tests.test_info',
2802
'bzrlib.tests.test_inv',
2803
'bzrlib.tests.test_knit',
2804
'bzrlib.tests.test_lazy_import',
2805
'bzrlib.tests.test_lazy_regex',
2806
'bzrlib.tests.test_lockdir',
2807
'bzrlib.tests.test_lockable_files',
2808
'bzrlib.tests.test_log',
2809
'bzrlib.tests.test_lsprof',
2810
'bzrlib.tests.test_lru_cache',
2811
'bzrlib.tests.test_mail_client',
2812
'bzrlib.tests.test_memorytree',
2813
'bzrlib.tests.test_merge',
2814
'bzrlib.tests.test_merge3',
2815
'bzrlib.tests.test_merge_core',
2816
'bzrlib.tests.test_merge_directive',
2817
'bzrlib.tests.test_missing',
2818
'bzrlib.tests.test_msgeditor',
2819
'bzrlib.tests.test_multiparent',
2820
'bzrlib.tests.test_mutabletree',
2821
'bzrlib.tests.test_nonascii',
2822
'bzrlib.tests.test_options',
2823
'bzrlib.tests.test_osutils',
2824
'bzrlib.tests.test_osutils_encodings',
2825
'bzrlib.tests.test_pack',
2826
'bzrlib.tests.test_pack_repository',
2827
'bzrlib.tests.test_patch',
2828
'bzrlib.tests.test_patches',
2829
'bzrlib.tests.test_permissions',
2830
'bzrlib.tests.test_plugins',
2831
'bzrlib.tests.test_progress',
2832
'bzrlib.tests.test_read_bundle',
2833
'bzrlib.tests.test_reconfigure',
2834
'bzrlib.tests.test_reconcile',
2835
'bzrlib.tests.test_registry',
2836
'bzrlib.tests.test_remote',
2837
'bzrlib.tests.test_repository',
2838
'bzrlib.tests.per_repository_reference',
2839
'bzrlib.tests.test_revert',
2840
'bzrlib.tests.test_revision',
2841
'bzrlib.tests.test_revisionspec',
2842
'bzrlib.tests.test_revisiontree',
2843
'bzrlib.tests.test_rio',
2844
'bzrlib.tests.test_rules',
2845
'bzrlib.tests.test_sampler',
2846
'bzrlib.tests.test_selftest',
2847
'bzrlib.tests.test_setup',
2848
'bzrlib.tests.test_sftp_transport',
2849
'bzrlib.tests.test_smart',
2850
'bzrlib.tests.test_smart_add',
2851
'bzrlib.tests.test_smart_transport',
2852
'bzrlib.tests.test_smtp_connection',
2853
'bzrlib.tests.test_source',
2854
'bzrlib.tests.test_ssh_transport',
2855
'bzrlib.tests.test_status',
2856
'bzrlib.tests.test_store',
2857
'bzrlib.tests.test_strace',
2858
'bzrlib.tests.test_subsume',
2859
'bzrlib.tests.test_switch',
2860
'bzrlib.tests.test_symbol_versioning',
2861
'bzrlib.tests.test_tag',
2862
'bzrlib.tests.test_testament',
2863
'bzrlib.tests.test_textfile',
2864
'bzrlib.tests.test_textmerge',
2865
'bzrlib.tests.test_timestamp',
2866
'bzrlib.tests.test_trace',
2867
'bzrlib.tests.test_transactions',
2868
'bzrlib.tests.test_transform',
2869
'bzrlib.tests.test_transport',
2870
'bzrlib.tests.test_transport_implementations',
2871
'bzrlib.tests.test_transport_log',
2872
'bzrlib.tests.test_tree',
2873
'bzrlib.tests.test_treebuilder',
2874
'bzrlib.tests.test_tsort',
2875
'bzrlib.tests.test_tuned_gzip',
2876
'bzrlib.tests.test_ui',
2877
'bzrlib.tests.test_uncommit',
2878
'bzrlib.tests.test_upgrade',
2879
'bzrlib.tests.test_upgrade_stacked',
2880
'bzrlib.tests.test_urlutils',
2881
'bzrlib.tests.test_versionedfile',
2882
'bzrlib.tests.test_version',
2883
'bzrlib.tests.test_version_info',
2884
'bzrlib.tests.test__walkdirs_win32',
2885
'bzrlib.tests.test_weave',
2886
'bzrlib.tests.test_whitebox',
2887
'bzrlib.tests.test_win32utils',
2888
'bzrlib.tests.test_workingtree',
2889
'bzrlib.tests.test_workingtree_4',
2890
'bzrlib.tests.test_wsgi',
2891
'bzrlib.tests.test_xml',
2892
'bzrlib.tests.tree_implementations',
2893
'bzrlib.tests.workingtree_implementations',
2896
4180
loader = TestUtil.TestLoader()
4182
if keep_only is not None:
4183
id_filter = TestIdList(keep_only)
2898
4184
if starting_with:
2899
starting_with = [test_prefix_alias_registry.resolve_alias(start)
2900
for start in starting_with]
2901
4185
# We take precedence over keep_only because *at loading time* using
2902
4186
# both options means we will load less tests for the same final result.
2903
4187
def interesting_module(name):
2993
4262
# Some tests mentioned in the list are not in the test suite. The
2994
4263
# list may be out of date, report to the tester.
2995
4264
for id in not_found:
2996
bzrlib.trace.warning('"%s" not found in the test suite', id)
4265
trace.warning('"%s" not found in the test suite', id)
2997
4266
for id in duplicates:
2998
bzrlib.trace.warning('"%s" is used as an id by several tests', id)
4267
trace.warning('"%s" is used as an id by several tests', id)
3003
def multiply_tests_from_modules(module_name_list, scenario_iter, loader=None):
3004
"""Adapt all tests in some given modules to given scenarios.
3006
This is the recommended public interface for test parameterization.
3007
Typically the test_suite() method for a per-implementation test
3008
suite will call multiply_tests_from_modules and return the
3011
:param module_name_list: List of fully-qualified names of test
3013
:param scenario_iter: Iterable of pairs of (scenario_name,
4272
def multiply_scenarios(*scenarios):
4273
"""Multiply two or more iterables of scenarios.
4275
It is safe to pass scenario generators or iterators.
4277
:returns: A list of compound scenarios: the cross-product of all
4278
scenarios, with the names concatenated and the parameters
4281
return reduce(_multiply_two_scenarios, map(list, scenarios))
4284
def _multiply_two_scenarios(scenarios_left, scenarios_right):
4285
"""Multiply two sets of scenarios.
4287
:returns: the cartesian product of the two sets of scenarios, that is
4288
a scenario for every possible combination of a left scenario and a
4292
('%s,%s' % (left_name, right_name),
4293
dict(left_dict.items() + right_dict.items()))
4294
for left_name, left_dict in scenarios_left
4295
for right_name, right_dict in scenarios_right]
4298
def multiply_tests(tests, scenarios, result):
4299
"""Multiply tests_list by scenarios into result.
4301
This is the core workhorse for test parameterisation.
4303
Typically the load_tests() method for a per-implementation test suite will
4304
call multiply_tests and return the result.
4306
:param tests: The tests to parameterise.
4307
:param scenarios: The scenarios to apply: pairs of (scenario_name,
3014
4308
scenario_param_dict).
3015
:param loader: If provided, will be used instead of a new
3016
bzrlib.tests.TestLoader() instance.
3018
This returns a new TestSuite containing the cross product of
3019
all the tests in all the modules, each repeated for each scenario.
3020
Each test is adapted by adding the scenario name at the end
3021
of its name, and updating the test object's __dict__ with the
3022
scenario_param_dict.
3024
>>> r = multiply_tests_from_modules(
3025
... ['bzrlib.tests.test_sampler'],
3026
... [('one', dict(param=1)),
3027
... ('two', dict(param=2))])
4309
:param result: A TestSuite to add created tests to.
4311
This returns the passed in result TestSuite with the cross product of all
4312
the tests repeated once for each scenario. Each test is adapted by adding
4313
the scenario name at the end of its id(), and updating the test object's
4314
__dict__ with the scenario_param_dict.
4316
>>> import bzrlib.tests.test_sampler
4317
>>> r = multiply_tests(
4318
... bzrlib.tests.test_sampler.DemoTest('test_nothing'),
4319
... [('one', dict(param=1)),
4320
... ('two', dict(param=2))],
4321
... TestUtil.TestSuite())
3028
4322
>>> tests = list(iter_suite_tests(r))
3035
4329
>>> tests[1].param
3038
# XXX: Isn't load_tests() a better way to provide the same functionality
3039
# without forcing a predefined TestScenarioApplier ? --vila 080215
3041
loader = TestUtil.TestLoader()
4332
for test in iter_suite_tests(tests):
4333
apply_scenarios(test, scenarios, result)
4337
def apply_scenarios(test, scenarios, result):
4338
"""Apply the scenarios in scenarios to test and add to result.
4340
:param test: The test to apply scenarios to.
4341
:param scenarios: An iterable of scenarios to apply to test.
4343
:seealso: apply_scenario
4345
for scenario in scenarios:
4346
result.addTest(apply_scenario(test, scenario))
4350
def apply_scenario(test, scenario):
4351
"""Copy test and apply scenario to it.
4353
:param test: A test to adapt.
4354
:param scenario: A tuple describing the scenario.
4355
The first element of the tuple is the new test id.
4356
The second element is a dict containing attributes to set on the
4358
:return: The adapted test.
4360
new_id = "%s(%s)" % (test.id(), scenario[0])
4361
new_test = clone_test(test, new_id)
4362
for name, value in scenario[1].items():
4363
setattr(new_test, name, value)
4367
def clone_test(test, new_id):
4368
"""Clone a test giving it a new id.
4370
:param test: The test to clone.
4371
:param new_id: The id to assign to it.
4372
:return: The new test.
4374
new_test = copy.copy(test)
4375
new_test.id = lambda: new_id
4376
# XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4377
# causes cloned tests to share the 'details' dict. This makes it hard to
4378
# read the test output for parameterized tests, because tracebacks will be
4379
# associated with irrelevant tests.
4381
details = new_test._TestCase__details
4382
except AttributeError:
4383
# must be a different version of testtools than expected. Do nothing.
4386
# Reset the '__details' dict.
4387
new_test._TestCase__details = {}
4391
def permute_tests_for_extension(standard_tests, loader, py_module_name,
4393
"""Helper for permutating tests against an extension module.
4395
This is meant to be used inside a modules 'load_tests()' function. It will
4396
create 2 scenarios, and cause all tests in the 'standard_tests' to be run
4397
against both implementations. Setting 'test.module' to the appropriate
4398
module. See bzrlib.tests.test__chk_map.load_tests as an example.
4400
:param standard_tests: A test suite to permute
4401
:param loader: A TestLoader
4402
:param py_module_name: The python path to a python module that can always
4403
be loaded, and will be considered the 'python' implementation. (eg
4404
'bzrlib._chk_map_py')
4405
:param ext_module_name: The python path to an extension module. If the
4406
module cannot be loaded, a single test will be added, which notes that
4407
the module is not available. If it can be loaded, all standard_tests
4408
will be run against that module.
4409
:return: (suite, feature) suite is a test-suite that has all the permuted
4410
tests. feature is the Feature object that can be used to determine if
4411
the module is available.
4414
from bzrlib.tests.features import ModuleAvailableFeature
4415
py_module = pyutils.get_named_object(py_module_name)
4417
('python', {'module': py_module}),
3043
4419
suite = loader.suiteClass()
3045
adapter = TestScenarioApplier()
3046
adapter.scenarios = list(scenario_iter)
3047
adapt_modules(module_name_list, adapter, loader, suite)
3051
def multiply_scenarios(scenarios_left, scenarios_right):
3052
"""Multiply two sets of scenarios.
3054
:returns: the cartesian product of the two sets of scenarios, that is
3055
a scenario for every possible combination of a left scenario and a
3059
('%s,%s' % (left_name, right_name),
3060
dict(left_dict.items() + right_dict.items()))
3061
for left_name, left_dict in scenarios_left
3062
for right_name, right_dict in scenarios_right]
3066
def adapt_modules(mods_list, adapter, loader, suite):
3067
"""Adapt the modules in mods_list using adapter and add to suite."""
3068
tests = loader.loadTestsFromModuleNames(mods_list)
3069
adapt_tests(tests, adapter, suite)
3072
def adapt_tests(tests_list, adapter, suite):
3073
"""Adapt the tests in tests_list using adapter and add to suite."""
3074
for test in iter_suite_tests(tests_list):
3075
suite.addTests(adapter.adapt(test))
3078
def _rmtree_temp_dir(dirname):
4420
feature = ModuleAvailableFeature(ext_module_name)
4421
if feature.available():
4422
scenarios.append(('C', {'module': feature.module}))
4424
# the compiled module isn't available, so we add a failing test
4425
class FailWithoutFeature(TestCase):
4426
def test_fail(self):
4427
self.requireFeature(feature)
4428
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4429
result = multiply_tests(standard_tests, scenarios, suite)
4430
return result, feature
4433
def _rmtree_temp_dir(dirname, test_id=None):
3079
4434
# If LANG=C we probably have created some bogus paths
3080
4435
# which rmtree(unicode) will fail to delete
3081
4436
# so make sure we are using rmtree(str) to delete everything
3091
4446
osutils.rmtree(dirname)
3092
4447
except OSError, e:
3093
if sys.platform == 'win32' and e.errno == errno.EACCES:
3094
sys.stderr.write(('Permission denied: '
3095
'unable to remove testing dir '
3096
'%s\n' % os.path.basename(dirname)))
3101
class Feature(object):
3102
"""An operating system Feature."""
3105
self._available = None
3107
def available(self):
3108
"""Is the feature available?
3110
:return: True if the feature is available.
3112
if self._available is None:
3113
self._available = self._probe()
3114
return self._available
3117
"""Implement this method in concrete features.
3119
:return: True if the feature is available.
3121
raise NotImplementedError
3124
if getattr(self, 'feature_name', None):
3125
return self.feature_name()
3126
return self.__class__.__name__
3129
class _SymlinkFeature(Feature):
3132
return osutils.has_symlinks()
3134
def feature_name(self):
3137
SymlinkFeature = _SymlinkFeature()
3140
class _HardlinkFeature(Feature):
3143
return osutils.has_hardlinks()
3145
def feature_name(self):
3148
HardlinkFeature = _HardlinkFeature()
3151
class _OsFifoFeature(Feature):
3154
return getattr(os, 'mkfifo', None)
3156
def feature_name(self):
3157
return 'filesystem fifos'
3159
OsFifoFeature = _OsFifoFeature()
3162
class _UnicodeFilenameFeature(Feature):
3163
"""Does the filesystem support Unicode filenames?"""
3167
# Check for character combinations unlikely to be covered by any
3168
# single non-unicode encoding. We use the characters
3169
# - greek small letter alpha (U+03B1) and
3170
# - braille pattern dots-123456 (U+283F).
3171
os.stat(u'\u03b1\u283f')
3172
except UnicodeEncodeError:
3174
except (IOError, OSError):
3175
# The filesystem allows the Unicode filename but the file doesn't
3179
# The filesystem allows the Unicode filename and the file exists,
3183
UnicodeFilenameFeature = _UnicodeFilenameFeature()
3186
class TestScenarioApplier(object):
3187
"""A tool to apply scenarios to tests."""
3189
def adapt(self, test):
3190
"""Return a TestSuite containing a copy of test for each scenario."""
3191
result = unittest.TestSuite()
3192
for scenario in self.scenarios:
3193
result.addTest(self.adapt_test_to_scenario(test, scenario))
3196
def adapt_test_to_scenario(self, test, scenario):
3197
"""Copy test and apply scenario to it.
3199
:param test: A test to adapt.
3200
:param scenario: A tuple describing the scenarion.
3201
The first element of the tuple is the new test id.
3202
The second element is a dict containing attributes to set on the
3204
:return: The adapted test.
3206
from copy import deepcopy
3207
new_test = deepcopy(test)
3208
for name, value in scenario[1].items():
3209
setattr(new_test, name, value)
3210
new_id = "%s(%s)" % (new_test.id(), scenario[0])
3211
new_test.id = lambda: new_id
4448
# We don't want to fail here because some useful display will be lost
4449
# otherwise. Polluting the tmp dir is bad, but not giving all the
4450
# possible info to the test runner is even worse.
4452
ui.ui_factory.clear_term()
4453
sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4454
# Ugly, but the last thing we want here is fail, so bear with it.
4455
printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4456
).encode('ascii', 'replace')
4457
sys.stderr.write('Unable to remove testing dir %s\n%s'
4458
% (os.path.basename(dirname), printable_e))
3215
4461
def probe_unicode_in_user_encoding():
3248
class _FTPServerFeature(Feature):
3249
"""Some tests want an FTP Server, check if one is available.
3251
Right now, the only way this is available is if 'medusa' is installed.
3252
http://www.amk.ca/python/code/medusa.html
3257
import bzrlib.tests.ftp_server
3262
def feature_name(self):
3265
FTPServerFeature = _FTPServerFeature()
3268
class _UnicodeFilename(Feature):
3269
"""Does the filesystem support Unicode filenames?"""
3274
except UnicodeEncodeError:
3276
except (IOError, OSError):
3277
# The filesystem allows the Unicode filename but the file doesn't
3281
# The filesystem allows the Unicode filename and the file exists,
3285
UnicodeFilename = _UnicodeFilename()
3288
class _UTF8Filesystem(Feature):
3289
"""Is the filesystem UTF-8?"""
3292
if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
3296
UTF8Filesystem = _UTF8Filesystem()
3299
class _CaseInsensitiveFilesystemFeature(Feature):
3300
"""Check if underlying filesystem is case-insensitive
3301
(e.g. on Windows, Cygwin, MacOS)
3305
if TestCaseWithMemoryTransport.TEST_ROOT is None:
3306
root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
3307
TestCaseWithMemoryTransport.TEST_ROOT = root
3309
root = TestCaseWithMemoryTransport.TEST_ROOT
3310
tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
3312
name_a = osutils.pathjoin(tdir, 'a')
3313
name_A = osutils.pathjoin(tdir, 'A')
3315
result = osutils.isdir(name_A)
3316
_rmtree_temp_dir(tdir)
3319
def feature_name(self):
3320
return 'case-insensitive filesystem'
3322
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
4494
# Only define SubUnitBzrRunner if subunit is available.
4496
from subunit import TestProtocolClient
4497
from subunit.test_results import AutoTimingTestResultDecorator
4498
class SubUnitBzrProtocolClient(TestProtocolClient):
4500
def stopTest(self, test):
4501
super(SubUnitBzrProtocolClient, self).stopTest(test)
4502
_clear__type_equality_funcs(test)
4504
def addSuccess(self, test, details=None):
4505
# The subunit client always includes the details in the subunit
4506
# stream, but we don't want to include it in ours.
4507
if details is not None and 'log' in details:
4509
return super(SubUnitBzrProtocolClient, self).addSuccess(
4512
class SubUnitBzrRunner(TextTestRunner):
4513
def run(self, test):
4514
result = AutoTimingTestResultDecorator(
4515
SubUnitBzrProtocolClient(self.stream))
4522
# API compatibility for old plugins; see bug 892622.
4525
'HTTPServerFeature',
4526
'ModuleAvailableFeature',
4527
'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
4528
'OsFifoFeature', 'UnicodeFilenameFeature',
4529
'ByteStringNamedFilesystem', 'UTF8Filesystem',
4530
'BreakinFeature', 'CaseInsCasePresFilenameFeature',
4531
'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
4532
'posix_permissions_feature',
4534
globals()[name] = _CompatabilityThunkFeature(
4535
symbol_versioning.deprecated_in((2, 5, 0)),
4536
'bzrlib.tests', name,
4537
name, 'bzrlib.tests.features')
4540
for (old_name, new_name) in [
4541
('UnicodeFilename', 'UnicodeFilenameFeature'),
4543
globals()[name] = _CompatabilityThunkFeature(
4544
symbol_versioning.deprecated_in((2, 5, 0)),
4545
'bzrlib.tests', old_name,
4546
new_name, 'bzrlib.tests.features')