355
276
"""The test will not be run because of a missing feature.
357
278
# this can be called in two different ways: it may be that the
358
# test started running, and then raised (through requireFeature)
279
# test started running, and then raised (through addError)
359
280
# UnavailableFeature. Alternatively this method can be called
360
# while probing for features before running the test code proper; in
361
# that case we will see startTest and stopTest, but the test will
362
# never actually run.
281
# while probing for features before running the tests; in that
282
# case we will see startTest and stopTest, but the test will never
363
284
self.unsupported.setdefault(str(feature), 0)
364
285
self.unsupported[str(feature)] += 1
365
286
self.report_unsupported(test, feature)
367
def addSkip(self, test, reason):
368
"""A test has not run for 'reason'."""
370
self.report_skip(test, reason)
372
def addNotApplicable(self, test, reason):
373
self.not_applicable_count += 1
374
self.report_not_applicable(test, reason)
376
def _post_mortem(self):
377
"""Start a PDB post mortem session."""
378
if os.environ.get('BZR_TEST_PDB', None):
379
import pdb;pdb.post_mortem()
381
def progress(self, offset, whence):
382
"""The test is adjusting the count of tests to run."""
383
if whence == SUBUNIT_SEEK_SET:
384
self.num_tests = offset
385
elif whence == SUBUNIT_SEEK_CUR:
386
self.num_tests += offset
388
raise errors.BzrError("Unknown whence %r" % whence)
288
def _addSkipped(self, test, skip_excinfo):
289
if isinstance(skip_excinfo[1], TestNotApplicable):
290
self.not_applicable_count += 1
291
self.report_not_applicable(test, skip_excinfo)
294
self.report_skip(test, skip_excinfo)
297
except KeyboardInterrupt:
300
self.addError(test, test._exc_info())
302
# seems best to treat this as success from point-of-view of unittest
303
# -- it actually does nothing so it barely matters :)
304
unittest.TestResult.addSuccess(self, test)
305
test._log_contents = ''
307
def printErrorList(self, flavour, errors):
308
for test, err in errors:
309
self.stream.writeln(self.separator1)
310
self.stream.write("%s: " % flavour)
311
self.stream.writeln(self.getDescription(test))
312
if getattr(test, '_get_log', None) is not None:
313
self.stream.write('\n')
315
('vvvv[log from %s]' % test.id()).ljust(78,'-'))
316
self.stream.write('\n')
317
self.stream.write(test._get_log())
318
self.stream.write('\n')
320
('^^^^[log from %s]' % test.id()).ljust(78,'-'))
321
self.stream.write('\n')
322
self.stream.writeln(self.separator2)
323
self.stream.writeln("%s" % err)
390
328
def report_cleaning_up(self):
393
def startTestRun(self):
394
self.startTime = time.time()
396
331
def report_success(self, test):
585
510
bench_history=None,
587
result_decorators=None,
589
"""Create a TextTestRunner.
591
:param result_decorators: An optional list of decorators to apply
592
to the result object being used by the runner. Decorators are
593
applied left to right - the first element in the list is the
596
# stream may know claim to know to write unicode strings, but in older
597
# pythons this goes sufficiently wrong that it is a bad idea. (
598
# specifically a built in file with encoding 'UTF-8' will still try
599
# to encode using ascii.
600
new_encoding = osutils.get_terminal_encoding()
601
codec = codecs.lookup(new_encoding)
602
if type(codec) is tuple:
606
encode = codec.encode
607
stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream)
608
stream.encoding = new_encoding
609
513
self.stream = unittest._WritelnDecorator(stream)
610
514
self.descriptions = descriptions
611
515
self.verbosity = verbosity
612
516
self._bench_history = bench_history
613
self._strict = strict
614
self._result_decorators = result_decorators or []
517
self.list_only = list_only
616
519
def run(self, test):
617
520
"Run the given test case or test suite."
521
startTime = time.time()
618
522
if self.verbosity == 1:
619
523
result_class = TextTestResult
620
524
elif self.verbosity >= 2:
621
525
result_class = VerboseTestResult
622
original_result = result_class(self.stream,
526
result = result_class(self.stream,
623
527
self.descriptions,
625
529
bench_history=self._bench_history,
530
num_tests=test.countTestCases(),
628
# Signal to result objects that look at stop early policy to stop,
629
original_result.stop_early = self.stop_on_failure
630
result = original_result
631
for decorator in self._result_decorators:
632
result = decorator(result)
633
result.stop_early = self.stop_on_failure
634
result.startTestRun()
532
result.stop_early = self.stop_on_failure
533
result.report_starting()
535
if self.verbosity >= 2:
536
self.stream.writeln("Listing tests only ...\n")
538
for t in iter_suite_tests(test):
539
self.stream.writeln("%s" % (t.id()))
541
actionTaken = "Listed"
639
# higher level code uses our extended protocol to determine
640
# what exit code to give.
641
return original_result
544
run = result.testsRun
546
stopTime = time.time()
547
timeTaken = stopTime - startTime
549
self.stream.writeln(result.separator2)
550
self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
551
run, run != 1 and "s" or "", timeTaken))
552
self.stream.writeln()
553
if not result.wasSuccessful():
554
self.stream.write("FAILED (")
555
failed, errored = map(len, (result.failures, result.errors))
557
self.stream.write("failures=%d" % failed)
559
if failed: self.stream.write(", ")
560
self.stream.write("errors=%d" % errored)
561
if result.known_failure_count:
562
if failed or errored: self.stream.write(", ")
563
self.stream.write("known_failure_count=%d" %
564
result.known_failure_count)
565
self.stream.writeln(")")
567
if result.known_failure_count:
568
self.stream.writeln("OK (known_failures=%d)" %
569
result.known_failure_count)
571
self.stream.writeln("OK")
572
if result.skip_count > 0:
573
skipped = result.skip_count
574
self.stream.writeln('%d test%s skipped' %
575
(skipped, skipped != 1 and "s" or ""))
576
if result.unsupported:
577
for feature, count in sorted(result.unsupported.items()):
578
self.stream.writeln("Missing feature '%s' skipped %d tests." %
644
584
def iter_suite_tests(suite):
645
585
"""Return all tests in a suite, recursing through nested suites"""
646
if isinstance(suite, unittest.TestCase):
648
elif isinstance(suite, unittest.TestSuite):
586
for item in suite._tests:
587
if isinstance(item, unittest.TestCase):
589
elif isinstance(item, unittest.TestSuite):
650
590
for r in iter_suite_tests(item):
653
raise Exception('unknown type %r for object %r'
654
% (type(suite), suite))
657
TestSkipped = testtools.testcase.TestSkipped
593
raise Exception('unknown object %r inside test suite %r'
597
class TestSkipped(Exception):
598
"""Indicates that a test was intentionally skipped, rather than failing."""
660
601
class TestNotApplicable(TestSkipped):
661
602
"""A test is not applicable to the situation where it was run.
663
This is only normally raised by parameterized tests, if they find that
664
the instance they're constructed upon does not support one aspect
604
This is only normally raised by parameterized tests, if they find that
605
the instance they're constructed upon does not support one aspect
665
606
of its interface.
669
# traceback._some_str fails to format exceptions that have the default
670
# __str__ which does an implicit ascii conversion. However, repr() on those
671
# objects works, for all that its not quite what the doctor may have ordered.
672
def _clever_some_str(value):
677
return repr(value).replace('\\n', '\n')
679
return '<unprintable %s object>' % type(value).__name__
681
traceback._some_str = _clever_some_str
684
# deprecated - use self.knownFailure(), or self.expectFailure.
685
KnownFailure = testtools.testcase._ExpectedFailure
610
class KnownFailure(AssertionError):
611
"""Indicates that a test failed in a precisely expected manner.
613
Such failures dont block the whole test suite from passing because they are
614
indicators of partially completed code or of future work. We have an
615
explicit error for them so that we can ensure that they are always visible:
616
KnownFailures are always shown in the output of bzr selftest.
688
620
class UnavailableFeature(Exception):
689
621
"""A feature required for this test was not available.
691
This can be considered a specialised form of SkippedTest.
693
623
The feature should be used to construct the exception.
789
750
_leaking_threads_tests = 0
790
751
_first_thread_leaker_id = None
791
752
_log_file_name = None
754
_keep_log_file = False
792
755
# record lsprof data when performing benchmark calls.
793
756
_gather_lsprof_in_benchmarks = False
757
attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
758
'_log_contents', '_log_file_name', '_benchtime',
759
'_TestCase__testMethodName')
795
761
def __init__(self, methodName='testMethod'):
796
762
super(TestCase, self).__init__(methodName)
797
763
self._cleanups = []
798
self._directory_isolation = True
799
self.exception_handlers.insert(0,
800
(UnavailableFeature, self._do_unsupported_or_skip))
801
self.exception_handlers.insert(0,
802
(TestNotApplicable, self._do_not_applicable))
805
super(TestCase, self).setUp()
806
for feature in getattr(self, '_test_needs_features', []):
807
self.requireFeature(feature)
808
self._log_contents = None
809
self.addDetail("log", content.Content(content.ContentType("text",
810
"plain", {"charset": "utf8"}),
811
lambda:[self._get_log(keep_log_file=True)]))
766
unittest.TestCase.setUp(self)
812
767
self._cleanEnvironment()
813
768
self._silenceUI()
814
769
self._startLogFile()
815
770
self._benchcalls = []
816
771
self._benchtime = None
817
772
self._clear_hooks()
818
self._track_transports()
820
773
self._clear_debug_flags()
821
774
TestCase._active_threads = threading.activeCount()
822
775
self.addCleanup(self._check_leaked_threads)
827
pdb.Pdb().set_trace(sys._getframe().f_back)
829
777
def _check_leaked_threads(self):
830
778
active = threading.activeCount()
831
779
leaked_threads = active - TestCase._active_threads
832
780
TestCase._active_threads = active
833
# If some tests make the number of threads *decrease*, we'll consider
834
# that they are just observing old threads dieing, not agressively kill
835
# random threads. So we don't report these tests as leaking. The risk
836
# is that we have false positives that way (the test see 2 threads
837
# going away but leak one) but it seems less likely than the actual
838
# false positives (the test see threads going away and does not leak).
839
if leaked_threads > 0:
840
782
TestCase._leaking_threads_tests += 1
841
783
if TestCase._first_thread_leaker_id is None:
842
784
TestCase._first_thread_leaker_id = self.id()
785
# we're not specifically told when all tests are finished.
786
# This will do. We use a function to avoid keeping a reference
787
# to a TestCase object.
788
atexit.register(_report_leaked_threads)
844
790
def _clear_debug_flags(self):
845
791
"""Prevent externally set debug flags affecting tests.
885
824
ui.ui_factory = ui.SilentUIFactory()
886
825
self.addCleanup(_restore)
888
def _check_locks(self):
889
"""Check that all lock take/release actions have been paired."""
890
# We always check for mismatched locks. If a mismatch is found, we
891
# fail unless -Edisable_lock_checks is supplied to selftest, in which
892
# case we just print a warning.
894
acquired_locks = [lock for action, lock in self._lock_actions
895
if action == 'acquired']
896
released_locks = [lock for action, lock in self._lock_actions
897
if action == 'released']
898
broken_locks = [lock for action, lock in self._lock_actions
899
if action == 'broken']
900
# trivially, given the tests for lock acquistion and release, if we
901
# have as many in each list, it should be ok. Some lock tests also
902
# break some locks on purpose and should be taken into account by
903
# considering that breaking a lock is just a dirty way of releasing it.
904
if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
905
message = ('Different number of acquired and '
906
'released or broken locks. (%s, %s + %s)' %
907
(acquired_locks, released_locks, broken_locks))
908
if not self._lock_check_thorough:
909
# Rather than fail, just warn
910
print "Broken test %s: %s" % (self, message)
914
def _track_locks(self):
915
"""Track lock activity during tests."""
916
self._lock_actions = []
917
if 'disable_lock_checks' in selftest_debug_flags:
918
self._lock_check_thorough = False
920
self._lock_check_thorough = True
922
self.addCleanup(self._check_locks)
923
_mod_lock.Lock.hooks.install_named_hook('lock_acquired',
924
self._lock_acquired, None)
925
_mod_lock.Lock.hooks.install_named_hook('lock_released',
926
self._lock_released, None)
927
_mod_lock.Lock.hooks.install_named_hook('lock_broken',
928
self._lock_broken, None)
930
def _lock_acquired(self, result):
931
self._lock_actions.append(('acquired', result))
933
def _lock_released(self, result):
934
self._lock_actions.append(('released', result))
936
def _lock_broken(self, result):
937
self._lock_actions.append(('broken', result))
939
def permit_dir(self, name):
940
"""Permit a directory to be used by this test. See permit_url."""
941
name_transport = get_transport(name)
942
self.permit_url(name)
943
self.permit_url(name_transport.base)
945
def permit_url(self, url):
946
"""Declare that url is an ok url to use in this test.
948
Do this for memory transports, temporary test directory etc.
950
Do not do this for the current working directory, /tmp, or any other
951
preexisting non isolated url.
953
if not url.endswith('/'):
955
self._bzr_selftest_roots.append(url)
957
def permit_source_tree_branch_repo(self):
958
"""Permit the source tree bzr is running from to be opened.
960
Some code such as bzrlib.version attempts to read from the bzr branch
961
that bzr is executing from (if any). This method permits that directory
962
to be used in the test suite.
964
path = self.get_source_path()
965
self.record_directory_isolation()
968
workingtree.WorkingTree.open(path)
969
except (errors.NotBranchError, errors.NoWorkingTree):
972
self.enable_directory_isolation()
974
def _preopen_isolate_transport(self, transport):
975
"""Check that all transport openings are done in the test work area."""
976
while isinstance(transport, pathfilter.PathFilteringTransport):
977
# Unwrap pathfiltered transports
978
transport = transport.server.backing_transport.clone(
979
transport._filter('.'))
981
# ReadonlySmartTCPServer_for_testing decorates the backing transport
982
# urls it is given by prepending readonly+. This is appropriate as the
983
# client shouldn't know that the server is readonly (or not readonly).
984
# We could register all servers twice, with readonly+ prepending, but
985
# that makes for a long list; this is about the same but easier to
987
if url.startswith('readonly+'):
988
url = url[len('readonly+'):]
989
self._preopen_isolate_url(url)
991
def _preopen_isolate_url(self, url):
992
if not self._directory_isolation:
994
if self._directory_isolation == 'record':
995
self._bzr_selftest_roots.append(url)
997
# This prevents all transports, including e.g. sftp ones backed on disk
998
# from working unless they are explicitly granted permission. We then
999
# depend on the code that sets up test transports to check that they are
1000
# appropriately isolated and enable their use by calling
1001
# self.permit_transport()
1002
if not osutils.is_inside_any(self._bzr_selftest_roots, url):
1003
raise errors.BzrError("Attempt to escape test isolation: %r %r"
1004
% (url, self._bzr_selftest_roots))
1006
def record_directory_isolation(self):
1007
"""Gather accessed directories to permit later access.
1009
This is used for tests that access the branch bzr is running from.
1011
self._directory_isolation = "record"
1013
def start_server(self, transport_server, backing_server=None):
1014
"""Start transport_server for this test.
1016
This starts the server, registers a cleanup for it and permits the
1017
server's urls to be used.
1019
if backing_server is None:
1020
transport_server.start_server()
1022
transport_server.start_server(backing_server)
1023
self.addCleanup(transport_server.stop_server)
1024
# Obtain a real transport because if the server supplies a password, it
1025
# will be hidden from the base on the client side.
1026
t = get_transport(transport_server.get_url())
1027
# Some transport servers effectively chroot the backing transport;
1028
# others like SFTPServer don't - users of the transport can walk up the
1029
# transport to read the entire backing transport. This wouldn't matter
1030
# except that the workdir tests are given - and that they expect the
1031
# server's url to point at - is one directory under the safety net. So
1032
# Branch operations into the transport will attempt to walk up one
1033
# directory. Chrooting all servers would avoid this but also mean that
1034
# we wouldn't be testing directly against non-root urls. Alternatively
1035
# getting the test framework to start the server with a backing server
1036
# at the actual safety net directory would work too, but this then
1037
# means that the self.get_url/self.get_transport methods would need
1038
# to transform all their results. On balance its cleaner to handle it
1039
# here, and permit a higher url when we have one of these transports.
1040
if t.base.endswith('/work/'):
1041
# we have safety net/test root/work
1042
t = t.clone('../..')
1043
elif isinstance(transport_server, server.SmartTCPServer_for_testing):
1044
# The smart server adds a path similar to work, which is traversed
1045
# up from by the client. But the server is chrooted - the actual
1046
# backing transport is not escaped from, and VFS requests to the
1047
# root will error (because they try to escape the chroot).
1049
while t2.base != t.base:
1052
self.permit_url(t.base)
1054
def _track_transports(self):
1055
"""Install checks for transport usage."""
1056
# TestCase has no safe place it can write to.
1057
self._bzr_selftest_roots = []
1058
# Currently the easiest way to be sure that nothing is going on is to
1059
# hook into bzr dir opening. This leaves a small window of error for
1060
# transport tests, but they are well known, and we can improve on this
1062
bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1063
self._preopen_isolate_transport, "Check bzr directories are safe.")
1065
827
def _ndiff_strings(self, a, b):
1066
828
"""Return ndiff between two strings containing lines.
1068
830
A trailing newline is added if missing to make the strings
1069
831
print properly."""
1070
832
if b and b[-1] != '\n':
1536
1272
osutils.set_or_unset_env(name, value)
1538
1274
def _restoreHooks(self):
1539
for klass, (name, hooks) in self._preserved_hooks.items():
1540
setattr(klass, name, hooks)
1275
for klass, hooks in self._preserved_hooks.items():
1276
setattr(klass, 'hooks', hooks)
1542
1278
def knownFailure(self, reason):
1543
1279
"""This test has failed for some known reason."""
1544
1280
raise KnownFailure(reason)
1546
def _do_skip(self, result, reason):
1547
addSkip = getattr(result, 'addSkip', None)
1548
if not callable(addSkip):
1549
result.addSuccess(result)
1551
addSkip(self, reason)
1554
def _do_known_failure(self, result, e):
1555
err = sys.exc_info()
1556
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1557
if addExpectedFailure is not None:
1558
addExpectedFailure(self, err)
1560
result.addSuccess(self)
1563
def _do_not_applicable(self, result, e):
1565
reason = 'No reason given'
1568
addNotApplicable = getattr(result, 'addNotApplicable', None)
1569
if addNotApplicable is not None:
1570
result.addNotApplicable(self, reason)
1572
self._do_skip(result, reason)
1575
def _do_unsupported_or_skip(self, result, e):
1577
addNotSupported = getattr(result, 'addNotSupported', None)
1578
if addNotSupported is not None:
1579
result.addNotSupported(self, reason)
1581
self._do_skip(result, reason)
1282
def run(self, result=None):
1283
if result is None: result = self.defaultTestResult()
1284
for feature in getattr(self, '_test_needs_features', []):
1285
if not feature.available():
1286
result.startTest(self)
1287
if getattr(result, 'addNotSupported', None):
1288
result.addNotSupported(self, feature)
1290
result.addSuccess(self)
1291
result.stopTest(self)
1294
return unittest.TestCase.run(self, result)
1297
absent_attr = object()
1298
for attr_name in self.attrs_to_keep:
1299
attr = getattr(self, attr_name, absent_attr)
1300
if attr is not absent_attr:
1301
saved_attrs[attr_name] = attr
1302
self.__dict__ = saved_attrs
1306
unittest.TestCase.tearDown(self)
1583
1308
def time(self, callable, *args, **kwargs):
1584
1309
"""Run callable and accrue the time it takes to the benchmark time.
1586
1311
If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1587
1312
this will cause lsprofile statistics to be gathered and stored in
1588
1313
self._benchcalls.
1590
1315
if self._benchtime is None:
1591
self.addDetail('benchtime', content.Content(content.ContentType(
1592
"text", "plain"), lambda:[str(self._benchtime)]))
1593
1316
self._benchtime = 0
1594
1317
start = time.time()
2871
2485
list_only=False,
2872
2486
random_seed=None,
2873
2487
exclude_pattern=None,
2876
suite_decorators=None,
2878
result_decorators=None,
2880
"""Run a test suite for bzr selftest.
2882
:param runner_class: The class of runner to use. Must support the
2883
constructor arguments passed by run_suite which are more than standard
2885
:return: A boolean indicating success.
2887
2489
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2892
if runner_class is None:
2893
runner_class = TextTestRunner
2896
runner = runner_class(stream=stream,
2494
runner = TextTestRunner(stream=sys.stdout,
2897
2495
descriptions=0,
2898
2496
verbosity=verbosity,
2899
2497
bench_history=bench_history,
2901
result_decorators=result_decorators,
2498
list_only=list_only,
2903
2500
runner.stop_on_failure=stop_on_failure
2904
# built in decorator factories:
2906
random_order(random_seed, runner),
2907
exclude_tests(exclude_pattern),
2909
if matching_tests_first:
2910
decorators.append(tests_first(pattern))
2501
# Initialise the random number generator and display the seed used.
2502
# We convert the seed to a long to make it reuseable across invocations.
2503
random_order = False
2504
if random_seed is not None:
2506
if random_seed == "now":
2507
random_seed = long(time.time())
2509
# Convert the seed to a long if we can
2511
random_seed = long(random_seed)
2514
runner.stream.writeln("Randomizing test order using seed %s\n" %
2516
random.seed(random_seed)
2517
# Customise the list of tests if requested
2518
if exclude_pattern is not None:
2519
suite = exclude_tests_by_re(suite, exclude_pattern)
2521
order_changer = randomize_suite
2912
decorators.append(filter_tests(pattern))
2913
if suite_decorators:
2914
decorators.extend(suite_decorators)
2915
# tell the result object how many tests will be running: (except if
2916
# --parallel=fork is being used. Robert said he will provide a better
2917
# progress design later -- vila 20090817)
2918
if fork_decorator not in decorators:
2919
decorators.append(CountingDecorator)
2920
for decorator in decorators:
2921
suite = decorator(suite)
2923
# Done after test suite decoration to allow randomisation etc
2924
# to take effect, though that is of marginal benefit.
2926
stream.write("Listing tests only ...\n")
2927
for t in iter_suite_tests(suite):
2928
stream.write("%s\n" % (t.id()))
2523
order_changer = preserve_input
2524
if pattern != '.*' or random_order:
2525
if matching_tests_first:
2526
suites = map(order_changer, split_suite_by_re(suite, pattern))
2527
suite = TestUtil.TestSuite(suites)
2529
suite = order_changer(filter_suite_by_re(suite, pattern))
2930
2531
result = runner.run(suite)
2932
2534
return result.wasStrictlySuccessful()
2934
return result.wasSuccessful()
2937
# A registry where get() returns a suite decorator.
2938
parallel_registry = registry.Registry()
2941
def fork_decorator(suite):
2942
concurrency = osutils.local_concurrency()
2943
if concurrency == 1:
2945
from testtools import ConcurrentTestSuite
2946
return ConcurrentTestSuite(suite, fork_for_tests)
2947
parallel_registry.register('fork', fork_decorator)
2950
def subprocess_decorator(suite):
2951
concurrency = osutils.local_concurrency()
2952
if concurrency == 1:
2954
from testtools import ConcurrentTestSuite
2955
return ConcurrentTestSuite(suite, reinvoke_for_tests)
2956
parallel_registry.register('subprocess', subprocess_decorator)
2959
def exclude_tests(exclude_pattern):
2960
"""Return a test suite decorator that excludes tests."""
2961
if exclude_pattern is None:
2962
return identity_decorator
2963
def decorator(suite):
2964
return ExcludeDecorator(suite, exclude_pattern)
2968
def filter_tests(pattern):
2970
return identity_decorator
2971
def decorator(suite):
2972
return FilterTestsDecorator(suite, pattern)
2976
def random_order(random_seed, runner):
2977
"""Return a test suite decorator factory for randomising tests order.
2979
:param random_seed: now, a string which casts to a long, or a long.
2980
:param runner: A test runner with a stream attribute to report on.
2982
if random_seed is None:
2983
return identity_decorator
2984
def decorator(suite):
2985
return RandomDecorator(suite, random_seed, runner.stream)
2989
def tests_first(pattern):
2991
return identity_decorator
2992
def decorator(suite):
2993
return TestFirstDecorator(suite, pattern)
2997
def identity_decorator(suite):
3002
class TestDecorator(TestSuite):
3003
"""A decorator for TestCase/TestSuite objects.
3005
Usually, subclasses should override __iter__(used when flattening test
3006
suites), which we do to filter, reorder, parallelise and so on, run() and
3010
def __init__(self, suite):
3011
TestSuite.__init__(self)
3014
def countTestCases(self):
3017
cases += test.countTestCases()
3024
def run(self, result):
3025
# Use iteration on self, not self._tests, to allow subclasses to hook
3028
if result.shouldStop:
3034
class CountingDecorator(TestDecorator):
3035
"""A decorator which calls result.progress(self.countTestCases)."""
3037
def run(self, result):
3038
progress_method = getattr(result, 'progress', None)
3039
if callable(progress_method):
3040
progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
3041
return super(CountingDecorator, self).run(result)
3044
class ExcludeDecorator(TestDecorator):
3045
"""A decorator which excludes test matching an exclude pattern."""
3047
def __init__(self, suite, exclude_pattern):
3048
TestDecorator.__init__(self, suite)
3049
self.exclude_pattern = exclude_pattern
3050
self.excluded = False
3054
return iter(self._tests)
3055
self.excluded = True
3056
suite = exclude_tests_by_re(self, self.exclude_pattern)
3058
self.addTests(suite)
3059
return iter(self._tests)
3062
class FilterTestsDecorator(TestDecorator):
3063
"""A decorator which filters tests to those matching a pattern."""
3065
def __init__(self, suite, pattern):
3066
TestDecorator.__init__(self, suite)
3067
self.pattern = pattern
3068
self.filtered = False
3072
return iter(self._tests)
3073
self.filtered = True
3074
suite = filter_suite_by_re(self, self.pattern)
3076
self.addTests(suite)
3077
return iter(self._tests)
3080
class RandomDecorator(TestDecorator):
3081
"""A decorator which randomises the order of its tests."""
3083
def __init__(self, suite, random_seed, stream):
3084
TestDecorator.__init__(self, suite)
3085
self.random_seed = random_seed
3086
self.randomised = False
3087
self.stream = stream
3091
return iter(self._tests)
3092
self.randomised = True
3093
self.stream.write("Randomizing test order using seed %s\n\n" %
3094
(self.actual_seed()))
3095
# Initialise the random number generator.
3096
random.seed(self.actual_seed())
3097
suite = randomize_suite(self)
3099
self.addTests(suite)
3100
return iter(self._tests)
3102
def actual_seed(self):
3103
if self.random_seed == "now":
3104
# We convert the seed to a long to make it reuseable across
3105
# invocations (because the user can reenter it).
3106
self.random_seed = long(time.time())
3108
# Convert the seed to a long if we can
3110
self.random_seed = long(self.random_seed)
3113
return self.random_seed
3116
class TestFirstDecorator(TestDecorator):
3117
"""A decorator which moves named tests to the front."""
3119
def __init__(self, suite, pattern):
3120
TestDecorator.__init__(self, suite)
3121
self.pattern = pattern
3122
self.filtered = False
3126
return iter(self._tests)
3127
self.filtered = True
3128
suites = split_suite_by_re(self, self.pattern)
3130
self.addTests(suites)
3131
return iter(self._tests)
3134
def partition_tests(suite, count):
3135
"""Partition suite into count lists of tests."""
3137
tests = list(iter_suite_tests(suite))
3138
tests_per_process = int(math.ceil(float(len(tests)) / count))
3139
for block in range(count):
3140
low_test = block * tests_per_process
3141
high_test = low_test + tests_per_process
3142
process_tests = tests[low_test:high_test]
3143
result.append(process_tests)
3147
def fork_for_tests(suite):
3148
"""Take suite and start up one runner per CPU by forking()
3150
:return: An iterable of TestCase-like objects which can each have
3151
run(result) called on them to feed tests to result.
3153
concurrency = osutils.local_concurrency()
3155
from subunit import TestProtocolClient, ProtocolTestCase
3156
from subunit.test_results import AutoTimingTestResultDecorator
3157
class TestInOtherProcess(ProtocolTestCase):
3158
# Should be in subunit, I think. RBC.
3159
def __init__(self, stream, pid):
3160
ProtocolTestCase.__init__(self, stream)
3163
def run(self, result):
3165
ProtocolTestCase.run(self, result)
3167
os.waitpid(self.pid, os.WNOHANG)
3169
test_blocks = partition_tests(suite, concurrency)
3170
for process_tests in test_blocks:
3171
process_suite = TestSuite()
3172
process_suite.addTests(process_tests)
3173
c2pread, c2pwrite = os.pipe()
3178
# Leave stderr and stdout open so we can see test noise
3179
# Close stdin so that the child goes away if it decides to
3180
# read from stdin (otherwise its a roulette to see what
3181
# child actually gets keystrokes for pdb etc).
3184
stream = os.fdopen(c2pwrite, 'wb', 1)
3185
subunit_result = AutoTimingTestResultDecorator(
3186
TestProtocolClient(stream))
3187
process_suite.run(subunit_result)
3192
stream = os.fdopen(c2pread, 'rb', 1)
3193
test = TestInOtherProcess(stream, pid)
3198
def reinvoke_for_tests(suite):
3199
"""Take suite and start up one runner per CPU using subprocess().
3201
:return: An iterable of TestCase-like objects which can each have
3202
run(result) called on them to feed tests to result.
3204
concurrency = osutils.local_concurrency()
3206
from subunit import ProtocolTestCase
3207
class TestInSubprocess(ProtocolTestCase):
3208
def __init__(self, process, name):
3209
ProtocolTestCase.__init__(self, process.stdout)
3210
self.process = process
3211
self.process.stdin.close()
3214
def run(self, result):
3216
ProtocolTestCase.run(self, result)
3219
os.unlink(self.name)
3220
# print "pid %d finished" % finished_process
3221
test_blocks = partition_tests(suite, concurrency)
3222
for process_tests in test_blocks:
3223
# ugly; currently reimplement rather than reuses TestCase methods.
3224
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
3225
if not os.path.isfile(bzr_path):
3226
# We are probably installed. Assume sys.argv is the right file
3227
bzr_path = sys.argv[0]
3228
bzr_path = [bzr_path]
3229
if sys.platform == "win32":
3230
# if we're on windows, we can't execute the bzr script directly
3231
bzr_path = [sys.executable] + bzr_path
3232
fd, test_list_file_name = tempfile.mkstemp()
3233
test_list_file = os.fdopen(fd, 'wb', 1)
3234
for test in process_tests:
3235
test_list_file.write(test.id() + '\n')
3236
test_list_file.close()
3238
argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
3240
if '--no-plugins' in sys.argv:
3241
argv.append('--no-plugins')
3242
# stderr=STDOUT would be ideal, but until we prevent noise on
3243
# stderr it can interrupt the subunit protocol.
3244
process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
3246
test = TestInSubprocess(process, test_list_file_name)
3249
os.unlink(test_list_file_name)
3254
class ForwardingResult(unittest.TestResult):
3256
def __init__(self, target):
3257
unittest.TestResult.__init__(self)
3258
self.result = target
3260
def startTest(self, test):
3261
self.result.startTest(test)
3263
def stopTest(self, test):
3264
self.result.stopTest(test)
3266
def startTestRun(self):
3267
self.result.startTestRun()
3269
def stopTestRun(self):
3270
self.result.stopTestRun()
3272
def addSkip(self, test, reason):
3273
self.result.addSkip(test, reason)
3275
def addSuccess(self, test):
3276
self.result.addSuccess(test)
3278
def addError(self, test, err):
3279
self.result.addError(test, err)
3281
def addFailure(self, test, err):
3282
self.result.addFailure(test, err)
3283
ForwardingResult = testtools.ExtendedToOriginalDecorator
3286
class ProfileResult(ForwardingResult):
3287
"""Generate profiling data for all activity between start and success.
3289
The profile data is appended to the test's _benchcalls attribute and can
3290
be accessed by the forwarded-to TestResult.
3292
While it might be cleaner do accumulate this in stopTest, addSuccess is
3293
where our existing output support for lsprof is, and this class aims to
3294
fit in with that: while it could be moved it's not necessary to accomplish
3295
test profiling, nor would it be dramatically cleaner.
3298
def startTest(self, test):
3299
self.profiler = bzrlib.lsprof.BzrProfiler()
3300
self.profiler.start()
3301
ForwardingResult.startTest(self, test)
3303
def addSuccess(self, test):
3304
stats = self.profiler.stop()
3306
calls = test._benchcalls
3307
except AttributeError:
3308
test._benchcalls = []
3309
calls = test._benchcalls
3310
calls.append(((test.id(), "", ""), stats))
3311
ForwardingResult.addSuccess(self, test)
3313
def stopTest(self, test):
3314
ForwardingResult.stopTest(self, test)
3315
self.profiler = None
2536
return result.wasSuccessful()
3318
2539
# Controlled by "bzr selftest -E=..." option
3319
# Currently supported:
3320
# -Eallow_debug Will no longer clear debug.debug_flags() so it
3321
# preserves any flags supplied at the command line.
3322
# -Edisable_lock_checks Turns errors in mismatched locks into simple prints
3323
# rather than failing tests. And no longer raise
3324
# LockContention when fctnl locks are not being used
3325
# with proper exclusion rules.
3326
2540
selftest_debug_flags = set()
3555
2749
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3558
def _test_suite_testmod_names():
3559
"""Return the standard list of test module names to test."""
3562
'bzrlib.tests.blackbox',
3563
'bzrlib.tests.commands',
3564
'bzrlib.tests.per_branch',
3565
'bzrlib.tests.per_bzrdir',
3566
'bzrlib.tests.per_foreign_vcs',
3567
'bzrlib.tests.per_interrepository',
3568
'bzrlib.tests.per_intertree',
3569
'bzrlib.tests.per_inventory',
3570
'bzrlib.tests.per_interbranch',
3571
'bzrlib.tests.per_lock',
3572
'bzrlib.tests.per_merger',
3573
'bzrlib.tests.per_transport',
3574
'bzrlib.tests.per_tree',
3575
'bzrlib.tests.per_pack_repository',
3576
'bzrlib.tests.per_repository',
3577
'bzrlib.tests.per_repository_chk',
3578
'bzrlib.tests.per_repository_reference',
3579
'bzrlib.tests.per_uifactory',
3580
'bzrlib.tests.per_versionedfile',
3581
'bzrlib.tests.per_workingtree',
3582
'bzrlib.tests.test__annotator',
3583
'bzrlib.tests.test__bencode',
3584
'bzrlib.tests.test__chk_map',
3585
'bzrlib.tests.test__dirstate_helpers',
3586
'bzrlib.tests.test__groupcompress',
3587
'bzrlib.tests.test__known_graph',
3588
'bzrlib.tests.test__rio',
3589
'bzrlib.tests.test__simple_set',
3590
'bzrlib.tests.test__static_tuple',
3591
'bzrlib.tests.test__walkdirs_win32',
3592
'bzrlib.tests.test_ancestry',
3593
'bzrlib.tests.test_annotate',
3594
'bzrlib.tests.test_api',
3595
'bzrlib.tests.test_atomicfile',
3596
'bzrlib.tests.test_bad_files',
3597
'bzrlib.tests.test_bisect_multi',
3598
'bzrlib.tests.test_branch',
3599
'bzrlib.tests.test_branchbuilder',
3600
'bzrlib.tests.test_btree_index',
3601
'bzrlib.tests.test_bugtracker',
3602
'bzrlib.tests.test_bundle',
3603
'bzrlib.tests.test_bzrdir',
3604
'bzrlib.tests.test__chunks_to_lines',
3605
'bzrlib.tests.test_cache_utf8',
3606
'bzrlib.tests.test_chk_map',
3607
'bzrlib.tests.test_chk_serializer',
3608
'bzrlib.tests.test_chunk_writer',
3609
'bzrlib.tests.test_clean_tree',
3610
'bzrlib.tests.test_cleanup',
3611
'bzrlib.tests.test_commands',
3612
'bzrlib.tests.test_commit',
3613
'bzrlib.tests.test_commit_merge',
3614
'bzrlib.tests.test_config',
3615
'bzrlib.tests.test_conflicts',
3616
'bzrlib.tests.test_counted_lock',
3617
'bzrlib.tests.test_crash',
3618
'bzrlib.tests.test_decorators',
3619
'bzrlib.tests.test_delta',
3620
'bzrlib.tests.test_debug',
3621
'bzrlib.tests.test_deprecated_graph',
3622
'bzrlib.tests.test_diff',
3623
'bzrlib.tests.test_directory_service',
3624
'bzrlib.tests.test_dirstate',
3625
'bzrlib.tests.test_email_message',
3626
'bzrlib.tests.test_eol_filters',
3627
'bzrlib.tests.test_errors',
3628
'bzrlib.tests.test_export',
3629
'bzrlib.tests.test_extract',
3630
'bzrlib.tests.test_fetch',
3631
'bzrlib.tests.test_fifo_cache',
3632
'bzrlib.tests.test_filters',
3633
'bzrlib.tests.test_ftp_transport',
3634
'bzrlib.tests.test_foreign',
3635
'bzrlib.tests.test_generate_docs',
3636
'bzrlib.tests.test_generate_ids',
3637
'bzrlib.tests.test_globbing',
3638
'bzrlib.tests.test_gpg',
3639
'bzrlib.tests.test_graph',
3640
'bzrlib.tests.test_groupcompress',
3641
'bzrlib.tests.test_hashcache',
3642
'bzrlib.tests.test_help',
3643
'bzrlib.tests.test_hooks',
3644
'bzrlib.tests.test_http',
3645
'bzrlib.tests.test_http_response',
3646
'bzrlib.tests.test_https_ca_bundle',
3647
'bzrlib.tests.test_identitymap',
3648
'bzrlib.tests.test_ignores',
3649
'bzrlib.tests.test_index',
3650
'bzrlib.tests.test_info',
3651
'bzrlib.tests.test_inv',
3652
'bzrlib.tests.test_inventory_delta',
3653
'bzrlib.tests.test_knit',
3654
'bzrlib.tests.test_lazy_import',
3655
'bzrlib.tests.test_lazy_regex',
3656
'bzrlib.tests.test_lock',
3657
'bzrlib.tests.test_lockable_files',
3658
'bzrlib.tests.test_lockdir',
3659
'bzrlib.tests.test_log',
3660
'bzrlib.tests.test_lru_cache',
3661
'bzrlib.tests.test_lsprof',
3662
'bzrlib.tests.test_mail_client',
3663
'bzrlib.tests.test_memorytree',
3664
'bzrlib.tests.test_merge',
3665
'bzrlib.tests.test_merge3',
3666
'bzrlib.tests.test_merge_core',
3667
'bzrlib.tests.test_merge_directive',
3668
'bzrlib.tests.test_missing',
3669
'bzrlib.tests.test_msgeditor',
3670
'bzrlib.tests.test_multiparent',
3671
'bzrlib.tests.test_mutabletree',
3672
'bzrlib.tests.test_nonascii',
3673
'bzrlib.tests.test_options',
3674
'bzrlib.tests.test_osutils',
3675
'bzrlib.tests.test_osutils_encodings',
3676
'bzrlib.tests.test_pack',
3677
'bzrlib.tests.test_patch',
3678
'bzrlib.tests.test_patches',
3679
'bzrlib.tests.test_permissions',
3680
'bzrlib.tests.test_plugins',
3681
'bzrlib.tests.test_progress',
3682
'bzrlib.tests.test_read_bundle',
3683
'bzrlib.tests.test_reconcile',
3684
'bzrlib.tests.test_reconfigure',
3685
'bzrlib.tests.test_registry',
3686
'bzrlib.tests.test_remote',
3687
'bzrlib.tests.test_rename_map',
3688
'bzrlib.tests.test_repository',
3689
'bzrlib.tests.test_revert',
3690
'bzrlib.tests.test_revision',
3691
'bzrlib.tests.test_revisionspec',
3692
'bzrlib.tests.test_revisiontree',
3693
'bzrlib.tests.test_rio',
3694
'bzrlib.tests.test_rules',
3695
'bzrlib.tests.test_sampler',
3696
'bzrlib.tests.test_script',
3697
'bzrlib.tests.test_selftest',
3698
'bzrlib.tests.test_serializer',
3699
'bzrlib.tests.test_setup',
3700
'bzrlib.tests.test_sftp_transport',
3701
'bzrlib.tests.test_shelf',
3702
'bzrlib.tests.test_shelf_ui',
3703
'bzrlib.tests.test_smart',
3704
'bzrlib.tests.test_smart_add',
3705
'bzrlib.tests.test_smart_request',
3706
'bzrlib.tests.test_smart_transport',
3707
'bzrlib.tests.test_smtp_connection',
3708
'bzrlib.tests.test_source',
3709
'bzrlib.tests.test_ssh_transport',
3710
'bzrlib.tests.test_status',
3711
'bzrlib.tests.test_store',
3712
'bzrlib.tests.test_strace',
3713
'bzrlib.tests.test_subsume',
3714
'bzrlib.tests.test_switch',
3715
'bzrlib.tests.test_symbol_versioning',
3716
'bzrlib.tests.test_tag',
3717
'bzrlib.tests.test_testament',
3718
'bzrlib.tests.test_textfile',
3719
'bzrlib.tests.test_textmerge',
3720
'bzrlib.tests.test_timestamp',
3721
'bzrlib.tests.test_trace',
3722
'bzrlib.tests.test_transactions',
3723
'bzrlib.tests.test_transform',
3724
'bzrlib.tests.test_transport',
3725
'bzrlib.tests.test_transport_log',
3726
'bzrlib.tests.test_tree',
3727
'bzrlib.tests.test_treebuilder',
3728
'bzrlib.tests.test_tsort',
3729
'bzrlib.tests.test_tuned_gzip',
3730
'bzrlib.tests.test_ui',
3731
'bzrlib.tests.test_uncommit',
3732
'bzrlib.tests.test_upgrade',
3733
'bzrlib.tests.test_upgrade_stacked',
3734
'bzrlib.tests.test_urlutils',
3735
'bzrlib.tests.test_version',
3736
'bzrlib.tests.test_version_info',
3737
'bzrlib.tests.test_weave',
3738
'bzrlib.tests.test_whitebox',
3739
'bzrlib.tests.test_win32utils',
3740
'bzrlib.tests.test_workingtree',
3741
'bzrlib.tests.test_workingtree_4',
3742
'bzrlib.tests.test_wsgi',
3743
'bzrlib.tests.test_xml',
3747
def _test_suite_modules_to_doctest():
3748
"""Return the list of modules to doctest."""
3751
'bzrlib.branchbuilder',
3754
'bzrlib.iterablefile',
3758
'bzrlib.symbol_versioning',
3761
'bzrlib.version_info_formats.format_custom',
3765
2752
def test_suite(keep_only=None, starting_with=None):
3766
2753
"""Build and return TestSuite for the whole of bzrlib.
3773
2760
This function can be replaced if you need to change the default test
3774
2761
suite on a global basis, but it is not encouraged.
2765
'bzrlib.tests.blackbox',
2766
'bzrlib.tests.branch_implementations',
2767
'bzrlib.tests.bzrdir_implementations',
2768
'bzrlib.tests.commands',
2769
'bzrlib.tests.interrepository_implementations',
2770
'bzrlib.tests.intertree_implementations',
2771
'bzrlib.tests.inventory_implementations',
2772
'bzrlib.tests.per_lock',
2773
'bzrlib.tests.per_repository',
2774
'bzrlib.tests.per_repository_reference',
2775
'bzrlib.tests.test__dirstate_helpers',
2776
'bzrlib.tests.test__walkdirs_win32',
2777
'bzrlib.tests.test_ancestry',
2778
'bzrlib.tests.test_annotate',
2779
'bzrlib.tests.test_api',
2780
'bzrlib.tests.test_atomicfile',
2781
'bzrlib.tests.test_bad_files',
2782
'bzrlib.tests.test_bisect_multi',
2783
'bzrlib.tests.test_branch',
2784
'bzrlib.tests.test_branchbuilder',
2785
'bzrlib.tests.test_btree_index',
2786
'bzrlib.tests.test_bugtracker',
2787
'bzrlib.tests.test_bundle',
2788
'bzrlib.tests.test_bzrdir',
2789
'bzrlib.tests.test_cache_utf8',
2790
'bzrlib.tests.test_chunk_writer',
2791
'bzrlib.tests.test__chunks_to_lines',
2792
'bzrlib.tests.test_commands',
2793
'bzrlib.tests.test_commit',
2794
'bzrlib.tests.test_commit_merge',
2795
'bzrlib.tests.test_config',
2796
'bzrlib.tests.test_conflicts',
2797
'bzrlib.tests.test_counted_lock',
2798
'bzrlib.tests.test_decorators',
2799
'bzrlib.tests.test_delta',
2800
'bzrlib.tests.test_deprecated_graph',
2801
'bzrlib.tests.test_diff',
2802
'bzrlib.tests.test_directory_service',
2803
'bzrlib.tests.test_dirstate',
2804
'bzrlib.tests.test_email_message',
2805
'bzrlib.tests.test_errors',
2806
'bzrlib.tests.test_extract',
2807
'bzrlib.tests.test_fetch',
2808
'bzrlib.tests.test_fifo_cache',
2809
'bzrlib.tests.test_ftp_transport',
2810
'bzrlib.tests.test_foreign',
2811
'bzrlib.tests.test_generate_docs',
2812
'bzrlib.tests.test_generate_ids',
2813
'bzrlib.tests.test_globbing',
2814
'bzrlib.tests.test_gpg',
2815
'bzrlib.tests.test_graph',
2816
'bzrlib.tests.test_hashcache',
2817
'bzrlib.tests.test_help',
2818
'bzrlib.tests.test_hooks',
2819
'bzrlib.tests.test_http',
2820
'bzrlib.tests.test_http_implementations',
2821
'bzrlib.tests.test_http_response',
2822
'bzrlib.tests.test_https_ca_bundle',
2823
'bzrlib.tests.test_identitymap',
2824
'bzrlib.tests.test_ignores',
2825
'bzrlib.tests.test_index',
2826
'bzrlib.tests.test_info',
2827
'bzrlib.tests.test_inv',
2828
'bzrlib.tests.test_knit',
2829
'bzrlib.tests.test_lazy_import',
2830
'bzrlib.tests.test_lazy_regex',
2831
'bzrlib.tests.test_lockable_files',
2832
'bzrlib.tests.test_lockdir',
2833
'bzrlib.tests.test_log',
2834
'bzrlib.tests.test_lru_cache',
2835
'bzrlib.tests.test_lsprof',
2836
'bzrlib.tests.test_mail_client',
2837
'bzrlib.tests.test_memorytree',
2838
'bzrlib.tests.test_merge',
2839
'bzrlib.tests.test_merge3',
2840
'bzrlib.tests.test_merge_core',
2841
'bzrlib.tests.test_merge_directive',
2842
'bzrlib.tests.test_missing',
2843
'bzrlib.tests.test_msgeditor',
2844
'bzrlib.tests.test_multiparent',
2845
'bzrlib.tests.test_mutabletree',
2846
'bzrlib.tests.test_nonascii',
2847
'bzrlib.tests.test_options',
2848
'bzrlib.tests.test_osutils',
2849
'bzrlib.tests.test_osutils_encodings',
2850
'bzrlib.tests.test_pack',
2851
'bzrlib.tests.test_pack_repository',
2852
'bzrlib.tests.test_patch',
2853
'bzrlib.tests.test_patches',
2854
'bzrlib.tests.test_permissions',
2855
'bzrlib.tests.test_plugins',
2856
'bzrlib.tests.test_progress',
2857
'bzrlib.tests.test_read_bundle',
2858
'bzrlib.tests.test_reconcile',
2859
'bzrlib.tests.test_reconfigure',
2860
'bzrlib.tests.test_registry',
2861
'bzrlib.tests.test_remote',
2862
'bzrlib.tests.test_repository',
2863
'bzrlib.tests.test_revert',
2864
'bzrlib.tests.test_revision',
2865
'bzrlib.tests.test_revisionspec',
2866
'bzrlib.tests.test_revisiontree',
2867
'bzrlib.tests.test_rio',
2868
'bzrlib.tests.test_rules',
2869
'bzrlib.tests.test_sampler',
2870
'bzrlib.tests.test_selftest',
2871
'bzrlib.tests.test_setup',
2872
'bzrlib.tests.test_sftp_transport',
2873
'bzrlib.tests.test_shelf',
2874
'bzrlib.tests.test_shelf_ui',
2875
'bzrlib.tests.test_smart',
2876
'bzrlib.tests.test_smart_add',
2877
'bzrlib.tests.test_smart_transport',
2878
'bzrlib.tests.test_smtp_connection',
2879
'bzrlib.tests.test_source',
2880
'bzrlib.tests.test_ssh_transport',
2881
'bzrlib.tests.test_status',
2882
'bzrlib.tests.test_store',
2883
'bzrlib.tests.test_strace',
2884
'bzrlib.tests.test_subsume',
2885
'bzrlib.tests.test_switch',
2886
'bzrlib.tests.test_symbol_versioning',
2887
'bzrlib.tests.test_tag',
2888
'bzrlib.tests.test_testament',
2889
'bzrlib.tests.test_textfile',
2890
'bzrlib.tests.test_textmerge',
2891
'bzrlib.tests.test_timestamp',
2892
'bzrlib.tests.test_trace',
2893
'bzrlib.tests.test_transactions',
2894
'bzrlib.tests.test_transform',
2895
'bzrlib.tests.test_transport',
2896
'bzrlib.tests.test_transport_implementations',
2897
'bzrlib.tests.test_transport_log',
2898
'bzrlib.tests.test_tree',
2899
'bzrlib.tests.test_treebuilder',
2900
'bzrlib.tests.test_tsort',
2901
'bzrlib.tests.test_tuned_gzip',
2902
'bzrlib.tests.test_ui',
2903
'bzrlib.tests.test_uncommit',
2904
'bzrlib.tests.test_upgrade',
2905
'bzrlib.tests.test_upgrade_stacked',
2906
'bzrlib.tests.test_urlutils',
2907
'bzrlib.tests.test_version',
2908
'bzrlib.tests.test_version_info',
2909
'bzrlib.tests.test_versionedfile',
2910
'bzrlib.tests.test_weave',
2911
'bzrlib.tests.test_whitebox',
2912
'bzrlib.tests.test_win32utils',
2913
'bzrlib.tests.test_workingtree',
2914
'bzrlib.tests.test_workingtree_4',
2915
'bzrlib.tests.test_wsgi',
2916
'bzrlib.tests.test_xml',
2917
'bzrlib.tests.tree_implementations',
2918
'bzrlib.tests.workingtree_implementations',
2919
'bzrlib.util.tests.test_bencode',
3777
2922
loader = TestUtil.TestLoader()
3779
if keep_only is not None:
3780
id_filter = TestIdList(keep_only)
3781
2924
if starting_with:
2925
starting_with = [test_prefix_alias_registry.resolve_alias(start)
2926
for start in starting_with]
3782
2927
# We take precedence over keep_only because *at loading time* using
3783
2928
# both options means we will load less tests for the same final result.
3784
2929
def interesting_module(name):
3880
3092
for right_name, right_dict in scenarios_right]
3883
def multiply_tests(tests, scenarios, result):
3884
"""Multiply tests_list by scenarios into result.
3886
This is the core workhorse for test parameterisation.
3888
Typically the load_tests() method for a per-implementation test suite will
3889
call multiply_tests and return the result.
3891
:param tests: The tests to parameterise.
3892
:param scenarios: The scenarios to apply: pairs of (scenario_name,
3893
scenario_param_dict).
3894
:param result: A TestSuite to add created tests to.
3896
This returns the passed in result TestSuite with the cross product of all
3897
the tests repeated once for each scenario. Each test is adapted by adding
3898
the scenario name at the end of its id(), and updating the test object's
3899
__dict__ with the scenario_param_dict.
3901
>>> import bzrlib.tests.test_sampler
3902
>>> r = multiply_tests(
3903
... bzrlib.tests.test_sampler.DemoTest('test_nothing'),
3904
... [('one', dict(param=1)),
3905
... ('two', dict(param=2))],
3907
>>> tests = list(iter_suite_tests(r))
3911
'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
3917
for test in iter_suite_tests(tests):
3918
apply_scenarios(test, scenarios, result)
3922
def apply_scenarios(test, scenarios, result):
3923
"""Apply the scenarios in scenarios to test and add to result.
3925
:param test: The test to apply scenarios to.
3926
:param scenarios: An iterable of scenarios to apply to test.
3928
:seealso: apply_scenario
3930
for scenario in scenarios:
3931
result.addTest(apply_scenario(test, scenario))
3935
def apply_scenario(test, scenario):
3936
"""Copy test and apply scenario to it.
3938
:param test: A test to adapt.
3939
:param scenario: A tuple describing the scenarion.
3940
The first element of the tuple is the new test id.
3941
The second element is a dict containing attributes to set on the
3943
:return: The adapted test.
3945
new_id = "%s(%s)" % (test.id(), scenario[0])
3946
new_test = clone_test(test, new_id)
3947
for name, value in scenario[1].items():
3948
setattr(new_test, name, value)
3952
def clone_test(test, new_id):
3953
"""Clone a test giving it a new id.
3955
:param test: The test to clone.
3956
:param new_id: The id to assign to it.
3957
:return: The new test.
3959
new_test = copy(test)
3960
new_test.id = lambda: new_id
3964
def permute_tests_for_extension(standard_tests, loader, py_module_name,
3966
"""Helper for permutating tests against an extension module.
3968
This is meant to be used inside a modules 'load_tests()' function. It will
3969
create 2 scenarios, and cause all tests in the 'standard_tests' to be run
3970
against both implementations. Setting 'test.module' to the appropriate
3971
module. See bzrlib.tests.test__chk_map.load_tests as an example.
3973
:param standard_tests: A test suite to permute
3974
:param loader: A TestLoader
3975
:param py_module_name: The python path to a python module that can always
3976
be loaded, and will be considered the 'python' implementation. (eg
3977
'bzrlib._chk_map_py')
3978
:param ext_module_name: The python path to an extension module. If the
3979
module cannot be loaded, a single test will be added, which notes that
3980
the module is not available. If it can be loaded, all standard_tests
3981
will be run against that module.
3982
:return: (suite, feature) suite is a test-suite that has all the permuted
3983
tests. feature is the Feature object that can be used to determine if
3984
the module is available.
3987
py_module = __import__(py_module_name, {}, {}, ['NO_SUCH_ATTRIB'])
3989
('python', {'module': py_module}),
3991
suite = loader.suiteClass()
3992
feature = ModuleAvailableFeature(ext_module_name)
3993
if feature.available():
3994
scenarios.append(('C', {'module': feature.module}))
3996
# the compiled module isn't available, so we add a failing test
3997
class FailWithoutFeature(TestCase):
3998
def test_fail(self):
3999
self.requireFeature(feature)
4000
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4001
result = multiply_tests(standard_tests, scenarios, suite)
4002
return result, feature
4005
def _rmtree_temp_dir(dirname, test_id=None):
3096
def adapt_modules(mods_list, adapter, loader, suite):
3097
"""Adapt the modules in mods_list using adapter and add to suite."""
3098
tests = loader.loadTestsFromModuleNames(mods_list)
3099
adapt_tests(tests, adapter, suite)
3102
def adapt_tests(tests_list, adapter, suite):
3103
"""Adapt the tests in tests_list using adapter and add to suite."""
3104
for test in iter_suite_tests(tests_list):
3105
suite.addTests(adapter.adapt(test))
3108
def _rmtree_temp_dir(dirname):
4006
3109
# If LANG=C we probably have created some bogus paths
4007
3110
# which rmtree(unicode) will fail to delete
4008
3111
# so make sure we are using rmtree(str) to delete everything
4112
3213
UnicodeFilenameFeature = _UnicodeFilenameFeature()
4115
class _CompatabilityThunkFeature(Feature):
4116
"""This feature is just a thunk to another feature.
4118
It issues a deprecation warning if it is accessed, to let you know that you
4119
should really use a different feature.
4122
def __init__(self, module, name, this_name, dep_version):
4123
super(_CompatabilityThunkFeature, self).__init__()
4124
self._module = module
4126
self._this_name = this_name
4127
self._dep_version = dep_version
4128
self._feature = None
4131
if self._feature is None:
4132
msg = (self._dep_version % self._this_name) + (
4133
' Use %s.%s instead.' % (self._module, self._name))
4134
symbol_versioning.warn(msg, DeprecationWarning)
4135
mod = __import__(self._module, {}, {}, [self._name])
4136
self._feature = getattr(mod, self._name)
4140
return self._feature._probe()
4143
class ModuleAvailableFeature(Feature):
4144
"""This is a feature than describes a module we want to be available.
4146
Declare the name of the module in __init__(), and then after probing, the
4147
module will be available as 'self.module'.
4149
:ivar module: The module if it is available, else None.
4152
def __init__(self, module_name):
4153
super(ModuleAvailableFeature, self).__init__()
4154
self.module_name = module_name
4158
self._module = __import__(self.module_name, {}, {}, [''])
4165
if self.available(): # Make sure the probe has been done
4169
def feature_name(self):
4170
return self.module_name
4173
# This is kept here for compatibility, it is recommended to use
4174
# 'bzrlib.tests.feature.paramiko' instead
4175
ParamikoFeature = _CompatabilityThunkFeature('bzrlib.tests.features',
4176
'paramiko', 'bzrlib.tests.ParamikoFeature', deprecated_in((2,1,0)))
3216
class TestScenarioApplier(object):
3217
"""A tool to apply scenarios to tests."""
3219
def adapt(self, test):
3220
"""Return a TestSuite containing a copy of test for each scenario."""
3221
result = unittest.TestSuite()
3222
for scenario in self.scenarios:
3223
result.addTest(self.adapt_test_to_scenario(test, scenario))
3226
def adapt_test_to_scenario(self, test, scenario):
3227
"""Copy test and apply scenario to it.
3229
:param test: A test to adapt.
3230
:param scenario: A tuple describing the scenarion.
3231
The first element of the tuple is the new test id.
3232
The second element is a dict containing attributes to set on the
3234
:return: The adapted test.
3236
from copy import deepcopy
3237
new_test = deepcopy(test)
3238
for name, value in scenario[1].items():
3239
setattr(new_test, name, value)
3240
new_id = "%s(%s)" % (new_test.id(), scenario[0])
3241
new_test.id = lambda: new_id
4179
3245
def probe_unicode_in_user_encoding():