13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
# TODO: Perhaps there should be an API to find out if bzr running under the
19
# test suite -- some plugins might want to avoid making intrusive changes if
20
# this is the case. However, we want behaviour under to test to diverge as
21
# little as possible, so this should be used rarely if it's added at all.
22
# (Suggestion from j-a-meinel, 2005-11-24)
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Testing framework extensions"""
19
from __future__ import absolute_import
24
21
# NOTE: Some classes in here use camelCaseNaming() rather than
25
22
# underscore_naming(). That's for consistency with unittest; it's not the
26
23
# general style of bzrlib. Please continue that consistency when adding e.g.
27
24
# new assertFoo() methods.
30
29
from cStringIO import StringIO
36
from pprint import pformat
40
from subprocess import Popen, PIPE
53
# nb: check this before importing anything else from within it
54
_testtools_version = getattr(testtools, '__version__', ())
55
if _testtools_version < (0, 9, 5):
56
raise ImportError("need at least testtools 0.9.5: %s is %r"
57
% (testtools.__file__, _testtools_version))
58
from testtools import content
47
61
from bzrlib import (
65
commands as _mod_commands,
75
plugin as _mod_plugin,
82
transport as _mod_transport,
58
import bzrlib.commands
59
import bzrlib.timestamp
61
import bzrlib.inventory
62
import bzrlib.iterablefile
65
86
import bzrlib.lsprof
66
87
except ImportError:
67
88
# lsprof not available
69
from bzrlib.merge import merge_inner
73
from bzrlib.revision import common_ancestor
75
from bzrlib import symbol_versioning
77
from bzrlib.transport import get_transport
78
import bzrlib.transport
79
from bzrlib.transport.local import LocalURLServer
80
from bzrlib.transport.memory import MemoryServer
81
from bzrlib.transport.readonly import ReadonlyServer
82
from bzrlib.trace import mutter, note
83
from bzrlib.tests import TestUtil
84
from bzrlib.tests.HttpServer import HttpServer
85
from bzrlib.tests.TestUtil import (
89
from bzrlib.tests.treeshape import build_tree_contents
90
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
92
default_transport = LocalURLServer
95
MODULES_TO_DOCTEST = [
108
def packages_to_test():
109
"""Return a list of packages to test.
111
The packages are not globally imported so that import failures are
112
triggered when running selftest, not when importing the command.
115
import bzrlib.tests.blackbox
116
import bzrlib.tests.branch_implementations
117
import bzrlib.tests.bzrdir_implementations
118
import bzrlib.tests.interrepository_implementations
119
import bzrlib.tests.interversionedfile_implementations
120
import bzrlib.tests.intertree_implementations
121
import bzrlib.tests.per_lock
122
import bzrlib.tests.repository_implementations
123
import bzrlib.tests.revisionstore_implementations
124
import bzrlib.tests.tree_implementations
125
import bzrlib.tests.workingtree_implementations
128
bzrlib.tests.blackbox,
129
bzrlib.tests.branch_implementations,
130
bzrlib.tests.bzrdir_implementations,
131
bzrlib.tests.interrepository_implementations,
132
bzrlib.tests.interversionedfile_implementations,
133
bzrlib.tests.intertree_implementations,
134
bzrlib.tests.per_lock,
135
bzrlib.tests.repository_implementations,
136
bzrlib.tests.revisionstore_implementations,
137
bzrlib.tests.tree_implementations,
138
bzrlib.tests.workingtree_implementations,
142
class ExtendedTestResult(unittest._TextTestResult):
90
from bzrlib.smart import client, request
91
from bzrlib.transport import (
95
from bzrlib.symbol_versioning import (
99
from bzrlib.tests import (
105
from bzrlib.ui import NullProgressView
106
from bzrlib.ui.text import TextUIFactory
107
from bzrlib.tests.features import _CompatabilityThunkFeature
109
# Mark this python module as being part of the implementation
110
# of unittest: this gives us better tracebacks where the last
111
# shown frame is the test code, not our assertXYZ.
114
default_transport = test_server.LocalURLServer
117
_unitialized_attr = object()
118
"""A sentinel needed to act as a default value in a method signature."""
121
# Subunit result codes, defined here to prevent a hard dependency on subunit.
125
# These are intentionally brought into this namespace. That way plugins, etc
126
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
127
TestSuite = TestUtil.TestSuite
128
TestLoader = TestUtil.TestLoader
130
# Tests should run in a clean and clearly defined environment. The goal is to
131
# keep them isolated from the running environment as mush as possible. The test
132
# framework ensures the variables defined below are set (or deleted if the
133
# value is None) before a test is run and reset to their original value after
134
# the test is run. Generally if some code depends on an environment variable,
135
# the tests should start without this variable in the environment. There are a
136
# few exceptions but you shouldn't violate this rule lightly.
140
'XDG_CONFIG_HOME': None,
141
# bzr now uses the Win32 API and doesn't rely on APPDATA, but the
142
# tests do check our impls match APPDATA
143
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
147
'BZREMAIL': None, # may still be present in the environment
148
'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
149
'BZR_PROGRESS_BAR': None,
150
# This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
151
# as a base class instead of TestCaseInTempDir. Tests inheriting from
152
# TestCase should not use disk resources, BZR_LOG is one.
153
'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
154
'BZR_PLUGIN_PATH': None,
155
'BZR_DISABLE_PLUGINS': None,
156
'BZR_PLUGINS_AT': None,
157
'BZR_CONCURRENCY': None,
158
# Make sure that any text ui tests are consistent regardless of
159
# the environment the test case is run in; you may want tests that
160
# test other combinations. 'dumb' is a reasonable guess for tests
161
# going to a pipe or a StringIO.
167
'SSH_AUTH_SOCK': None,
177
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
178
# least. If you do (care), please update this comment
182
'BZR_REMOTE_PATH': None,
183
# Generally speaking, we don't want apport reporting on crashes in
184
# the test envirnoment unless we're specifically testing apport,
185
# so that it doesn't leak into the real system environment. We
186
# use an env var so it propagates to subprocesses.
187
'APPORT_DISABLE': '1',
191
def override_os_environ(test, env=None):
192
"""Modify os.environ keeping a copy.
194
:param test: A test instance
196
:param env: A dict containing variable definitions to be installed
199
env = isolated_environ
200
test._original_os_environ = dict([(var, value)
201
for var, value in os.environ.iteritems()])
202
for var, value in env.iteritems():
203
osutils.set_or_unset_env(var, value)
204
if var not in test._original_os_environ:
205
# The var is new, add it with a value of None, so
206
# restore_os_environ will delete it
207
test._original_os_environ[var] = None
210
def restore_os_environ(test):
211
"""Restore os.environ to its original state.
213
:param test: A test instance previously passed to override_os_environ.
215
for var, value in test._original_os_environ.iteritems():
216
# Restore the original value (or delete it if the value has been set to
217
# None in override_os_environ).
218
osutils.set_or_unset_env(var, value)
221
def _clear__type_equality_funcs(test):
222
"""Cleanup bound methods stored on TestCase instances
224
Clear the dict breaking a few (mostly) harmless cycles in the affected
225
unittests released with Python 2.6 and initial Python 2.7 versions.
227
For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
228
shipped in Oneiric, an object with no clear method was used, hence the
229
extra complications, see bug 809048 for details.
231
type_equality_funcs = getattr(test, "_type_equality_funcs", None)
232
if type_equality_funcs is not None:
233
tef_clear = getattr(type_equality_funcs, "clear", None)
234
if tef_clear is None:
235
tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
236
if tef_instance_dict is not None:
237
tef_clear = tef_instance_dict.clear
238
if tef_clear is not None:
242
class ExtendedTestResult(testtools.TextTestResult):
143
243
"""Accepts, reports and accumulates the results of running tests.
145
Compared to this unittest version this class adds support for profiling,
146
benchmarking, stopping as soon as a test fails, and skipping tests.
147
There are further-specialized subclasses for different types of display.
245
Compared to the unittest version this class adds support for
246
profiling, benchmarking, stopping as soon as a test fails, and
247
skipping tests. There are further-specialized subclasses for
248
different types of display.
250
When a test finishes, in whatever way, it calls one of the addSuccess,
251
addFailure or addError classes. These in turn may redirect to a more
252
specific case for the special test results supported by our extended
255
Note that just one of these objects is fed the results from many tests.
150
258
stop_early = False
152
260
def __init__(self, stream, descriptions, verbosity,
153
261
bench_history=None,
155
use_numbered_dirs=False,
157
264
"""Construct new TestResult.
159
266
:param bench_history: Optionally, a writable file object to accumulate
160
267
benchmark results.
162
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
269
testtools.TextTestResult.__init__(self, stream)
163
270
if bench_history is not None:
164
271
from bzrlib.version import _get_bzr_source_tree
165
272
src_tree = _get_bzr_source_tree()
211
380
def _shortened_test_description(self, test):
213
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
382
what = re.sub(r'^bzrlib\.tests\.', '', what)
385
# GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
386
# multiple times in a row, because the handler is added for
387
# each test but the container list is shared between cases.
388
# See lp:498869 lp:625574 and lp:637725 for background.
389
def _record_traceback_from_test(self, exc_info):
390
"""Store the traceback from passed exc_info tuple till"""
391
self._traceback_from_test = exc_info[2]
216
393
def startTest(self, test):
217
unittest.TestResult.startTest(self, test)
394
super(ExtendedTestResult, self).startTest(test)
218
398
self.report_test_start(test)
219
399
test.number = self.count
220
400
self._recordTestStartTime()
401
# Make testtools cases give us the real traceback on failure
402
addOnException = getattr(test, "addOnException", None)
403
if addOnException is not None:
404
addOnException(self._record_traceback_from_test)
405
# Only check for thread leaks on bzrlib derived test cases
406
if isinstance(test, TestCase):
407
test.addCleanup(self._check_leaked_threads, test)
409
def stopTest(self, test):
410
super(ExtendedTestResult, self).stopTest(test)
411
# Manually break cycles, means touching various private things but hey
412
getDetails = getattr(test, "getDetails", None)
413
if getDetails is not None:
415
_clear__type_equality_funcs(test)
416
self._traceback_from_test = None
418
def startTests(self):
419
self.report_tests_starting()
420
self._active_threads = threading.enumerate()
422
def _check_leaked_threads(self, test):
423
"""See if any threads have leaked since last call
425
A sample of live threads is stored in the _active_threads attribute,
426
when this method runs it compares the current live threads and any not
427
in the previous sample are treated as having leaked.
429
now_active_threads = set(threading.enumerate())
430
threads_leaked = now_active_threads.difference(self._active_threads)
432
self._report_thread_leak(test, threads_leaked, now_active_threads)
433
self._tests_leaking_threads_count += 1
434
if self._first_thread_leaker_id is None:
435
self._first_thread_leaker_id = test.id()
436
self._active_threads = now_active_threads
222
438
def _recordTestStartTime(self):
223
439
"""Record that a test has started."""
224
self._start_time = time.time()
226
def _cleanupLogFile(self, test):
227
# We can only do this if we have one of our TestCases, not if
229
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
230
if setKeepLogfile is not None:
440
self._start_datetime = self._now()
233
442
def addError(self, test, err):
234
self.extractBenchmarkTime(test)
235
self._cleanupLogFile(test)
236
if isinstance(err[1], TestSkipped):
237
return self.addSkipped(test, err)
238
elif isinstance(err[1], UnavailableFeature):
239
return self.addNotSupported(test, err[1].args[0])
240
unittest.TestResult.addError(self, test, err)
443
"""Tell result that test finished with an error.
445
Called from the TestCase run() method when the test
446
fails with an unexpected error.
448
self._post_mortem(self._traceback_from_test)
449
super(ExtendedTestResult, self).addError(test, err)
241
450
self.error_count += 1
242
451
self.report_error(test, err)
243
452
if self.stop_early:
246
455
def addFailure(self, test, err):
247
self._cleanupLogFile(test)
248
self.extractBenchmarkTime(test)
249
if isinstance(err[1], KnownFailure):
250
return self.addKnownFailure(test, err)
251
unittest.TestResult.addFailure(self, test, err)
456
"""Tell result that test failed.
458
Called from the TestCase run() method when the test
459
fails because e.g. an assert() method failed.
461
self._post_mortem(self._traceback_from_test)
462
super(ExtendedTestResult, self).addFailure(test, err)
252
463
self.failure_count += 1
253
464
self.report_failure(test, err)
254
465
if self.stop_early:
257
def addKnownFailure(self, test, err):
468
def addSuccess(self, test, details=None):
469
"""Tell result that test completed successfully.
471
Called from the TestCase run()
473
if self._bench_history is not None:
474
benchmark_time = self._extractBenchmarkTime(test, details)
475
if benchmark_time is not None:
476
self._bench_history.write("%s %s\n" % (
477
self._formatTime(benchmark_time),
479
self.report_success(test)
480
super(ExtendedTestResult, self).addSuccess(test)
481
test._log_contents = ''
483
def addExpectedFailure(self, test, err):
258
484
self.known_failure_count += 1
259
485
self.report_known_failure(test, err)
487
def addUnexpectedSuccess(self, test, details=None):
488
"""Tell result the test unexpectedly passed, counting as a failure
490
When the minimum version of testtools required becomes 0.9.8 this
491
can be updated to use the new handling there.
493
super(ExtendedTestResult, self).addFailure(test, details=details)
494
self.failure_count += 1
495
self.report_unexpected_success(test,
496
"".join(details["reason"].iter_text()))
261
500
def addNotSupported(self, test, feature):
501
"""The test will not be run because of a missing feature.
503
# this can be called in two different ways: it may be that the
504
# test started running, and then raised (through requireFeature)
505
# UnavailableFeature. Alternatively this method can be called
506
# while probing for features before running the test code proper; in
507
# that case we will see startTest and stopTest, but the test will
508
# never actually run.
262
509
self.unsupported.setdefault(str(feature), 0)
263
510
self.unsupported[str(feature)] += 1
264
511
self.report_unsupported(test, feature)
266
def addSuccess(self, test):
267
self.extractBenchmarkTime(test)
268
if self._bench_history is not None:
269
if self._benchmarkTime is not None:
270
self._bench_history.write("%s %s\n" % (
271
self._formatTime(self._benchmarkTime),
273
self.report_success(test)
274
unittest.TestResult.addSuccess(self, test)
276
def addSkipped(self, test, skip_excinfo):
277
self.report_skip(test, skip_excinfo)
278
# seems best to treat this as success from point-of-view of unittest
279
# -- it actually does nothing so it barely matters :)
282
except KeyboardInterrupt:
285
self.addError(test, test.__exc_info())
287
unittest.TestResult.addSuccess(self, test)
289
def printErrorList(self, flavour, errors):
290
for test, err in errors:
291
self.stream.writeln(self.separator1)
292
self.stream.write("%s: " % flavour)
293
if self.use_numbered_dirs:
294
self.stream.write('#%d ' % test.number)
295
self.stream.writeln(self.getDescription(test))
296
if getattr(test, '_get_log', None) is not None:
298
print >>self.stream, \
299
('vvvv[log from %s]' % test.id()).ljust(78,'-')
300
print >>self.stream, test._get_log()
301
print >>self.stream, \
302
('^^^^[log from %s]' % test.id()).ljust(78,'-')
303
self.stream.writeln(self.separator2)
304
self.stream.writeln("%s" % err)
309
def report_cleaning_up(self):
513
def addSkip(self, test, reason):
514
"""A test has not run for 'reason'."""
516
self.report_skip(test, reason)
518
def addNotApplicable(self, test, reason):
519
self.not_applicable_count += 1
520
self.report_not_applicable(test, reason)
522
def _count_stored_tests(self):
523
"""Count of tests instances kept alive due to not succeeding"""
524
return self.error_count + self.failure_count + self.known_failure_count
526
def _post_mortem(self, tb=None):
527
"""Start a PDB post mortem session."""
528
if os.environ.get('BZR_TEST_PDB', None):
532
def progress(self, offset, whence):
533
"""The test is adjusting the count of tests to run."""
534
if whence == SUBUNIT_SEEK_SET:
535
self.num_tests = offset
536
elif whence == SUBUNIT_SEEK_CUR:
537
self.num_tests += offset
539
raise errors.BzrError("Unknown whence %r" % whence)
541
def report_tests_starting(self):
542
"""Display information before the test run begins"""
543
if getattr(sys, 'frozen', None) is None:
544
bzr_path = osutils.realpath(sys.argv[0])
546
bzr_path = sys.executable
548
'bzr selftest: %s\n' % (bzr_path,))
551
bzrlib.__path__[0],))
553
' bzr-%s python-%s %s\n' % (
554
bzrlib.version_string,
555
bzrlib._format_version_tuple(sys.version_info),
556
platform.platform(aliased=1),
558
self.stream.write('\n')
560
def report_test_start(self, test):
561
"""Display information on the test just about to be run"""
563
def _report_thread_leak(self, test, leaked_threads, active_threads):
564
"""Display information on a test that leaked one or more threads"""
565
# GZ 2010-09-09: A leak summary reported separately from the general
566
# thread debugging would be nice. Tests under subunit
567
# need something not using stream, perhaps adding a
568
# testtools details object would be fitting.
569
if 'threads' in selftest_debug_flags:
570
self.stream.write('%s is leaking, active is now %d\n' %
571
(test.id(), len(active_threads)))
573
def startTestRun(self):
574
self.startTime = time.time()
312
576
def report_success(self, test):
579
def wasStrictlySuccessful(self):
580
if self.unsupported or self.known_failure_count:
582
return self.wasSuccessful()
316
585
class TextTestResult(ExtendedTestResult):
317
586
"""Displays progress and results of tests in text form"""
319
588
def __init__(self, stream, descriptions, verbosity,
320
589
bench_history=None,
323
use_numbered_dirs=False,
325
593
ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
326
bench_history, num_tests, use_numbered_dirs)
328
self.pb = self.ui.nested_progress_bar()
329
self._supplied_pb = False
332
self._supplied_pb = True
594
bench_history, strict)
595
# We no longer pass them around, but just rely on the UIFactory stack
598
warnings.warn("Passing pb to TextTestResult is deprecated")
599
self.pb = self.ui.nested_progress_bar()
333
600
self.pb.show_pct = False
334
601
self.pb.show_spinner = False
335
602
self.pb.show_eta = False,
336
603
self.pb.show_count = False
337
604
self.pb.show_bar = False
339
def report_starting(self):
340
self.pb.update('[test 0/%d] starting...' % (self.num_tests))
605
self.pb.update_latency = 0
606
self.pb.show_transport_activity = False
608
def stopTestRun(self):
609
# called when the tests that are going to run have run
612
super(TextTestResult, self).stopTestRun()
614
def report_tests_starting(self):
615
super(TextTestResult, self).report_tests_starting()
616
self.pb.update('[test 0/%d] Starting' % (self.num_tests))
342
618
def _progress_prefix_text(self):
343
a = '[%d' % self.count
344
if self.num_tests is not None:
619
# the longer this text, the less space we have to show the test
621
a = '[%d' % self.count # total that have been run
622
# tests skipped as known not to be relevant are not important enough
624
## if self.skip_count:
625
## a += ', %d skip' % self.skip_count
626
## if self.known_failure_count:
627
## a += '+%dX' % self.known_failure_count
345
629
a +='/%d' % self.num_tests
346
a += ' in %ds' % (time.time() - self._overall_start_time)
348
a += ', %d errors' % self.error_count
349
if self.failure_count:
350
a += ', %d failed' % self.failure_count
351
if self.known_failure_count:
352
a += ', %d known failures' % self.known_failure_count
354
a += ', %d skipped' % self.skip_count
356
a += ', %d missing features' % len(self.unsupported)
631
runtime = time.time() - self._overall_start_time
633
a += '%dm%ds' % (runtime / 60, runtime % 60)
636
total_fail_count = self.error_count + self.failure_count
638
a += ', %d failed' % total_fail_count
639
# if self.unsupported:
640
# a += ', %d missing' % len(self.unsupported)
360
644
def report_test_start(self, test):
363
646
self._progress_prefix_text()
365
648
+ self._shortened_test_description(test))
367
650
def _test_description(self, test):
368
if self.use_numbered_dirs:
369
return '#%d %s' % (self.count,
370
self._shortened_test_description(test))
372
return self._shortened_test_description(test)
651
return self._shortened_test_description(test)
374
653
def report_error(self, test, err):
375
self.pb.note('ERROR: %s\n %s\n',
654
self.stream.write('ERROR: %s\n %s\n' % (
376
655
self._test_description(test),
380
659
def report_failure(self, test, err):
381
self.pb.note('FAIL: %s\n %s\n',
660
self.stream.write('FAIL: %s\n %s\n' % (
382
661
self._test_description(test),
386
665
def report_known_failure(self, test, err):
387
self.pb.note('XFAIL: %s\n%s\n',
388
self._test_description(test), err[1])
390
def report_skip(self, test, skip_excinfo):
393
# at the moment these are mostly not things we can fix
394
# and so they just produce stipple; use the verbose reporter
397
# show test and reason for skip
398
self.pb.note('SKIP: %s\n %s\n',
399
self._shortened_test_description(test),
402
# since the class name was left behind in the still-visible
404
self.pb.note('SKIP: %s', skip_excinfo[1])
668
def report_unexpected_success(self, test, reason):
669
self.stream.write('FAIL: %s\n %s: %s\n' % (
670
self._test_description(test),
671
"Unexpected success. Should have failed",
675
def report_skip(self, test, reason):
678
def report_not_applicable(self, test, reason):
406
681
def report_unsupported(self, test, feature):
407
682
"""test cannot be run because feature is missing."""
409
def report_cleaning_up(self):
410
self.pb.update('cleaning up...')
413
if not self._supplied_pb:
417
685
class VerboseTestResult(ExtendedTestResult):
723
976
retrieved by _get_log(). We use a real OS file, not an in-memory object,
724
977
so that it can also capture file IO. When the test completes this file
725
978
is read into memory and removed from disk.
727
980
There are also convenience functions to invoke bzr's command-line
728
981
routine, and to build and check bzr trees.
730
983
In addition to the usual method of overriding tearDown(), this class also
731
allows subclasses to register functions into the _cleanups list, which is
984
allows subclasses to register cleanup functions via addCleanup, which are
732
985
run in order as the object is torn down. It's less likely this will be
733
986
accidentally overlooked.
736
_log_file_name = None
738
_keep_log_file = False
739
990
# record lsprof data when performing benchmark calls.
740
991
_gather_lsprof_in_benchmarks = False
742
993
def __init__(self, methodName='testMethod'):
743
994
super(TestCase, self).__init__(methodName)
995
self._directory_isolation = True
996
self.exception_handlers.insert(0,
997
(UnavailableFeature, self._do_unsupported_or_skip))
998
self.exception_handlers.insert(0,
999
(TestNotApplicable, self._do_not_applicable))
746
1001
def setUp(self):
747
unittest.TestCase.setUp(self)
1002
super(TestCase, self).setUp()
1004
timeout = config.GlobalStack().get('selftest.timeout')
1006
timeout_fixture = fixtures.TimeoutFixture(timeout)
1007
timeout_fixture.setUp()
1008
self.addCleanup(timeout_fixture.cleanUp)
1010
for feature in getattr(self, '_test_needs_features', []):
1011
self.requireFeature(feature)
748
1012
self._cleanEnvironment()
749
bzrlib.trace.disable_default_logging()
1014
if bzrlib.global_state is not None:
1015
self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1016
config.CommandLineStore())
750
1018
self._silenceUI()
751
1019
self._startLogFile()
752
1020
self._benchcalls = []
753
1021
self._benchtime = None
754
1022
self._clear_hooks()
1023
self._track_transports()
1025
self._clear_debug_flags()
1026
# Isolate global verbosity level, to make sure it's reproducible
1027
# between tests. We should get rid of this altogether: bug 656694. --
1029
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
1030
# Isolate config option expansion until its default value for bzrlib is
1031
# settled on or a the FIXME associated with _get_expand_default_value
1032
# is addressed -- vila 20110219
1033
self.overrideAttr(config, '_expand_default_value', None)
1034
self._log_files = set()
1035
# Each key in the ``_counters`` dict holds a value for a different
1036
# counter. When the test ends, addDetail() should be used to output the
1037
# counter values. This happens in install_counter_hook().
1039
if 'config_stats' in selftest_debug_flags:
1040
self._install_config_stats_hooks()
1041
# Do not use i18n for tests (unless the test reverses this)
1047
# The sys preserved stdin/stdout should allow blackbox tests debugging
1048
pdb.Pdb(stdin=sys.__stdin__, stdout=sys.__stdout__
1049
).set_trace(sys._getframe().f_back)
1051
def discardDetail(self, name):
1052
"""Extend the addDetail, getDetails api so we can remove a detail.
1054
eg. bzr always adds the 'log' detail at startup, but we don't want to
1055
include it for skipped, xfail, etc tests.
1057
It is safe to call this for a detail that doesn't exist, in case this
1058
gets called multiple times.
1060
# We cheat. details is stored in __details which means we shouldn't
1061
# touch it. but getDetails() returns the dict directly, so we can
1063
details = self.getDetails()
1067
def install_counter_hook(self, hooks, name, counter_name=None):
1068
"""Install a counting hook.
1070
Any hook can be counted as long as it doesn't need to return a value.
1072
:param hooks: Where the hook should be installed.
1074
:param name: The hook name that will be counted.
1076
:param counter_name: The counter identifier in ``_counters``, defaults
1079
_counters = self._counters # Avoid closing over self
1080
if counter_name is None:
1082
if _counters.has_key(counter_name):
1083
raise AssertionError('%s is already used as a counter name'
1085
_counters[counter_name] = 0
1086
self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1087
lambda: ['%d' % (_counters[counter_name],)]))
1088
def increment_counter(*args, **kwargs):
1089
_counters[counter_name] += 1
1090
label = 'count %s calls' % (counter_name,)
1091
hooks.install_named_hook(name, increment_counter, label)
1092
self.addCleanup(hooks.uninstall_named_hook, name, label)
1094
def _install_config_stats_hooks(self):
1095
"""Install config hooks to count hook calls.
1098
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1099
self.install_counter_hook(config.ConfigHooks, hook_name,
1100
'config.%s' % (hook_name,))
1102
# The OldConfigHooks are private and need special handling to protect
1103
# against recursive tests (tests that run other tests), so we just do
1104
# manually what registering them into _builtin_known_hooks will provide
1106
self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1107
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1108
self.install_counter_hook(config.OldConfigHooks, hook_name,
1109
'old_config.%s' % (hook_name,))
1111
def _clear_debug_flags(self):
1112
"""Prevent externally set debug flags affecting tests.
1114
Tests that want to use debug flags can just set them in the
1115
debug_flags set during setup/teardown.
1117
# Start with a copy of the current debug flags we can safely modify.
1118
self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
1119
if 'allow_debug' not in selftest_debug_flags:
1120
debug.debug_flags.clear()
1121
if 'disable_lock_checks' not in selftest_debug_flags:
1122
debug.debug_flags.add('strict_locks')
756
1124
def _clear_hooks(self):
757
1125
# prevent hooks affecting tests
759
import bzrlib.smart.server
760
self._preserved_hooks = {
761
bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
762
bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
1126
known_hooks = hooks.known_hooks
1127
self._preserved_hooks = {}
1128
for key, (parent, name) in known_hooks.iter_parent_objects():
1129
current_hooks = getattr(parent, name)
1130
self._preserved_hooks[parent] = (name, current_hooks)
1131
self._preserved_lazy_hooks = hooks._lazy_hooks
1132
hooks._lazy_hooks = {}
764
1133
self.addCleanup(self._restoreHooks)
765
# this list of hooks must be kept in sync with the defaults
767
bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
768
bzrlib.smart.server.SmartTCPServer.hooks = \
769
bzrlib.smart.server.SmartServerHooks()
1134
for key, (parent, name) in known_hooks.iter_parent_objects():
1135
factory = known_hooks.get(key)
1136
setattr(parent, name, factory())
1137
# this hook should always be installed
1138
request._install_hook()
1140
def disable_directory_isolation(self):
1141
"""Turn off directory isolation checks."""
1142
self._directory_isolation = False
1144
def enable_directory_isolation(self):
1145
"""Enable directory isolation checks."""
1146
self._directory_isolation = True
771
1148
def _silenceUI(self):
772
1149
"""Turn off UI for duration of test"""
773
1150
# by default the UI is off; tests can turn it on if they want it.
774
saved = ui.ui_factory
776
ui.ui_factory = saved
777
ui.ui_factory = ui.SilentUIFactory()
778
self.addCleanup(_restore)
1151
self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
1153
def _check_locks(self):
1154
"""Check that all lock take/release actions have been paired."""
1155
# We always check for mismatched locks. If a mismatch is found, we
1156
# fail unless -Edisable_lock_checks is supplied to selftest, in which
1157
# case we just print a warning.
1159
acquired_locks = [lock for action, lock in self._lock_actions
1160
if action == 'acquired']
1161
released_locks = [lock for action, lock in self._lock_actions
1162
if action == 'released']
1163
broken_locks = [lock for action, lock in self._lock_actions
1164
if action == 'broken']
1165
# trivially, given the tests for lock acquistion and release, if we
1166
# have as many in each list, it should be ok. Some lock tests also
1167
# break some locks on purpose and should be taken into account by
1168
# considering that breaking a lock is just a dirty way of releasing it.
1169
if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1171
'Different number of acquired and '
1172
'released or broken locks.\n'
1176
(acquired_locks, released_locks, broken_locks))
1177
if not self._lock_check_thorough:
1178
# Rather than fail, just warn
1179
print "Broken test %s: %s" % (self, message)
1183
def _track_locks(self):
1184
"""Track lock activity during tests."""
1185
self._lock_actions = []
1186
if 'disable_lock_checks' in selftest_debug_flags:
1187
self._lock_check_thorough = False
1189
self._lock_check_thorough = True
1191
self.addCleanup(self._check_locks)
1192
_mod_lock.Lock.hooks.install_named_hook('lock_acquired',
1193
self._lock_acquired, None)
1194
_mod_lock.Lock.hooks.install_named_hook('lock_released',
1195
self._lock_released, None)
1196
_mod_lock.Lock.hooks.install_named_hook('lock_broken',
1197
self._lock_broken, None)
1199
def _lock_acquired(self, result):
1200
self._lock_actions.append(('acquired', result))
1202
def _lock_released(self, result):
1203
self._lock_actions.append(('released', result))
1205
def _lock_broken(self, result):
1206
self._lock_actions.append(('broken', result))
1208
def permit_dir(self, name):
1209
"""Permit a directory to be used by this test. See permit_url."""
1210
name_transport = _mod_transport.get_transport_from_path(name)
1211
self.permit_url(name)
1212
self.permit_url(name_transport.base)
1214
def permit_url(self, url):
1215
"""Declare that url is an ok url to use in this test.
1217
Do this for memory transports, temporary test directory etc.
1219
Do not do this for the current working directory, /tmp, or any other
1220
preexisting non isolated url.
1222
if not url.endswith('/'):
1224
self._bzr_selftest_roots.append(url)
1226
def permit_source_tree_branch_repo(self):
1227
"""Permit the source tree bzr is running from to be opened.
1229
Some code such as bzrlib.version attempts to read from the bzr branch
1230
that bzr is executing from (if any). This method permits that directory
1231
to be used in the test suite.
1233
path = self.get_source_path()
1234
self.record_directory_isolation()
1237
workingtree.WorkingTree.open(path)
1238
except (errors.NotBranchError, errors.NoWorkingTree):
1239
raise TestSkipped('Needs a working tree of bzr sources')
1241
self.enable_directory_isolation()
1243
def _preopen_isolate_transport(self, transport):
1244
"""Check that all transport openings are done in the test work area."""
1245
while isinstance(transport, pathfilter.PathFilteringTransport):
1246
# Unwrap pathfiltered transports
1247
transport = transport.server.backing_transport.clone(
1248
transport._filter('.'))
1249
url = transport.base
1250
# ReadonlySmartTCPServer_for_testing decorates the backing transport
1251
# urls it is given by prepending readonly+. This is appropriate as the
1252
# client shouldn't know that the server is readonly (or not readonly).
1253
# We could register all servers twice, with readonly+ prepending, but
1254
# that makes for a long list; this is about the same but easier to
1256
if url.startswith('readonly+'):
1257
url = url[len('readonly+'):]
1258
self._preopen_isolate_url(url)
1260
def _preopen_isolate_url(self, url):
1261
if not self._directory_isolation:
1263
if self._directory_isolation == 'record':
1264
self._bzr_selftest_roots.append(url)
1266
# This prevents all transports, including e.g. sftp ones backed on disk
1267
# from working unless they are explicitly granted permission. We then
1268
# depend on the code that sets up test transports to check that they are
1269
# appropriately isolated and enable their use by calling
1270
# self.permit_transport()
1271
if not osutils.is_inside_any(self._bzr_selftest_roots, url):
1272
raise errors.BzrError("Attempt to escape test isolation: %r %r"
1273
% (url, self._bzr_selftest_roots))
1275
def record_directory_isolation(self):
1276
"""Gather accessed directories to permit later access.
1278
This is used for tests that access the branch bzr is running from.
1280
self._directory_isolation = "record"
1282
def start_server(self, transport_server, backing_server=None):
1283
"""Start transport_server for this test.
1285
This starts the server, registers a cleanup for it and permits the
1286
server's urls to be used.
1288
if backing_server is None:
1289
transport_server.start_server()
1291
transport_server.start_server(backing_server)
1292
self.addCleanup(transport_server.stop_server)
1293
# Obtain a real transport because if the server supplies a password, it
1294
# will be hidden from the base on the client side.
1295
t = _mod_transport.get_transport_from_url(transport_server.get_url())
1296
# Some transport servers effectively chroot the backing transport;
1297
# others like SFTPServer don't - users of the transport can walk up the
1298
# transport to read the entire backing transport. This wouldn't matter
1299
# except that the workdir tests are given - and that they expect the
1300
# server's url to point at - is one directory under the safety net. So
1301
# Branch operations into the transport will attempt to walk up one
1302
# directory. Chrooting all servers would avoid this but also mean that
1303
# we wouldn't be testing directly against non-root urls. Alternatively
1304
# getting the test framework to start the server with a backing server
1305
# at the actual safety net directory would work too, but this then
1306
# means that the self.get_url/self.get_transport methods would need
1307
# to transform all their results. On balance its cleaner to handle it
1308
# here, and permit a higher url when we have one of these transports.
1309
if t.base.endswith('/work/'):
1310
# we have safety net/test root/work
1311
t = t.clone('../..')
1312
elif isinstance(transport_server,
1313
test_server.SmartTCPServer_for_testing):
1314
# The smart server adds a path similar to work, which is traversed
1315
# up from by the client. But the server is chrooted - the actual
1316
# backing transport is not escaped from, and VFS requests to the
1317
# root will error (because they try to escape the chroot).
1319
while t2.base != t.base:
1322
self.permit_url(t.base)
1324
def _track_transports(self):
1325
"""Install checks for transport usage."""
1326
# TestCase has no safe place it can write to.
1327
self._bzr_selftest_roots = []
1328
# Currently the easiest way to be sure that nothing is going on is to
1329
# hook into bzr dir opening. This leaves a small window of error for
1330
# transport tests, but they are well known, and we can improve on this
1332
bzrdir.BzrDir.hooks.install_named_hook("pre_open",
1333
self._preopen_isolate_transport, "Check bzr directories are safe.")
780
1335
def _ndiff_strings(self, a, b):
781
1336
"""Return ndiff between two strings containing lines.
783
1338
A trailing newline is added if missing to make the strings
784
1339
print properly."""
785
1340
if b and b[-1] != '\n':
1009
1679
self.assertEqual(expected_first_warning, call_warnings[0])
1682
def callCatchWarnings(self, fn, *args, **kw):
1683
"""Call a callable that raises python warnings.
1685
The caller's responsible for examining the returned warnings.
1687
If the callable raises an exception, the exception is not
1688
caught and propagates up to the caller. In that case, the list
1689
of warnings is not available.
1691
:returns: ([warning_object, ...], fn_result)
1693
# XXX: This is not perfect, because it completely overrides the
1694
# warnings filters, and some code may depend on suppressing particular
1695
# warnings. It's the easiest way to insulate ourselves from -Werror,
1696
# though. -- Andrew, 20071062
1698
def _catcher(message, category, filename, lineno, file=None, line=None):
1699
# despite the name, 'message' is normally(?) a Warning subclass
1701
wlist.append(message)
1702
saved_showwarning = warnings.showwarning
1703
saved_filters = warnings.filters
1705
warnings.showwarning = _catcher
1706
warnings.filters = []
1707
result = fn(*args, **kw)
1709
warnings.showwarning = saved_showwarning
1710
warnings.filters = saved_filters
1711
return wlist, result
1012
1713
def callDeprecated(self, expected, callable, *args, **kwargs):
1013
1714
"""Assert that a callable is deprecated in a particular way.
1015
This is a very precise test for unusual requirements. The
1716
This is a very precise test for unusual requirements. The
1016
1717
applyDeprecated helper function is probably more suited for most tests
1017
1718
as it allows you to simply specify the deprecation format being used
1018
1719
and will ensure that that is issued for the function being called.
1721
Note that this only captures warnings raised by symbol_versioning.warn,
1722
not other callers that go direct to the warning module. To catch
1723
general warnings, use callCatchWarnings.
1020
1725
:param expected: a list of the deprecation warnings expected, in order
1021
1726
:param callable: The callable to call
1022
1727
:param args: The positional arguments for the callable
1023
1728
:param kwargs: The keyword arguments for the callable
1025
call_warnings, result = self._capture_warnings(callable,
1730
call_warnings, result = self._capture_deprecation_warnings(callable,
1026
1731
*args, **kwargs)
1027
1732
self.assertEqual(expected, call_warnings)
1030
1735
def _startLogFile(self):
1031
"""Send bzr and test log messages to a temporary file.
1033
The file is removed as the test is torn down.
1035
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1036
self._log_file = os.fdopen(fileno, 'w+')
1037
self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
1038
self._log_file_name = name
1736
"""Setup a in-memory target for bzr and testcase log messages"""
1737
pseudo_log_file = StringIO()
1738
def _get_log_contents_for_weird_testtools_api():
1739
return [pseudo_log_file.getvalue().decode(
1740
"utf-8", "replace").encode("utf-8")]
1741
self.addDetail("log", content.Content(content.ContentType("text",
1742
"plain", {"charset": "utf8"}),
1743
_get_log_contents_for_weird_testtools_api))
1744
self._log_file = pseudo_log_file
1745
self._log_memento = trace.push_log_file(self._log_file)
1039
1746
self.addCleanup(self._finishLogFile)
1041
1748
def _finishLogFile(self):
1042
"""Finished with the log file.
1044
Close the file and delete it, unless setKeepLogfile was called.
1046
if self._log_file is None:
1048
bzrlib.trace.disable_test_log(self._log_nonce)
1049
self._log_file.close()
1050
self._log_file = None
1051
if not self._keep_log_file:
1052
os.remove(self._log_file_name)
1053
self._log_file_name = None
1055
def setKeepLogfile(self):
1056
"""Make the logfile not be deleted when _finishLogFile is called."""
1057
self._keep_log_file = True
1059
def addCleanup(self, callable):
1060
"""Arrange to run a callable when this case is torn down.
1062
Callables are run in the reverse of the order they are registered,
1063
ie last-in first-out.
1065
if callable in self._cleanups:
1066
raise ValueError("cleanup function %r already registered on %s"
1068
self._cleanups.append(callable)
1749
"""Flush and dereference the in-memory log for this testcase"""
1750
if trace._trace_file:
1751
# flush the log file, to get all content
1752
trace._trace_file.flush()
1753
trace.pop_log_file(self._log_memento)
1754
# The logging module now tracks references for cleanup so discard ours
1755
del self._log_memento
1757
def thisFailsStrictLockCheck(self):
1758
"""It is known that this test would fail with -Dstrict_locks.
1760
By default, all tests are run with strict lock checking unless
1761
-Edisable_lock_checks is supplied. However there are some tests which
1762
we know fail strict locks at this point that have not been fixed.
1763
They should call this function to disable the strict checking.
1765
This should be used sparingly, it is much better to fix the locking
1766
issues rather than papering over the problem by calling this function.
1768
debug.debug_flags.discard('strict_locks')
1770
def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1771
"""Overrides an object attribute restoring it after the test.
1773
:note: This should be used with discretion; you should think about
1774
whether it's better to make the code testable without monkey-patching.
1776
:param obj: The object that will be mutated.
1778
:param attr_name: The attribute name we want to preserve/override in
1781
:param new: The optional value we want to set the attribute to.
1783
:returns: The actual attr value.
1785
# The actual value is captured by the call below
1786
value = getattr(obj, attr_name, _unitialized_attr)
1787
if value is _unitialized_attr:
1788
# When the test completes, the attribute should not exist, but if
1789
# we aren't setting a value, we don't need to do anything.
1790
if new is not _unitialized_attr:
1791
self.addCleanup(delattr, obj, attr_name)
1793
self.addCleanup(setattr, obj, attr_name, value)
1794
if new is not _unitialized_attr:
1795
setattr(obj, attr_name, new)
1798
def overrideEnv(self, name, new):
1799
"""Set an environment variable, and reset it after the test.
1801
:param name: The environment variable name.
1803
:param new: The value to set the variable to. If None, the
1804
variable is deleted from the environment.
1806
:returns: The actual variable value.
1808
value = osutils.set_or_unset_env(name, new)
1809
self.addCleanup(osutils.set_or_unset_env, name, value)
1812
def recordCalls(self, obj, attr_name):
1813
"""Monkeypatch in a wrapper that will record calls.
1815
The monkeypatch is automatically removed when the test concludes.
1817
:param obj: The namespace holding the reference to be replaced;
1818
typically a module, class, or object.
1819
:param attr_name: A string for the name of the attribute to
1821
:returns: A list that will be extended with one item every time the
1822
function is called, with a tuple of (args, kwargs).
1826
def decorator(*args, **kwargs):
1827
calls.append((args, kwargs))
1828
return orig(*args, **kwargs)
1829
orig = self.overrideAttr(obj, attr_name, decorator)
1070
1832
def _cleanEnvironment(self):
1072
'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1073
'HOME': os.getcwd(),
1074
'APPDATA': None, # bzr now use Win32 API and don't rely on APPDATA
1076
'BZREMAIL': None, # may still be present in the environment
1078
'BZR_PROGRESS_BAR': None,
1082
'https_proxy': None,
1083
'HTTPS_PROXY': None,
1088
# Nobody cares about these ones AFAIK. So far at
1089
# least. If you do (care), please update this comment
1095
self.addCleanup(self._restoreEnvironment)
1096
for name, value in new_env.iteritems():
1097
self._captureVar(name, value)
1099
def _captureVar(self, name, newvalue):
1100
"""Set an environment variable, and reset it when finished."""
1101
self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1103
def _restoreEnvironment(self):
1104
for name, value in self.__old_env.iteritems():
1105
osutils.set_or_unset_env(name, value)
1833
for name, value in isolated_environ.iteritems():
1834
self.overrideEnv(name, value)
1107
1836
def _restoreHooks(self):
1108
for klass, hooks in self._preserved_hooks.items():
1109
setattr(klass, 'hooks', hooks)
1837
for klass, (name, hooks) in self._preserved_hooks.items():
1838
setattr(klass, name, hooks)
1839
self._preserved_hooks.clear()
1840
bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1841
self._preserved_lazy_hooks.clear()
1111
1843
def knownFailure(self, reason):
1112
"""This test has failed for some known reason."""
1113
raise KnownFailure(reason)
1115
def run(self, result=None):
1116
if result is None: result = self.defaultTestResult()
1117
for feature in getattr(self, '_test_needs_features', []):
1118
if not feature.available():
1119
result.startTest(self)
1120
if getattr(result, 'addNotSupported', None):
1121
result.addNotSupported(self, feature)
1123
result.addSuccess(self)
1124
result.stopTest(self)
1126
return unittest.TestCase.run(self, result)
1130
unittest.TestCase.tearDown(self)
1844
"""Declare that this test fails for a known reason
1846
Tests that are known to fail should generally be using expectedFailure
1847
with an appropriate reverse assertion if a change could cause the test
1848
to start passing. Conversely if the test has no immediate prospect of
1849
succeeding then using skip is more suitable.
1851
When this method is called while an exception is being handled, that
1852
traceback will be used, otherwise a new exception will be thrown to
1853
provide one but won't be reported.
1855
self._add_reason(reason)
1857
exc_info = sys.exc_info()
1858
if exc_info != (None, None, None):
1859
self._report_traceback(exc_info)
1862
raise self.failureException(reason)
1863
except self.failureException:
1864
exc_info = sys.exc_info()
1865
# GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
1866
raise testtools.testcase._ExpectedFailure(exc_info)
1870
def _suppress_log(self):
1871
"""Remove the log info from details."""
1872
self.discardDetail('log')
1874
def _do_skip(self, result, reason):
1875
self._suppress_log()
1876
addSkip = getattr(result, 'addSkip', None)
1877
if not callable(addSkip):
1878
result.addSuccess(result)
1880
addSkip(self, reason)
1883
def _do_known_failure(self, result, e):
1884
self._suppress_log()
1885
err = sys.exc_info()
1886
addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1887
if addExpectedFailure is not None:
1888
addExpectedFailure(self, err)
1890
result.addSuccess(self)
1893
def _do_not_applicable(self, result, e):
1895
reason = 'No reason given'
1898
self._suppress_log ()
1899
addNotApplicable = getattr(result, 'addNotApplicable', None)
1900
if addNotApplicable is not None:
1901
result.addNotApplicable(self, reason)
1903
self._do_skip(result, reason)
1906
def _report_skip(self, result, err):
1907
"""Override the default _report_skip.
1909
We want to strip the 'log' detail. If we waint until _do_skip, it has
1910
already been formatted into the 'reason' string, and we can't pull it
1913
self._suppress_log()
1914
super(TestCase, self)._report_skip(self, result, err)
1917
def _report_expected_failure(self, result, err):
1920
See _report_skip for motivation.
1922
self._suppress_log()
1923
super(TestCase, self)._report_expected_failure(self, result, err)
1926
def _do_unsupported_or_skip(self, result, e):
1928
self._suppress_log()
1929
addNotSupported = getattr(result, 'addNotSupported', None)
1930
if addNotSupported is not None:
1931
result.addNotSupported(self, reason)
1933
self._do_skip(result, reason)
1132
1935
def time(self, callable, *args, **kwargs):
1133
1936
"""Run callable and accrue the time it takes to the benchmark time.
1135
1938
If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1136
1939
this will cause lsprofile statistics to be gathered and stored in
1137
1940
self._benchcalls.
1139
1942
if self._benchtime is None:
1943
self.addDetail('benchtime', content.Content(content.ContentType(
1944
"text", "plain"), lambda:[str(self._benchtime)]))
1140
1945
self._benchtime = 0
1141
1946
start = time.time()
1721
2584
def get_vfs_only_url(self, relpath=None):
1722
2585
"""Get a URL (or maybe a path for the plain old vfs transport.
1724
This will never be a smart protocol.
2587
This will never be a smart protocol. It always has all the
2588
capabilities of the local filesystem, but it might actually be a
2589
MemoryTransport or some other similar virtual filesystem.
2591
This is the backing transport (if any) of the server returned by
2592
get_url and get_readonly_url.
1725
2594
:param relpath: provides for clients to get a path relative to the base
1726
2595
url. These should only be downwards relative, not upwards.
1728
2598
base = self.get_vfs_only_server().get_url()
1729
2599
return self._adjust_url(base, relpath)
2601
def _create_safety_net(self):
2602
"""Make a fake bzr directory.
2604
This prevents any tests propagating up onto the TEST_ROOT directory's
2607
root = TestCaseWithMemoryTransport.TEST_ROOT
2608
# Make sure we get a readable and accessible home for .bzr.log
2609
# and/or config files, and not fallback to weird defaults (see
2610
# http://pad.lv/825027).
2611
self.assertIs(None, os.environ.get('BZR_HOME', None))
2612
os.environ['BZR_HOME'] = root
2613
wt = bzrdir.BzrDir.create_standalone_workingtree(root)
2614
del os.environ['BZR_HOME']
2615
# Hack for speed: remember the raw bytes of the dirstate file so that
2616
# we don't need to re-open the wt to check it hasn't changed.
2617
TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2618
wt.control_transport.get_bytes('dirstate'))
2620
def _check_safety_net(self):
2621
"""Check that the safety .bzr directory have not been touched.
2623
_make_test_root have created a .bzr directory to prevent tests from
2624
propagating. This method ensures than a test did not leaked.
2626
root = TestCaseWithMemoryTransport.TEST_ROOT
2627
t = _mod_transport.get_transport_from_path(root)
2628
self.permit_url(t.base)
2629
if (t.get_bytes('.bzr/checkout/dirstate') !=
2630
TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE):
2631
# The current test have modified the /bzr directory, we need to
2632
# recreate a new one or all the followng tests will fail.
2633
# If you need to inspect its content uncomment the following line
2634
# import pdb; pdb.set_trace()
2635
_rmtree_temp_dir(root + '/.bzr', test_id=self.id())
2636
self._create_safety_net()
2637
raise AssertionError('%s/.bzr should not be modified' % root)
1731
2639
def _make_test_root(self):
1732
if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1736
root = u'test%04d.tmp' % i
1740
if e.errno == errno.EEXIST:
1745
# successfully created
1746
TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
1748
# make a fake bzr directory there to prevent any tests propagating
1749
# up onto the source directory's real branch
1750
bzrdir.BzrDir.create_standalone_workingtree(
1751
TestCaseWithMemoryTransport.TEST_ROOT)
2640
if TestCaseWithMemoryTransport.TEST_ROOT is None:
2641
# Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
2642
root = osutils.realpath(osutils.mkdtemp(prefix='testbzr-',
2644
TestCaseWithMemoryTransport.TEST_ROOT = root
2646
self._create_safety_net()
2648
# The same directory is used by all tests, and we're not
2649
# specifically told when all tests are finished. This will do.
2650
atexit.register(_rmtree_temp_dir, root)
2652
self.permit_dir(TestCaseWithMemoryTransport.TEST_ROOT)
2653
self.addCleanup(self._check_safety_net)
1753
2655
def makeAndChdirToTestDir(self):
1754
2656
"""Create a temporary directories for this one test.
1756
2658
This must set self.test_home_dir and self.test_dir and chdir to
1759
2661
For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1761
2663
os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1762
2664
self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1763
2665
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1765
def make_branch(self, relpath, format=None):
2666
self.permit_dir(self.test_dir)
2668
def make_branch(self, relpath, format=None, name=None):
1766
2669
"""Create a branch on the transport at relpath."""
1767
2670
repo = self.make_repository(relpath, format=format)
1768
return repo.bzrdir.create_branch()
2671
return repo.bzrdir.create_branch(append_revisions_only=False,
2674
def get_default_format(self):
2677
def resolve_format(self, format):
2678
"""Resolve an object to a ControlDir format object.
2680
The initial format object can either already be
2681
a ControlDirFormat, None (for the default format),
2682
or a string with the name of the control dir format.
2684
:param format: Object to resolve
2685
:return A ControlDirFormat instance
2688
format = self.get_default_format()
2689
if isinstance(format, basestring):
2690
format = bzrdir.format_registry.make_bzrdir(format)
1770
2693
def make_bzrdir(self, relpath, format=None):
1772
2695
# might be a relative or absolute path
1773
2696
maybe_a_url = self.get_url(relpath)
1774
2697
segments = maybe_a_url.rsplit('/', 1)
1775
t = get_transport(maybe_a_url)
2698
t = _mod_transport.get_transport(maybe_a_url)
1776
2699
if len(segments) > 1 and segments[-1] not in ('', '.'):
1779
except errors.FileExists:
1783
if isinstance(format, basestring):
1784
format = bzrdir.format_registry.make_bzrdir(format)
2701
format = self.resolve_format(format)
1785
2702
return format.initialize_on_transport(t)
1786
2703
except errors.UninitializableFormat:
1787
2704
raise TestSkipped("Format %s is not initializable." % format)
1789
def make_repository(self, relpath, shared=False, format=None):
1790
"""Create a repository on our default transport at relpath."""
2706
def make_repository(self, relpath, shared=None, format=None):
2707
"""Create a repository on our default transport at relpath.
2709
Note that relpath must be a relative path, not a full url.
2711
# FIXME: If you create a remoterepository this returns the underlying
2712
# real format, which is incorrect. Actually we should make sure that
2713
# RemoteBzrDir returns a RemoteRepository.
2714
# maybe mbp 20070410
1791
2715
made_control = self.make_bzrdir(relpath, format=format)
1792
2716
return made_control.create_repository(shared=shared)
2718
def make_smart_server(self, path, backing_server=None):
2719
if backing_server is None:
2720
backing_server = self.get_server()
2721
smart_server = test_server.SmartTCPServer_for_testing()
2722
self.start_server(smart_server, backing_server)
2723
remote_transport = _mod_transport.get_transport_from_url(smart_server.get_url()
2725
return remote_transport
1794
2727
def make_branch_and_memory_tree(self, relpath, format=None):
1795
2728
"""Create a branch on the default transport and a MemoryTree for it."""
1796
2729
b = self.make_branch(relpath, format=format)
1797
2730
return memorytree.MemoryTree.create_on_branch(b)
2732
def make_branch_builder(self, relpath, format=None):
2733
branch = self.make_branch(relpath, format=format)
2734
return branchbuilder.BranchBuilder(branch=branch)
1799
2736
def overrideEnvironmentForTesting(self):
1800
os.environ['HOME'] = self.test_home_dir
1801
os.environ['BZR_HOME'] = self.test_home_dir
2737
test_home_dir = self.test_home_dir
2738
if isinstance(test_home_dir, unicode):
2739
test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2740
self.overrideEnv('HOME', test_home_dir)
2741
self.overrideEnv('BZR_HOME', test_home_dir)
1803
2743
def setUp(self):
1804
2744
super(TestCaseWithMemoryTransport, self).setUp()
2746
def _add_disconnect_cleanup(transport):
2747
"""Schedule disconnection of given transport at test cleanup
2749
This needs to happen for all connected transports or leaks occur.
2751
Note reconnections may mean we call disconnect multiple times per
2752
transport which is suboptimal but seems harmless.
2754
self.addCleanup(transport.disconnect)
2756
_mod_transport.Transport.hooks.install_named_hook('post_connect',
2757
_add_disconnect_cleanup, None)
1805
2759
self._make_test_root()
1806
_currentdir = os.getcwdu()
1807
def _leaveDirectory():
1808
os.chdir(_currentdir)
1809
self.addCleanup(_leaveDirectory)
2760
self.addCleanup(os.chdir, os.getcwdu())
1810
2761
self.makeAndChdirToTestDir()
1811
2762
self.overrideEnvironmentForTesting()
1812
2763
self.__readonly_server = None
1813
2764
self.__server = None
1814
2765
self.reduceLockdirTimeout()
2767
def setup_smart_server_with_call_log(self):
2768
"""Sets up a smart server as the transport server with a call log."""
2769
self.transport_server = test_server.SmartTCPServer_for_testing
2770
self.hpss_connections = []
2771
self.hpss_calls = []
2773
# Skip the current stack down to the caller of
2774
# setup_smart_server_with_call_log
2775
prefix_length = len(traceback.extract_stack()) - 2
2776
def capture_hpss_call(params):
2777
self.hpss_calls.append(
2778
CapturedCall(params, prefix_length))
2779
def capture_connect(transport):
2780
self.hpss_connections.append(transport)
2781
client._SmartClient.hooks.install_named_hook(
2782
'call', capture_hpss_call, None)
2783
_mod_transport.Transport.hooks.install_named_hook(
2784
'post_connect', capture_connect, None)
2786
def reset_smart_call_log(self):
2787
self.hpss_calls = []
2788
self.hpss_connections = []
1817
2791
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1818
2792
"""Derived class that runs a test within a temporary directory.
2038
3064
for readonly urls.
2040
3066
TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
2041
be used without needed to redo it when a different
3067
be used without needed to redo it when a different
2042
3068
subclass is in use ?
2045
3071
def setUp(self):
3072
from bzrlib.tests import http_server
2046
3073
super(ChrootedTestCase, self).setUp()
2047
if not self.vfs_transport_factory == MemoryServer:
2048
self.transport_readonly_server = HttpServer
3074
if not self.vfs_transport_factory == memory.MemoryServer:
3075
self.transport_readonly_server = http_server.HttpServer
3078
def condition_id_re(pattern):
3079
"""Create a condition filter which performs a re check on a test's id.
3081
:param pattern: A regular expression string.
3082
:return: A callable that returns True if the re matches.
3084
filter_re = re.compile(pattern, 0)
3085
def condition(test):
3087
return filter_re.search(test_id)
3091
def condition_isinstance(klass_or_klass_list):
3092
"""Create a condition filter which returns isinstance(param, klass).
3094
:return: A callable which when called with one parameter obj return the
3095
result of isinstance(obj, klass_or_klass_list).
3098
return isinstance(obj, klass_or_klass_list)
3102
def condition_id_in_list(id_list):
3103
"""Create a condition filter which verify that test's id in a list.
3105
:param id_list: A TestIdList object.
3106
:return: A callable that returns True if the test's id appears in the list.
3108
def condition(test):
3109
return id_list.includes(test.id())
3113
def condition_id_startswith(starts):
3114
"""Create a condition filter verifying that test's id starts with a string.
3116
:param starts: A list of string.
3117
:return: A callable that returns True if the test's id starts with one of
3120
def condition(test):
3121
for start in starts:
3122
if test.id().startswith(start):
3128
def exclude_tests_by_condition(suite, condition):
3129
"""Create a test suite which excludes some tests from suite.
3131
:param suite: The suite to get tests from.
3132
:param condition: A callable whose result evaluates True when called with a
3133
test case which should be excluded from the result.
3134
:return: A suite which contains the tests found in suite that fail
3138
for test in iter_suite_tests(suite):
3139
if not condition(test):
3141
return TestUtil.TestSuite(result)
3144
def filter_suite_by_condition(suite, condition):
3145
"""Create a test suite by filtering another one.
3147
:param suite: The source suite.
3148
:param condition: A callable whose result evaluates True when called with a
3149
test case which should be included in the result.
3150
:return: A suite which contains the tests found in suite that pass
3154
for test in iter_suite_tests(suite):
3157
return TestUtil.TestSuite(result)
2051
3160
def filter_suite_by_re(suite, pattern):
2052
result = TestUtil.TestSuite()
2053
filter_re = re.compile(pattern)
2054
for test in iter_suite_tests(suite):
2055
if filter_re.search(test.id()):
2056
result.addTest(test)
2060
def sort_suite_by_re(suite, pattern):
2063
filter_re = re.compile(pattern)
2064
for test in iter_suite_tests(suite):
2065
if filter_re.search(test.id()):
3161
"""Create a test suite by filtering another one.
3163
:param suite: the source suite
3164
:param pattern: pattern that names must match
3165
:returns: the newly created suite
3167
condition = condition_id_re(pattern)
3168
result_suite = filter_suite_by_condition(suite, condition)
3172
def filter_suite_by_id_list(suite, test_id_list):
3173
"""Create a test suite by filtering another one.
3175
:param suite: The source suite.
3176
:param test_id_list: A list of the test ids to keep as strings.
3177
:returns: the newly created suite
3179
condition = condition_id_in_list(test_id_list)
3180
result_suite = filter_suite_by_condition(suite, condition)
3184
def filter_suite_by_id_startswith(suite, start):
3185
"""Create a test suite by filtering another one.
3187
:param suite: The source suite.
3188
:param start: A list of string the test id must start with one of.
3189
:returns: the newly created suite
3191
condition = condition_id_startswith(start)
3192
result_suite = filter_suite_by_condition(suite, condition)
3196
def exclude_tests_by_re(suite, pattern):
3197
"""Create a test suite which excludes some tests from suite.
3199
:param suite: The suite to get tests from.
3200
:param pattern: A regular expression string. Test ids that match this
3201
pattern will be excluded from the result.
3202
:return: A TestSuite that contains all the tests from suite without the
3203
tests that matched pattern. The order of tests is the same as it was in
3206
return exclude_tests_by_condition(suite, condition_id_re(pattern))
3209
def preserve_input(something):
3210
"""A helper for performing test suite transformation chains.
3212
:param something: Anything you want to preserve.
3218
def randomize_suite(suite):
3219
"""Return a new TestSuite with suite's tests in random order.
3221
The tests in the input suite are flattened into a single suite in order to
3222
accomplish this. Any nested TestSuites are removed to provide global
3225
tests = list(iter_suite_tests(suite))
3226
random.shuffle(tests)
3227
return TestUtil.TestSuite(tests)
3230
def split_suite_by_condition(suite, condition):
3231
"""Split a test suite into two by a condition.
3233
:param suite: The suite to split.
3234
:param condition: The condition to match on. Tests that match this
3235
condition are returned in the first test suite, ones that do not match
3236
are in the second suite.
3237
:return: A tuple of two test suites, where the first contains tests from
3238
suite matching the condition, and the second contains the remainder
3239
from suite. The order within each output suite is the same as it was in
3244
for test in iter_suite_tests(suite):
3246
matched.append(test)
2069
return TestUtil.TestSuite(first + second)
3248
did_not_match.append(test)
3249
return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
3252
def split_suite_by_re(suite, pattern):
3253
"""Split a test suite into two by a regular expression.
3255
:param suite: The suite to split.
3256
:param pattern: A regular expression string. Test ids that match this
3257
pattern will be in the first test suite returned, and the others in the
3258
second test suite returned.
3259
:return: A tuple of two test suites, where the first contains tests from
3260
suite matching pattern, and the second contains the remainder from
3261
suite. The order within each output suite is the same as it was in
3264
return split_suite_by_condition(suite, condition_id_re(pattern))
2072
3267
def run_suite(suite, name='test', verbose=False, pattern=".*",
2073
stop_on_failure=False, keep_output=False,
3268
stop_on_failure=False,
2074
3269
transport=None, lsprof_timed=None, bench_history=None,
2075
3270
matching_tests_first=None,
2076
numbered_dirs=None):
2077
use_numbered_dirs = bool(numbered_dirs)
3273
exclude_pattern=None,
3276
suite_decorators=None,
3278
result_decorators=None,
3280
"""Run a test suite for bzr selftest.
3282
:param runner_class: The class of runner to use. Must support the
3283
constructor arguments passed by run_suite which are more than standard
3285
:return: A boolean indicating success.
2079
3287
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2080
if numbered_dirs is not None:
2081
TestCaseInTempDir.use_numbered_dirs = use_numbered_dirs
2086
runner = TextTestRunner(stream=sys.stdout,
3292
if runner_class is None:
3293
runner_class = TextTestRunner
3296
runner = runner_class(stream=stream,
2087
3297
descriptions=0,
2088
3298
verbosity=verbosity,
2089
keep_output=keep_output,
2090
3299
bench_history=bench_history,
2091
use_numbered_dirs=use_numbered_dirs,
3301
result_decorators=result_decorators,
2093
3303
runner.stop_on_failure=stop_on_failure
2095
if matching_tests_first:
2096
suite = sort_suite_by_re(suite, pattern)
2098
suite = filter_suite_by_re(suite, pattern)
3304
if isinstance(suite, unittest.TestSuite):
3305
# Empty out _tests list of passed suite and populate new TestSuite
3306
suite._tests[:], suite = [], TestSuite(suite)
3307
# built in decorator factories:
3309
random_order(random_seed, runner),
3310
exclude_tests(exclude_pattern),
3312
if matching_tests_first:
3313
decorators.append(tests_first(pattern))
3315
decorators.append(filter_tests(pattern))
3316
if suite_decorators:
3317
decorators.extend(suite_decorators)
3318
# tell the result object how many tests will be running: (except if
3319
# --parallel=fork is being used. Robert said he will provide a better
3320
# progress design later -- vila 20090817)
3321
if fork_decorator not in decorators:
3322
decorators.append(CountingDecorator)
3323
for decorator in decorators:
3324
suite = decorator(suite)
3326
# Done after test suite decoration to allow randomisation etc
3327
# to take effect, though that is of marginal benefit.
3329
stream.write("Listing tests only ...\n")
3330
for t in iter_suite_tests(suite):
3331
stream.write("%s\n" % (t.id()))
2099
3333
result = runner.run(suite)
2100
return result.wasSuccessful()
3335
return result.wasStrictlySuccessful()
3337
return result.wasSuccessful()
3340
# A registry where get() returns a suite decorator.
3341
parallel_registry = registry.Registry()
3344
def fork_decorator(suite):
3345
if getattr(os, "fork", None) is None:
3346
raise errors.BzrCommandError("platform does not support fork,"
3347
" try --parallel=subprocess instead.")
3348
concurrency = osutils.local_concurrency()
3349
if concurrency == 1:
3351
from testtools import ConcurrentTestSuite
3352
return ConcurrentTestSuite(suite, fork_for_tests)
3353
parallel_registry.register('fork', fork_decorator)
3356
def subprocess_decorator(suite):
3357
concurrency = osutils.local_concurrency()
3358
if concurrency == 1:
3360
from testtools import ConcurrentTestSuite
3361
return ConcurrentTestSuite(suite, reinvoke_for_tests)
3362
parallel_registry.register('subprocess', subprocess_decorator)
3365
def exclude_tests(exclude_pattern):
3366
"""Return a test suite decorator that excludes tests."""
3367
if exclude_pattern is None:
3368
return identity_decorator
3369
def decorator(suite):
3370
return ExcludeDecorator(suite, exclude_pattern)
3374
def filter_tests(pattern):
3376
return identity_decorator
3377
def decorator(suite):
3378
return FilterTestsDecorator(suite, pattern)
3382
def random_order(random_seed, runner):
3383
"""Return a test suite decorator factory for randomising tests order.
3385
:param random_seed: now, a string which casts to a long, or a long.
3386
:param runner: A test runner with a stream attribute to report on.
3388
if random_seed is None:
3389
return identity_decorator
3390
def decorator(suite):
3391
return RandomDecorator(suite, random_seed, runner.stream)
3395
def tests_first(pattern):
3397
return identity_decorator
3398
def decorator(suite):
3399
return TestFirstDecorator(suite, pattern)
3403
def identity_decorator(suite):
3408
class TestDecorator(TestUtil.TestSuite):
3409
"""A decorator for TestCase/TestSuite objects.
3411
Contains rather than flattening suite passed on construction
3414
def __init__(self, suite=None):
3415
super(TestDecorator, self).__init__()
3416
if suite is not None:
3419
# Don't need subclass run method with suite emptying
3420
run = unittest.TestSuite.run
3423
class CountingDecorator(TestDecorator):
3424
"""A decorator which calls result.progress(self.countTestCases)."""
3426
def run(self, result):
3427
progress_method = getattr(result, 'progress', None)
3428
if callable(progress_method):
3429
progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
3430
return super(CountingDecorator, self).run(result)
3433
class ExcludeDecorator(TestDecorator):
3434
"""A decorator which excludes test matching an exclude pattern."""
3436
def __init__(self, suite, exclude_pattern):
3437
super(ExcludeDecorator, self).__init__(
3438
exclude_tests_by_re(suite, exclude_pattern))
3441
class FilterTestsDecorator(TestDecorator):
3442
"""A decorator which filters tests to those matching a pattern."""
3444
def __init__(self, suite, pattern):
3445
super(FilterTestsDecorator, self).__init__(
3446
filter_suite_by_re(suite, pattern))
3449
class RandomDecorator(TestDecorator):
3450
"""A decorator which randomises the order of its tests."""
3452
def __init__(self, suite, random_seed, stream):
3453
random_seed = self.actual_seed(random_seed)
3454
stream.write("Randomizing test order using seed %s\n\n" %
3456
# Initialise the random number generator.
3457
random.seed(random_seed)
3458
super(RandomDecorator, self).__init__(randomize_suite(suite))
3461
def actual_seed(seed):
3463
# We convert the seed to a long to make it reuseable across
3464
# invocations (because the user can reenter it).
3465
return long(time.time())
3467
# Convert the seed to a long if we can
3470
except (TypeError, ValueError):
3475
class TestFirstDecorator(TestDecorator):
3476
"""A decorator which moves named tests to the front."""
3478
def __init__(self, suite, pattern):
3479
super(TestFirstDecorator, self).__init__()
3480
self.addTests(split_suite_by_re(suite, pattern))
3483
def partition_tests(suite, count):
3484
"""Partition suite into count lists of tests."""
3485
# This just assigns tests in a round-robin fashion. On one hand this
3486
# splits up blocks of related tests that might run faster if they shared
3487
# resources, but on the other it avoids assigning blocks of slow tests to
3488
# just one partition. So the slowest partition shouldn't be much slower
3490
partitions = [list() for i in range(count)]
3491
tests = iter_suite_tests(suite)
3492
for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3493
partition.append(test)
3497
def workaround_zealous_crypto_random():
3498
"""Crypto.Random want to help us being secure, but we don't care here.
3500
This workaround some test failure related to the sftp server. Once paramiko
3501
stop using the controversial API in Crypto.Random, we may get rid of it.
3504
from Crypto.Random import atfork
3510
def fork_for_tests(suite):
3511
"""Take suite and start up one runner per CPU by forking()
3513
:return: An iterable of TestCase-like objects which can each have
3514
run(result) called on them to feed tests to result.
3516
concurrency = osutils.local_concurrency()
3518
from subunit import ProtocolTestCase
3519
from subunit.test_results import AutoTimingTestResultDecorator
3520
class TestInOtherProcess(ProtocolTestCase):
3521
# Should be in subunit, I think. RBC.
3522
def __init__(self, stream, pid):
3523
ProtocolTestCase.__init__(self, stream)
3526
def run(self, result):
3528
ProtocolTestCase.run(self, result)
3530
pid, status = os.waitpid(self.pid, 0)
3531
# GZ 2011-10-18: If status is nonzero, should report to the result
3532
# that something went wrong.
3534
test_blocks = partition_tests(suite, concurrency)
3535
# Clear the tests from the original suite so it doesn't keep them alive
3536
suite._tests[:] = []
3537
for process_tests in test_blocks:
3538
process_suite = TestUtil.TestSuite(process_tests)
3539
# Also clear each split list so new suite has only reference
3540
process_tests[:] = []
3541
c2pread, c2pwrite = os.pipe()
3545
stream = os.fdopen(c2pwrite, 'wb', 1)
3546
workaround_zealous_crypto_random()
3548
# Leave stderr and stdout open so we can see test noise
3549
# Close stdin so that the child goes away if it decides to
3550
# read from stdin (otherwise its a roulette to see what
3551
# child actually gets keystrokes for pdb etc).
3553
subunit_result = AutoTimingTestResultDecorator(
3554
SubUnitBzrProtocolClient(stream))
3555
process_suite.run(subunit_result)
3557
# Try and report traceback on stream, but exit with error even
3558
# if stream couldn't be created or something else goes wrong.
3559
# The traceback is formatted to a string and written in one go
3560
# to avoid interleaving lines from multiple failing children.
3562
stream.write(traceback.format_exc())
3568
stream = os.fdopen(c2pread, 'rb', 1)
3569
test = TestInOtherProcess(stream, pid)
3574
def reinvoke_for_tests(suite):
3575
"""Take suite and start up one runner per CPU using subprocess().
3577
:return: An iterable of TestCase-like objects which can each have
3578
run(result) called on them to feed tests to result.
3580
concurrency = osutils.local_concurrency()
3582
from subunit import ProtocolTestCase
3583
class TestInSubprocess(ProtocolTestCase):
3584
def __init__(self, process, name):
3585
ProtocolTestCase.__init__(self, process.stdout)
3586
self.process = process
3587
self.process.stdin.close()
3590
def run(self, result):
3592
ProtocolTestCase.run(self, result)
3595
os.unlink(self.name)
3596
# print "pid %d finished" % finished_process
3597
test_blocks = partition_tests(suite, concurrency)
3598
for process_tests in test_blocks:
3599
# ugly; currently reimplement rather than reuses TestCase methods.
3600
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
3601
if not os.path.isfile(bzr_path):
3602
# We are probably installed. Assume sys.argv is the right file
3603
bzr_path = sys.argv[0]
3604
bzr_path = [bzr_path]
3605
if sys.platform == "win32":
3606
# if we're on windows, we can't execute the bzr script directly
3607
bzr_path = [sys.executable] + bzr_path
3608
fd, test_list_file_name = tempfile.mkstemp()
3609
test_list_file = os.fdopen(fd, 'wb', 1)
3610
for test in process_tests:
3611
test_list_file.write(test.id() + '\n')
3612
test_list_file.close()
3614
argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
3616
if '--no-plugins' in sys.argv:
3617
argv.append('--no-plugins')
3618
# stderr=subprocess.STDOUT would be ideal, but until we prevent
3619
# noise on stderr it can interrupt the subunit protocol.
3620
process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3621
stdout=subprocess.PIPE,
3622
stderr=subprocess.PIPE,
3624
test = TestInSubprocess(process, test_list_file_name)
3627
os.unlink(test_list_file_name)
3632
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3633
"""Generate profiling data for all activity between start and success.
3635
The profile data is appended to the test's _benchcalls attribute and can
3636
be accessed by the forwarded-to TestResult.
3638
While it might be cleaner do accumulate this in stopTest, addSuccess is
3639
where our existing output support for lsprof is, and this class aims to
3640
fit in with that: while it could be moved it's not necessary to accomplish
3641
test profiling, nor would it be dramatically cleaner.
3644
def startTest(self, test):
3645
self.profiler = bzrlib.lsprof.BzrProfiler()
3646
# Prevent deadlocks in tests that use lsprof: those tests will
3648
bzrlib.lsprof.BzrProfiler.profiler_block = 0
3649
self.profiler.start()
3650
testtools.ExtendedToOriginalDecorator.startTest(self, test)
3652
def addSuccess(self, test):
3653
stats = self.profiler.stop()
3655
calls = test._benchcalls
3656
except AttributeError:
3657
test._benchcalls = []
3658
calls = test._benchcalls
3659
calls.append(((test.id(), "", ""), stats))
3660
testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
3662
def stopTest(self, test):
3663
testtools.ExtendedToOriginalDecorator.stopTest(self, test)
3664
self.profiler = None
3667
# Controlled by "bzr selftest -E=..." option
3668
# Currently supported:
3669
# -Eallow_debug Will no longer clear debug.debug_flags() so it
3670
# preserves any flags supplied at the command line.
3671
# -Edisable_lock_checks Turns errors in mismatched locks into simple prints
3672
# rather than failing tests. And no longer raise
3673
# LockContention when fctnl locks are not being used
3674
# with proper exclusion rules.
3675
# -Ethreads Will display thread ident at creation/join time to
3676
# help track thread leaks
3677
# -Euncollected_cases Display the identity of any test cases that weren't
3678
# deallocated after being completed.
3679
# -Econfig_stats Will collect statistics using addDetail
3680
selftest_debug_flags = set()
2103
3683
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
2105
3684
transport=None,
2106
3685
test_suite_factory=None,
2107
3686
lsprof_timed=None,
2108
3687
bench_history=None,
2109
3688
matching_tests_first=None,
2110
numbered_dirs=None):
3691
exclude_pattern=None,
3697
suite_decorators=None,
2111
3701
"""Run the whole test suite under the enhanced runner"""
2112
3702
# XXX: Very ugly way to do this...
2113
3703
# Disable warning about old formats because we don't want it to disturb
2120
3710
transport = default_transport
2121
3711
old_transport = default_transport
2122
3712
default_transport = transport
3713
global selftest_debug_flags
3714
old_debug_flags = selftest_debug_flags
3715
if debug_flags is not None:
3716
selftest_debug_flags = set(debug_flags)
3718
if load_list is None:
3721
keep_only = load_test_id_list(load_list)
3723
starting_with = [test_prefix_alias_registry.resolve_alias(start)
3724
for start in starting_with]
2124
3725
if test_suite_factory is None:
2125
suite = test_suite()
3726
# Reduce loading time by loading modules based on the starting_with
3728
suite = test_suite(keep_only, starting_with)
2127
3730
suite = test_suite_factory()
3732
# But always filter as requested.
3733
suite = filter_suite_by_id_startswith(suite, starting_with)
3734
result_decorators = []
3736
result_decorators.append(ProfileResult)
2128
3737
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2129
stop_on_failure=stop_on_failure, keep_output=keep_output,
3738
stop_on_failure=stop_on_failure,
2130
3739
transport=transport,
2131
3740
lsprof_timed=lsprof_timed,
2132
3741
bench_history=bench_history,
2133
3742
matching_tests_first=matching_tests_first,
2134
numbered_dirs=numbered_dirs)
3743
list_only=list_only,
3744
random_seed=random_seed,
3745
exclude_pattern=exclude_pattern,
3747
runner_class=runner_class,
3748
suite_decorators=suite_decorators,
3750
result_decorators=result_decorators,
2136
3753
default_transport = old_transport
3754
selftest_debug_flags = old_debug_flags
3757
def load_test_id_list(file_name):
3758
"""Load a test id list from a text file.
3760
The format is one test id by line. No special care is taken to impose
3761
strict rules, these test ids are used to filter the test suite so a test id
3762
that do not match an existing test will do no harm. This allows user to add
3763
comments, leave blank lines, etc.
3767
ftest = open(file_name, 'rt')
3769
if e.errno != errno.ENOENT:
3772
raise errors.NoSuchFile(file_name)
3774
for test_name in ftest.readlines():
3775
test_list.append(test_name.strip())
3780
def suite_matches_id_list(test_suite, id_list):
3781
"""Warns about tests not appearing or appearing more than once.
3783
:param test_suite: A TestSuite object.
3784
:param test_id_list: The list of test ids that should be found in
3787
:return: (absents, duplicates) absents is a list containing the test found
3788
in id_list but not in test_suite, duplicates is a list containing the
3789
test found multiple times in test_suite.
3791
When using a prefined test id list, it may occurs that some tests do not
3792
exist anymore or that some tests use the same id. This function warns the
3793
tester about potential problems in his workflow (test lists are volatile)
3794
or in the test suite itself (using the same id for several tests does not
3795
help to localize defects).
3797
# Build a dict counting id occurrences
3799
for test in iter_suite_tests(test_suite):
3801
tests[id] = tests.get(id, 0) + 1
3806
occurs = tests.get(id, 0)
3808
not_found.append(id)
3810
duplicates.append(id)
3812
return not_found, duplicates
3815
class TestIdList(object):
3816
"""Test id list to filter a test suite.
3818
Relying on the assumption that test ids are built as:
3819
<module>[.<class>.<method>][(<param>+)], <module> being in python dotted
3820
notation, this class offers methods to :
3821
- avoid building a test suite for modules not refered to in the test list,
3822
- keep only the tests listed from the module test suite.
3825
def __init__(self, test_id_list):
3826
# When a test suite needs to be filtered against us we compare test ids
3827
# for equality, so a simple dict offers a quick and simple solution.
3828
self.tests = dict().fromkeys(test_id_list, True)
3830
# While unittest.TestCase have ids like:
3831
# <module>.<class>.<method>[(<param+)],
3832
# doctest.DocTestCase can have ids like:
3835
# <module>.<function>
3836
# <module>.<class>.<method>
3838
# Since we can't predict a test class from its name only, we settle on
3839
# a simple constraint: a test id always begins with its module name.
3842
for test_id in test_id_list:
3843
parts = test_id.split('.')
3844
mod_name = parts.pop(0)
3845
modules[mod_name] = True
3847
mod_name += '.' + part
3848
modules[mod_name] = True
3849
self.modules = modules
3851
def refers_to(self, module_name):
3852
"""Is there tests for the module or one of its sub modules."""
3853
return self.modules.has_key(module_name)
3855
def includes(self, test_id):
3856
return self.tests.has_key(test_id)
3859
class TestPrefixAliasRegistry(registry.Registry):
3860
"""A registry for test prefix aliases.
3862
This helps implement shorcuts for the --starting-with selftest
3863
option. Overriding existing prefixes is not allowed but not fatal (a
3864
warning will be emitted).
3867
def register(self, key, obj, help=None, info=None,
3868
override_existing=False):
3869
"""See Registry.register.
3871
Trying to override an existing alias causes a warning to be emitted,
3872
not a fatal execption.
3875
super(TestPrefixAliasRegistry, self).register(
3876
key, obj, help=help, info=info, override_existing=False)
3878
actual = self.get(key)
3880
'Test prefix alias %s is already used for %s, ignoring %s'
3881
% (key, actual, obj))
3883
def resolve_alias(self, id_start):
3884
"""Replace the alias by the prefix in the given string.
3886
Using an unknown prefix is an error to help catching typos.
3888
parts = id_start.split('.')
3890
parts[0] = self.get(parts[0])
3892
raise errors.BzrCommandError(
3893
'%s is not a known test prefix alias' % parts[0])
3894
return '.'.join(parts)
3897
test_prefix_alias_registry = TestPrefixAliasRegistry()
3898
"""Registry of test prefix aliases."""
3901
# This alias allows to detect typos ('bzrlin.') by making all valid test ids
3902
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
3903
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
3905
# Obvious highest levels prefixes, feel free to add your own via a plugin
3906
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
3907
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
3908
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
3909
test_prefix_alias_registry.register('bb', 'bzrlib.tests.blackbox')
3910
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3913
def _test_suite_testmod_names():
3914
"""Return the standard list of test module names to test."""
3917
'bzrlib.tests.blackbox',
3918
'bzrlib.tests.commands',
3919
'bzrlib.tests.per_branch',
3920
'bzrlib.tests.per_bzrdir',
3921
'bzrlib.tests.per_controldir',
3922
'bzrlib.tests.per_controldir_colo',
3923
'bzrlib.tests.per_foreign_vcs',
3924
'bzrlib.tests.per_interrepository',
3925
'bzrlib.tests.per_intertree',
3926
'bzrlib.tests.per_inventory',
3927
'bzrlib.tests.per_interbranch',
3928
'bzrlib.tests.per_lock',
3929
'bzrlib.tests.per_merger',
3930
'bzrlib.tests.per_transport',
3931
'bzrlib.tests.per_tree',
3932
'bzrlib.tests.per_pack_repository',
3933
'bzrlib.tests.per_repository',
3934
'bzrlib.tests.per_repository_chk',
3935
'bzrlib.tests.per_repository_reference',
3936
'bzrlib.tests.per_repository_vf',
3937
'bzrlib.tests.per_uifactory',
3938
'bzrlib.tests.per_versionedfile',
3939
'bzrlib.tests.per_workingtree',
3940
'bzrlib.tests.test__annotator',
3941
'bzrlib.tests.test__bencode',
3942
'bzrlib.tests.test__btree_serializer',
3943
'bzrlib.tests.test__chk_map',
3944
'bzrlib.tests.test__dirstate_helpers',
3945
'bzrlib.tests.test__groupcompress',
3946
'bzrlib.tests.test__known_graph',
3947
'bzrlib.tests.test__rio',
3948
'bzrlib.tests.test__simple_set',
3949
'bzrlib.tests.test__static_tuple',
3950
'bzrlib.tests.test__walkdirs_win32',
3951
'bzrlib.tests.test_ancestry',
3952
'bzrlib.tests.test_annotate',
3953
'bzrlib.tests.test_api',
3954
'bzrlib.tests.test_atomicfile',
3955
'bzrlib.tests.test_bad_files',
3956
'bzrlib.tests.test_bisect_multi',
3957
'bzrlib.tests.test_branch',
3958
'bzrlib.tests.test_branchbuilder',
3959
'bzrlib.tests.test_btree_index',
3960
'bzrlib.tests.test_bugtracker',
3961
'bzrlib.tests.test_bundle',
3962
'bzrlib.tests.test_bzrdir',
3963
'bzrlib.tests.test__chunks_to_lines',
3964
'bzrlib.tests.test_cache_utf8',
3965
'bzrlib.tests.test_chk_map',
3966
'bzrlib.tests.test_chk_serializer',
3967
'bzrlib.tests.test_chunk_writer',
3968
'bzrlib.tests.test_clean_tree',
3969
'bzrlib.tests.test_cleanup',
3970
'bzrlib.tests.test_cmdline',
3971
'bzrlib.tests.test_commands',
3972
'bzrlib.tests.test_commit',
3973
'bzrlib.tests.test_commit_merge',
3974
'bzrlib.tests.test_config',
3975
'bzrlib.tests.test_conflicts',
3976
'bzrlib.tests.test_controldir',
3977
'bzrlib.tests.test_counted_lock',
3978
'bzrlib.tests.test_crash',
3979
'bzrlib.tests.test_decorators',
3980
'bzrlib.tests.test_delta',
3981
'bzrlib.tests.test_debug',
3982
'bzrlib.tests.test_diff',
3983
'bzrlib.tests.test_directory_service',
3984
'bzrlib.tests.test_dirstate',
3985
'bzrlib.tests.test_email_message',
3986
'bzrlib.tests.test_eol_filters',
3987
'bzrlib.tests.test_errors',
3988
'bzrlib.tests.test_estimate_compressed_size',
3989
'bzrlib.tests.test_export',
3990
'bzrlib.tests.test_export_pot',
3991
'bzrlib.tests.test_extract',
3992
'bzrlib.tests.test_features',
3993
'bzrlib.tests.test_fetch',
3994
'bzrlib.tests.test_fixtures',
3995
'bzrlib.tests.test_fifo_cache',
3996
'bzrlib.tests.test_filters',
3997
'bzrlib.tests.test_filter_tree',
3998
'bzrlib.tests.test_ftp_transport',
3999
'bzrlib.tests.test_foreign',
4000
'bzrlib.tests.test_generate_docs',
4001
'bzrlib.tests.test_generate_ids',
4002
'bzrlib.tests.test_globbing',
4003
'bzrlib.tests.test_gpg',
4004
'bzrlib.tests.test_graph',
4005
'bzrlib.tests.test_groupcompress',
4006
'bzrlib.tests.test_hashcache',
4007
'bzrlib.tests.test_help',
4008
'bzrlib.tests.test_hooks',
4009
'bzrlib.tests.test_http',
4010
'bzrlib.tests.test_http_response',
4011
'bzrlib.tests.test_https_ca_bundle',
4012
'bzrlib.tests.test_https_urllib',
4013
'bzrlib.tests.test_i18n',
4014
'bzrlib.tests.test_identitymap',
4015
'bzrlib.tests.test_ignores',
4016
'bzrlib.tests.test_index',
4017
'bzrlib.tests.test_import_tariff',
4018
'bzrlib.tests.test_info',
4019
'bzrlib.tests.test_inv',
4020
'bzrlib.tests.test_inventory_delta',
4021
'bzrlib.tests.test_knit',
4022
'bzrlib.tests.test_lazy_import',
4023
'bzrlib.tests.test_lazy_regex',
4024
'bzrlib.tests.test_library_state',
4025
'bzrlib.tests.test_lock',
4026
'bzrlib.tests.test_lockable_files',
4027
'bzrlib.tests.test_lockdir',
4028
'bzrlib.tests.test_log',
4029
'bzrlib.tests.test_lru_cache',
4030
'bzrlib.tests.test_lsprof',
4031
'bzrlib.tests.test_mail_client',
4032
'bzrlib.tests.test_matchers',
4033
'bzrlib.tests.test_memorytree',
4034
'bzrlib.tests.test_merge',
4035
'bzrlib.tests.test_merge3',
4036
'bzrlib.tests.test_merge_core',
4037
'bzrlib.tests.test_merge_directive',
4038
'bzrlib.tests.test_mergetools',
4039
'bzrlib.tests.test_missing',
4040
'bzrlib.tests.test_msgeditor',
4041
'bzrlib.tests.test_multiparent',
4042
'bzrlib.tests.test_mutabletree',
4043
'bzrlib.tests.test_nonascii',
4044
'bzrlib.tests.test_options',
4045
'bzrlib.tests.test_osutils',
4046
'bzrlib.tests.test_osutils_encodings',
4047
'bzrlib.tests.test_pack',
4048
'bzrlib.tests.test_patch',
4049
'bzrlib.tests.test_patches',
4050
'bzrlib.tests.test_permissions',
4051
'bzrlib.tests.test_plugins',
4052
'bzrlib.tests.test_progress',
4053
'bzrlib.tests.test_pyutils',
4054
'bzrlib.tests.test_read_bundle',
4055
'bzrlib.tests.test_reconcile',
4056
'bzrlib.tests.test_reconfigure',
4057
'bzrlib.tests.test_registry',
4058
'bzrlib.tests.test_remote',
4059
'bzrlib.tests.test_rename_map',
4060
'bzrlib.tests.test_repository',
4061
'bzrlib.tests.test_revert',
4062
'bzrlib.tests.test_revision',
4063
'bzrlib.tests.test_revisionspec',
4064
'bzrlib.tests.test_revisiontree',
4065
'bzrlib.tests.test_rio',
4066
'bzrlib.tests.test_rules',
4067
'bzrlib.tests.test_url_policy_open',
4068
'bzrlib.tests.test_sampler',
4069
'bzrlib.tests.test_scenarios',
4070
'bzrlib.tests.test_script',
4071
'bzrlib.tests.test_selftest',
4072
'bzrlib.tests.test_serializer',
4073
'bzrlib.tests.test_setup',
4074
'bzrlib.tests.test_sftp_transport',
4075
'bzrlib.tests.test_shelf',
4076
'bzrlib.tests.test_shelf_ui',
4077
'bzrlib.tests.test_smart',
4078
'bzrlib.tests.test_smart_add',
4079
'bzrlib.tests.test_smart_request',
4080
'bzrlib.tests.test_smart_signals',
4081
'bzrlib.tests.test_smart_transport',
4082
'bzrlib.tests.test_smtp_connection',
4083
'bzrlib.tests.test_source',
4084
'bzrlib.tests.test_ssh_transport',
4085
'bzrlib.tests.test_status',
4086
'bzrlib.tests.test_store',
4087
'bzrlib.tests.test_strace',
4088
'bzrlib.tests.test_subsume',
4089
'bzrlib.tests.test_switch',
4090
'bzrlib.tests.test_symbol_versioning',
4091
'bzrlib.tests.test_tag',
4092
'bzrlib.tests.test_test_server',
4093
'bzrlib.tests.test_testament',
4094
'bzrlib.tests.test_textfile',
4095
'bzrlib.tests.test_textmerge',
4096
'bzrlib.tests.test_cethread',
4097
'bzrlib.tests.test_timestamp',
4098
'bzrlib.tests.test_trace',
4099
'bzrlib.tests.test_transactions',
4100
'bzrlib.tests.test_transform',
4101
'bzrlib.tests.test_transport',
4102
'bzrlib.tests.test_transport_log',
4103
'bzrlib.tests.test_tree',
4104
'bzrlib.tests.test_treebuilder',
4105
'bzrlib.tests.test_treeshape',
4106
'bzrlib.tests.test_tsort',
4107
'bzrlib.tests.test_tuned_gzip',
4108
'bzrlib.tests.test_ui',
4109
'bzrlib.tests.test_uncommit',
4110
'bzrlib.tests.test_upgrade',
4111
'bzrlib.tests.test_upgrade_stacked',
4112
'bzrlib.tests.test_urlutils',
4113
'bzrlib.tests.test_utextwrap',
4114
'bzrlib.tests.test_version',
4115
'bzrlib.tests.test_version_info',
4116
'bzrlib.tests.test_versionedfile',
4117
'bzrlib.tests.test_vf_search',
4118
'bzrlib.tests.test_weave',
4119
'bzrlib.tests.test_whitebox',
4120
'bzrlib.tests.test_win32utils',
4121
'bzrlib.tests.test_workingtree',
4122
'bzrlib.tests.test_workingtree_4',
4123
'bzrlib.tests.test_wsgi',
4124
'bzrlib.tests.test_xml',
4128
def _test_suite_modules_to_doctest():
4129
"""Return the list of modules to doctest."""
4131
# GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
4135
'bzrlib.branchbuilder',
4136
'bzrlib.decorators',
4138
'bzrlib.iterablefile',
4143
'bzrlib.symbol_versioning',
4145
'bzrlib.tests.fixtures',
4147
'bzrlib.transport.http',
4148
'bzrlib.version_info_formats.format_custom',
4152
def test_suite(keep_only=None, starting_with=None):
2140
4153
"""Build and return TestSuite for the whole of bzrlib.
4155
:param keep_only: A list of test ids limiting the suite returned.
4157
:param starting_with: An id limiting the suite returned to the tests
2142
4160
This function can be replaced if you need to change the default test
2143
4161
suite on a global basis, but it is not encouraged.
2146
'bzrlib.tests.test_ancestry',
2147
'bzrlib.tests.test_annotate',
2148
'bzrlib.tests.test_api',
2149
'bzrlib.tests.test_atomicfile',
2150
'bzrlib.tests.test_bad_files',
2151
'bzrlib.tests.test_branch',
2152
'bzrlib.tests.test_bundle',
2153
'bzrlib.tests.test_bzrdir',
2154
'bzrlib.tests.test_cache_utf8',
2155
'bzrlib.tests.test_commands',
2156
'bzrlib.tests.test_commit',
2157
'bzrlib.tests.test_commit_merge',
2158
'bzrlib.tests.test_config',
2159
'bzrlib.tests.test_conflicts',
2160
'bzrlib.tests.test_decorators',
2161
'bzrlib.tests.test_delta',
2162
'bzrlib.tests.test_diff',
2163
'bzrlib.tests.test_dirstate',
2164
'bzrlib.tests.test_doc_generate',
2165
'bzrlib.tests.test_errors',
2166
'bzrlib.tests.test_escaped_store',
2167
'bzrlib.tests.test_extract',
2168
'bzrlib.tests.test_fetch',
2169
'bzrlib.tests.test_ftp_transport',
2170
'bzrlib.tests.test_generate_docs',
2171
'bzrlib.tests.test_generate_ids',
2172
'bzrlib.tests.test_globbing',
2173
'bzrlib.tests.test_gpg',
2174
'bzrlib.tests.test_graph',
2175
'bzrlib.tests.test_hashcache',
2176
'bzrlib.tests.test_http',
2177
'bzrlib.tests.test_http_response',
2178
'bzrlib.tests.test_https_ca_bundle',
2179
'bzrlib.tests.test_identitymap',
2180
'bzrlib.tests.test_ignores',
2181
'bzrlib.tests.test_inv',
2182
'bzrlib.tests.test_knit',
2183
'bzrlib.tests.test_lazy_import',
2184
'bzrlib.tests.test_lazy_regex',
2185
'bzrlib.tests.test_lockdir',
2186
'bzrlib.tests.test_lockable_files',
2187
'bzrlib.tests.test_log',
2188
'bzrlib.tests.test_memorytree',
2189
'bzrlib.tests.test_merge',
2190
'bzrlib.tests.test_merge3',
2191
'bzrlib.tests.test_merge_core',
2192
'bzrlib.tests.test_merge_directive',
2193
'bzrlib.tests.test_missing',
2194
'bzrlib.tests.test_msgeditor',
2195
'bzrlib.tests.test_nonascii',
2196
'bzrlib.tests.test_options',
2197
'bzrlib.tests.test_osutils',
2198
'bzrlib.tests.test_osutils_encodings',
2199
'bzrlib.tests.test_patch',
2200
'bzrlib.tests.test_patches',
2201
'bzrlib.tests.test_permissions',
2202
'bzrlib.tests.test_plugins',
2203
'bzrlib.tests.test_progress',
2204
'bzrlib.tests.test_reconcile',
2205
'bzrlib.tests.test_registry',
2206
'bzrlib.tests.test_repository',
2207
'bzrlib.tests.test_revert',
2208
'bzrlib.tests.test_revision',
2209
'bzrlib.tests.test_revisionnamespaces',
2210
'bzrlib.tests.test_revisiontree',
2211
'bzrlib.tests.test_rio',
2212
'bzrlib.tests.test_sampler',
2213
'bzrlib.tests.test_selftest',
2214
'bzrlib.tests.test_setup',
2215
'bzrlib.tests.test_sftp_transport',
2216
'bzrlib.tests.test_smart_add',
2217
'bzrlib.tests.test_smart_transport',
2218
'bzrlib.tests.test_source',
2219
'bzrlib.tests.test_ssh_transport',
2220
'bzrlib.tests.test_status',
2221
'bzrlib.tests.test_store',
2222
'bzrlib.tests.test_strace',
2223
'bzrlib.tests.test_subsume',
2224
'bzrlib.tests.test_symbol_versioning',
2225
'bzrlib.tests.test_tag',
2226
'bzrlib.tests.test_testament',
2227
'bzrlib.tests.test_textfile',
2228
'bzrlib.tests.test_textmerge',
2229
'bzrlib.tests.test_timestamp',
2230
'bzrlib.tests.test_trace',
2231
'bzrlib.tests.test_transactions',
2232
'bzrlib.tests.test_transform',
2233
'bzrlib.tests.test_transport',
2234
'bzrlib.tests.test_tree',
2235
'bzrlib.tests.test_treebuilder',
2236
'bzrlib.tests.test_tsort',
2237
'bzrlib.tests.test_tuned_gzip',
2238
'bzrlib.tests.test_ui',
2239
'bzrlib.tests.test_upgrade',
2240
'bzrlib.tests.test_urlutils',
2241
'bzrlib.tests.test_versionedfile',
2242
'bzrlib.tests.test_version',
2243
'bzrlib.tests.test_version_info',
2244
'bzrlib.tests.test_weave',
2245
'bzrlib.tests.test_whitebox',
2246
'bzrlib.tests.test_workingtree',
2247
'bzrlib.tests.test_workingtree_4',
2248
'bzrlib.tests.test_wsgi',
2249
'bzrlib.tests.test_xml',
2251
test_transport_implementations = [
2252
'bzrlib.tests.test_transport_implementations',
2253
'bzrlib.tests.test_read_bundle',
2255
suite = TestUtil.TestSuite()
2256
4164
loader = TestUtil.TestLoader()
2257
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2258
from bzrlib.transport import TransportTestProviderAdapter
2259
adapter = TransportTestProviderAdapter()
2260
adapt_modules(test_transport_implementations, adapter, loader, suite)
2261
for package in packages_to_test():
2262
suite.addTest(package.test_suite())
2263
for m in MODULES_TO_TEST:
2264
suite.addTest(loader.loadTestsFromModule(m))
2265
for m in MODULES_TO_DOCTEST:
4166
if keep_only is not None:
4167
id_filter = TestIdList(keep_only)
4169
# We take precedence over keep_only because *at loading time* using
4170
# both options means we will load less tests for the same final result.
4171
def interesting_module(name):
4172
for start in starting_with:
4174
# Either the module name starts with the specified string
4175
name.startswith(start)
4176
# or it may contain tests starting with the specified string
4177
or start.startswith(name)
4181
loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
4183
elif keep_only is not None:
4184
loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
4185
def interesting_module(name):
4186
return id_filter.refers_to(name)
4189
loader = TestUtil.TestLoader()
4190
def interesting_module(name):
4191
# No filtering, all modules are interesting
4194
suite = loader.suiteClass()
4196
# modules building their suite with loadTestsFromModuleNames
4197
suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
4199
for mod in _test_suite_modules_to_doctest():
4200
if not interesting_module(mod):
4201
# No tests to keep here, move along
2267
suite.addTest(doctest.DocTestSuite(m))
4204
# note that this really does mean "report only" -- doctest
4205
# still runs the rest of the examples
4206
doc_suite = IsolatedDocTestSuite(
4207
mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
2268
4208
except ValueError, e:
2269
print '**failed to get doctest for: %s\n%s' %(m,e)
4209
print '**failed to get doctest for: %s\n%s' % (mod, e)
2271
for name, plugin in bzrlib.plugin.all_plugins().items():
2272
if getattr(plugin, 'test_suite', None) is not None:
2273
default_encoding = sys.getdefaultencoding()
2275
plugin_suite = plugin.test_suite()
2276
except ImportError, e:
2277
bzrlib.trace.warning(
2278
'Unable to test plugin "%s": %s', name, e)
2280
suite.addTest(plugin_suite)
2281
if default_encoding != sys.getdefaultencoding():
2282
bzrlib.trace.warning(
2283
'Plugin "%s" tried to reset default encoding to: %s', name,
2284
sys.getdefaultencoding())
2286
sys.setdefaultencoding(default_encoding)
4211
if len(doc_suite._tests) == 0:
4212
raise errors.BzrError("no doctests found in %s" % (mod,))
4213
suite.addTest(doc_suite)
4215
default_encoding = sys.getdefaultencoding()
4216
for name, plugin in _mod_plugin.plugins().items():
4217
if not interesting_module(plugin.module.__name__):
4219
plugin_suite = plugin.test_suite()
4220
# We used to catch ImportError here and turn it into just a warning,
4221
# but really if you don't have --no-plugins this should be a failure.
4222
# mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
4223
if plugin_suite is None:
4224
plugin_suite = plugin.load_plugin_tests(loader)
4225
if plugin_suite is not None:
4226
suite.addTest(plugin_suite)
4227
if default_encoding != sys.getdefaultencoding():
4229
'Plugin "%s" tried to reset default encoding to: %s', name,
4230
sys.getdefaultencoding())
4232
sys.setdefaultencoding(default_encoding)
4234
if keep_only is not None:
4235
# Now that the referred modules have loaded their tests, keep only the
4237
suite = filter_suite_by_id_list(suite, id_filter)
4238
# Do some sanity checks on the id_list filtering
4239
not_found, duplicates = suite_matches_id_list(suite, keep_only)
4241
# The tester has used both keep_only and starting_with, so he is
4242
# already aware that some tests are excluded from the list, there
4243
# is no need to tell him which.
4246
# Some tests mentioned in the list are not in the test suite. The
4247
# list may be out of date, report to the tester.
4248
for id in not_found:
4249
trace.warning('"%s" not found in the test suite', id)
4250
for id in duplicates:
4251
trace.warning('"%s" is used as an id by several tests', id)
2290
def adapt_modules(mods_list, adapter, loader, suite):
2291
"""Adapt the modules in mods_list using adapter and add to suite."""
2292
for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
2293
suite.addTests(adapter.adapt(test))
2296
def _rmtree_temp_dir(dirname):
4256
def multiply_scenarios(*scenarios):
4257
"""Multiply two or more iterables of scenarios.
4259
It is safe to pass scenario generators or iterators.
4261
:returns: A list of compound scenarios: the cross-product of all
4262
scenarios, with the names concatenated and the parameters
4265
return reduce(_multiply_two_scenarios, map(list, scenarios))
4268
def _multiply_two_scenarios(scenarios_left, scenarios_right):
4269
"""Multiply two sets of scenarios.
4271
:returns: the cartesian product of the two sets of scenarios, that is
4272
a scenario for every possible combination of a left scenario and a
4276
('%s,%s' % (left_name, right_name),
4277
dict(left_dict.items() + right_dict.items()))
4278
for left_name, left_dict in scenarios_left
4279
for right_name, right_dict in scenarios_right]
4282
def multiply_tests(tests, scenarios, result):
4283
"""Multiply tests_list by scenarios into result.
4285
This is the core workhorse for test parameterisation.
4287
Typically the load_tests() method for a per-implementation test suite will
4288
call multiply_tests and return the result.
4290
:param tests: The tests to parameterise.
4291
:param scenarios: The scenarios to apply: pairs of (scenario_name,
4292
scenario_param_dict).
4293
:param result: A TestSuite to add created tests to.
4295
This returns the passed in result TestSuite with the cross product of all
4296
the tests repeated once for each scenario. Each test is adapted by adding
4297
the scenario name at the end of its id(), and updating the test object's
4298
__dict__ with the scenario_param_dict.
4300
>>> import bzrlib.tests.test_sampler
4301
>>> r = multiply_tests(
4302
... bzrlib.tests.test_sampler.DemoTest('test_nothing'),
4303
... [('one', dict(param=1)),
4304
... ('two', dict(param=2))],
4305
... TestUtil.TestSuite())
4306
>>> tests = list(iter_suite_tests(r))
4310
'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
4316
for test in iter_suite_tests(tests):
4317
apply_scenarios(test, scenarios, result)
4321
def apply_scenarios(test, scenarios, result):
4322
"""Apply the scenarios in scenarios to test and add to result.
4324
:param test: The test to apply scenarios to.
4325
:param scenarios: An iterable of scenarios to apply to test.
4327
:seealso: apply_scenario
4329
for scenario in scenarios:
4330
result.addTest(apply_scenario(test, scenario))
4334
def apply_scenario(test, scenario):
4335
"""Copy test and apply scenario to it.
4337
:param test: A test to adapt.
4338
:param scenario: A tuple describing the scenarion.
4339
The first element of the tuple is the new test id.
4340
The second element is a dict containing attributes to set on the
4342
:return: The adapted test.
4344
new_id = "%s(%s)" % (test.id(), scenario[0])
4345
new_test = clone_test(test, new_id)
4346
for name, value in scenario[1].items():
4347
setattr(new_test, name, value)
4351
def clone_test(test, new_id):
4352
"""Clone a test giving it a new id.
4354
:param test: The test to clone.
4355
:param new_id: The id to assign to it.
4356
:return: The new test.
4358
new_test = copy.copy(test)
4359
new_test.id = lambda: new_id
4360
# XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4361
# causes cloned tests to share the 'details' dict. This makes it hard to
4362
# read the test output for parameterized tests, because tracebacks will be
4363
# associated with irrelevant tests.
4365
details = new_test._TestCase__details
4366
except AttributeError:
4367
# must be a different version of testtools than expected. Do nothing.
4370
# Reset the '__details' dict.
4371
new_test._TestCase__details = {}
4375
def permute_tests_for_extension(standard_tests, loader, py_module_name,
4377
"""Helper for permutating tests against an extension module.
4379
This is meant to be used inside a modules 'load_tests()' function. It will
4380
create 2 scenarios, and cause all tests in the 'standard_tests' to be run
4381
against both implementations. Setting 'test.module' to the appropriate
4382
module. See bzrlib.tests.test__chk_map.load_tests as an example.
4384
:param standard_tests: A test suite to permute
4385
:param loader: A TestLoader
4386
:param py_module_name: The python path to a python module that can always
4387
be loaded, and will be considered the 'python' implementation. (eg
4388
'bzrlib._chk_map_py')
4389
:param ext_module_name: The python path to an extension module. If the
4390
module cannot be loaded, a single test will be added, which notes that
4391
the module is not available. If it can be loaded, all standard_tests
4392
will be run against that module.
4393
:return: (suite, feature) suite is a test-suite that has all the permuted
4394
tests. feature is the Feature object that can be used to determine if
4395
the module is available.
4398
from bzrlib.tests.features import ModuleAvailableFeature
4399
py_module = pyutils.get_named_object(py_module_name)
4401
('python', {'module': py_module}),
4403
suite = loader.suiteClass()
4404
feature = ModuleAvailableFeature(ext_module_name)
4405
if feature.available():
4406
scenarios.append(('C', {'module': feature.module}))
4408
# the compiled module isn't available, so we add a failing test
4409
class FailWithoutFeature(TestCase):
4410
def test_fail(self):
4411
self.requireFeature(feature)
4412
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
4413
result = multiply_tests(standard_tests, scenarios, suite)
4414
return result, feature
4417
def _rmtree_temp_dir(dirname, test_id=None):
4418
# If LANG=C we probably have created some bogus paths
4419
# which rmtree(unicode) will fail to delete
4420
# so make sure we are using rmtree(str) to delete everything
4421
# except on win32, where rmtree(str) will fail
4422
# since it doesn't have the property of byte-stream paths
4423
# (they are either ascii or mbcs)
4424
if sys.platform == 'win32':
4425
# make sure we are using the unicode win32 api
4426
dirname = unicode(dirname)
4428
dirname = dirname.encode(sys.getfilesystemencoding())
2298
4430
osutils.rmtree(dirname)
2299
4431
except OSError, e:
2300
if sys.platform == 'win32' and e.errno == errno.EACCES:
2301
print >>sys.stderr, ('Permission denied: '
2302
'unable to remove testing dir '
2303
'%s' % os.path.basename(dirname))
4432
# We don't want to fail here because some useful display will be lost
4433
# otherwise. Polluting the tmp dir is bad, but not giving all the
4434
# possible info to the test runner is even worse.
4436
ui.ui_factory.clear_term()
4437
sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4438
# Ugly, but the last thing we want here is fail, so bear with it.
4439
printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4440
).encode('ascii', 'replace')
4441
sys.stderr.write('Unable to remove testing dir %s\n%s'
4442
% (os.path.basename(dirname), printable_e))
4445
def probe_unicode_in_user_encoding():
4446
"""Try to encode several unicode strings to use in unicode-aware tests.
4447
Return first successfull match.
4449
:return: (unicode value, encoded plain string value) or (None, None)
4451
possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
4452
for uni_val in possible_vals:
4454
str_val = uni_val.encode(osutils.get_user_encoding())
4455
except UnicodeEncodeError:
4456
# Try a different character
2308
def clean_selftest_output(root=None, quiet=False):
2309
"""Remove all selftest output directories from root directory.
2311
:param root: root directory for clean
2312
(if ommitted or None then clean current directory).
2313
:param quiet: suppress report about deleting directories
4459
return uni_val, str_val
4463
def probe_bad_non_ascii(encoding):
4464
"""Try to find [bad] character with code [128..255]
4465
that cannot be decoded to unicode in some encoding.
4466
Return None if all non-ascii characters is valid
2318
re_dir = re.compile(r'''test\d\d\d\d\.tmp''')
2321
for i in os.listdir(root):
2322
if os.path.isdir(i) and re_dir.match(i):
2324
print 'delete directory:', i
2328
class Feature(object):
2329
"""An operating system Feature."""
2332
self._available = None
2334
def available(self):
2335
"""Is the feature available?
2337
:return: True if the feature is available.
2339
if self._available is None:
2340
self._available = self._probe()
2341
return self._available
2344
"""Implement this method in concrete features.
2346
:return: True if the feature is available.
2348
raise NotImplementedError
2351
if getattr(self, 'feature_name', None):
2352
return self.feature_name()
2353
return self.__class__.__name__
4469
for i in xrange(128, 256):
4472
char.decode(encoding)
4473
except UnicodeDecodeError:
4478
# Only define SubUnitBzrRunner if subunit is available.
4480
from subunit import TestProtocolClient
4481
from subunit.test_results import AutoTimingTestResultDecorator
4482
class SubUnitBzrProtocolClient(TestProtocolClient):
4484
def stopTest(self, test):
4485
super(SubUnitBzrProtocolClient, self).stopTest(test)
4486
_clear__type_equality_funcs(test)
4488
def addSuccess(self, test, details=None):
4489
# The subunit client always includes the details in the subunit
4490
# stream, but we don't want to include it in ours.
4491
if details is not None and 'log' in details:
4493
return super(SubUnitBzrProtocolClient, self).addSuccess(
4496
class SubUnitBzrRunner(TextTestRunner):
4497
def run(self, test):
4498
result = AutoTimingTestResultDecorator(
4499
SubUnitBzrProtocolClient(self.stream))
4506
# API compatibility for old plugins; see bug 892622.
4509
'HTTPServerFeature',
4510
'ModuleAvailableFeature',
4511
'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
4512
'OsFifoFeature', 'UnicodeFilenameFeature',
4513
'ByteStringNamedFilesystem', 'UTF8Filesystem',
4514
'BreakinFeature', 'CaseInsCasePresFilenameFeature',
4515
'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
4516
'posix_permissions_feature',
4518
globals()[name] = _CompatabilityThunkFeature(
4519
symbol_versioning.deprecated_in((2, 5, 0)),
4520
'bzrlib.tests', name,
4521
name, 'bzrlib.tests.features')
4524
for (old_name, new_name) in [
4525
('UnicodeFilename', 'UnicodeFilenameFeature'),
4527
globals()[name] = _CompatabilityThunkFeature(
4528
symbol_versioning.deprecated_in((2, 5, 0)),
4529
'bzrlib.tests', old_name,
4530
new_name, 'bzrlib.tests.features')