29
31
from cStringIO import StringIO
38
from pprint import pformat
43
from subprocess import Popen, PIPE, STDOUT
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
62
52
from bzrlib import (
66
commands as _mod_commands,
76
plugin as _mod_plugin,
83
transport as _mod_transport,
68
import bzrlib.commands
69
import bzrlib.timestamp
71
import bzrlib.inventory
72
import bzrlib.iterablefile
87
75
import bzrlib.lsprof
88
76
except ImportError:
89
77
# lsprof not available
91
from bzrlib.smart import client, request
92
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
96
85
from bzrlib.symbol_versioning import (
97
87
deprecated_function,
100
from bzrlib.tests import (
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
106
105
from bzrlib.ui import NullProgressView
107
106
from bzrlib.ui.text import TextUIFactory
108
from bzrlib.tests.features import _CompatabilityThunkFeature
107
import bzrlib.version_info_formats.format_custom
108
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
110
110
# Mark this python module as being part of the implementation
111
111
# of unittest: this gives us better tracebacks where the last
112
112
# shown frame is the test code, not our assertXYZ.
115
default_transport = test_server.LocalURLServer
118
_unitialized_attr = object()
119
"""A sentinel needed to act as a default value in a method signature."""
115
default_transport = LocalURLServer
122
117
# Subunit result codes, defined here to prevent a hard dependency on subunit.
123
118
SUBUNIT_SEEK_SET = 0
124
119
SUBUNIT_SEEK_CUR = 1
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):
122
class ExtendedTestResult(unittest._TextTestResult):
244
123
"""Accepts, reports and accumulates the results of running tests.
246
125
Compared to the unittest version this class adds support for
295
174
self._overall_start_time = time.time()
296
175
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" %
178
# nb: called stopTestRun in the version of this that Python merged
179
# upstream, according to lifeless 20090803
341
181
ok = self.wasStrictlySuccessful()
343
183
ok = self.wasSuccessful()
344
if self._first_thread_leaker_id:
185
self.stream.write('tests passed\n')
187
self.stream.write('tests failed\n')
188
if TestCase._first_thread_leaker_id:
345
189
self.stream.write(
346
190
'%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):
191
TestCase._first_thread_leaker_id,
192
TestCase._leaking_threads_tests))
194
def _extractBenchmarkTime(self, testCase):
358
195
"""Add a benchmark time for the current test case."""
359
if details and 'benchtime' in details:
360
return float(''.join(details['benchtime'].iter_bytes()))
361
196
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
372
198
def _elapsedTestTimeString(self):
373
199
"""Return a time string for the overall time the current test has taken."""
374
return self._formatTime(self._delta_to_float(
375
self._now() - self._start_datetime, 3))
200
return self._formatTime(time.time() - self._start_time)
377
202
def _testTimeString(self, testCase):
378
203
benchmark_time = self._extractBenchmarkTime(testCase)
390
215
def _shortened_test_description(self, test):
392
what = re.sub(r'^bzrlib\.tests\.', '', what)
217
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', 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]
403
220
def startTest(self, test):
404
super(ExtendedTestResult, self).startTest(test)
221
unittest.TestResult.startTest(self, test)
405
222
if self.count == 0:
406
223
self.startTests()
408
224
self.report_test_start(test)
409
225
test.number = self.count
410
226
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
228
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
230
if getattr(sys, 'frozen', None) is None:
231
bzr_path = osutils.realpath(sys.argv[0])
233
bzr_path = sys.executable
235
'testing: %s\n' % (bzr_path,))
238
bzrlib.__path__[0],))
240
' bzr-%s python-%s %s\n' % (
241
bzrlib.version_string,
242
bzrlib._format_version_tuple(sys.version_info),
243
platform.platform(aliased=1),
245
self.stream.write('\n')
448
247
def _recordTestStartTime(self):
449
248
"""Record that a test has started."""
450
self._start_datetime = self._now()
249
self._start_time = time.time()
251
def _cleanupLogFile(self, test):
252
# We can only do this if we have one of our TestCases, not if
254
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
255
if setKeepLogfile is not None:
452
258
def addError(self, test, err):
453
259
"""Tell result that test finished with an error.
468
280
Called from the TestCase run() method when the test
469
281
fails because e.g. an assert() method failed.
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)
283
self._testConcluded(test)
284
if isinstance(err[1], KnownFailure):
285
return self._addKnownFailure(test, err)
287
unittest.TestResult.addFailure(self, test, err)
288
self.failure_count += 1
289
self.report_failure(test, err)
292
self._cleanupLogFile(test)
478
def addSuccess(self, test, details=None):
294
def addSuccess(self, test):
479
295
"""Tell result that test completed successfully.
481
297
Called from the TestCase run()
299
self._testConcluded(test)
483
300
if self._bench_history is not None:
484
benchmark_time = self._extractBenchmarkTime(test, details)
301
benchmark_time = self._extractBenchmarkTime(test)
485
302
if benchmark_time is not None:
486
303
self._bench_history.write("%s %s\n" % (
487
304
self._formatTime(benchmark_time),
489
306
self.report_success(test)
490
super(ExtendedTestResult, self).addSuccess(test)
307
self._cleanupLogFile(test)
308
unittest.TestResult.addSuccess(self, test)
491
309
test._log_contents = ''
493
def addExpectedFailure(self, test, err):
311
def _testConcluded(self, test):
312
"""Common code when a test has finished.
314
Called regardless of whether it succeded, failed, etc.
318
def _addKnownFailure(self, test, err):
494
319
self.known_failure_count += 1
495
320
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()))
510
322
def addNotSupported(self, test, feature):
511
323
"""The test will not be run because of a missing feature.
513
325
# this can be called in two different ways: it may be that the
514
# test started running, and then raised (through requireFeature)
326
# test started running, and then raised (through addError)
515
327
# UnavailableFeature. Alternatively this method can be called
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.
328
# while probing for features before running the tests; in that
329
# case we will see startTest and stopTest, but the test will never
519
331
self.unsupported.setdefault(str(feature), 0)
520
332
self.unsupported[str(feature)] += 1
521
333
self.report_unsupported(test, feature)
725
531
return '%s%s' % (indent, err[1])
727
533
def report_error(self, test, err):
728
self.stream.write('ERROR %s\n%s\n'
534
self.stream.writeln('ERROR %s\n%s'
729
535
% (self._testTimeString(test),
730
536
self._error_summary(err)))
732
538
def report_failure(self, test, err):
733
self.stream.write(' FAIL %s\n%s\n'
539
self.stream.writeln(' FAIL %s\n%s'
734
540
% (self._testTimeString(test),
735
541
self._error_summary(err)))
737
543
def report_known_failure(self, test, err):
738
self.stream.write('XFAIL %s\n%s\n'
544
self.stream.writeln('XFAIL %s\n%s'
739
545
% (self._testTimeString(test),
740
546
self._error_summary(err)))
742
def report_unexpected_success(self, test, reason):
743
self.stream.write(' FAIL %s\n%s: %s\n'
744
% (self._testTimeString(test),
745
"Unexpected success. Should have failed",
748
548
def report_success(self, test):
749
self.stream.write(' OK %s\n' % self._testTimeString(test))
549
self.stream.writeln(' OK %s' % self._testTimeString(test))
750
550
for bench_called, stats in getattr(test, '_benchcalls', []):
751
self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
551
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
752
552
stats.pprint(file=self.stream)
753
553
# flush the stream so that we get smooth output. This verbose mode is
754
554
# used to show the output in PQM.
755
555
self.stream.flush()
757
557
def report_skip(self, test, reason):
758
self.stream.write(' SKIP %s\n%s\n'
558
self.stream.writeln(' SKIP %s\n%s'
759
559
% (self._testTimeString(test), reason))
761
def report_not_applicable(self, test, reason):
762
self.stream.write(' N/A %s\n %s\n'
763
% (self._testTimeString(test), reason))
561
def report_not_applicable(self, test, skip_excinfo):
562
self.stream.writeln(' N/A %s\n%s'
563
% (self._testTimeString(test),
564
self._error_summary(skip_excinfo)))
765
566
def report_unsupported(self, test, feature):
766
567
"""test cannot be run because feature is missing."""
767
self.stream.write("NODEP %s\n The feature '%s' is not available.\n"
568
self.stream.writeln("NODEP %s\n The feature '%s' is not available."
768
569
%(self._testTimeString(test), feature))
778
579
bench_history=None,
780
result_decorators=None,
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
583
self.stream = unittest._WritelnDecorator(stream)
806
584
self.descriptions = descriptions
807
585
self.verbosity = verbosity
808
586
self._bench_history = bench_history
587
self.list_only = list_only
809
588
self._strict = strict
810
self._result_decorators = result_decorators or []
812
590
def run(self, test):
813
591
"Run the given test case or test suite."
592
startTime = time.time()
814
593
if self.verbosity == 1:
815
594
result_class = TextTestResult
816
595
elif self.verbosity >= 2:
817
596
result_class = VerboseTestResult
818
original_result = result_class(self.stream,
597
result = result_class(self.stream,
819
598
self.descriptions,
821
600
bench_history=self._bench_history,
822
601
strict=self._strict,
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()
835
# higher level code uses our extended protocol to determine
836
# what exit code to give.
837
return original_result
603
result.stop_early = self.stop_on_failure
604
result.report_starting()
606
if self.verbosity >= 2:
607
self.stream.writeln("Listing tests only ...\n")
609
for t in iter_suite_tests(test):
610
self.stream.writeln("%s" % (t.id()))
619
if isinstance(test, testtools.ConcurrentTestSuite):
620
# We need to catch bzr specific behaviors
621
test.run(BZRTransformingResult(result))
624
run = result.testsRun
626
stopTime = time.time()
627
timeTaken = stopTime - startTime
629
self.stream.writeln(result.separator2)
630
self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
631
run, run != 1 and "s" or "", timeTaken))
632
self.stream.writeln()
633
if not result.wasSuccessful():
634
self.stream.write("FAILED (")
635
failed, errored = map(len, (result.failures, result.errors))
637
self.stream.write("failures=%d" % failed)
639
if failed: self.stream.write(", ")
640
self.stream.write("errors=%d" % errored)
641
if result.known_failure_count:
642
if failed or errored: self.stream.write(", ")
643
self.stream.write("known_failure_count=%d" %
644
result.known_failure_count)
645
self.stream.writeln(")")
647
if result.known_failure_count:
648
self.stream.writeln("OK (known_failures=%d)" %
649
result.known_failure_count)
651
self.stream.writeln("OK")
652
if result.skip_count > 0:
653
skipped = result.skip_count
654
self.stream.writeln('%d test%s skipped' %
655
(skipped, skipped != 1 and "s" or ""))
656
if result.unsupported:
657
for feature, count in sorted(result.unsupported.items()):
658
self.stream.writeln("Missing feature '%s' skipped %d tests." %
840
664
def iter_suite_tests(suite):
991
790
routine, and to build and check bzr trees.
993
792
In addition to the usual method of overriding tearDown(), this class also
994
allows subclasses to register cleanup functions via addCleanup, which are
793
allows subclasses to register functions into the _cleanups list, which is
995
794
run in order as the object is torn down. It's less likely this will be
996
795
accidentally overlooked.
798
_active_threads = None
799
_leaking_threads_tests = 0
800
_first_thread_leaker_id = None
801
_log_file_name = None
803
_keep_log_file = False
1000
804
# record lsprof data when performing benchmark calls.
1001
805
_gather_lsprof_in_benchmarks = False
806
attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
807
'_log_contents', '_log_file_name', '_benchtime',
808
'_TestCase__testMethodName', '_TestCase__testMethodDoc',)
1003
810
def __init__(self, methodName='testMethod'):
1004
811
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))
813
self._bzr_test_setUp_run = False
814
self._bzr_test_tearDown_run = False
1011
816
def 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)
817
unittest.TestCase.setUp(self)
818
self._bzr_test_setUp_run = True
1024
819
self._cleanEnvironment()
1026
if bzrlib.global_state is not None:
1027
self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1028
config.CommandLineStore())
1030
820
self._silenceUI()
1031
821
self._startLogFile()
1032
822
self._benchcalls = []
1033
823
self._benchtime = None
1034
824
self._clear_hooks()
1035
self._track_transports()
1036
825
self._track_locks()
1037
826
self._clear_debug_flags()
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)
827
TestCase._active_threads = threading.activeCount()
828
self.addCleanup(self._check_leaked_threads)
1052
830
def debug(self):
1053
831
# debug a frame up.
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,))
833
pdb.Pdb().set_trace(sys._getframe().f_back)
835
def _check_leaked_threads(self):
836
active = threading.activeCount()
837
leaked_threads = active - TestCase._active_threads
838
TestCase._active_threads = active
840
TestCase._leaking_threads_tests += 1
841
if TestCase._first_thread_leaker_id is None:
842
TestCase._first_thread_leaker_id = self.id()
1119
844
def _clear_debug_flags(self):
1120
845
"""Prevent externally set debug flags affecting tests.
1213
928
def _lock_broken(self, result):
1214
929
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.")
1343
931
def _ndiff_strings(self, a, b):
1344
932
"""Return ndiff between two strings containing lines.
1778
1346
debug.debug_flags.discard('strict_locks')
1780
def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1781
"""Overrides an object attribute restoring it after the test.
1783
:note: This should be used with discretion; you should think about
1784
whether it's better to make the code testable without monkey-patching.
1786
:param obj: The object that will be mutated.
1788
:param attr_name: The attribute name we want to preserve/override in
1791
:param new: The optional value we want to set the attribute to.
1793
:returns: The actual attr value.
1795
# The actual value is captured by the call below
1796
value = getattr(obj, attr_name, _unitialized_attr)
1797
if value is _unitialized_attr:
1798
# When the test completes, the attribute should not exist, but if
1799
# we aren't setting a value, we don't need to do anything.
1800
if new is not _unitialized_attr:
1801
self.addCleanup(delattr, obj, attr_name)
1803
self.addCleanup(setattr, obj, attr_name, value)
1804
if new is not _unitialized_attr:
1805
setattr(obj, attr_name, new)
1808
def overrideEnv(self, name, new):
1809
"""Set an environment variable, and reset it after the test.
1811
:param name: The environment variable name.
1813
:param new: The value to set the variable to. If None, the
1814
variable is deleted from the environment.
1816
:returns: The actual variable value.
1818
value = osutils.set_or_unset_env(name, new)
1819
self.addCleanup(osutils.set_or_unset_env, name, value)
1822
def recordCalls(self, obj, attr_name):
1823
"""Monkeypatch in a wrapper that will record calls.
1825
The monkeypatch is automatically removed when the test concludes.
1827
:param obj: The namespace holding the reference to be replaced;
1828
typically a module, class, or object.
1829
:param attr_name: A string for the name of the attribute to
1831
:returns: A list that will be extended with one item every time the
1832
function is called, with a tuple of (args, kwargs).
1836
def decorator(*args, **kwargs):
1837
calls.append((args, kwargs))
1838
return orig(*args, **kwargs)
1839
orig = self.overrideAttr(obj, attr_name, decorator)
1348
def addCleanup(self, callable, *args, **kwargs):
1349
"""Arrange to run a callable when this case is torn down.
1351
Callables are run in the reverse of the order they are registered,
1352
ie last-in first-out.
1354
self._cleanups.append((callable, args, kwargs))
1842
1356
def _cleanEnvironment(self):
1843
for name, value in isolated_environ.iteritems():
1844
self.overrideEnv(name, value)
1358
'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1359
'HOME': os.getcwd(),
1360
# bzr now uses the Win32 API and doesn't rely on APPDATA, but the
1361
# tests do check our impls match APPDATA
1362
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
1366
'BZREMAIL': None, # may still be present in the environment
1368
'BZR_PROGRESS_BAR': None,
1370
'BZR_PLUGIN_PATH': None,
1371
# Make sure that any text ui tests are consistent regardless of
1372
# the environment the test case is run in; you may want tests that
1373
# test other combinations. 'dumb' is a reasonable guess for tests
1374
# going to a pipe or a StringIO.
1379
'SSH_AUTH_SOCK': None,
1383
'https_proxy': None,
1384
'HTTPS_PROXY': None,
1389
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
1390
# least. If you do (care), please update this comment
1394
'BZR_REMOTE_PATH': None,
1397
self.addCleanup(self._restoreEnvironment)
1398
for name, value in new_env.iteritems():
1399
self._captureVar(name, value)
1401
def _captureVar(self, name, newvalue):
1402
"""Set an environment variable, and reset it when finished."""
1403
self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1405
def _restore_debug_flags(self):
1406
debug.debug_flags.clear()
1407
debug.debug_flags.update(self._preserved_debug_flags)
1409
def _restoreEnvironment(self):
1410
for name, value in self.__old_env.iteritems():
1411
osutils.set_or_unset_env(name, value)
1846
1413
def _restoreHooks(self):
1847
1414
for klass, (name, hooks) in self._preserved_hooks.items():
1848
1415
setattr(klass, name, hooks)
1849
self._preserved_hooks.clear()
1850
bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1851
self._preserved_lazy_hooks.clear()
1853
1417
def knownFailure(self, reason):
1854
"""Declare that this test fails for a known reason
1856
Tests that are known to fail should generally be using expectedFailure
1857
with an appropriate reverse assertion if a change could cause the test
1858
to start passing. Conversely if the test has no immediate prospect of
1859
succeeding then using skip is more suitable.
1861
When this method is called while an exception is being handled, that
1862
traceback will be used, otherwise a new exception will be thrown to
1863
provide one but won't be reported.
1865
self._add_reason(reason)
1867
exc_info = sys.exc_info()
1868
if exc_info != (None, None, None):
1869
self._report_traceback(exc_info)
1872
raise self.failureException(reason)
1873
except self.failureException:
1874
exc_info = sys.exc_info()
1875
# GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
1876
raise testtools.testcase._ExpectedFailure(exc_info)
1880
def _suppress_log(self):
1881
"""Remove the log info from details."""
1882
self.discardDetail('log')
1418
"""This test has failed for some known reason."""
1419
raise KnownFailure(reason)
1884
1421
def _do_skip(self, result, reason):
1885
self._suppress_log()
1886
1422
addSkip = getattr(result, 'addSkip', None)
1887
1423
if not callable(addSkip):
1888
result.addSuccess(result)
1424
result.addError(self, sys.exc_info())
1890
1426
addSkip(self, reason)
1893
def _do_known_failure(self, result, e):
1894
self._suppress_log()
1895
err = sys.exc_info()
1896
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1897
if addExpectedFailure is not None:
1898
addExpectedFailure(self, err)
1900
result.addSuccess(self)
1903
def _do_not_applicable(self, result, e):
1905
reason = 'No reason given'
1908
self._suppress_log ()
1909
addNotApplicable = getattr(result, 'addNotApplicable', None)
1910
if addNotApplicable is not None:
1911
result.addNotApplicable(self, reason)
1913
self._do_skip(result, reason)
1916
def _report_skip(self, result, err):
1917
"""Override the default _report_skip.
1919
We want to strip the 'log' detail. If we waint until _do_skip, it has
1920
already been formatted into the 'reason' string, and we can't pull it
1923
self._suppress_log()
1924
super(TestCase, self)._report_skip(self, result, err)
1927
def _report_expected_failure(self, result, err):
1930
See _report_skip for motivation.
1932
self._suppress_log()
1933
super(TestCase, self)._report_expected_failure(self, result, err)
1936
def _do_unsupported_or_skip(self, result, e):
1938
self._suppress_log()
1939
addNotSupported = getattr(result, 'addNotSupported', None)
1940
if addNotSupported is not None:
1941
result.addNotSupported(self, reason)
1943
self._do_skip(result, reason)
1428
def run(self, result=None):
1429
if result is None: result = self.defaultTestResult()
1430
for feature in getattr(self, '_test_needs_features', []):
1431
if not feature.available():
1432
result.startTest(self)
1433
if getattr(result, 'addNotSupported', None):
1434
result.addNotSupported(self, feature)
1436
result.addSuccess(self)
1437
result.stopTest(self)
1441
result.startTest(self)
1442
absent_attr = object()
1444
method_name = getattr(self, '_testMethodName', absent_attr)
1445
if method_name is absent_attr:
1447
method_name = getattr(self, '_TestCase__testMethodName')
1448
testMethod = getattr(self, method_name)
1452
if not self._bzr_test_setUp_run:
1454
"test setUp did not invoke "
1455
"bzrlib.tests.TestCase's setUp")
1456
except KeyboardInterrupt:
1459
except TestSkipped, e:
1460
self._do_skip(result, e.args[0])
1464
result.addError(self, sys.exc_info())
1472
except self.failureException:
1473
result.addFailure(self, sys.exc_info())
1474
except TestSkipped, e:
1476
reason = "No reason given."
1479
self._do_skip(result, reason)
1480
except KeyboardInterrupt:
1484
result.addError(self, sys.exc_info())
1488
if not self._bzr_test_tearDown_run:
1490
"test tearDown did not invoke "
1491
"bzrlib.tests.TestCase's tearDown")
1492
except KeyboardInterrupt:
1496
result.addError(self, sys.exc_info())
1499
if ok: result.addSuccess(self)
1501
result.stopTest(self)
1503
except TestNotApplicable:
1504
# Not moved from the result [yet].
1507
except KeyboardInterrupt:
1512
for attr_name in self.attrs_to_keep:
1513
if attr_name in self.__dict__:
1514
saved_attrs[attr_name] = self.__dict__[attr_name]
1515
self.__dict__ = saved_attrs
1519
self._log_contents = ''
1520
self._bzr_test_tearDown_run = True
1521
unittest.TestCase.tearDown(self)
1945
1523
def time(self, callable, *args, **kwargs):
1946
1524
"""Run callable and accrue the time it takes to the benchmark time.
3452
2926
"""A decorator which excludes test matching an exclude pattern."""
3454
2928
def __init__(self, suite, exclude_pattern):
3455
super(ExcludeDecorator, self).__init__(
3456
exclude_tests_by_re(suite, exclude_pattern))
2929
TestDecorator.__init__(self, suite)
2930
self.exclude_pattern = exclude_pattern
2931
self.excluded = False
2935
return iter(self._tests)
2936
self.excluded = True
2937
suite = exclude_tests_by_re(self, self.exclude_pattern)
2939
self.addTests(suite)
2940
return iter(self._tests)
3459
2943
class FilterTestsDecorator(TestDecorator):
3460
2944
"""A decorator which filters tests to those matching a pattern."""
3462
2946
def __init__(self, suite, pattern):
3463
super(FilterTestsDecorator, self).__init__(
3464
filter_suite_by_re(suite, pattern))
2947
TestDecorator.__init__(self, suite)
2948
self.pattern = pattern
2949
self.filtered = False
2953
return iter(self._tests)
2954
self.filtered = True
2955
suite = filter_suite_by_re(self, self.pattern)
2957
self.addTests(suite)
2958
return iter(self._tests)
3467
2961
class RandomDecorator(TestDecorator):
3468
2962
"""A decorator which randomises the order of its tests."""
3470
2964
def __init__(self, suite, random_seed, stream):
3471
random_seed = self.actual_seed(random_seed)
3472
stream.write("Randomizing test order using seed %s\n\n" %
2965
TestDecorator.__init__(self, suite)
2966
self.random_seed = random_seed
2967
self.randomised = False
2968
self.stream = stream
2972
return iter(self._tests)
2973
self.randomised = True
2974
self.stream.writeln("Randomizing test order using seed %s\n" %
2975
(self.actual_seed()))
3474
2976
# Initialise the random number generator.
3475
random.seed(random_seed)
3476
super(RandomDecorator, self).__init__(randomize_suite(suite))
2977
random.seed(self.actual_seed())
2978
suite = randomize_suite(self)
2980
self.addTests(suite)
2981
return iter(self._tests)
3479
def actual_seed(seed):
2983
def actual_seed(self):
2984
if self.random_seed == "now":
3481
2985
# We convert the seed to a long to make it reuseable across
3482
2986
# invocations (because the user can reenter it).
3483
return long(time.time())
2987
self.random_seed = long(time.time())
3485
2989
# Convert the seed to a long if we can
3488
except (TypeError, ValueError):
2991
self.random_seed = long(self.random_seed)
2994
return self.random_seed
3493
2997
class TestFirstDecorator(TestDecorator):
3494
2998
"""A decorator which moves named tests to the front."""
3496
3000
def __init__(self, suite, pattern):
3497
super(TestFirstDecorator, self).__init__()
3498
self.addTests(split_suite_by_re(suite, pattern))
3001
TestDecorator.__init__(self, suite)
3002
self.pattern = pattern
3003
self.filtered = False
3007
return iter(self._tests)
3008
self.filtered = True
3009
suites = split_suite_by_re(self, self.pattern)
3011
self.addTests(suites)
3012
return iter(self._tests)
3501
3015
def partition_tests(suite, count):
3502
3016
"""Partition suite into count lists of tests."""
3503
# This just assigns tests in a round-robin fashion. On one hand this
3504
# splits up blocks of related tests that might run faster if they shared
3505
# resources, but on the other it avoids assigning blocks of slow tests to
3506
# just one partition. So the slowest partition shouldn't be much slower
3508
partitions = [list() for i in range(count)]
3509
tests = iter_suite_tests(suite)
3510
for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3511
partition.append(test)
3515
def workaround_zealous_crypto_random():
3516
"""Crypto.Random want to help us being secure, but we don't care here.
3518
This workaround some test failure related to the sftp server. Once paramiko
3519
stop using the controversial API in Crypto.Random, we may get rid of it.
3522
from Crypto.Random import atfork
3018
tests = list(iter_suite_tests(suite))
3019
tests_per_process = int(math.ceil(float(len(tests)) / count))
3020
for block in range(count):
3021
low_test = block * tests_per_process
3022
high_test = low_test + tests_per_process
3023
process_tests = tests[low_test:high_test]
3024
result.append(process_tests)
3528
3028
def fork_for_tests(suite):
3650
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3651
"""Generate profiling data for all activity between start and success.
3653
The profile data is appended to the test's _benchcalls attribute and can
3654
be accessed by the forwarded-to TestResult.
3134
class BZRTransformingResult(unittest.TestResult):
3656
While it might be cleaner do accumulate this in stopTest, addSuccess is
3657
where our existing output support for lsprof is, and this class aims to
3658
fit in with that: while it could be moved it's not necessary to accomplish
3659
test profiling, nor would it be dramatically cleaner.
3136
def __init__(self, target):
3137
unittest.TestResult.__init__(self)
3138
self.result = target
3662
3140
def startTest(self, test):
3663
self.profiler = bzrlib.lsprof.BzrProfiler()
3664
# Prevent deadlocks in tests that use lsprof: those tests will
3666
bzrlib.lsprof.BzrProfiler.profiler_block = 0
3667
self.profiler.start()
3668
testtools.ExtendedToOriginalDecorator.startTest(self, test)
3141
self.result.startTest(test)
3143
def stopTest(self, test):
3144
self.result.stopTest(test)
3146
def addError(self, test, err):
3147
feature = self._error_looks_like('UnavailableFeature: ', err)
3148
if feature is not None:
3149
self.result.addNotSupported(test, feature)
3151
self.result.addError(test, err)
3153
def addFailure(self, test, err):
3154
known = self._error_looks_like('KnownFailure: ', err)
3155
if known is not None:
3156
self.result._addKnownFailure(test, [KnownFailure,
3157
KnownFailure(known), None])
3159
self.result.addFailure(test, err)
3161
def addSkip(self, test, reason):
3162
self.result.addSkip(test, reason)
3670
3164
def addSuccess(self, test):
3671
stats = self.profiler.stop()
3673
calls = test._benchcalls
3674
except AttributeError:
3675
test._benchcalls = []
3676
calls = test._benchcalls
3677
calls.append(((test.id(), "", ""), stats))
3678
testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
3165
self.result.addSuccess(test)
3680
def stopTest(self, test):
3681
testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3682
self.profiler = None
3167
def _error_looks_like(self, prefix, err):
3168
"""Deserialize exception and returns the stringify value."""
3172
if isinstance(exc, subunit.RemoteException):
3173
# stringify the exception gives access to the remote traceback
3174
# We search the last line for 'prefix'
3175
lines = str(exc).split('\n')
3176
while lines and not lines[-1]:
3179
if lines[-1].startswith(prefix):
3180
value = lines[-1][len(prefix):]
3685
3184
# Controlled by "bzr selftest -E=..." option
3928
3416
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3931
def _test_suite_testmod_names():
3932
"""Return the standard list of test module names to test."""
3935
'bzrlib.tests.blackbox',
3936
'bzrlib.tests.commands',
3937
'bzrlib.tests.per_branch',
3938
'bzrlib.tests.per_bzrdir',
3939
'bzrlib.tests.per_controldir',
3940
'bzrlib.tests.per_controldir_colo',
3941
'bzrlib.tests.per_foreign_vcs',
3942
'bzrlib.tests.per_interrepository',
3943
'bzrlib.tests.per_intertree',
3944
'bzrlib.tests.per_inventory',
3945
'bzrlib.tests.per_interbranch',
3946
'bzrlib.tests.per_lock',
3947
'bzrlib.tests.per_merger',
3948
'bzrlib.tests.per_transport',
3949
'bzrlib.tests.per_tree',
3950
'bzrlib.tests.per_pack_repository',
3951
'bzrlib.tests.per_repository',
3952
'bzrlib.tests.per_repository_chk',
3953
'bzrlib.tests.per_repository_reference',
3954
'bzrlib.tests.per_repository_vf',
3955
'bzrlib.tests.per_uifactory',
3956
'bzrlib.tests.per_versionedfile',
3957
'bzrlib.tests.per_workingtree',
3958
'bzrlib.tests.test__annotator',
3959
'bzrlib.tests.test__bencode',
3960
'bzrlib.tests.test__btree_serializer',
3961
'bzrlib.tests.test__chk_map',
3962
'bzrlib.tests.test__dirstate_helpers',
3963
'bzrlib.tests.test__groupcompress',
3964
'bzrlib.tests.test__known_graph',
3965
'bzrlib.tests.test__rio',
3966
'bzrlib.tests.test__simple_set',
3967
'bzrlib.tests.test__static_tuple',
3968
'bzrlib.tests.test__walkdirs_win32',
3969
'bzrlib.tests.test_ancestry',
3970
'bzrlib.tests.test_annotate',
3971
'bzrlib.tests.test_api',
3972
'bzrlib.tests.test_atomicfile',
3973
'bzrlib.tests.test_bad_files',
3974
'bzrlib.tests.test_bisect_multi',
3975
'bzrlib.tests.test_branch',
3976
'bzrlib.tests.test_branchbuilder',
3977
'bzrlib.tests.test_btree_index',
3978
'bzrlib.tests.test_bugtracker',
3979
'bzrlib.tests.test_bundle',
3980
'bzrlib.tests.test_bzrdir',
3981
'bzrlib.tests.test__chunks_to_lines',
3982
'bzrlib.tests.test_cache_utf8',
3983
'bzrlib.tests.test_chk_map',
3984
'bzrlib.tests.test_chk_serializer',
3985
'bzrlib.tests.test_chunk_writer',
3986
'bzrlib.tests.test_clean_tree',
3987
'bzrlib.tests.test_cleanup',
3988
'bzrlib.tests.test_cmdline',
3989
'bzrlib.tests.test_commands',
3990
'bzrlib.tests.test_commit',
3991
'bzrlib.tests.test_commit_merge',
3992
'bzrlib.tests.test_config',
3993
'bzrlib.tests.test_conflicts',
3994
'bzrlib.tests.test_controldir',
3995
'bzrlib.tests.test_counted_lock',
3996
'bzrlib.tests.test_crash',
3997
'bzrlib.tests.test_decorators',
3998
'bzrlib.tests.test_delta',
3999
'bzrlib.tests.test_debug',
4000
'bzrlib.tests.test_diff',
4001
'bzrlib.tests.test_directory_service',
4002
'bzrlib.tests.test_dirstate',
4003
'bzrlib.tests.test_email_message',
4004
'bzrlib.tests.test_eol_filters',
4005
'bzrlib.tests.test_errors',
4006
'bzrlib.tests.test_estimate_compressed_size',
4007
'bzrlib.tests.test_export',
4008
'bzrlib.tests.test_export_pot',
4009
'bzrlib.tests.test_extract',
4010
'bzrlib.tests.test_features',
4011
'bzrlib.tests.test_fetch',
4012
'bzrlib.tests.test_fixtures',
4013
'bzrlib.tests.test_fifo_cache',
4014
'bzrlib.tests.test_filters',
4015
'bzrlib.tests.test_filter_tree',
4016
'bzrlib.tests.test_ftp_transport',
4017
'bzrlib.tests.test_foreign',
4018
'bzrlib.tests.test_generate_docs',
4019
'bzrlib.tests.test_generate_ids',
4020
'bzrlib.tests.test_globbing',
4021
'bzrlib.tests.test_gpg',
4022
'bzrlib.tests.test_graph',
4023
'bzrlib.tests.test_groupcompress',
4024
'bzrlib.tests.test_hashcache',
4025
'bzrlib.tests.test_help',
4026
'bzrlib.tests.test_hooks',
4027
'bzrlib.tests.test_http',
4028
'bzrlib.tests.test_http_response',
4029
'bzrlib.tests.test_https_ca_bundle',
4030
'bzrlib.tests.test_https_urllib',
4031
'bzrlib.tests.test_i18n',
4032
'bzrlib.tests.test_identitymap',
4033
'bzrlib.tests.test_ignores',
4034
'bzrlib.tests.test_index',
4035
'bzrlib.tests.test_import_tariff',
4036
'bzrlib.tests.test_info',
4037
'bzrlib.tests.test_inv',
4038
'bzrlib.tests.test_inventory_delta',
4039
'bzrlib.tests.test_knit',
4040
'bzrlib.tests.test_lazy_import',
4041
'bzrlib.tests.test_lazy_regex',
4042
'bzrlib.tests.test_library_state',
4043
'bzrlib.tests.test_lock',
4044
'bzrlib.tests.test_lockable_files',
4045
'bzrlib.tests.test_lockdir',
4046
'bzrlib.tests.test_log',
4047
'bzrlib.tests.test_lru_cache',
4048
'bzrlib.tests.test_lsprof',
4049
'bzrlib.tests.test_mail_client',
4050
'bzrlib.tests.test_matchers',
4051
'bzrlib.tests.test_memorytree',
4052
'bzrlib.tests.test_merge',
4053
'bzrlib.tests.test_merge3',
4054
'bzrlib.tests.test_merge_core',
4055
'bzrlib.tests.test_merge_directive',
4056
'bzrlib.tests.test_mergetools',
4057
'bzrlib.tests.test_missing',
4058
'bzrlib.tests.test_msgeditor',
4059
'bzrlib.tests.test_multiparent',
4060
'bzrlib.tests.test_mutabletree',
4061
'bzrlib.tests.test_nonascii',
4062
'bzrlib.tests.test_options',
4063
'bzrlib.tests.test_osutils',
4064
'bzrlib.tests.test_osutils_encodings',
4065
'bzrlib.tests.test_pack',
4066
'bzrlib.tests.test_patch',
4067
'bzrlib.tests.test_patches',
4068
'bzrlib.tests.test_permissions',
4069
'bzrlib.tests.test_plugins',
4070
'bzrlib.tests.test_progress',
4071
'bzrlib.tests.test_pyutils',
4072
'bzrlib.tests.test_read_bundle',
4073
'bzrlib.tests.test_reconcile',
4074
'bzrlib.tests.test_reconfigure',
4075
'bzrlib.tests.test_registry',
4076
'bzrlib.tests.test_remote',
4077
'bzrlib.tests.test_rename_map',
4078
'bzrlib.tests.test_repository',
4079
'bzrlib.tests.test_revert',
4080
'bzrlib.tests.test_revision',
4081
'bzrlib.tests.test_revisionspec',
4082
'bzrlib.tests.test_revisiontree',
4083
'bzrlib.tests.test_rio',
4084
'bzrlib.tests.test_rules',
4085
'bzrlib.tests.test_url_policy_open',
4086
'bzrlib.tests.test_sampler',
4087
'bzrlib.tests.test_scenarios',
4088
'bzrlib.tests.test_script',
4089
'bzrlib.tests.test_selftest',
4090
'bzrlib.tests.test_serializer',
4091
'bzrlib.tests.test_setup',
4092
'bzrlib.tests.test_sftp_transport',
4093
'bzrlib.tests.test_shelf',
4094
'bzrlib.tests.test_shelf_ui',
4095
'bzrlib.tests.test_smart',
4096
'bzrlib.tests.test_smart_add',
4097
'bzrlib.tests.test_smart_request',
4098
'bzrlib.tests.test_smart_signals',
4099
'bzrlib.tests.test_smart_transport',
4100
'bzrlib.tests.test_smtp_connection',
4101
'bzrlib.tests.test_source',
4102
'bzrlib.tests.test_ssh_transport',
4103
'bzrlib.tests.test_status',
4104
'bzrlib.tests.test_store',
4105
'bzrlib.tests.test_strace',
4106
'bzrlib.tests.test_subsume',
4107
'bzrlib.tests.test_switch',
4108
'bzrlib.tests.test_symbol_versioning',
4109
'bzrlib.tests.test_tag',
4110
'bzrlib.tests.test_test_server',
4111
'bzrlib.tests.test_testament',
4112
'bzrlib.tests.test_textfile',
4113
'bzrlib.tests.test_textmerge',
4114
'bzrlib.tests.test_cethread',
4115
'bzrlib.tests.test_timestamp',
4116
'bzrlib.tests.test_trace',
4117
'bzrlib.tests.test_transactions',
4118
'bzrlib.tests.test_transform',
4119
'bzrlib.tests.test_transport',
4120
'bzrlib.tests.test_transport_log',
4121
'bzrlib.tests.test_tree',
4122
'bzrlib.tests.test_treebuilder',
4123
'bzrlib.tests.test_treeshape',
4124
'bzrlib.tests.test_tsort',
4125
'bzrlib.tests.test_tuned_gzip',
4126
'bzrlib.tests.test_ui',
4127
'bzrlib.tests.test_uncommit',
4128
'bzrlib.tests.test_upgrade',
4129
'bzrlib.tests.test_upgrade_stacked',
4130
'bzrlib.tests.test_urlutils',
4131
'bzrlib.tests.test_utextwrap',
4132
'bzrlib.tests.test_version',
4133
'bzrlib.tests.test_version_info',
4134
'bzrlib.tests.test_versionedfile',
4135
'bzrlib.tests.test_vf_search',
4136
'bzrlib.tests.test_weave',
4137
'bzrlib.tests.test_whitebox',
4138
'bzrlib.tests.test_win32utils',
4139
'bzrlib.tests.test_workingtree',
4140
'bzrlib.tests.test_workingtree_4',
4141
'bzrlib.tests.test_wsgi',
4142
'bzrlib.tests.test_xml',
4146
def _test_suite_modules_to_doctest():
4147
"""Return the list of modules to doctest."""
4149
# GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
4153
'bzrlib.branchbuilder',
4154
'bzrlib.decorators',
4156
'bzrlib.iterablefile',
4161
'bzrlib.symbol_versioning',
4163
'bzrlib.tests.fixtures',
4165
'bzrlib.transport.http',
4166
'bzrlib.version_info_formats.format_custom',
4170
3419
def test_suite(keep_only=None, starting_with=None):
4171
3420
"""Build and return TestSuite for the whole of bzrlib.
4178
3427
This function can be replaced if you need to change the default test
4179
3428
suite on a global basis, but it is not encouraged.
3432
'bzrlib.tests.blackbox',
3433
'bzrlib.tests.commands',
3434
'bzrlib.tests.per_branch',
3435
'bzrlib.tests.per_bzrdir',
3436
'bzrlib.tests.per_interrepository',
3437
'bzrlib.tests.per_intertree',
3438
'bzrlib.tests.per_inventory',
3439
'bzrlib.tests.per_interbranch',
3440
'bzrlib.tests.per_lock',
3441
'bzrlib.tests.per_transport',
3442
'bzrlib.tests.per_tree',
3443
'bzrlib.tests.per_pack_repository',
3444
'bzrlib.tests.per_repository',
3445
'bzrlib.tests.per_repository_chk',
3446
'bzrlib.tests.per_repository_reference',
3447
'bzrlib.tests.per_versionedfile',
3448
'bzrlib.tests.per_workingtree',
3449
'bzrlib.tests.test__annotator',
3450
'bzrlib.tests.test__chk_map',
3451
'bzrlib.tests.test__dirstate_helpers',
3452
'bzrlib.tests.test__groupcompress',
3453
'bzrlib.tests.test__known_graph',
3454
'bzrlib.tests.test__rio',
3455
'bzrlib.tests.test__walkdirs_win32',
3456
'bzrlib.tests.test_ancestry',
3457
'bzrlib.tests.test_annotate',
3458
'bzrlib.tests.test_api',
3459
'bzrlib.tests.test_atomicfile',
3460
'bzrlib.tests.test_bad_files',
3461
'bzrlib.tests.test_bencode',
3462
'bzrlib.tests.test_bisect_multi',
3463
'bzrlib.tests.test_branch',
3464
'bzrlib.tests.test_branchbuilder',
3465
'bzrlib.tests.test_btree_index',
3466
'bzrlib.tests.test_bugtracker',
3467
'bzrlib.tests.test_bundle',
3468
'bzrlib.tests.test_bzrdir',
3469
'bzrlib.tests.test__chunks_to_lines',
3470
'bzrlib.tests.test_cache_utf8',
3471
'bzrlib.tests.test_chk_map',
3472
'bzrlib.tests.test_chk_serializer',
3473
'bzrlib.tests.test_chunk_writer',
3474
'bzrlib.tests.test_clean_tree',
3475
'bzrlib.tests.test_commands',
3476
'bzrlib.tests.test_commit',
3477
'bzrlib.tests.test_commit_merge',
3478
'bzrlib.tests.test_config',
3479
'bzrlib.tests.test_conflicts',
3480
'bzrlib.tests.test_counted_lock',
3481
'bzrlib.tests.test_crash',
3482
'bzrlib.tests.test_decorators',
3483
'bzrlib.tests.test_delta',
3484
'bzrlib.tests.test_debug',
3485
'bzrlib.tests.test_deprecated_graph',
3486
'bzrlib.tests.test_diff',
3487
'bzrlib.tests.test_directory_service',
3488
'bzrlib.tests.test_dirstate',
3489
'bzrlib.tests.test_email_message',
3490
'bzrlib.tests.test_eol_filters',
3491
'bzrlib.tests.test_errors',
3492
'bzrlib.tests.test_export',
3493
'bzrlib.tests.test_extract',
3494
'bzrlib.tests.test_fetch',
3495
'bzrlib.tests.test_fifo_cache',
3496
'bzrlib.tests.test_filters',
3497
'bzrlib.tests.test_ftp_transport',
3498
'bzrlib.tests.test_foreign',
3499
'bzrlib.tests.test_generate_docs',
3500
'bzrlib.tests.test_generate_ids',
3501
'bzrlib.tests.test_globbing',
3502
'bzrlib.tests.test_gpg',
3503
'bzrlib.tests.test_graph',
3504
'bzrlib.tests.test_groupcompress',
3505
'bzrlib.tests.test_hashcache',
3506
'bzrlib.tests.test_help',
3507
'bzrlib.tests.test_hooks',
3508
'bzrlib.tests.test_http',
3509
'bzrlib.tests.test_http_response',
3510
'bzrlib.tests.test_https_ca_bundle',
3511
'bzrlib.tests.test_identitymap',
3512
'bzrlib.tests.test_ignores',
3513
'bzrlib.tests.test_index',
3514
'bzrlib.tests.test_info',
3515
'bzrlib.tests.test_inv',
3516
'bzrlib.tests.test_inventory_delta',
3517
'bzrlib.tests.test_knit',
3518
'bzrlib.tests.test_lazy_import',
3519
'bzrlib.tests.test_lazy_regex',
3520
'bzrlib.tests.test_lock',
3521
'bzrlib.tests.test_lockable_files',
3522
'bzrlib.tests.test_lockdir',
3523
'bzrlib.tests.test_log',
3524
'bzrlib.tests.test_lru_cache',
3525
'bzrlib.tests.test_lsprof',
3526
'bzrlib.tests.test_mail_client',
3527
'bzrlib.tests.test_memorytree',
3528
'bzrlib.tests.test_merge',
3529
'bzrlib.tests.test_merge3',
3530
'bzrlib.tests.test_merge_core',
3531
'bzrlib.tests.test_merge_directive',
3532
'bzrlib.tests.test_missing',
3533
'bzrlib.tests.test_msgeditor',
3534
'bzrlib.tests.test_multiparent',
3535
'bzrlib.tests.test_mutabletree',
3536
'bzrlib.tests.test_nonascii',
3537
'bzrlib.tests.test_options',
3538
'bzrlib.tests.test_osutils',
3539
'bzrlib.tests.test_osutils_encodings',
3540
'bzrlib.tests.test_pack',
3541
'bzrlib.tests.test_patch',
3542
'bzrlib.tests.test_patches',
3543
'bzrlib.tests.test_permissions',
3544
'bzrlib.tests.test_plugins',
3545
'bzrlib.tests.test_progress',
3546
'bzrlib.tests.test_read_bundle',
3547
'bzrlib.tests.test_reconcile',
3548
'bzrlib.tests.test_reconfigure',
3549
'bzrlib.tests.test_registry',
3550
'bzrlib.tests.test_remote',
3551
'bzrlib.tests.test_rename_map',
3552
'bzrlib.tests.test_repository',
3553
'bzrlib.tests.test_revert',
3554
'bzrlib.tests.test_revision',
3555
'bzrlib.tests.test_revisionspec',
3556
'bzrlib.tests.test_revisiontree',
3557
'bzrlib.tests.test_rio',
3558
'bzrlib.tests.test_rules',
3559
'bzrlib.tests.test_sampler',
3560
'bzrlib.tests.test_selftest',
3561
'bzrlib.tests.test_serializer',
3562
'bzrlib.tests.test_setup',
3563
'bzrlib.tests.test_sftp_transport',
3564
'bzrlib.tests.test_shelf',
3565
'bzrlib.tests.test_shelf_ui',
3566
'bzrlib.tests.test_smart',
3567
'bzrlib.tests.test_smart_add',
3568
'bzrlib.tests.test_smart_request',
3569
'bzrlib.tests.test_smart_transport',
3570
'bzrlib.tests.test_smtp_connection',
3571
'bzrlib.tests.test_source',
3572
'bzrlib.tests.test_ssh_transport',
3573
'bzrlib.tests.test_status',
3574
'bzrlib.tests.test_store',
3575
'bzrlib.tests.test_strace',
3576
'bzrlib.tests.test_subsume',
3577
'bzrlib.tests.test_switch',
3578
'bzrlib.tests.test_symbol_versioning',
3579
'bzrlib.tests.test_tag',
3580
'bzrlib.tests.test_testament',
3581
'bzrlib.tests.test_textfile',
3582
'bzrlib.tests.test_textmerge',
3583
'bzrlib.tests.test_timestamp',
3584
'bzrlib.tests.test_trace',
3585
'bzrlib.tests.test_transactions',
3586
'bzrlib.tests.test_transform',
3587
'bzrlib.tests.test_transport',
3588
'bzrlib.tests.test_transport_log',
3589
'bzrlib.tests.test_tree',
3590
'bzrlib.tests.test_treebuilder',
3591
'bzrlib.tests.test_tsort',
3592
'bzrlib.tests.test_tuned_gzip',
3593
'bzrlib.tests.test_ui',
3594
'bzrlib.tests.test_uncommit',
3595
'bzrlib.tests.test_upgrade',
3596
'bzrlib.tests.test_upgrade_stacked',
3597
'bzrlib.tests.test_urlutils',
3598
'bzrlib.tests.test_version',
3599
'bzrlib.tests.test_version_info',
3600
'bzrlib.tests.test_weave',
3601
'bzrlib.tests.test_whitebox',
3602
'bzrlib.tests.test_win32utils',
3603
'bzrlib.tests.test_workingtree',
3604
'bzrlib.tests.test_workingtree_4',
3605
'bzrlib.tests.test_wsgi',
3606
'bzrlib.tests.test_xml',
4182
3609
loader = TestUtil.TestLoader()
4373
3803
:param new_id: The id to assign to it.
4374
3804
:return: The new test.
4376
new_test = copy.copy(test)
3806
from copy import deepcopy
3807
new_test = deepcopy(test)
4377
3808
new_test.id = lambda: new_id
4378
# XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4379
# causes cloned tests to share the 'details' dict. This makes it hard to
4380
# read the test output for parameterized tests, because tracebacks will be
4381
# associated with irrelevant tests.
4383
details = new_test._TestCase__details
4384
except AttributeError:
4385
# must be a different version of testtools than expected. Do nothing.
4388
# Reset the '__details' dict.
4389
new_test._TestCase__details = {}
4390
3809
return new_test
4393
def permute_tests_for_extension(standard_tests, loader, py_module_name,
4395
"""Helper for permutating tests against an extension module.
4397
This is meant to be used inside a modules 'load_tests()' function. It will
4398
create 2 scenarios, and cause all tests in the 'standard_tests' to be run
4399
against both implementations. Setting 'test.module' to the appropriate
4400
module. See bzrlib.tests.test__chk_map.load_tests as an example.
4402
:param standard_tests: A test suite to permute
4403
:param loader: A TestLoader
4404
:param py_module_name: The python path to a python module that can always
4405
be loaded, and will be considered the 'python' implementation. (eg
4406
'bzrlib._chk_map_py')
4407
:param ext_module_name: The python path to an extension module. If the
4408
module cannot be loaded, a single test will be added, which notes that
4409
the module is not available. If it can be loaded, all standard_tests
4410
will be run against that module.
4411
:return: (suite, feature) suite is a test-suite that has all the permuted
4412
tests. feature is the Feature object that can be used to determine if
4413
the module is available.
4416
from bzrlib.tests.features import ModuleAvailableFeature
4417
py_module = pyutils.get_named_object(py_module_name)
4419
('python', {'module': py_module}),
4421
suite = loader.suiteClass()
4422
feature = ModuleAvailableFeature(ext_module_name)
4423
if feature.available():
4424
scenarios.append(('C', {'module': feature.module}))
4426
# the compiled module isn't available, so we add a failing test
4427
class FailWithoutFeature(TestCase):
4428
def test_fail(self):
4429
self.requireFeature(feature)
4430
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4431
result = multiply_tests(standard_tests, scenarios, suite)
4432
return result, feature
4435
def _rmtree_temp_dir(dirname, test_id=None):
3812
def _rmtree_temp_dir(dirname):
4436
3813
# If LANG=C we probably have created some bogus paths
4437
3814
# which rmtree(unicode) will fail to delete
4438
3815
# so make sure we are using rmtree(str) to delete everything
3952
class _HTTPSServerFeature(Feature):
3953
"""Some tests want an https Server, check if one is available.
3955
Right now, the only way this is available is under python2.6 which provides
3966
def feature_name(self):
3967
return 'HTTPSServer'
3970
HTTPSServerFeature = _HTTPSServerFeature()
3973
class _UnicodeFilename(Feature):
3974
"""Does the filesystem support Unicode filenames?"""
3979
except UnicodeEncodeError:
3981
except (IOError, OSError):
3982
# The filesystem allows the Unicode filename but the file doesn't
3986
# The filesystem allows the Unicode filename and the file exists,
3990
UnicodeFilename = _UnicodeFilename()
3993
class _UTF8Filesystem(Feature):
3994
"""Is the filesystem UTF-8?"""
3997
if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
4001
UTF8Filesystem = _UTF8Filesystem()
4004
class _CaseInsCasePresFilenameFeature(Feature):
4005
"""Is the file-system case insensitive, but case-preserving?"""
4008
fileno, name = tempfile.mkstemp(prefix='MixedCase')
4010
# first check truly case-preserving for created files, then check
4011
# case insensitive when opening existing files.
4012
name = osutils.normpath(name)
4013
base, rel = osutils.split(name)
4014
found_rel = osutils.canonical_relpath(base, name)
4015
return (found_rel == rel
4016
and os.path.isfile(name.upper())
4017
and os.path.isfile(name.lower()))
4022
def feature_name(self):
4023
return "case-insensitive case-preserving filesystem"
4025
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
4028
class _CaseInsensitiveFilesystemFeature(Feature):
4029
"""Check if underlying filesystem is case-insensitive but *not* case
4032
# Note that on Windows, Cygwin, MacOS etc, the file-systems are far
4033
# more likely to be case preserving, so this case is rare.
4036
if CaseInsCasePresFilenameFeature.available():
4039
if TestCaseWithMemoryTransport.TEST_ROOT is None:
4040
root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
4041
TestCaseWithMemoryTransport.TEST_ROOT = root
4043
root = TestCaseWithMemoryTransport.TEST_ROOT
4044
tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
4046
name_a = osutils.pathjoin(tdir, 'a')
4047
name_A = osutils.pathjoin(tdir, 'A')
4049
result = osutils.isdir(name_A)
4050
_rmtree_temp_dir(tdir)
4053
def feature_name(self):
4054
return 'case-insensitive filesystem'
4056
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
4059
class _SubUnitFeature(Feature):
4060
"""Check if subunit is available."""
4069
def feature_name(self):
4072
SubUnitFeature = _SubUnitFeature()
4496
4073
# Only define SubUnitBzrRunner if subunit is available.
4498
4075
from subunit import TestProtocolClient
4499
from subunit.test_results import AutoTimingTestResultDecorator
4500
class SubUnitBzrProtocolClient(TestProtocolClient):
4502
def stopTest(self, test):
4503
super(SubUnitBzrProtocolClient, self).stopTest(test)
4504
_clear__type_equality_funcs(test)
4506
def addSuccess(self, test, details=None):
4507
# The subunit client always includes the details in the subunit
4508
# stream, but we don't want to include it in ours.
4509
if details is not None and 'log' in details:
4511
return super(SubUnitBzrProtocolClient, self).addSuccess(
4077
from subunit.test_results import AutoTimingTestResultDecorator
4079
AutoTimingTestResultDecorator = lambda x:x
4514
4080
class SubUnitBzrRunner(TextTestRunner):
4515
4081
def run(self, test):
4516
4082
result = AutoTimingTestResultDecorator(
4517
SubUnitBzrProtocolClient(self.stream))
4083
TestProtocolClient(self.stream))
4518
4084
test.run(result)
4520
4086
except ImportError:
4524
# API compatibility for old plugins; see bug 892622.
4527
'HTTPServerFeature',
4528
'ModuleAvailableFeature',
4529
'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
4530
'OsFifoFeature', 'UnicodeFilenameFeature',
4531
'ByteStringNamedFilesystem', 'UTF8Filesystem',
4532
'BreakinFeature', 'CaseInsCasePresFilenameFeature',
4533
'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
4534
'posix_permissions_feature',
4536
globals()[name] = _CompatabilityThunkFeature(
4537
symbol_versioning.deprecated_in((2, 5, 0)),
4538
'bzrlib.tests', name,
4539
name, 'bzrlib.tests.features')
4542
for (old_name, new_name) in [
4543
('UnicodeFilename', 'UnicodeFilenameFeature'),
4545
globals()[name] = _CompatabilityThunkFeature(
4546
symbol_versioning.deprecated_in((2, 5, 0)),
4547
'bzrlib.tests', old_name,
4548
new_name, 'bzrlib.tests.features')