27
31
from cStringIO import StringIO
38
from pprint import pformat
43
from subprocess import Popen, PIPE, STDOUT
50
# nb: check this before importing anything else from within it
51
_testtools_version = getattr(testtools, '__version__', ())
52
if _testtools_version < (0, 9, 5):
53
raise ImportError("need at least testtools 0.9.5: %s is %r"
54
% (testtools.__file__, _testtools_version))
55
from testtools import content
58
52
from bzrlib import (
62
commands as _mod_commands,
71
plugin as _mod_plugin,
78
transport as _mod_transport,
68
import bzrlib.commands
69
import bzrlib.timestamp
71
import bzrlib.inventory
72
import bzrlib.iterablefile
82
75
import bzrlib.lsprof
83
76
except ImportError:
84
77
# lsprof not available
86
from bzrlib.smart import client, request
87
from bzrlib.transport import (
79
from bzrlib.merge import merge_inner
82
from bzrlib.smart import client, request, server
84
from bzrlib import symbol_versioning
91
85
from bzrlib.symbol_versioning import (
92
87
deprecated_function,
95
from bzrlib.tests import (
100
from bzrlib.ui import NullProgressView
101
from bzrlib.ui.text import TextUIFactory
92
from bzrlib.transport import get_transport
93
import bzrlib.transport
94
from bzrlib.transport.local import LocalURLServer
95
from bzrlib.transport.memory import MemoryServer
96
from bzrlib.transport.readonly import ReadonlyServer
97
from bzrlib.trace import mutter, note
98
from bzrlib.tests import TestUtil
99
from bzrlib.tests.http_server import HttpServer
100
from bzrlib.tests.TestUtil import (
104
from bzrlib.tests.treeshape import build_tree_contents
105
import bzrlib.version_info_formats.format_custom
106
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
103
108
# Mark this python module as being part of the implementation
104
109
# of unittest: this gives us better tracebacks where the last
105
110
# shown frame is the test code, not our assertXYZ.
108
default_transport = test_server.LocalURLServer
111
_unitialized_attr = object()
112
"""A sentinel needed to act as a default value in a method signature."""
115
# Subunit result codes, defined here to prevent a hard dependency on subunit.
119
# These are intentionally brought into this namespace. That way plugins, etc
120
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
121
TestSuite = TestUtil.TestSuite
122
TestLoader = TestUtil.TestLoader
124
# Tests should run in a clean and clearly defined environment. The goal is to
125
# keep them isolated from the running environment as mush as possible. The test
126
# framework ensures the variables defined below are set (or deleted if the
127
# value is None) before a test is run and reset to their original value after
128
# the test is run. Generally if some code depends on an environment variable,
129
# the tests should start without this variable in the environment. There are a
130
# few exceptions but you shouldn't violate this rule lightly.
134
# bzr now uses the Win32 API and doesn't rely on APPDATA, but the
135
# tests do check our impls match APPDATA
136
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
140
'BZREMAIL': None, # may still be present in the environment
141
'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
142
'BZR_PROGRESS_BAR': None,
143
# This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
144
# as a base class instead of TestCaseInTempDir. Tests inheriting from
145
# TestCase should not use disk resources, BZR_LOG is one.
146
'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
147
'BZR_PLUGIN_PATH': None,
148
'BZR_DISABLE_PLUGINS': None,
149
'BZR_PLUGINS_AT': None,
150
'BZR_CONCURRENCY': None,
151
# Make sure that any text ui tests are consistent regardless of
152
# the environment the test case is run in; you may want tests that
153
# test other combinations. 'dumb' is a reasonable guess for tests
154
# going to a pipe or a StringIO.
160
'SSH_AUTH_SOCK': None,
170
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
171
# least. If you do (care), please update this comment
175
'BZR_REMOTE_PATH': None,
176
# Generally speaking, we don't want apport reporting on crashes in
177
# the test envirnoment unless we're specifically testing apport,
178
# so that it doesn't leak into the real system environment. We
179
# use an env var so it propagates to subprocesses.
180
'APPORT_DISABLE': '1',
184
def override_os_environ(test, env=None):
185
"""Modify os.environ keeping a copy.
187
:param test: A test instance
189
:param env: A dict containing variable definitions to be installed
192
env = isolated_environ
193
test._original_os_environ = dict([(var, value)
194
for var, value in os.environ.iteritems()])
195
for var, value in env.iteritems():
196
osutils.set_or_unset_env(var, value)
197
if var not in test._original_os_environ:
198
# The var is new, add it with a value of None, so
199
# restore_os_environ will delete it
200
test._original_os_environ[var] = None
203
def restore_os_environ(test):
204
"""Restore os.environ to its original state.
206
:param test: A test instance previously passed to override_os_environ.
208
for var, value in test._original_os_environ.iteritems():
209
# Restore the original value (or delete it if the value has been set to
210
# None in override_os_environ).
211
osutils.set_or_unset_env(var, value)
214
class ExtendedTestResult(testtools.TextTestResult):
113
default_transport = LocalURLServer
116
class ExtendedTestResult(unittest._TextTestResult):
215
117
"""Accepts, reports and accumulates the results of running tests.
217
119
Compared to the unittest version this class adds support for
266
169
self._overall_start_time = time.time()
267
170
self._strict = strict
268
self._first_thread_leaker_id = None
269
self._tests_leaking_threads_count = 0
270
self._traceback_from_test = None
272
def stopTestRun(self):
275
stopTime = time.time()
276
timeTaken = stopTime - self.startTime
277
# GZ 2010-07-19: Seems testtools has no printErrors method, and though
278
# the parent class method is similar have to duplicate
279
self._show_list('ERROR', self.errors)
280
self._show_list('FAIL', self.failures)
281
self.stream.write(self.sep2)
282
self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
283
run, run != 1 and "s" or "", timeTaken))
284
if not self.wasSuccessful():
285
self.stream.write("FAILED (")
286
failed, errored = map(len, (self.failures, self.errors))
288
self.stream.write("failures=%d" % failed)
290
if failed: self.stream.write(", ")
291
self.stream.write("errors=%d" % errored)
292
if self.known_failure_count:
293
if failed or errored: self.stream.write(", ")
294
self.stream.write("known_failure_count=%d" %
295
self.known_failure_count)
296
self.stream.write(")\n")
298
if self.known_failure_count:
299
self.stream.write("OK (known_failures=%d)\n" %
300
self.known_failure_count)
302
self.stream.write("OK\n")
303
if self.skip_count > 0:
304
skipped = self.skip_count
305
self.stream.write('%d test%s skipped\n' %
306
(skipped, skipped != 1 and "s" or ""))
308
for feature, count in sorted(self.unsupported.items()):
309
self.stream.write("Missing feature '%s' skipped %d tests.\n" %
312
174
ok = self.wasStrictlySuccessful()
314
176
ok = self.wasSuccessful()
315
if self._first_thread_leaker_id:
178
self.stream.write('tests passed\n')
180
self.stream.write('tests failed\n')
181
if TestCase._first_thread_leaker_id:
316
182
self.stream.write(
317
183
'%s is leaking threads among %d leaking tests.\n' % (
318
self._first_thread_leaker_id,
319
self._tests_leaking_threads_count))
320
# We don't report the main thread as an active one.
322
'%d non-main threads were left active in the end.\n'
323
% (len(self._active_threads) - 1))
325
def getDescription(self, test):
328
def _extractBenchmarkTime(self, testCase, details=None):
184
TestCase._first_thread_leaker_id,
185
TestCase._leaking_threads_tests))
187
def _extractBenchmarkTime(self, testCase):
329
188
"""Add a benchmark time for the current test case."""
330
if details and 'benchtime' in details:
331
return float(''.join(details['benchtime'].iter_bytes()))
332
189
return getattr(testCase, "_benchtime", None)
334
191
def _elapsedTestTimeString(self):
335
192
"""Return a time string for the overall time the current test has taken."""
336
return self._formatTime(self._delta_to_float(
337
self._now() - self._start_datetime))
193
return self._formatTime(time.time() - self._start_time)
339
195
def _testTimeString(self, testCase):
340
196
benchmark_time = self._extractBenchmarkTime(testCase)
341
197
if benchmark_time is not None:
342
return self._formatTime(benchmark_time) + "*"
199
self._formatTime(benchmark_time),
200
self._elapsedTestTimeString())
344
return self._elapsedTestTimeString()
202
return " %s" % self._elapsedTestTimeString()
346
204
def _formatTime(self, seconds):
347
205
"""Format seconds as milliseconds with leading spaces."""
352
210
def _shortened_test_description(self, test):
354
what = re.sub(r'^bzrlib\.tests\.', '', what)
212
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
357
# GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
358
# multiple times in a row, because the handler is added for
359
# each test but the container list is shared between cases.
360
# See lp:498869 lp:625574 and lp:637725 for background.
361
def _record_traceback_from_test(self, exc_info):
362
"""Store the traceback from passed exc_info tuple till"""
363
self._traceback_from_test = exc_info[2]
365
215
def startTest(self, test):
366
super(ExtendedTestResult, self).startTest(test)
216
unittest.TestResult.startTest(self, test)
367
217
if self.count == 0:
368
218
self.startTests()
370
219
self.report_test_start(test)
371
220
test.number = self.count
372
221
self._recordTestStartTime()
373
# Make testtools cases give us the real traceback on failure
374
addOnException = getattr(test, "addOnException", None)
375
if addOnException is not None:
376
addOnException(self._record_traceback_from_test)
377
# Only check for thread leaks on bzrlib derived test cases
378
if isinstance(test, TestCase):
379
test.addCleanup(self._check_leaked_threads, test)
381
def stopTest(self, test):
382
super(ExtendedTestResult, self).stopTest(test)
383
# Manually break cycles, means touching various private things but hey
384
getDetails = getattr(test, "getDetails", None)
385
if getDetails is not None:
387
# Clear _type_equality_funcs to try to stop TestCase instances
388
# from wasting memory. 'clear' is not available in all Python
389
# versions (bug 809048)
390
type_equality_funcs = getattr(test, "_type_equality_funcs", None)
391
if type_equality_funcs is not None:
392
tef_clear = getattr(type_equality_funcs, "clear", None)
393
if tef_clear is None:
394
tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
395
if tef_instance_dict is not None:
396
tef_clear = tef_instance_dict.clear
397
if tef_clear is not None:
399
self._traceback_from_test = None
401
223
def startTests(self):
402
self.report_tests_starting()
403
self._active_threads = threading.enumerate()
405
def _check_leaked_threads(self, test):
406
"""See if any threads have leaked since last call
408
A sample of live threads is stored in the _active_threads attribute,
409
when this method runs it compares the current live threads and any not
410
in the previous sample are treated as having leaked.
412
now_active_threads = set(threading.enumerate())
413
threads_leaked = now_active_threads.difference(self._active_threads)
415
self._report_thread_leak(test, threads_leaked, now_active_threads)
416
self._tests_leaking_threads_count += 1
417
if self._first_thread_leaker_id is None:
418
self._first_thread_leaker_id = test.id()
419
self._active_threads = now_active_threads
225
'testing: %s\n' % (osutils.realpath(sys.argv[0]),))
227
' %s (%s python%s)\n' % (
229
bzrlib.version_string,
230
bzrlib._format_version_tuple(sys.version_info),
232
self.stream.write('\n')
421
234
def _recordTestStartTime(self):
422
235
"""Record that a test has started."""
423
self._start_datetime = self._now()
236
self._start_time = time.time()
238
def _cleanupLogFile(self, test):
239
# We can only do this if we have one of our TestCases, not if
241
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
242
if setKeepLogfile is not None:
425
245
def addError(self, test, err):
426
246
"""Tell result that test finished with an error.
441
267
Called from the TestCase run() method when the test
442
268
fails because e.g. an assert() method failed.
444
self._post_mortem(self._traceback_from_test)
445
super(ExtendedTestResult, self).addFailure(test, err)
446
self.failure_count += 1
447
self.report_failure(test, err)
270
self._testConcluded(test)
271
if isinstance(err[1], KnownFailure):
272
return self._addKnownFailure(test, err)
274
unittest.TestResult.addFailure(self, test, err)
275
self.failure_count += 1
276
self.report_failure(test, err)
279
self._cleanupLogFile(test)
451
def addSuccess(self, test, details=None):
281
def addSuccess(self, test):
452
282
"""Tell result that test completed successfully.
454
284
Called from the TestCase run()
286
self._testConcluded(test)
456
287
if self._bench_history is not None:
457
benchmark_time = self._extractBenchmarkTime(test, details)
288
benchmark_time = self._extractBenchmarkTime(test)
458
289
if benchmark_time is not None:
459
290
self._bench_history.write("%s %s\n" % (
460
291
self._formatTime(benchmark_time),
462
293
self.report_success(test)
463
super(ExtendedTestResult, self).addSuccess(test)
294
self._cleanupLogFile(test)
295
unittest.TestResult.addSuccess(self, test)
464
296
test._log_contents = ''
466
def addExpectedFailure(self, test, err):
298
def _testConcluded(self, test):
299
"""Common code when a test has finished.
301
Called regardless of whether it succeded, failed, etc.
305
def _addKnownFailure(self, test, err):
467
306
self.known_failure_count += 1
468
307
self.report_known_failure(test, err)
470
def addUnexpectedSuccess(self, test, details=None):
471
"""Tell result the test unexpectedly passed, counting as a failure
473
When the minimum version of testtools required becomes 0.9.8 this
474
can be updated to use the new handling there.
476
super(ExtendedTestResult, self).addFailure(test, details=details)
477
self.failure_count += 1
478
self.report_unexpected_success(test,
479
"".join(details["reason"].iter_text()))
483
309
def addNotSupported(self, test, feature):
484
310
"""The test will not be run because of a missing feature.
486
312
# this can be called in two different ways: it may be that the
487
# test started running, and then raised (through requireFeature)
313
# test started running, and then raised (through addError)
488
314
# UnavailableFeature. Alternatively this method can be called
489
# while probing for features before running the test code proper; in
490
# that case we will see startTest and stopTest, but the test will
491
# never actually run.
315
# while probing for features before running the tests; in that
316
# case we will see startTest and stopTest, but the test will never
492
318
self.unsupported.setdefault(str(feature), 0)
493
319
self.unsupported[str(feature)] += 1
494
320
self.report_unsupported(test, feature)
498
324
self.skip_count += 1
499
325
self.report_skip(test, reason)
501
def addNotApplicable(self, test, reason):
502
self.not_applicable_count += 1
503
self.report_not_applicable(test, reason)
505
def _post_mortem(self, tb=None):
506
"""Start a PDB post mortem session."""
507
if os.environ.get('BZR_TEST_PDB', None):
511
def progress(self, offset, whence):
512
"""The test is adjusting the count of tests to run."""
513
if whence == SUBUNIT_SEEK_SET:
514
self.num_tests = offset
515
elif whence == SUBUNIT_SEEK_CUR:
516
self.num_tests += offset
518
raise errors.BzrError("Unknown whence %r" % whence)
520
def report_tests_starting(self):
521
"""Display information before the test run begins"""
522
if getattr(sys, 'frozen', None) is None:
523
bzr_path = osutils.realpath(sys.argv[0])
525
bzr_path = sys.executable
527
'bzr selftest: %s\n' % (bzr_path,))
530
bzrlib.__path__[0],))
532
' bzr-%s python-%s %s\n' % (
533
bzrlib.version_string,
534
bzrlib._format_version_tuple(sys.version_info),
535
platform.platform(aliased=1),
537
self.stream.write('\n')
539
def report_test_start(self, test):
540
"""Display information on the test just about to be run"""
542
def _report_thread_leak(self, test, leaked_threads, active_threads):
543
"""Display information on a test that leaked one or more threads"""
544
# GZ 2010-09-09: A leak summary reported separately from the general
545
# thread debugging would be nice. Tests under subunit
546
# need something not using stream, perhaps adding a
547
# testtools details object would be fitting.
548
if 'threads' in selftest_debug_flags:
549
self.stream.write('%s is leaking, active is now %d\n' %
550
(test.id(), len(active_threads)))
552
def startTestRun(self):
553
self.startTime = time.time()
327
def _addNotApplicable(self, test, skip_excinfo):
328
if isinstance(skip_excinfo[1], TestNotApplicable):
329
self.not_applicable_count += 1
330
self.report_not_applicable(test, skip_excinfo)
333
except KeyboardInterrupt:
336
self.addError(test, test.exc_info())
338
# seems best to treat this as success from point-of-view of unittest
339
# -- it actually does nothing so it barely matters :)
340
unittest.TestResult.addSuccess(self, test)
341
test._log_contents = ''
343
def printErrorList(self, flavour, errors):
344
for test, err in errors:
345
self.stream.writeln(self.separator1)
346
self.stream.write("%s: " % flavour)
347
self.stream.writeln(self.getDescription(test))
348
if getattr(test, '_get_log', None) is not None:
349
self.stream.write('\n')
351
('vvvv[log from %s]' % test.id()).ljust(78,'-'))
352
self.stream.write('\n')
353
self.stream.write(test._get_log())
354
self.stream.write('\n')
356
('^^^^[log from %s]' % test.id()).ljust(78,'-'))
357
self.stream.write('\n')
358
self.stream.writeln(self.separator2)
359
self.stream.writeln("%s" % err)
364
def report_cleaning_up(self):
555
367
def report_success(self, test):
694
498
return '%s%s' % (indent, err[1])
696
500
def report_error(self, test, err):
697
self.stream.write('ERROR %s\n%s\n'
501
self.stream.writeln('ERROR %s\n%s'
698
502
% (self._testTimeString(test),
699
503
self._error_summary(err)))
701
505
def report_failure(self, test, err):
702
self.stream.write(' FAIL %s\n%s\n'
506
self.stream.writeln(' FAIL %s\n%s'
703
507
% (self._testTimeString(test),
704
508
self._error_summary(err)))
706
510
def report_known_failure(self, test, err):
707
self.stream.write('XFAIL %s\n%s\n'
511
self.stream.writeln('XFAIL %s\n%s'
708
512
% (self._testTimeString(test),
709
513
self._error_summary(err)))
711
def report_unexpected_success(self, test, reason):
712
self.stream.write(' FAIL %s\n%s: %s\n'
713
% (self._testTimeString(test),
714
"Unexpected success. Should have failed",
717
515
def report_success(self, test):
718
self.stream.write(' OK %s\n' % self._testTimeString(test))
516
self.stream.writeln(' OK %s' % self._testTimeString(test))
719
517
for bench_called, stats in getattr(test, '_benchcalls', []):
720
self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
518
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
721
519
stats.pprint(file=self.stream)
722
520
# flush the stream so that we get smooth output. This verbose mode is
723
521
# used to show the output in PQM.
724
522
self.stream.flush()
726
524
def report_skip(self, test, reason):
727
self.stream.write(' SKIP %s\n%s\n'
525
self.stream.writeln(' SKIP %s\n%s'
728
526
% (self._testTimeString(test), reason))
730
def report_not_applicable(self, test, reason):
731
self.stream.write(' N/A %s\n %s\n'
732
% (self._testTimeString(test), reason))
528
def report_not_applicable(self, test, skip_excinfo):
529
self.stream.writeln(' N/A %s\n%s'
530
% (self._testTimeString(test),
531
self._error_summary(skip_excinfo)))
734
533
def report_unsupported(self, test, feature):
735
534
"""test cannot be run because feature is missing."""
736
self.stream.write("NODEP %s\n The feature '%s' is not available.\n"
535
self.stream.writeln("NODEP %s\n The feature '%s' is not available."
737
536
%(self._testTimeString(test), feature))
747
546
bench_history=None,
749
result_decorators=None,
751
"""Create a TextTestRunner.
753
:param result_decorators: An optional list of decorators to apply
754
to the result object being used by the runner. Decorators are
755
applied left to right - the first element in the list is the
758
# stream may know claim to know to write unicode strings, but in older
759
# pythons this goes sufficiently wrong that it is a bad idea. (
760
# specifically a built in file with encoding 'UTF-8' will still try
761
# to encode using ascii.
762
new_encoding = osutils.get_terminal_encoding()
763
codec = codecs.lookup(new_encoding)
764
if type(codec) is tuple:
768
encode = codec.encode
769
# GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
770
# so should swap to the plain codecs.StreamWriter
771
stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
773
stream.encoding = new_encoding
550
self.stream = unittest._WritelnDecorator(stream)
775
551
self.descriptions = descriptions
776
552
self.verbosity = verbosity
777
553
self._bench_history = bench_history
554
self.list_only = list_only
778
555
self._strict = strict
779
self._result_decorators = result_decorators or []
781
557
def run(self, test):
782
558
"Run the given test case or test suite."
559
startTime = time.time()
783
560
if self.verbosity == 1:
784
561
result_class = TextTestResult
785
562
elif self.verbosity >= 2:
786
563
result_class = VerboseTestResult
787
original_result = result_class(self.stream,
564
result = result_class(self.stream,
788
565
self.descriptions,
790
567
bench_history=self._bench_history,
568
num_tests=test.countTestCases(),
791
569
strict=self._strict,
793
# Signal to result objects that look at stop early policy to stop,
794
original_result.stop_early = self.stop_on_failure
795
result = original_result
796
for decorator in self._result_decorators:
797
result = decorator(result)
798
result.stop_early = self.stop_on_failure
799
result.startTestRun()
804
# higher level code uses our extended protocol to determine
805
# what exit code to give.
806
return original_result
571
result.stop_early = self.stop_on_failure
572
result.report_starting()
574
if self.verbosity >= 2:
575
self.stream.writeln("Listing tests only ...\n")
577
for t in iter_suite_tests(test):
578
self.stream.writeln("%s" % (t.id()))
587
if isinstance(test, testtools.ConcurrentTestSuite):
588
# We need to catch bzr specific behaviors
589
test.run(BZRTransformingResult(result))
592
run = result.testsRun
594
stopTime = time.time()
595
timeTaken = stopTime - startTime
597
self.stream.writeln(result.separator2)
598
self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
599
run, run != 1 and "s" or "", timeTaken))
600
self.stream.writeln()
601
if not result.wasSuccessful():
602
self.stream.write("FAILED (")
603
failed, errored = map(len, (result.failures, result.errors))
605
self.stream.write("failures=%d" % failed)
607
if failed: self.stream.write(", ")
608
self.stream.write("errors=%d" % errored)
609
if result.known_failure_count:
610
if failed or errored: self.stream.write(", ")
611
self.stream.write("known_failure_count=%d" %
612
result.known_failure_count)
613
self.stream.writeln(")")
615
if result.known_failure_count:
616
self.stream.writeln("OK (known_failures=%d)" %
617
result.known_failure_count)
619
self.stream.writeln("OK")
620
if result.skip_count > 0:
621
skipped = result.skip_count
622
self.stream.writeln('%d test%s skipped' %
623
(skipped, skipped != 1 and "s" or ""))
624
if result.unsupported:
625
for feature, count in sorted(result.unsupported.items()):
626
self.stream.writeln("Missing feature '%s' skipped %d tests." %
809
632
def iter_suite_tests(suite):
960
769
routine, and to build and check bzr trees.
962
771
In addition to the usual method of overriding tearDown(), this class also
963
allows subclasses to register cleanup functions via addCleanup, which are
772
allows subclasses to register functions into the _cleanups list, which is
964
773
run in order as the object is torn down. It's less likely this will be
965
774
accidentally overlooked.
777
_active_threads = None
778
_leaking_threads_tests = 0
779
_first_thread_leaker_id = None
780
_log_file_name = None
782
_keep_log_file = False
969
783
# record lsprof data when performing benchmark calls.
970
784
_gather_lsprof_in_benchmarks = False
785
attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
786
'_log_contents', '_log_file_name', '_benchtime',
787
'_TestCase__testMethodName', '_TestCase__testMethodDoc',)
972
789
def __init__(self, methodName='testMethod'):
973
790
super(TestCase, self).__init__(methodName)
974
self._directory_isolation = True
975
self.exception_handlers.insert(0,
976
(UnavailableFeature, self._do_unsupported_or_skip))
977
self.exception_handlers.insert(0,
978
(TestNotApplicable, self._do_not_applicable))
792
self._bzr_test_setUp_run = False
793
self._bzr_test_tearDown_run = False
981
super(TestCase, self).setUp()
982
for feature in getattr(self, '_test_needs_features', []):
983
self.requireFeature(feature)
796
unittest.TestCase.setUp(self)
797
self._bzr_test_setUp_run = True
984
798
self._cleanEnvironment()
985
799
self._silenceUI()
986
800
self._startLogFile()
987
801
self._benchcalls = []
988
802
self._benchtime = None
989
803
self._clear_hooks()
990
self._track_transports()
804
# Track locks - needs to be called before _clear_debug_flags.
991
805
self._track_locks()
992
806
self._clear_debug_flags()
993
# Isolate global verbosity level, to make sure it's reproducible
994
# between tests. We should get rid of this altogether: bug 656694. --
996
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
997
# Isolate config option expansion until its default value for bzrlib is
998
# settled on or a the FIXME associated with _get_expand_default_value
999
# is addressed -- vila 20110219
1000
self.overrideAttr(config, '_expand_default_value', None)
1001
self._log_files = set()
1002
# Each key in the ``_counters`` dict holds a value for a different
1003
# counter. When the test ends, addDetail() should be used to output the
1004
# counter values. This happens in install_counter_hook().
1006
if 'config_stats' in selftest_debug_flags:
1007
self._install_config_stats_hooks()
807
TestCase._active_threads = threading.activeCount()
808
self.addCleanup(self._check_leaked_threads)
1009
810
def debug(self):
1010
811
# debug a frame up.
1012
813
pdb.Pdb().set_trace(sys._getframe().f_back)
1014
def discardDetail(self, name):
1015
"""Extend the addDetail, getDetails api so we can remove a detail.
1017
eg. bzr always adds the 'log' detail at startup, but we don't want to
1018
include it for skipped, xfail, etc tests.
1020
It is safe to call this for a detail that doesn't exist, in case this
1021
gets called multiple times.
1023
# We cheat. details is stored in __details which means we shouldn't
1024
# touch it. but getDetails() returns the dict directly, so we can
1026
details = self.getDetails()
1030
def install_counter_hook(self, hooks, name, counter_name=None):
1031
"""Install a counting hook.
1033
Any hook can be counted as long as it doesn't need to return a value.
1035
:param hooks: Where the hook should be installed.
1037
:param name: The hook name that will be counted.
1039
:param counter_name: The counter identifier in ``_counters``, defaults
1042
_counters = self._counters # Avoid closing over self
1043
if counter_name is None:
1045
if _counters.has_key(counter_name):
1046
raise AssertionError('%s is already used as a counter name'
1048
_counters[counter_name] = 0
1049
self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1050
lambda: ['%d' % (_counters[counter_name],)]))
1051
def increment_counter(*args, **kwargs):
1052
_counters[counter_name] += 1
1053
label = 'count %s calls' % (counter_name,)
1054
hooks.install_named_hook(name, increment_counter, label)
1055
self.addCleanup(hooks.uninstall_named_hook, name, label)
1057
def _install_config_stats_hooks(self):
1058
"""Install config hooks to count hook calls.
1061
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1062
self.install_counter_hook(config.ConfigHooks, hook_name,
1063
'config.%s' % (hook_name,))
1065
# The OldConfigHooks are private and need special handling to protect
1066
# against recursive tests (tests that run other tests), so we just do
1067
# manually what registering them into _builtin_known_hooks will provide
1069
self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1070
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1071
self.install_counter_hook(config.OldConfigHooks, hook_name,
1072
'old_config.%s' % (hook_name,))
815
def _check_leaked_threads(self):
816
active = threading.activeCount()
817
leaked_threads = active - TestCase._active_threads
818
TestCase._active_threads = active
820
TestCase._leaking_threads_tests += 1
821
if TestCase._first_thread_leaker_id is None:
822
TestCase._first_thread_leaker_id = self.id()
1074
824
def _clear_debug_flags(self):
1075
825
"""Prevent externally set debug flags affecting tests.
1077
827
Tests that want to use debug flags can just set them in the
1078
828
debug_flags set during setup/teardown.
1080
# Start with a copy of the current debug flags we can safely modify.
1081
self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
830
self._preserved_debug_flags = set(debug.debug_flags)
1082
831
if 'allow_debug' not in selftest_debug_flags:
1083
832
debug.debug_flags.clear()
1084
if 'disable_lock_checks' not in selftest_debug_flags:
1085
debug.debug_flags.add('strict_locks')
833
self.addCleanup(self._restore_debug_flags)
1087
835
def _clear_hooks(self):
1088
836
# prevent hooks affecting tests
1089
known_hooks = hooks.known_hooks
1090
837
self._preserved_hooks = {}
1091
for key, (parent, name) in known_hooks.iter_parent_objects():
1092
current_hooks = getattr(parent, name)
838
for key, factory in hooks.known_hooks.items():
839
parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
840
current_hooks = hooks.known_hooks_key_to_object(key)
1093
841
self._preserved_hooks[parent] = (name, current_hooks)
1094
self._preserved_lazy_hooks = hooks._lazy_hooks
1095
hooks._lazy_hooks = {}
1096
842
self.addCleanup(self._restoreHooks)
1097
for key, (parent, name) in known_hooks.iter_parent_objects():
1098
factory = known_hooks.get(key)
843
for key, factory in hooks.known_hooks.items():
844
parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
1099
845
setattr(parent, name, factory())
1100
846
# this hook should always be installed
1101
847
request._install_hook()
1103
def disable_directory_isolation(self):
1104
"""Turn off directory isolation checks."""
1105
self._directory_isolation = False
1107
def enable_directory_isolation(self):
1108
"""Enable directory isolation checks."""
1109
self._directory_isolation = True
1111
849
def _silenceUI(self):
1112
850
"""Turn off UI for duration of test"""
1113
851
# by default the UI is off; tests can turn it on if they want it.
1114
self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
852
saved = ui.ui_factory
854
ui.ui_factory = saved
855
ui.ui_factory = ui.SilentUIFactory()
856
self.addCleanup(_restore)
1116
858
def _check_locks(self):
1117
859
"""Check that all lock take/release actions have been paired."""
1118
# We always check for mismatched locks. If a mismatch is found, we
1119
# fail unless -Edisable_lock_checks is supplied to selftest, in which
1120
# case we just print a warning.
860
# once we have fixed all the current lock problems, we can change the
861
# following code to always check for mismatched locks, but only do
862
# traceback showing with -Dlock (self._lock_check_thorough is True).
863
# For now, because the test suite will fail, we only assert that lock
864
# matching has occured with -Dlock.
1122
866
acquired_locks = [lock for action, lock in self._lock_actions
1123
867
if action == 'acquired']
1168
904
def _lock_broken(self, result):
1169
905
self._lock_actions.append(('broken', result))
1171
def permit_dir(self, name):
1172
"""Permit a directory to be used by this test. See permit_url."""
1173
name_transport = _mod_transport.get_transport_from_path(name)
1174
self.permit_url(name)
1175
self.permit_url(name_transport.base)
1177
def permit_url(self, url):
1178
"""Declare that url is an ok url to use in this test.
1180
Do this for memory transports, temporary test directory etc.
1182
Do not do this for the current working directory, /tmp, or any other
1183
preexisting non isolated url.
1185
if not url.endswith('/'):
1187
self._bzr_selftest_roots.append(url)
1189
def permit_source_tree_branch_repo(self):
1190
"""Permit the source tree bzr is running from to be opened.
1192
Some code such as bzrlib.version attempts to read from the bzr branch
1193
that bzr is executing from (if any). This method permits that directory
1194
to be used in the test suite.
1196
path = self.get_source_path()
1197
self.record_directory_isolation()
1200
workingtree.WorkingTree.open(path)
1201
except (errors.NotBranchError, errors.NoWorkingTree):
1202
raise TestSkipped('Needs a working tree of bzr sources')
1204
self.enable_directory_isolation()
1206
def _preopen_isolate_transport(self, transport):
1207
"""Check that all transport openings are done in the test work area."""
1208
while isinstance(transport, pathfilter.PathFilteringTransport):
1209
# Unwrap pathfiltered transports
1210
transport = transport.server.backing_transport.clone(
1211
transport._filter('.'))
1212
url = transport.base
1213
# ReadonlySmartTCPServer_for_testing decorates the backing transport
1214
# urls it is given by prepending readonly+. This is appropriate as the
1215
# client shouldn't know that the server is readonly (or not readonly).
1216
# We could register all servers twice, with readonly+ prepending, but
1217
# that makes for a long list; this is about the same but easier to
1219
if url.startswith('readonly+'):
1220
url = url[len('readonly+'):]
1221
self._preopen_isolate_url(url)
1223
def _preopen_isolate_url(self, url):
1224
if not self._directory_isolation:
1226
if self._directory_isolation == 'record':
1227
self._bzr_selftest_roots.append(url)
1229
# This prevents all transports, including e.g. sftp ones backed on disk
1230
# from working unless they are explicitly granted permission. We then
1231
# depend on the code that sets up test transports to check that they are
1232
# appropriately isolated and enable their use by calling
1233
# self.permit_transport()
1234
if not osutils.is_inside_any(self._bzr_selftest_roots, url):
1235
raise errors.BzrError("Attempt to escape test isolation: %r %r"
1236
% (url, self._bzr_selftest_roots))
1238
def record_directory_isolation(self):
1239
"""Gather accessed directories to permit later access.
1241
This is used for tests that access the branch bzr is running from.
1243
self._directory_isolation = "record"
1245
def start_server(self, transport_server, backing_server=None):
1246
"""Start transport_server for this test.
1248
This starts the server, registers a cleanup for it and permits the
1249
server's urls to be used.
1251
if backing_server is None:
1252
transport_server.start_server()
1254
transport_server.start_server(backing_server)
1255
self.addCleanup(transport_server.stop_server)
1256
# Obtain a real transport because if the server supplies a password, it
1257
# will be hidden from the base on the client side.
1258
t = _mod_transport.get_transport_from_url(transport_server.get_url())
1259
# Some transport servers effectively chroot the backing transport;
1260
# others like SFTPServer don't - users of the transport can walk up the
1261
# transport to read the entire backing transport. This wouldn't matter
1262
# except that the workdir tests are given - and that they expect the
1263
# server's url to point at - is one directory under the safety net. So
1264
# Branch operations into the transport will attempt to walk up one
1265
# directory. Chrooting all servers would avoid this but also mean that
1266
# we wouldn't be testing directly against non-root urls. Alternatively
1267
# getting the test framework to start the server with a backing server
1268
# at the actual safety net directory would work too, but this then
1269
# means that the self.get_url/self.get_transport methods would need
1270
# to transform all their results. On balance its cleaner to handle it
1271
# here, and permit a higher url when we have one of these transports.
1272
if t.base.endswith('/work/'):
1273
# we have safety net/test root/work
1274
t = t.clone('../..')
1275
elif isinstance(transport_server,
1276
test_server.SmartTCPServer_for_testing):
1277
# The smart server adds a path similar to work, which is traversed
1278
# up from by the client. But the server is chrooted - the actual
1279
# backing transport is not escaped from, and VFS requests to the
1280
# root will error (because they try to escape the chroot).
1282
while t2.base != t.base:
1285
self.permit_url(t.base)
1287
def _track_transports(self):
1288
"""Install checks for transport usage."""
1289
# TestCase has no safe place it can write to.
1290
self._bzr_selftest_roots = []
1291
# Currently the easiest way to be sure that nothing is going on is to
1292
# hook into bzr dir opening. This leaves a small window of error for
1293
# transport tests, but they are well known, and we can improve on this
1295
bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1296
self._preopen_isolate_transport, "Check bzr directories are safe.")
1298
907
def _ndiff_strings(self, a, b):
1299
908
"""Return ndiff between two strings containing lines.
1701
1279
The file is removed as the test is torn down.
1703
pseudo_log_file = StringIO()
1704
def _get_log_contents_for_weird_testtools_api():
1705
return [pseudo_log_file.getvalue().decode(
1706
"utf-8", "replace").encode("utf-8")]
1707
self.addDetail("log", content.Content(content.ContentType("text",
1708
"plain", {"charset": "utf8"}),
1709
_get_log_contents_for_weird_testtools_api))
1710
self._log_file = pseudo_log_file
1711
self._log_memento = trace.push_log_file(self._log_file)
1281
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1282
self._log_file = os.fdopen(fileno, 'w+')
1283
self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1284
self._log_file_name = name
1712
1285
self.addCleanup(self._finishLogFile)
1714
1287
def _finishLogFile(self):
1715
1288
"""Finished with the log file.
1717
Close the file and delete it.
1719
if trace._trace_file:
1720
# flush the log file, to get all content
1721
trace._trace_file.flush()
1722
trace.pop_log_file(self._log_memento)
1724
def thisFailsStrictLockCheck(self):
1725
"""It is known that this test would fail with -Dstrict_locks.
1727
By default, all tests are run with strict lock checking unless
1728
-Edisable_lock_checks is supplied. However there are some tests which
1729
we know fail strict locks at this point that have not been fixed.
1730
They should call this function to disable the strict checking.
1732
This should be used sparingly, it is much better to fix the locking
1733
issues rather than papering over the problem by calling this function.
1735
debug.debug_flags.discard('strict_locks')
1737
def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1738
"""Overrides an object attribute restoring it after the test.
1740
:note: This should be used with discretion; you should think about
1741
whether it's better to make the code testable without monkey-patching.
1743
:param obj: The object that will be mutated.
1745
:param attr_name: The attribute name we want to preserve/override in
1748
:param new: The optional value we want to set the attribute to.
1750
:returns: The actual attr value.
1752
value = getattr(obj, attr_name)
1753
# The actual value is captured by the call below
1754
self.addCleanup(setattr, obj, attr_name, value)
1755
if new is not _unitialized_attr:
1756
setattr(obj, attr_name, new)
1759
def overrideEnv(self, name, new):
1760
"""Set an environment variable, and reset it after the test.
1762
:param name: The environment variable name.
1764
:param new: The value to set the variable to. If None, the
1765
variable is deleted from the environment.
1767
:returns: The actual variable value.
1769
value = osutils.set_or_unset_env(name, new)
1770
self.addCleanup(osutils.set_or_unset_env, name, value)
1773
def recordCalls(self, obj, attr_name):
1774
"""Monkeypatch in a wrapper that will record calls.
1776
The monkeypatch is automatically removed when the test concludes.
1778
:param obj: The namespace holding the reference to be replaced;
1779
typically a module, class, or object.
1780
:param attr_name: A string for the name of the attribute to
1782
:returns: A list that will be extended with one item every time the
1783
function is called, with a tuple of (args, kwargs).
1787
def decorator(*args, **kwargs):
1788
calls.append((args, kwargs))
1789
return orig(*args, **kwargs)
1790
orig = self.overrideAttr(obj, attr_name, decorator)
1290
Close the file and delete it, unless setKeepLogfile was called.
1292
if self._log_file is None:
1294
bzrlib.trace.pop_log_file(self._log_memento)
1295
self._log_file.close()
1296
self._log_file = None
1297
if not self._keep_log_file:
1298
os.remove(self._log_file_name)
1299
self._log_file_name = None
1301
def setKeepLogfile(self):
1302
"""Make the logfile not be deleted when _finishLogFile is called."""
1303
self._keep_log_file = True
1305
def addCleanup(self, callable, *args, **kwargs):
1306
"""Arrange to run a callable when this case is torn down.
1308
Callables are run in the reverse of the order they are registered,
1309
ie last-in first-out.
1311
self._cleanups.append((callable, args, kwargs))
1793
1313
def _cleanEnvironment(self):
1794
for name, value in isolated_environ.iteritems():
1795
self.overrideEnv(name, value)
1315
'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1316
'HOME': os.getcwd(),
1317
# bzr now uses the Win32 API and doesn't rely on APPDATA, but the
1318
# tests do check our impls match APPDATA
1319
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
1323
'BZREMAIL': None, # may still be present in the environment
1325
'BZR_PROGRESS_BAR': None,
1327
'BZR_PLUGIN_PATH': None,
1329
'SSH_AUTH_SOCK': None,
1333
'https_proxy': None,
1334
'HTTPS_PROXY': None,
1339
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
1340
# least. If you do (care), please update this comment
1344
'BZR_REMOTE_PATH': None,
1347
self.addCleanup(self._restoreEnvironment)
1348
for name, value in new_env.iteritems():
1349
self._captureVar(name, value)
1351
def _captureVar(self, name, newvalue):
1352
"""Set an environment variable, and reset it when finished."""
1353
self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1355
def _restore_debug_flags(self):
1356
debug.debug_flags.clear()
1357
debug.debug_flags.update(self._preserved_debug_flags)
1359
def _restoreEnvironment(self):
1360
for name, value in self.__old_env.iteritems():
1361
osutils.set_or_unset_env(name, value)
1797
1363
def _restoreHooks(self):
1798
1364
for klass, (name, hooks) in self._preserved_hooks.items():
1799
1365
setattr(klass, name, hooks)
1800
self._preserved_hooks.clear()
1801
bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1802
self._preserved_lazy_hooks.clear()
1804
1367
def knownFailure(self, reason):
1805
"""Declare that this test fails for a known reason
1807
Tests that are known to fail should generally be using expectedFailure
1808
with an appropriate reverse assertion if a change could cause the test
1809
to start passing. Conversely if the test has no immediate prospect of
1810
succeeding then using skip is more suitable.
1812
When this method is called while an exception is being handled, that
1813
traceback will be used, otherwise a new exception will be thrown to
1814
provide one but won't be reported.
1816
self._add_reason(reason)
1818
exc_info = sys.exc_info()
1819
if exc_info != (None, None, None):
1820
self._report_traceback(exc_info)
1823
raise self.failureException(reason)
1824
except self.failureException:
1825
exc_info = sys.exc_info()
1826
# GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
1827
raise testtools.testcase._ExpectedFailure(exc_info)
1831
def _suppress_log(self):
1832
"""Remove the log info from details."""
1833
self.discardDetail('log')
1368
"""This test has failed for some known reason."""
1369
raise KnownFailure(reason)
1835
1371
def _do_skip(self, result, reason):
1836
self._suppress_log()
1837
1372
addSkip = getattr(result, 'addSkip', None)
1838
1373
if not callable(addSkip):
1839
result.addSuccess(result)
1374
result.addError(self, sys.exc_info())
1841
1376
addSkip(self, reason)
1844
def _do_known_failure(self, result, e):
1845
self._suppress_log()
1846
err = sys.exc_info()
1847
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1848
if addExpectedFailure is not None:
1849
addExpectedFailure(self, err)
1851
result.addSuccess(self)
1854
def _do_not_applicable(self, result, e):
1856
reason = 'No reason given'
1859
self._suppress_log ()
1860
addNotApplicable = getattr(result, 'addNotApplicable', None)
1861
if addNotApplicable is not None:
1862
result.addNotApplicable(self, reason)
1864
self._do_skip(result, reason)
1867
def _report_skip(self, result, err):
1868
"""Override the default _report_skip.
1870
We want to strip the 'log' detail. If we waint until _do_skip, it has
1871
already been formatted into the 'reason' string, and we can't pull it
1874
self._suppress_log()
1875
super(TestCase, self)._report_skip(self, result, err)
1878
def _report_expected_failure(self, result, err):
1881
See _report_skip for motivation.
1883
self._suppress_log()
1884
super(TestCase, self)._report_expected_failure(self, result, err)
1887
def _do_unsupported_or_skip(self, result, e):
1889
self._suppress_log()
1890
addNotSupported = getattr(result, 'addNotSupported', None)
1891
if addNotSupported is not None:
1892
result.addNotSupported(self, reason)
1894
self._do_skip(result, reason)
1378
def run(self, result=None):
1379
if result is None: result = self.defaultTestResult()
1380
for feature in getattr(self, '_test_needs_features', []):
1381
if not feature.available():
1382
result.startTest(self)
1383
if getattr(result, 'addNotSupported', None):
1384
result.addNotSupported(self, feature)
1386
result.addSuccess(self)
1387
result.stopTest(self)
1391
result.startTest(self)
1392
absent_attr = object()
1394
method_name = getattr(self, '_testMethodName', absent_attr)
1395
if method_name is absent_attr:
1397
method_name = getattr(self, '_TestCase__testMethodName')
1398
testMethod = getattr(self, method_name)
1402
if not self._bzr_test_setUp_run:
1404
"test setUp did not invoke "
1405
"bzrlib.tests.TestCase's setUp")
1406
except KeyboardInterrupt:
1409
except TestSkipped, e:
1410
self._do_skip(result, e.args[0])
1414
result.addError(self, sys.exc_info())
1422
except self.failureException:
1423
result.addFailure(self, sys.exc_info())
1424
except TestSkipped, e:
1426
reason = "No reason given."
1429
self._do_skip(result, reason)
1430
except KeyboardInterrupt:
1434
result.addError(self, sys.exc_info())
1438
if not self._bzr_test_tearDown_run:
1440
"test tearDown did not invoke "
1441
"bzrlib.tests.TestCase's tearDown")
1442
except KeyboardInterrupt:
1446
result.addError(self, sys.exc_info())
1449
if ok: result.addSuccess(self)
1451
result.stopTest(self)
1453
except TestNotApplicable:
1454
# Not moved from the result [yet].
1457
except KeyboardInterrupt:
1462
for attr_name in self.attrs_to_keep:
1463
if attr_name in self.__dict__:
1464
saved_attrs[attr_name] = self.__dict__[attr_name]
1465
self.__dict__ = saved_attrs
1469
self._log_contents = ''
1470
self._bzr_test_tearDown_run = True
1471
unittest.TestCase.tearDown(self)
1896
1473
def time(self, callable, *args, **kwargs):
1897
1474
"""Run callable and accrue the time it takes to the benchmark time.
3590
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3591
"""Generate profiling data for all activity between start and success.
3593
The profile data is appended to the test's _benchcalls attribute and can
3594
be accessed by the forwarded-to TestResult.
3054
class BZRTransformingResult(unittest.TestResult):
3596
While it might be cleaner do accumulate this in stopTest, addSuccess is
3597
where our existing output support for lsprof is, and this class aims to
3598
fit in with that: while it could be moved it's not necessary to accomplish
3599
test profiling, nor would it be dramatically cleaner.
3056
def __init__(self, target):
3057
unittest.TestResult.__init__(self)
3058
self.result = target
3602
3060
def startTest(self, test):
3603
self.profiler = bzrlib.lsprof.BzrProfiler()
3604
# Prevent deadlocks in tests that use lsprof: those tests will
3606
bzrlib.lsprof.BzrProfiler.profiler_block = 0
3607
self.profiler.start()
3608
testtools.ExtendedToOriginalDecorator.startTest(self, test)
3061
self.result.startTest(test)
3063
def stopTest(self, test):
3064
self.result.stopTest(test)
3066
def addError(self, test, err):
3067
feature = self._error_looks_like('UnavailableFeature: ', err)
3068
if feature is not None:
3069
self.result.addNotSupported(test, feature)
3071
self.result.addError(test, err)
3073
def addFailure(self, test, err):
3074
known = self._error_looks_like('KnownFailure: ', err)
3075
if known is not None:
3076
self.result._addKnownFailure(test, [KnownFailure,
3077
KnownFailure(known), None])
3079
self.result.addFailure(test, err)
3081
def addSkip(self, test, reason):
3082
self.result.addSkip(test, reason)
3610
3084
def addSuccess(self, test):
3611
stats = self.profiler.stop()
3613
calls = test._benchcalls
3614
except AttributeError:
3615
test._benchcalls = []
3616
calls = test._benchcalls
3617
calls.append(((test.id(), "", ""), stats))
3618
testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
3085
self.result.addSuccess(test)
3620
def stopTest(self, test):
3621
testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3622
self.profiler = None
3087
def _error_looks_like(self, prefix, err):
3088
"""Deserialize exception and returns the stringify value."""
3092
if isinstance(exc, subunit.RemoteException):
3093
# stringify the exception gives access to the remote traceback
3094
# We search the last line for 'prefix'
3095
lines = str(exc).split('\n')
3096
while lines and not lines[-1]:
3099
if lines[-1].startswith(prefix):
3100
value = lines[-1][len(prefix):]
3625
3104
# Controlled by "bzr selftest -E=..." option
3626
# Currently supported:
3627
# -Eallow_debug Will no longer clear debug.debug_flags() so it
3628
# preserves any flags supplied at the command line.
3629
# -Edisable_lock_checks Turns errors in mismatched locks into simple prints
3630
# rather than failing tests. And no longer raise
3631
# LockContention when fctnl locks are not being used
3632
# with proper exclusion rules.
3633
# -Ethreads Will display thread ident at creation/join time to
3634
# help track thread leaks
3636
# -Econfig_stats Will collect statistics using addDetail
3637
3105
selftest_debug_flags = set()
3867
3319
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3870
def _test_suite_testmod_names():
3871
"""Return the standard list of test module names to test."""
3874
'bzrlib.tests.blackbox',
3875
'bzrlib.tests.commands',
3876
'bzrlib.tests.doc_generate',
3877
'bzrlib.tests.per_branch',
3878
'bzrlib.tests.per_bzrdir',
3879
'bzrlib.tests.per_controldir',
3880
'bzrlib.tests.per_controldir_colo',
3881
'bzrlib.tests.per_foreign_vcs',
3882
'bzrlib.tests.per_interrepository',
3883
'bzrlib.tests.per_intertree',
3884
'bzrlib.tests.per_inventory',
3885
'bzrlib.tests.per_interbranch',
3886
'bzrlib.tests.per_lock',
3887
'bzrlib.tests.per_merger',
3888
'bzrlib.tests.per_transport',
3889
'bzrlib.tests.per_tree',
3890
'bzrlib.tests.per_pack_repository',
3891
'bzrlib.tests.per_repository',
3892
'bzrlib.tests.per_repository_chk',
3893
'bzrlib.tests.per_repository_reference',
3894
'bzrlib.tests.per_repository_vf',
3895
'bzrlib.tests.per_uifactory',
3896
'bzrlib.tests.per_versionedfile',
3897
'bzrlib.tests.per_workingtree',
3898
'bzrlib.tests.test__annotator',
3899
'bzrlib.tests.test__bencode',
3900
'bzrlib.tests.test__btree_serializer',
3901
'bzrlib.tests.test__chk_map',
3902
'bzrlib.tests.test__dirstate_helpers',
3903
'bzrlib.tests.test__groupcompress',
3904
'bzrlib.tests.test__known_graph',
3905
'bzrlib.tests.test__rio',
3906
'bzrlib.tests.test__simple_set',
3907
'bzrlib.tests.test__static_tuple',
3908
'bzrlib.tests.test__walkdirs_win32',
3909
'bzrlib.tests.test_ancestry',
3910
'bzrlib.tests.test_annotate',
3911
'bzrlib.tests.test_api',
3912
'bzrlib.tests.test_atomicfile',
3913
'bzrlib.tests.test_bad_files',
3914
'bzrlib.tests.test_bisect_multi',
3915
'bzrlib.tests.test_branch',
3916
'bzrlib.tests.test_branchbuilder',
3917
'bzrlib.tests.test_btree_index',
3918
'bzrlib.tests.test_bugtracker',
3919
'bzrlib.tests.test_bundle',
3920
'bzrlib.tests.test_bzrdir',
3921
'bzrlib.tests.test__chunks_to_lines',
3922
'bzrlib.tests.test_cache_utf8',
3923
'bzrlib.tests.test_chk_map',
3924
'bzrlib.tests.test_chk_serializer',
3925
'bzrlib.tests.test_chunk_writer',
3926
'bzrlib.tests.test_clean_tree',
3927
'bzrlib.tests.test_cleanup',
3928
'bzrlib.tests.test_cmdline',
3929
'bzrlib.tests.test_commands',
3930
'bzrlib.tests.test_commit',
3931
'bzrlib.tests.test_commit_merge',
3932
'bzrlib.tests.test_config',
3933
'bzrlib.tests.test_conflicts',
3934
'bzrlib.tests.test_controldir',
3935
'bzrlib.tests.test_counted_lock',
3936
'bzrlib.tests.test_crash',
3937
'bzrlib.tests.test_decorators',
3938
'bzrlib.tests.test_delta',
3939
'bzrlib.tests.test_debug',
3940
'bzrlib.tests.test_diff',
3941
'bzrlib.tests.test_directory_service',
3942
'bzrlib.tests.test_dirstate',
3943
'bzrlib.tests.test_email_message',
3944
'bzrlib.tests.test_eol_filters',
3945
'bzrlib.tests.test_errors',
3946
'bzrlib.tests.test_export',
3947
'bzrlib.tests.test_export_pot',
3948
'bzrlib.tests.test_extract',
3949
'bzrlib.tests.test_features',
3950
'bzrlib.tests.test_fetch',
3951
'bzrlib.tests.test_fixtures',
3952
'bzrlib.tests.test_fifo_cache',
3953
'bzrlib.tests.test_filters',
3954
'bzrlib.tests.test_filter_tree',
3955
'bzrlib.tests.test_ftp_transport',
3956
'bzrlib.tests.test_foreign',
3957
'bzrlib.tests.test_generate_docs',
3958
'bzrlib.tests.test_generate_ids',
3959
'bzrlib.tests.test_globbing',
3960
'bzrlib.tests.test_gpg',
3961
'bzrlib.tests.test_graph',
3962
'bzrlib.tests.test_groupcompress',
3963
'bzrlib.tests.test_hashcache',
3964
'bzrlib.tests.test_help',
3965
'bzrlib.tests.test_hooks',
3966
'bzrlib.tests.test_http',
3967
'bzrlib.tests.test_http_response',
3968
'bzrlib.tests.test_https_ca_bundle',
3969
'bzrlib.tests.test_i18n',
3970
'bzrlib.tests.test_identitymap',
3971
'bzrlib.tests.test_ignores',
3972
'bzrlib.tests.test_index',
3973
'bzrlib.tests.test_import_tariff',
3974
'bzrlib.tests.test_info',
3975
'bzrlib.tests.test_inv',
3976
'bzrlib.tests.test_inventory_delta',
3977
'bzrlib.tests.test_knit',
3978
'bzrlib.tests.test_lazy_import',
3979
'bzrlib.tests.test_lazy_regex',
3980
'bzrlib.tests.test_library_state',
3981
'bzrlib.tests.test_lock',
3982
'bzrlib.tests.test_lockable_files',
3983
'bzrlib.tests.test_lockdir',
3984
'bzrlib.tests.test_log',
3985
'bzrlib.tests.test_lru_cache',
3986
'bzrlib.tests.test_lsprof',
3987
'bzrlib.tests.test_mail_client',
3988
'bzrlib.tests.test_matchers',
3989
'bzrlib.tests.test_memorytree',
3990
'bzrlib.tests.test_merge',
3991
'bzrlib.tests.test_merge3',
3992
'bzrlib.tests.test_merge_core',
3993
'bzrlib.tests.test_merge_directive',
3994
'bzrlib.tests.test_mergetools',
3995
'bzrlib.tests.test_missing',
3996
'bzrlib.tests.test_msgeditor',
3997
'bzrlib.tests.test_multiparent',
3998
'bzrlib.tests.test_mutabletree',
3999
'bzrlib.tests.test_nonascii',
4000
'bzrlib.tests.test_options',
4001
'bzrlib.tests.test_osutils',
4002
'bzrlib.tests.test_osutils_encodings',
4003
'bzrlib.tests.test_pack',
4004
'bzrlib.tests.test_patch',
4005
'bzrlib.tests.test_patches',
4006
'bzrlib.tests.test_permissions',
4007
'bzrlib.tests.test_plugins',
4008
'bzrlib.tests.test_progress',
4009
'bzrlib.tests.test_pyutils',
4010
'bzrlib.tests.test_read_bundle',
4011
'bzrlib.tests.test_reconcile',
4012
'bzrlib.tests.test_reconfigure',
4013
'bzrlib.tests.test_registry',
4014
'bzrlib.tests.test_remote',
4015
'bzrlib.tests.test_rename_map',
4016
'bzrlib.tests.test_repository',
4017
'bzrlib.tests.test_revert',
4018
'bzrlib.tests.test_revision',
4019
'bzrlib.tests.test_revisionspec',
4020
'bzrlib.tests.test_revisiontree',
4021
'bzrlib.tests.test_rio',
4022
'bzrlib.tests.test_rules',
4023
'bzrlib.tests.test_sampler',
4024
'bzrlib.tests.test_scenarios',
4025
'bzrlib.tests.test_script',
4026
'bzrlib.tests.test_selftest',
4027
'bzrlib.tests.test_serializer',
4028
'bzrlib.tests.test_setup',
4029
'bzrlib.tests.test_sftp_transport',
4030
'bzrlib.tests.test_shelf',
4031
'bzrlib.tests.test_shelf_ui',
4032
'bzrlib.tests.test_smart',
4033
'bzrlib.tests.test_smart_add',
4034
'bzrlib.tests.test_smart_request',
4035
'bzrlib.tests.test_smart_transport',
4036
'bzrlib.tests.test_smtp_connection',
4037
'bzrlib.tests.test_source',
4038
'bzrlib.tests.test_ssh_transport',
4039
'bzrlib.tests.test_status',
4040
'bzrlib.tests.test_store',
4041
'bzrlib.tests.test_strace',
4042
'bzrlib.tests.test_subsume',
4043
'bzrlib.tests.test_switch',
4044
'bzrlib.tests.test_symbol_versioning',
4045
'bzrlib.tests.test_tag',
4046
'bzrlib.tests.test_test_server',
4047
'bzrlib.tests.test_testament',
4048
'bzrlib.tests.test_textfile',
4049
'bzrlib.tests.test_textmerge',
4050
'bzrlib.tests.test_cethread',
4051
'bzrlib.tests.test_timestamp',
4052
'bzrlib.tests.test_trace',
4053
'bzrlib.tests.test_transactions',
4054
'bzrlib.tests.test_transform',
4055
'bzrlib.tests.test_transport',
4056
'bzrlib.tests.test_transport_log',
4057
'bzrlib.tests.test_tree',
4058
'bzrlib.tests.test_treebuilder',
4059
'bzrlib.tests.test_treeshape',
4060
'bzrlib.tests.test_tsort',
4061
'bzrlib.tests.test_tuned_gzip',
4062
'bzrlib.tests.test_ui',
4063
'bzrlib.tests.test_uncommit',
4064
'bzrlib.tests.test_upgrade',
4065
'bzrlib.tests.test_upgrade_stacked',
4066
'bzrlib.tests.test_urlutils',
4067
'bzrlib.tests.test_utextwrap',
4068
'bzrlib.tests.test_version',
4069
'bzrlib.tests.test_version_info',
4070
'bzrlib.tests.test_versionedfile',
4071
'bzrlib.tests.test_weave',
4072
'bzrlib.tests.test_whitebox',
4073
'bzrlib.tests.test_win32utils',
4074
'bzrlib.tests.test_workingtree',
4075
'bzrlib.tests.test_workingtree_4',
4076
'bzrlib.tests.test_wsgi',
4077
'bzrlib.tests.test_xml',
4081
def _test_suite_modules_to_doctest():
4082
"""Return the list of modules to doctest."""
4084
# GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
4088
'bzrlib.branchbuilder',
4089
'bzrlib.decorators',
4091
'bzrlib.iterablefile',
4096
'bzrlib.symbol_versioning',
4098
'bzrlib.tests.fixtures',
4100
'bzrlib.transport.http',
4101
'bzrlib.version_info_formats.format_custom',
4105
3322
def test_suite(keep_only=None, starting_with=None):
4106
3323
"""Build and return TestSuite for the whole of bzrlib.
4113
3330
This function can be replaced if you need to change the default test
4114
3331
suite on a global basis, but it is not encouraged.
3335
'bzrlib.tests.blackbox',
3336
'bzrlib.tests.branch_implementations',
3337
'bzrlib.tests.bzrdir_implementations',
3338
'bzrlib.tests.commands',
3339
'bzrlib.tests.interrepository_implementations',
3340
'bzrlib.tests.intertree_implementations',
3341
'bzrlib.tests.inventory_implementations',
3342
'bzrlib.tests.per_interbranch',
3343
'bzrlib.tests.per_lock',
3344
'bzrlib.tests.per_repository',
3345
'bzrlib.tests.per_repository_chk',
3346
'bzrlib.tests.per_repository_reference',
3347
'bzrlib.tests.test__chk_map',
3348
'bzrlib.tests.test__dirstate_helpers',
3349
'bzrlib.tests.test__groupcompress',
3350
'bzrlib.tests.test__rio',
3351
'bzrlib.tests.test__walkdirs_win32',
3352
'bzrlib.tests.test_ancestry',
3353
'bzrlib.tests.test_annotate',
3354
'bzrlib.tests.test_api',
3355
'bzrlib.tests.test_atomicfile',
3356
'bzrlib.tests.test_bad_files',
3357
'bzrlib.tests.test_bencode',
3358
'bzrlib.tests.test_bisect_multi',
3359
'bzrlib.tests.test_branch',
3360
'bzrlib.tests.test_branchbuilder',
3361
'bzrlib.tests.test_btree_index',
3362
'bzrlib.tests.test_bugtracker',
3363
'bzrlib.tests.test_bundle',
3364
'bzrlib.tests.test_bzrdir',
3365
'bzrlib.tests.test__chunks_to_lines',
3366
'bzrlib.tests.test_cache_utf8',
3367
'bzrlib.tests.test_chk_map',
3368
'bzrlib.tests.test_chk_serializer',
3369
'bzrlib.tests.test_chunk_writer',
3370
'bzrlib.tests.test_clean_tree',
3371
'bzrlib.tests.test_commands',
3372
'bzrlib.tests.test_commit',
3373
'bzrlib.tests.test_commit_merge',
3374
'bzrlib.tests.test_config',
3375
'bzrlib.tests.test_conflicts',
3376
'bzrlib.tests.test_counted_lock',
3377
'bzrlib.tests.test_decorators',
3378
'bzrlib.tests.test_delta',
3379
'bzrlib.tests.test_debug',
3380
'bzrlib.tests.test_deprecated_graph',
3381
'bzrlib.tests.test_diff',
3382
'bzrlib.tests.test_directory_service',
3383
'bzrlib.tests.test_dirstate',
3384
'bzrlib.tests.test_email_message',
3385
'bzrlib.tests.test_eol_filters',
3386
'bzrlib.tests.test_errors',
3387
'bzrlib.tests.test_export',
3388
'bzrlib.tests.test_extract',
3389
'bzrlib.tests.test_fetch',
3390
'bzrlib.tests.test_fifo_cache',
3391
'bzrlib.tests.test_filters',
3392
'bzrlib.tests.test_ftp_transport',
3393
'bzrlib.tests.test_foreign',
3394
'bzrlib.tests.test_generate_docs',
3395
'bzrlib.tests.test_generate_ids',
3396
'bzrlib.tests.test_globbing',
3397
'bzrlib.tests.test_gpg',
3398
'bzrlib.tests.test_graph',
3399
'bzrlib.tests.test_groupcompress',
3400
'bzrlib.tests.test_hashcache',
3401
'bzrlib.tests.test_help',
3402
'bzrlib.tests.test_hooks',
3403
'bzrlib.tests.test_http',
3404
'bzrlib.tests.test_http_response',
3405
'bzrlib.tests.test_https_ca_bundle',
3406
'bzrlib.tests.test_identitymap',
3407
'bzrlib.tests.test_ignores',
3408
'bzrlib.tests.test_index',
3409
'bzrlib.tests.test_info',
3410
'bzrlib.tests.test_inv',
3411
'bzrlib.tests.test_inventory_delta',
3412
'bzrlib.tests.test_knit',
3413
'bzrlib.tests.test_lazy_import',
3414
'bzrlib.tests.test_lazy_regex',
3415
'bzrlib.tests.test_lockable_files',
3416
'bzrlib.tests.test_lockdir',
3417
'bzrlib.tests.test_log',
3418
'bzrlib.tests.test_lru_cache',
3419
'bzrlib.tests.test_lsprof',
3420
'bzrlib.tests.test_mail_client',
3421
'bzrlib.tests.test_memorytree',
3422
'bzrlib.tests.test_merge',
3423
'bzrlib.tests.test_merge3',
3424
'bzrlib.tests.test_merge_core',
3425
'bzrlib.tests.test_merge_directive',
3426
'bzrlib.tests.test_missing',
3427
'bzrlib.tests.test_msgeditor',
3428
'bzrlib.tests.test_multiparent',
3429
'bzrlib.tests.test_mutabletree',
3430
'bzrlib.tests.test_nonascii',
3431
'bzrlib.tests.test_options',
3432
'bzrlib.tests.test_osutils',
3433
'bzrlib.tests.test_osutils_encodings',
3434
'bzrlib.tests.test_pack',
3435
'bzrlib.tests.test_pack_repository',
3436
'bzrlib.tests.test_patch',
3437
'bzrlib.tests.test_patches',
3438
'bzrlib.tests.test_permissions',
3439
'bzrlib.tests.test_plugins',
3440
'bzrlib.tests.test_progress',
3441
'bzrlib.tests.test_read_bundle',
3442
'bzrlib.tests.test_reconcile',
3443
'bzrlib.tests.test_reconfigure',
3444
'bzrlib.tests.test_registry',
3445
'bzrlib.tests.test_remote',
3446
'bzrlib.tests.test_rename_map',
3447
'bzrlib.tests.test_repository',
3448
'bzrlib.tests.test_revert',
3449
'bzrlib.tests.test_revision',
3450
'bzrlib.tests.test_revisionspec',
3451
'bzrlib.tests.test_revisiontree',
3452
'bzrlib.tests.test_rio',
3453
'bzrlib.tests.test_rules',
3454
'bzrlib.tests.test_sampler',
3455
'bzrlib.tests.test_selftest',
3456
'bzrlib.tests.test_serializer',
3457
'bzrlib.tests.test_setup',
3458
'bzrlib.tests.test_sftp_transport',
3459
'bzrlib.tests.test_shelf',
3460
'bzrlib.tests.test_shelf_ui',
3461
'bzrlib.tests.test_smart',
3462
'bzrlib.tests.test_smart_add',
3463
'bzrlib.tests.test_smart_request',
3464
'bzrlib.tests.test_smart_transport',
3465
'bzrlib.tests.test_smtp_connection',
3466
'bzrlib.tests.test_source',
3467
'bzrlib.tests.test_ssh_transport',
3468
'bzrlib.tests.test_status',
3469
'bzrlib.tests.test_store',
3470
'bzrlib.tests.test_strace',
3471
'bzrlib.tests.test_subsume',
3472
'bzrlib.tests.test_switch',
3473
'bzrlib.tests.test_symbol_versioning',
3474
'bzrlib.tests.test_tag',
3475
'bzrlib.tests.test_testament',
3476
'bzrlib.tests.test_textfile',
3477
'bzrlib.tests.test_textmerge',
3478
'bzrlib.tests.test_timestamp',
3479
'bzrlib.tests.test_trace',
3480
'bzrlib.tests.test_transactions',
3481
'bzrlib.tests.test_transform',
3482
'bzrlib.tests.test_transport',
3483
'bzrlib.tests.test_transport_implementations',
3484
'bzrlib.tests.test_transport_log',
3485
'bzrlib.tests.test_tree',
3486
'bzrlib.tests.test_treebuilder',
3487
'bzrlib.tests.test_tsort',
3488
'bzrlib.tests.test_tuned_gzip',
3489
'bzrlib.tests.test_ui',
3490
'bzrlib.tests.test_uncommit',
3491
'bzrlib.tests.test_upgrade',
3492
'bzrlib.tests.test_upgrade_stacked',
3493
'bzrlib.tests.test_urlutils',
3494
'bzrlib.tests.test_version',
3495
'bzrlib.tests.test_version_info',
3496
'bzrlib.tests.test_versionedfile',
3497
'bzrlib.tests.test_weave',
3498
'bzrlib.tests.test_whitebox',
3499
'bzrlib.tests.test_win32utils',
3500
'bzrlib.tests.test_workingtree',
3501
'bzrlib.tests.test_workingtree_4',
3502
'bzrlib.tests.test_wsgi',
3503
'bzrlib.tests.test_xml',
3504
'bzrlib.tests.tree_implementations',
3505
'bzrlib.tests.workingtree_implementations',
4117
3508
loader = TestUtil.TestLoader()
4119
if keep_only is not None:
4120
id_filter = TestIdList(keep_only)
4121
3510
if starting_with:
3511
starting_with = [test_prefix_alias_registry.resolve_alias(start)
3512
for start in starting_with]
4122
3513
# We take precedence over keep_only because *at loading time* using
4123
3514
# both options means we will load less tests for the same final result.
4124
3515
def interesting_module(name):
4308
3706
:param new_id: The id to assign to it.
4309
3707
:return: The new test.
4311
new_test = copy.copy(test)
3709
from copy import deepcopy
3710
new_test = deepcopy(test)
4312
3711
new_test.id = lambda: new_id
4313
# XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4314
# causes cloned tests to share the 'details' dict. This makes it hard to
4315
# read the test output for parameterized tests, because tracebacks will be
4316
# associated with irrelevant tests.
4318
details = new_test._TestCase__details
4319
except AttributeError:
4320
# must be a different version of testtools than expected. Do nothing.
4323
# Reset the '__details' dict.
4324
new_test._TestCase__details = {}
4325
3712
return new_test
4328
def permute_tests_for_extension(standard_tests, loader, py_module_name,
4330
"""Helper for permutating tests against an extension module.
4332
This is meant to be used inside a modules 'load_tests()' function. It will
4333
create 2 scenarios, and cause all tests in the 'standard_tests' to be run
4334
against both implementations. Setting 'test.module' to the appropriate
4335
module. See bzrlib.tests.test__chk_map.load_tests as an example.
4337
:param standard_tests: A test suite to permute
4338
:param loader: A TestLoader
4339
:param py_module_name: The python path to a python module that can always
4340
be loaded, and will be considered the 'python' implementation. (eg
4341
'bzrlib._chk_map_py')
4342
:param ext_module_name: The python path to an extension module. If the
4343
module cannot be loaded, a single test will be added, which notes that
4344
the module is not available. If it can be loaded, all standard_tests
4345
will be run against that module.
4346
:return: (suite, feature) suite is a test-suite that has all the permuted
4347
tests. feature is the Feature object that can be used to determine if
4348
the module is available.
4351
from bzrlib.tests.features import ModuleAvailableFeature
4352
py_module = pyutils.get_named_object(py_module_name)
4354
('python', {'module': py_module}),
4356
suite = loader.suiteClass()
4357
feature = ModuleAvailableFeature(ext_module_name)
4358
if feature.available():
4359
scenarios.append(('C', {'module': feature.module}))
4361
# the compiled module isn't available, so we add a failing test
4362
class FailWithoutFeature(TestCase):
4363
def test_fail(self):
4364
self.requireFeature(feature)
4365
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4366
result = multiply_tests(standard_tests, scenarios, suite)
4367
return result, feature
4370
def _rmtree_temp_dir(dirname, test_id=None):
3715
def _rmtree_temp_dir(dirname):
4371
3716
# If LANG=C we probably have created some bogus paths
4372
3717
# which rmtree(unicode) will fail to delete
4373
3718
# so make sure we are using rmtree(str) to delete everything
4383
3728
osutils.rmtree(dirname)
4384
3729
except OSError, e:
4385
# We don't want to fail here because some useful display will be lost
4386
# otherwise. Polluting the tmp dir is bad, but not giving all the
4387
# possible info to the test runner is even worse.
4389
ui.ui_factory.clear_term()
4390
sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4391
# Ugly, but the last thing we want here is fail, so bear with it.
4392
printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4393
).encode('ascii', 'replace')
4394
sys.stderr.write('Unable to remove testing dir %s\n%s'
4395
% (os.path.basename(dirname), printable_e))
3730
if sys.platform == 'win32' and e.errno == errno.EACCES:
3731
sys.stderr.write('Permission denied: '
3732
'unable to remove testing dir '
3734
% (os.path.basename(dirname), e))
3739
class Feature(object):
3740
"""An operating system Feature."""
3743
self._available = None
3745
def available(self):
3746
"""Is the feature available?
3748
:return: True if the feature is available.
3750
if self._available is None:
3751
self._available = self._probe()
3752
return self._available
3755
"""Implement this method in concrete features.
3757
:return: True if the feature is available.
3759
raise NotImplementedError
3762
if getattr(self, 'feature_name', None):
3763
return self.feature_name()
3764
return self.__class__.__name__
3767
class _SymlinkFeature(Feature):
3770
return osutils.has_symlinks()
3772
def feature_name(self):
3775
SymlinkFeature = _SymlinkFeature()
3778
class _HardlinkFeature(Feature):
3781
return osutils.has_hardlinks()
3783
def feature_name(self):
3786
HardlinkFeature = _HardlinkFeature()
3789
class _OsFifoFeature(Feature):
3792
return getattr(os, 'mkfifo', None)
3794
def feature_name(self):
3795
return 'filesystem fifos'
3797
OsFifoFeature = _OsFifoFeature()
3800
class _UnicodeFilenameFeature(Feature):
3801
"""Does the filesystem support Unicode filenames?"""
3805
# Check for character combinations unlikely to be covered by any
3806
# single non-unicode encoding. We use the characters
3807
# - greek small letter alpha (U+03B1) and
3808
# - braille pattern dots-123456 (U+283F).
3809
os.stat(u'\u03b1\u283f')
3810
except UnicodeEncodeError:
3812
except (IOError, OSError):
3813
# The filesystem allows the Unicode filename but the file doesn't
3817
# The filesystem allows the Unicode filename and the file exists,
3821
UnicodeFilenameFeature = _UnicodeFilenameFeature()
4398
3824
def probe_unicode_in_user_encoding():
3857
class _HTTPSServerFeature(Feature):
3858
"""Some tests want an https Server, check if one is available.
3860
Right now, the only way this is available is under python2.6 which provides
3871
def feature_name(self):
3872
return 'HTTPSServer'
3875
HTTPSServerFeature = _HTTPSServerFeature()
3878
class _UnicodeFilename(Feature):
3879
"""Does the filesystem support Unicode filenames?"""
3884
except UnicodeEncodeError:
3886
except (IOError, OSError):
3887
# The filesystem allows the Unicode filename but the file doesn't
3891
# The filesystem allows the Unicode filename and the file exists,
3895
UnicodeFilename = _UnicodeFilename()
3898
class _UTF8Filesystem(Feature):
3899
"""Is the filesystem UTF-8?"""
3902
if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
3906
UTF8Filesystem = _UTF8Filesystem()
3909
class _CaseInsCasePresFilenameFeature(Feature):
3910
"""Is the file-system case insensitive, but case-preserving?"""
3913
fileno, name = tempfile.mkstemp(prefix='MixedCase')
3915
# first check truly case-preserving for created files, then check
3916
# case insensitive when opening existing files.
3917
name = osutils.normpath(name)
3918
base, rel = osutils.split(name)
3919
found_rel = osutils.canonical_relpath(base, name)
3920
return (found_rel == rel
3921
and os.path.isfile(name.upper())
3922
and os.path.isfile(name.lower()))
3927
def feature_name(self):
3928
return "case-insensitive case-preserving filesystem"
3930
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
3933
class _CaseInsensitiveFilesystemFeature(Feature):
3934
"""Check if underlying filesystem is case-insensitive but *not* case
3937
# Note that on Windows, Cygwin, MacOS etc, the file-systems are far
3938
# more likely to be case preserving, so this case is rare.
3941
if CaseInsCasePresFilenameFeature.available():
3944
if TestCaseWithMemoryTransport.TEST_ROOT is None:
3945
root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
3946
TestCaseWithMemoryTransport.TEST_ROOT = root
3948
root = TestCaseWithMemoryTransport.TEST_ROOT
3949
tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
3951
name_a = osutils.pathjoin(tdir, 'a')
3952
name_A = osutils.pathjoin(tdir, 'A')
3954
result = osutils.isdir(name_A)
3955
_rmtree_temp_dir(tdir)
3958
def feature_name(self):
3959
return 'case-insensitive filesystem'
3961
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
3964
class _SubUnitFeature(Feature):
3965
"""Check if subunit is available."""
3974
def feature_name(self):
3977
SubUnitFeature = _SubUnitFeature()
4431
3978
# Only define SubUnitBzrRunner if subunit is available.
4433
3980
from subunit import TestProtocolClient
4434
from subunit.test_results import AutoTimingTestResultDecorator
4435
class SubUnitBzrProtocolClient(TestProtocolClient):
4437
def addSuccess(self, test, details=None):
4438
# The subunit client always includes the details in the subunit
4439
# stream, but we don't want to include it in ours.
4440
if details is not None and 'log' in details:
4442
return super(SubUnitBzrProtocolClient, self).addSuccess(
4445
3981
class SubUnitBzrRunner(TextTestRunner):
4446
3982
def run(self, test):
4447
result = AutoTimingTestResultDecorator(
4448
SubUnitBzrProtocolClient(self.stream))
3983
result = TestProtocolClient(self.stream)
4449
3984
test.run(result)
4451
3986
except ImportError:
4455
@deprecated_function(deprecated_in((2, 5, 0)))
4456
def ModuleAvailableFeature(name):
4457
from bzrlib.tests import features
4458
return features.ModuleAvailableFeature(name)