14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Testing framework extensions"""
18
19
# TODO: Perhaps there should be an API to find out if bzr running under the
19
20
# test suite -- some plugins might want to avoid making intrusive changes if
103
105
import bzrlib.trace
104
106
from bzrlib.transport import (
109
import bzrlib.transport
110
110
from bzrlib.trace import mutter, note
111
111
from bzrlib.tests import (
115
from bzrlib.tests.http_server import HttpServer
116
from bzrlib.tests.TestUtil import (
120
from bzrlib.tests.treeshape import build_tree_contents
121
116
from bzrlib.ui import NullProgressView
122
117
from bzrlib.ui.text import TextUIFactory
123
118
import bzrlib.version_info_formats.format_custom
139
134
SUBUNIT_SEEK_SET = 0
140
135
SUBUNIT_SEEK_CUR = 1
137
# These are intentionally brought into this namespace. That way plugins, etc
138
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
139
TestSuite = TestUtil.TestSuite
140
TestLoader = TestUtil.TestLoader
143
class ExtendedTestResult(unittest._TextTestResult):
142
class ExtendedTestResult(testtools.TextTestResult):
144
143
"""Accepts, reports and accumulates the results of running tests.
146
145
Compared to the unittest version this class adds support for
167
166
:param bench_history: Optionally, a writable file object to accumulate
168
167
benchmark results.
170
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
169
testtools.TextTestResult.__init__(self, stream)
171
170
if bench_history is not None:
172
171
from bzrlib.version import _get_bzr_source_tree
173
172
src_tree = _get_bzr_source_tree()
195
194
self._overall_start_time = time.time()
196
195
self._strict = strict
196
self._first_thread_leaker_id = None
197
self._tests_leaking_threads_count = 0
198
199
def stopTestRun(self):
199
200
run = self.testsRun
200
201
actionTaken = "Ran"
201
202
stopTime = time.time()
202
203
timeTaken = stopTime - self.startTime
204
self.stream.writeln(self.separator2)
205
self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
204
# GZ 2010-07-19: Seems testtools has no printErrors method, and though
205
# the parent class method is similar have to duplicate
206
self._show_list('ERROR', self.errors)
207
self._show_list('FAIL', self.failures)
208
self.stream.write(self.sep2)
209
self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
206
210
run, run != 1 and "s" or "", timeTaken))
207
self.stream.writeln()
208
211
if not self.wasSuccessful():
209
212
self.stream.write("FAILED (")
210
213
failed, errored = map(len, (self.failures, self.errors))
217
220
if failed or errored: self.stream.write(", ")
218
221
self.stream.write("known_failure_count=%d" %
219
222
self.known_failure_count)
220
self.stream.writeln(")")
223
self.stream.write(")\n")
222
225
if self.known_failure_count:
223
self.stream.writeln("OK (known_failures=%d)" %
226
self.stream.write("OK (known_failures=%d)\n" %
224
227
self.known_failure_count)
226
self.stream.writeln("OK")
229
self.stream.write("OK\n")
227
230
if self.skip_count > 0:
228
231
skipped = self.skip_count
229
self.stream.writeln('%d test%s skipped' %
232
self.stream.write('%d test%s skipped\n' %
230
233
(skipped, skipped != 1 and "s" or ""))
231
234
if self.unsupported:
232
235
for feature, count in sorted(self.unsupported.items()):
233
self.stream.writeln("Missing feature '%s' skipped %d tests." %
236
self.stream.write("Missing feature '%s' skipped %d tests.\n" %
234
237
(feature, count))
236
239
ok = self.wasStrictlySuccessful()
238
241
ok = self.wasSuccessful()
239
if TestCase._first_thread_leaker_id:
242
if self._first_thread_leaker_id:
240
243
self.stream.write(
241
244
'%s is leaking threads among %d leaking tests.\n' % (
242
TestCase._first_thread_leaker_id,
243
TestCase._leaking_threads_tests))
245
self._first_thread_leaker_id,
246
self._tests_leaking_threads_count))
244
247
# We don't report the main thread as an active one.
245
248
self.stream.write(
246
249
'%d non-main threads were left active in the end.\n'
247
% (TestCase._active_threads - 1))
250
% (len(self._active_threads) - 1))
249
252
def getDescription(self, test):
275
278
def _shortened_test_description(self, test):
277
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
280
what = re.sub(r'^bzrlib\.tests\.', '', what)
280
283
def startTest(self, test):
281
unittest.TestResult.startTest(self, test)
284
super(ExtendedTestResult, self).startTest(test)
282
285
if self.count == 0:
283
286
self.startTests()
284
288
self.report_test_start(test)
285
289
test.number = self.count
286
290
self._recordTestStartTime()
291
# Only check for thread leaks if the test case supports cleanups
292
addCleanup = getattr(test, "addCleanup", None)
293
if addCleanup is not None:
294
addCleanup(self._check_leaked_threads, test)
288
296
def startTests(self):
290
if getattr(sys, 'frozen', None) is None:
291
bzr_path = osutils.realpath(sys.argv[0])
293
bzr_path = sys.executable
295
'bzr selftest: %s\n' % (bzr_path,))
298
bzrlib.__path__[0],))
300
' bzr-%s python-%s %s\n' % (
301
bzrlib.version_string,
302
bzrlib._format_version_tuple(sys.version_info),
303
platform.platform(aliased=1),
305
self.stream.write('\n')
297
self.report_tests_starting()
298
self._active_threads = threading.enumerate()
300
def _check_leaked_threads(self, test):
301
"""See if any threads have leaked since last call
303
A sample of live threads is stored in the _active_threads attribute,
304
when this method runs it compares the current live threads and any not
305
in the previous sample are treated as having leaked.
307
now_active_threads = set(threading.enumerate())
308
threads_leaked = now_active_threads.difference(self._active_threads)
310
self._report_thread_leak(test, threads_leaked, now_active_threads)
311
self._tests_leaking_threads_count += 1
312
if self._first_thread_leaker_id is None:
313
self._first_thread_leaker_id = test.id()
314
self._active_threads = now_active_threads
307
316
def _recordTestStartTime(self):
308
317
"""Record that a test has started."""
309
318
self._start_time = time.time()
311
def _cleanupLogFile(self, test):
312
# We can only do this if we have one of our TestCases, not if
314
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
315
if setKeepLogfile is not None:
318
320
def addError(self, test, err):
319
321
"""Tell result that test finished with an error.
322
324
fails with an unexpected error.
324
326
self._post_mortem()
325
unittest.TestResult.addError(self, test, err)
327
super(ExtendedTestResult, self).addError(test, err)
326
328
self.error_count += 1
327
329
self.report_error(test, err)
328
330
if self.stop_early:
330
self._cleanupLogFile(test)
332
333
def addFailure(self, test, err):
333
334
"""Tell result that test failed.
336
337
fails because e.g. an assert() method failed.
338
339
self._post_mortem()
339
unittest.TestResult.addFailure(self, test, err)
340
super(ExtendedTestResult, self).addFailure(test, err)
340
341
self.failure_count += 1
341
342
self.report_failure(test, err)
342
343
if self.stop_early:
344
self._cleanupLogFile(test)
346
346
def addSuccess(self, test, details=None):
347
347
"""Tell result that test completed successfully.
355
355
self._formatTime(benchmark_time),
357
357
self.report_success(test)
358
self._cleanupLogFile(test)
359
unittest.TestResult.addSuccess(self, test)
358
super(ExtendedTestResult, self).addSuccess(test)
360
359
test._log_contents = ''
362
361
def addExpectedFailure(self, test, err):
400
399
raise errors.BzrError("Unknown whence %r" % whence)
402
def report_cleaning_up(self):
401
def report_tests_starting(self):
402
"""Display information before the test run begins"""
403
if getattr(sys, 'frozen', None) is None:
404
bzr_path = osutils.realpath(sys.argv[0])
406
bzr_path = sys.executable
408
'bzr selftest: %s\n' % (bzr_path,))
411
bzrlib.__path__[0],))
413
' bzr-%s python-%s %s\n' % (
414
bzrlib.version_string,
415
bzrlib._format_version_tuple(sys.version_info),
416
platform.platform(aliased=1),
418
self.stream.write('\n')
420
def report_test_start(self, test):
421
"""Display information on the test just about to be run"""
423
def _report_thread_leak(self, test, leaked_threads, active_threads):
424
"""Display information on a test that leaked one or more threads"""
425
# GZ 2010-09-09: A leak summary reported separately from the general
426
# thread debugging would be nice. Tests under subunit
427
# need something not using stream, perhaps adding a
428
# testtools details object would be fitting.
429
if 'threads' in selftest_debug_flags:
430
self.stream.write('%s is leaking, active is now %d\n' %
431
(test.id(), len(active_threads)))
405
433
def startTestRun(self):
406
434
self.startTime = time.time()
443
471
self.pb.finished()
444
472
super(TextTestResult, self).stopTestRun()
446
def startTestRun(self):
447
super(TextTestResult, self).startTestRun()
474
def report_tests_starting(self):
475
super(TextTestResult, self).report_tests_starting()
448
476
self.pb.update('[test 0/%d] Starting' % (self.num_tests))
450
def printErrors(self):
451
# clear the pb to make room for the error listing
453
super(TextTestResult, self).printErrors()
455
478
def _progress_prefix_text(self):
456
479
# the longer this text, the less space we have to show the test
489
511
return self._shortened_test_description(test)
491
513
def report_error(self, test, err):
492
self.ui.note('ERROR: %s\n %s\n' % (
514
self.stream.write('ERROR: %s\n %s\n' % (
493
515
self._test_description(test),
497
519
def report_failure(self, test, err):
498
self.ui.note('FAIL: %s\n %s\n' % (
520
self.stream.write('FAIL: %s\n %s\n' % (
499
521
self._test_description(test),
512
534
def report_unsupported(self, test, feature):
513
535
"""test cannot be run because feature is missing."""
515
def report_cleaning_up(self):
516
self.pb.update('Cleaning up')
519
538
class VerboseTestResult(ExtendedTestResult):
520
539
"""Produce long output, with one line per test run plus times"""
527
546
result = a_string
528
547
return result.ljust(final_width)
530
def startTestRun(self):
531
super(VerboseTestResult, self).startTestRun()
549
def report_tests_starting(self):
532
550
self.stream.write('running %d tests...\n' % self.num_tests)
551
super(VerboseTestResult, self).report_tests_starting()
534
553
def report_test_start(self, test):
536
554
name = self._shortened_test_description(test)
537
555
width = osutils.terminal_width()
538
556
if width is not None:
550
568
return '%s%s' % (indent, err[1])
552
570
def report_error(self, test, err):
553
self.stream.writeln('ERROR %s\n%s'
571
self.stream.write('ERROR %s\n%s\n'
554
572
% (self._testTimeString(test),
555
573
self._error_summary(err)))
557
575
def report_failure(self, test, err):
558
self.stream.writeln(' FAIL %s\n%s'
576
self.stream.write(' FAIL %s\n%s\n'
559
577
% (self._testTimeString(test),
560
578
self._error_summary(err)))
562
580
def report_known_failure(self, test, err):
563
self.stream.writeln('XFAIL %s\n%s'
581
self.stream.write('XFAIL %s\n%s\n'
564
582
% (self._testTimeString(test),
565
583
self._error_summary(err)))
567
585
def report_success(self, test):
568
self.stream.writeln(' OK %s' % self._testTimeString(test))
586
self.stream.write(' OK %s\n' % self._testTimeString(test))
569
587
for bench_called, stats in getattr(test, '_benchcalls', []):
570
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
588
self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
571
589
stats.pprint(file=self.stream)
572
590
# flush the stream so that we get smooth output. This verbose mode is
573
591
# used to show the output in PQM.
574
592
self.stream.flush()
576
594
def report_skip(self, test, reason):
577
self.stream.writeln(' SKIP %s\n%s'
595
self.stream.write(' SKIP %s\n%s\n'
578
596
% (self._testTimeString(test), reason))
580
598
def report_not_applicable(self, test, reason):
581
self.stream.writeln(' N/A %s\n %s'
599
self.stream.write(' N/A %s\n %s\n'
582
600
% (self._testTimeString(test), reason))
584
602
def report_unsupported(self, test, feature):
585
603
"""test cannot be run because feature is missing."""
586
self.stream.writeln("NODEP %s\n The feature '%s' is not available."
604
self.stream.write("NODEP %s\n The feature '%s' is not available.\n"
587
605
%(self._testTimeString(test), feature))
748
766
# XXX: Should probably unify more with CannedInputUIFactory or a
749
767
# particular configuration of TextUIFactory, or otherwise have a clearer
750
768
# idea of how they're supposed to be different.
751
# See https://bugs.edge.launchpad.net/bzr/+bug/408213
769
# See https://bugs.launchpad.net/bzr/+bug/408213
753
771
def __init__(self, stdout=None, stderr=None, stdin=None):
754
772
if stdin is not None:
788
806
routine, and to build and check bzr trees.
790
808
In addition to the usual method of overriding tearDown(), this class also
791
allows subclasses to register functions into the _cleanups list, which is
809
allows subclasses to register cleanup functions via addCleanup, which are
792
810
run in order as the object is torn down. It's less likely this will be
793
811
accidentally overlooked.
796
_active_threads = None
797
_leaking_threads_tests = 0
798
_first_thread_leaker_id = None
799
_log_file_name = None
800
815
# record lsprof data when performing benchmark calls.
801
816
_gather_lsprof_in_benchmarks = False
803
818
def __init__(self, methodName='testMethod'):
804
819
super(TestCase, self).__init__(methodName)
806
820
self._directory_isolation = True
807
821
self.exception_handlers.insert(0,
808
822
(UnavailableFeature, self._do_unsupported_or_skip))
826
840
self._track_transports()
827
841
self._track_locks()
828
842
self._clear_debug_flags()
829
TestCase._active_threads = threading.activeCount()
830
self.addCleanup(self._check_leaked_threads)
833
845
# debug a frame up.
835
847
pdb.Pdb().set_trace(sys._getframe().f_back)
837
def _check_leaked_threads(self):
838
active = threading.activeCount()
839
leaked_threads = active - TestCase._active_threads
840
TestCase._active_threads = active
841
# If some tests make the number of threads *decrease*, we'll consider
842
# that they are just observing old threads dieing, not agressively kill
843
# random threads. So we don't report these tests as leaking. The risk
844
# is that we have false positives that way (the test see 2 threads
845
# going away but leak one) but it seems less likely than the actual
846
# false positives (the test see threads going away and does not leak).
847
if leaked_threads > 0:
848
TestCase._leaking_threads_tests += 1
849
if TestCase._first_thread_leaker_id is None:
850
TestCase._first_thread_leaker_id = self.id()
849
def discardDetail(self, name):
850
"""Extend the addDetail, getDetails api so we can remove a detail.
852
eg. bzr always adds the 'log' detail at startup, but we don't want to
853
include it for skipped, xfail, etc tests.
855
It is safe to call this for a detail that doesn't exist, in case this
856
gets called multiple times.
858
# We cheat. details is stored in __details which means we shouldn't
859
# touch it. but getDetails() returns the dict directly, so we can
861
details = self.getDetails()
852
865
def _clear_debug_flags(self):
853
866
"""Prevent externally set debug flags affecting tests.
1027
1040
self.addCleanup(transport_server.stop_server)
1028
1041
# Obtain a real transport because if the server supplies a password, it
1029
1042
# will be hidden from the base on the client side.
1030
t = get_transport(transport_server.get_url())
1043
t = _mod_transport.get_transport(transport_server.get_url())
1031
1044
# Some transport servers effectively chroot the backing transport;
1032
1045
# others like SFTPServer don't - users of the transport can walk up the
1033
1046
# transport to read the entire backing transport. This wouldn't matter
1313
1326
self.assertEqualDiff(content, s)
1328
def assertDocstring(self, expected_docstring, obj):
1329
"""Fail if obj does not have expected_docstring"""
1331
# With -OO the docstring should be None instead
1332
self.assertIs(obj.__doc__, None)
1334
self.assertEqual(expected_docstring, obj.__doc__)
1315
1336
def failUnlessExists(self, path):
1316
1337
"""Fail unless path or paths, which may be abs or relative, exist."""
1317
1338
if not isinstance(path, basestring):
1447
1468
The file is removed as the test is torn down.
1449
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1450
self._log_file = os.fdopen(fileno, 'w+')
1470
self._log_file = StringIO()
1451
1471
self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1452
self._log_file_name = name
1453
1472
self.addCleanup(self._finishLogFile)
1455
1474
def _finishLogFile(self):
1478
1497
debug.debug_flags.discard('strict_locks')
1480
def addCleanup(self, callable, *args, **kwargs):
1481
"""Arrange to run a callable when this case is torn down.
1483
Callables are run in the reverse of the order they are registered,
1484
ie last-in first-out.
1486
self._cleanups.append((callable, args, kwargs))
1488
1499
def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1489
1500
"""Overrides an object attribute restoring it after the test.
1574
1585
"""This test has failed for some known reason."""
1575
1586
raise KnownFailure(reason)
1588
def _suppress_log(self):
1589
"""Remove the log info from details."""
1590
self.discardDetail('log')
1577
1592
def _do_skip(self, result, reason):
1593
self._suppress_log()
1578
1594
addSkip = getattr(result, 'addSkip', None)
1579
1595
if not callable(addSkip):
1580
1596
result.addSuccess(result)
1603
1621
self._do_skip(result, reason)
1624
def _report_skip(self, result, err):
1625
"""Override the default _report_skip.
1627
We want to strip the 'log' detail. If we waint until _do_skip, it has
1628
already been formatted into the 'reason' string, and we can't pull it
1631
self._suppress_log()
1632
super(TestCase, self)._report_skip(self, result, err)
1635
def _report_expected_failure(self, result, err):
1638
See _report_skip for motivation.
1640
self._suppress_log()
1641
super(TestCase, self)._report_expected_failure(self, result, err)
1606
1644
def _do_unsupported_or_skip(self, result, e):
1607
1645
reason = e.args[0]
1646
self._suppress_log()
1608
1647
addNotSupported = getattr(result, 'addNotSupported', None)
1609
1648
if addNotSupported is not None:
1610
1649
result.addNotSupported(self, reason)
1657
1696
unicodestr = self._log_contents.decode('utf8', 'replace')
1658
1697
self._log_contents = unicodestr.encode('utf8')
1659
1698
return self._log_contents
1661
if bzrlib.trace._trace_file:
1662
# flush the log file, to get all content
1663
bzrlib.trace._trace_file.flush()
1664
if self._log_file_name is not None:
1665
logfile = open(self._log_file_name)
1667
log_contents = logfile.read()
1699
if self._log_file is not None:
1700
log_contents = self._log_file.getvalue()
1671
1702
log_contents.decode('utf8')
1672
1703
except UnicodeDecodeError:
1673
1704
unicodestr = log_contents.decode('utf8', 'replace')
1674
1705
log_contents = unicodestr.encode('utf8')
1675
1706
if not keep_log_file:
1677
max_close_attempts = 100
1678
first_close_error = None
1679
while close_attempts < max_close_attempts:
1682
self._log_file.close()
1683
except IOError, ioe:
1684
if ioe.errno is None:
1685
# No errno implies 'close() called during
1686
# concurrent operation on the same file object', so
1687
# retry. Probably a thread is trying to write to
1689
if first_close_error is None:
1690
first_close_error = ioe
1695
if close_attempts > 1:
1697
'Unable to close log file on first attempt, '
1698
'will retry: %s\n' % (first_close_error,))
1699
if close_attempts == max_close_attempts:
1701
'Unable to close log file after %d attempts.\n'
1702
% (max_close_attempts,))
1703
1707
self._log_file = None
1704
1708
# Permit multiple calls to get_log until we clean it up in
1705
1709
# finishLogFile
1706
1710
self._log_contents = log_contents
1708
os.remove(self._log_file_name)
1710
if sys.platform == 'win32' and e.errno == errno.EACCES:
1711
sys.stderr.write(('Unable to delete log file '
1712
' %r\n' % self._log_file_name))
1715
self._log_file_name = None
1716
1711
return log_contents
1718
return "No log file content and no log file name."
1713
return "No log file content."
1720
1715
def get_log(self):
1721
1716
"""Get a unicode string containing the log from bzrlib.trace.
1936
1931
variables. A value of None will unset the env variable.
1937
1932
The values must be strings. The change will only occur in the
1938
1933
child, so you don't need to fix the environment after running.
1939
:param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
1934
:param skip_if_plan_to_signal: raise TestSkipped when true and system
1935
doesn't support signalling subprocesses.
1941
1936
:param allow_plugins: If False (default) pass --no-plugins to bzr.
1943
1938
:returns: Popen object for the started process.
1945
1940
if skip_if_plan_to_signal:
1946
if not getattr(os, 'kill', None):
1947
raise TestSkipped("os.kill not available.")
1941
if os.name != "posix":
1942
raise TestSkipped("Sending signals not supported")
1949
1944
if env_changes is None:
1950
1945
env_changes = {}
2399
2396
made_control = self.make_bzrdir(relpath, format=format)
2400
2397
return made_control.create_repository(shared=shared)
2402
def make_smart_server(self, path):
2399
def make_smart_server(self, path, backing_server=None):
2400
if backing_server is None:
2401
backing_server = self.get_server()
2403
2402
smart_server = test_server.SmartTCPServer_for_testing()
2404
self.start_server(smart_server, self.get_server())
2405
remote_transport = get_transport(smart_server.get_url()).clone(path)
2403
self.start_server(smart_server, backing_server)
2404
remote_transport = _mod_transport.get_transport(smart_server.get_url()
2406
2406
return remote_transport
2408
2408
def make_branch_and_memory_tree(self, relpath, format=None):
2424
2424
def setUp(self):
2425
2425
super(TestCaseWithMemoryTransport, self).setUp()
2426
# Ensure that ConnectedTransport doesn't leak sockets
2427
def get_transport_with_cleanup(*args, **kwargs):
2428
t = orig_get_transport(*args, **kwargs)
2429
if isinstance(t, _mod_transport.ConnectedTransport):
2430
self.addCleanup(t.disconnect)
2433
orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
2434
get_transport_with_cleanup)
2426
2435
self._make_test_root()
2427
2436
self.addCleanup(os.chdir, os.getcwdu())
2428
2437
self.makeAndChdirToTestDir()
2569
2582
content = "contents of %s%s" % (name.encode('utf-8'), end)
2570
2583
transport.put_bytes_non_atomic(urlutils.escape(name), content)
2572
def build_tree_contents(self, shape):
2573
build_tree_contents(shape)
2585
build_tree_contents = staticmethod(treeshape.build_tree_contents)
2575
2587
def assertInWorkingTree(self, path, root_path='.', tree=None):
2576
2588
"""Assert whether path or paths are in the WorkingTree"""
3182
3197
def partition_tests(suite, count):
3183
3198
"""Partition suite into count lists of tests."""
3185
tests = list(iter_suite_tests(suite))
3186
tests_per_process = int(math.ceil(float(len(tests)) / count))
3187
for block in range(count):
3188
low_test = block * tests_per_process
3189
high_test = low_test + tests_per_process
3190
process_tests = tests[low_test:high_test]
3191
result.append(process_tests)
3199
# This just assigns tests in a round-robin fashion. On one hand this
3200
# splits up blocks of related tests that might run faster if they shared
3201
# resources, but on the other it avoids assigning blocks of slow tests to
3202
# just one partition. So the slowest partition shouldn't be much slower
3204
partitions = [list() for i in range(count)]
3205
tests = iter_suite_tests(suite)
3206
for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3207
partition.append(test)
3211
def workaround_zealous_crypto_random():
3212
"""Crypto.Random want to help us being secure, but we don't care here.
3214
This workaround some test failure related to the sftp server. Once paramiko
3215
stop using the controversial API in Crypto.Random, we may get rid of it.
3218
from Crypto.Random import atfork
3195
3224
def fork_for_tests(suite):
3213
3242
ProtocolTestCase.run(self, result)
3215
os.waitpid(self.pid, os.WNOHANG)
3244
os.waitpid(self.pid, 0)
3217
3246
test_blocks = partition_tests(suite, concurrency)
3218
3247
for process_tests in test_blocks:
3219
process_suite = TestSuite()
3248
process_suite = TestUtil.TestSuite()
3220
3249
process_suite.addTests(process_tests)
3221
3250
c2pread, c2pwrite = os.pipe()
3222
3251
pid = os.fork()
3253
workaround_zealous_crypto_random()
3225
3255
os.close(c2pread)
3226
3256
# Leave stderr and stdout open so we can see test noise
3288
3318
if '--no-plugins' in sys.argv:
3289
3319
argv.append('--no-plugins')
3290
# stderr=STDOUT would be ideal, but until we prevent noise on
3291
# stderr it can interrupt the subunit protocol.
3292
process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
3320
# stderr=subprocess.STDOUT would be ideal, but until we prevent
3321
# noise on stderr it can interrupt the subunit protocol.
3322
process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3323
stdout=subprocess.PIPE,
3324
stderr=subprocess.PIPE,
3294
3326
test = TestInSubprocess(process, test_list_file_name)
3295
3327
result.append(test)
3610
3647
'bzrlib.tests.blackbox',
3611
3648
'bzrlib.tests.commands',
3649
'bzrlib.tests.doc_generate',
3612
3650
'bzrlib.tests.per_branch',
3613
3651
'bzrlib.tests.per_bzrdir',
3652
'bzrlib.tests.per_controldir',
3653
'bzrlib.tests.per_controldir_colo',
3614
3654
'bzrlib.tests.per_foreign_vcs',
3615
3655
'bzrlib.tests.per_interrepository',
3616
3656
'bzrlib.tests.per_intertree',
3629
3669
'bzrlib.tests.per_workingtree',
3630
3670
'bzrlib.tests.test__annotator',
3631
3671
'bzrlib.tests.test__bencode',
3672
'bzrlib.tests.test__btree_serializer',
3632
3673
'bzrlib.tests.test__chk_map',
3633
3674
'bzrlib.tests.test__dirstate_helpers',
3634
3675
'bzrlib.tests.test__groupcompress',
3677
3718
'bzrlib.tests.test_export',
3678
3719
'bzrlib.tests.test_extract',
3679
3720
'bzrlib.tests.test_fetch',
3721
'bzrlib.tests.test_fixtures',
3680
3722
'bzrlib.tests.test_fifo_cache',
3681
3723
'bzrlib.tests.test_filters',
3682
3724
'bzrlib.tests.test_ftp_transport',
3703
3745
'bzrlib.tests.test_knit',
3704
3746
'bzrlib.tests.test_lazy_import',
3705
3747
'bzrlib.tests.test_lazy_regex',
3748
'bzrlib.tests.test_library_state',
3706
3749
'bzrlib.tests.test_lock',
3707
3750
'bzrlib.tests.test_lockable_files',
3708
3751
'bzrlib.tests.test_lockdir',
3710
3753
'bzrlib.tests.test_lru_cache',
3711
3754
'bzrlib.tests.test_lsprof',
3712
3755
'bzrlib.tests.test_mail_client',
3756
'bzrlib.tests.test_matchers',
3713
3757
'bzrlib.tests.test_memorytree',
3714
3758
'bzrlib.tests.test_merge',
3715
3759
'bzrlib.tests.test_merge3',
3764
3808
'bzrlib.tests.test_switch',
3765
3809
'bzrlib.tests.test_symbol_versioning',
3766
3810
'bzrlib.tests.test_tag',
3811
'bzrlib.tests.test_test_server',
3767
3812
'bzrlib.tests.test_testament',
3768
3813
'bzrlib.tests.test_textfile',
3769
3814
'bzrlib.tests.test_textmerge',
3775
3820
'bzrlib.tests.test_transport_log',
3776
3821
'bzrlib.tests.test_tree',
3777
3822
'bzrlib.tests.test_treebuilder',
3823
'bzrlib.tests.test_treeshape',
3778
3824
'bzrlib.tests.test_tsort',
3779
3825
'bzrlib.tests.test_tuned_gzip',
3780
3826
'bzrlib.tests.test_ui',
3784
3830
'bzrlib.tests.test_urlutils',
3785
3831
'bzrlib.tests.test_version',
3786
3832
'bzrlib.tests.test_version_info',
3833
'bzrlib.tests.test_versionedfile',
3787
3834
'bzrlib.tests.test_weave',
3788
3835
'bzrlib.tests.test_whitebox',
3789
3836
'bzrlib.tests.test_win32utils',
4007
4058
:param new_id: The id to assign to it.
4008
4059
:return: The new test.
4010
new_test = copy(test)
4061
new_test = copy.copy(test)
4011
4062
new_test.id = lambda: new_id
4063
# XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4064
# causes cloned tests to share the 'details' dict. This makes it hard to
4065
# read the test output for parameterized tests, because tracebacks will be
4066
# associated with irrelevant tests.
4068
details = new_test._TestCase__details
4069
except AttributeError:
4070
# must be a different version of testtools than expected. Do nothing.
4073
# Reset the '__details' dict.
4074
new_test._TestCase__details = {}
4012
4075
return new_test
4074
4137
if test_id != None:
4075
4138
ui.ui_factory.clear_term()
4076
4139
sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4140
# Ugly, but the last thing we want here is fail, so bear with it.
4141
printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4142
).encode('ascii', 'replace')
4077
4143
sys.stderr.write('Unable to remove testing dir %s\n%s'
4078
% (os.path.basename(dirname), e))
4144
% (os.path.basename(dirname), printable_e))
4081
4147
class Feature(object):
4427
4504
from subunit import TestProtocolClient
4428
4505
from subunit.test_results import AutoTimingTestResultDecorator
4506
class SubUnitBzrProtocolClient(TestProtocolClient):
4508
def addSuccess(self, test, details=None):
4509
# The subunit client always includes the details in the subunit
4510
# stream, but we don't want to include it in ours.
4511
if details is not None and 'log' in details:
4513
return super(SubUnitBzrProtocolClient, self).addSuccess(
4429
4516
class SubUnitBzrRunner(TextTestRunner):
4430
4517
def run(self, test):
4431
4518
result = AutoTimingTestResultDecorator(
4432
TestProtocolClient(self.stream))
4519
SubUnitBzrProtocolClient(self.stream))
4433
4520
test.run(result)
4435
4522
except ImportError:
4525
class _PosixPermissionsFeature(Feature):
4529
# create temporary file and check if specified perms are maintained.
4532
write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
4533
f = tempfile.mkstemp(prefix='bzr_perms_chk_')
4536
os.chmod(name, write_perms)
4538
read_perms = os.stat(name).st_mode & 0777
4540
return (write_perms == read_perms)
4542
return (os.name == 'posix') and has_perms()
4544
def feature_name(self):
4545
return 'POSIX permissions support'
4547
posix_permissions_feature = _PosixPermissionsFeature()