221
223
"""Record that a test has started."""
222
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:
224
233
def addError(self, test, err):
234
self.extractBenchmarkTime(test)
235
self._cleanupLogFile(test)
225
236
if isinstance(err[1], TestSkipped):
226
return self.addSkipped(test, err)
237
return self.addSkipped(test, err)
238
elif isinstance(err[1], UnavailableFeature):
239
return self.addNotSupported(test, err[1].args[0])
227
240
unittest.TestResult.addError(self, test, err)
228
# We can only do this if we have one of our TestCases, not if
230
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
231
if setKeepLogfile is not None:
233
self.extractBenchmarkTime(test)
241
self.error_count += 1
234
242
self.report_error(test, err)
235
243
if self.stop_early:
238
246
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)
239
251
unittest.TestResult.addFailure(self, test, err)
240
# We can only do this if we have one of our TestCases, not if
242
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
243
if setKeepLogfile is not None:
245
self.extractBenchmarkTime(test)
252
self.failure_count += 1
246
253
self.report_failure(test, err)
247
254
if self.stop_early:
257
def addKnownFailure(self, test, err):
258
self.known_failure_count += 1
259
self.report_known_failure(test, err)
261
def addNotSupported(self, test, feature):
262
self.unsupported.setdefault(str(feature), 0)
263
self.unsupported[str(feature)] += 1
264
self.report_unsupported(test, feature)
250
266
def addSuccess(self, test):
251
267
self.extractBenchmarkTime(test)
252
268
if self._bench_history is not None:
258
274
unittest.TestResult.addSuccess(self, test)
260
276
def addSkipped(self, test, skip_excinfo):
261
self.extractBenchmarkTime(test)
262
277
self.report_skip(test, skip_excinfo)
263
278
# seems best to treat this as success from point-of-view of unittest
264
279
# -- it actually does nothing so it barely matters :)
301
316
class TextTestResult(ExtendedTestResult):
302
317
"""Displays progress and results of tests in text form"""
304
def __init__(self, *args, **kw):
305
ExtendedTestResult.__init__(self, *args, **kw)
306
self.pb = self.ui.nested_progress_bar()
319
def __init__(self, stream, descriptions, verbosity,
324
ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
325
bench_history, num_tests)
327
self.pb = self.ui.nested_progress_bar()
328
self._supplied_pb = False
331
self._supplied_pb = True
307
332
self.pb.show_pct = False
308
333
self.pb.show_spinner = False
309
self.pb.show_eta = False,
334
self.pb.show_eta = False,
310
335
self.pb.show_count = False
311
336
self.pb.show_bar = False
322
347
a += ', %d errors' % self.error_count
323
348
if self.failure_count:
324
349
a += ', %d failed' % self.failure_count
350
if self.known_failure_count:
351
a += ', %d known failures' % self.known_failure_count
325
352
if self.skip_count:
326
353
a += ', %d skipped' % self.skip_count
355
a += ', %d missing features' % len(self.unsupported)
342
371
return self._shortened_test_description(test)
344
373
def report_error(self, test, err):
345
self.error_count += 1
346
374
self.pb.note('ERROR: %s\n %s\n',
347
375
self._test_description(test),
351
379
def report_failure(self, test, err):
352
self.failure_count += 1
353
380
self.pb.note('FAIL: %s\n %s\n',
354
381
self._test_description(test),
385
def report_known_failure(self, test, err):
386
self.pb.note('XFAIL: %s\n%s\n',
387
self._test_description(test), err[1])
358
389
def report_skip(self, test, skip_excinfo):
359
390
self.skip_count += 1
371
402
# progress bar...
372
403
self.pb.note('SKIP: %s', skip_excinfo[1])
405
def report_unsupported(self, test, feature):
406
"""test cannot be run because feature is missing."""
374
408
def report_cleaning_up(self):
375
409
self.pb.update('cleaning up...')
377
411
def finished(self):
412
if not self._supplied_pb:
381
416
class VerboseTestResult(ExtendedTestResult):
414
449
return '%s%s' % (indent, err[1])
416
451
def report_error(self, test, err):
417
self.error_count += 1
418
452
self.stream.writeln('ERROR %s\n%s'
419
453
% (self._testTimeString(),
420
454
self._error_summary(err)))
422
456
def report_failure(self, test, err):
423
self.failure_count += 1
424
457
self.stream.writeln(' FAIL %s\n%s'
425
458
% (self._testTimeString(),
426
459
self._error_summary(err)))
461
def report_known_failure(self, test, err):
462
self.stream.writeln('XFAIL %s\n%s'
463
% (self._testTimeString(),
464
self._error_summary(err)))
428
466
def report_success(self, test):
429
467
self.stream.writeln(' OK %s' % self._testTimeString())
430
468
for bench_called, stats in getattr(test, '_benchcalls', []):
431
469
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
432
470
stats.pprint(file=self.stream)
471
# flush the stream so that we get smooth output. This verbose mode is
472
# used to show the output in PQM.
433
473
self.stream.flush()
435
475
def report_skip(self, test, skip_excinfo):
438
478
% (self._testTimeString(),
439
479
self._error_summary(skip_excinfo)))
481
def report_unsupported(self, test, feature):
482
"""test cannot be run because feature is missing."""
483
self.stream.writeln("NODEP %s\n The feature '%s' is not available."
484
%(self._testTimeString(), feature))
442
488
class TextTestRunner(object):
443
489
stop_on_failure = False
487
533
if failed: self.stream.write(", ")
488
534
self.stream.write("errors=%d" % errored)
535
if result.known_failure_count:
536
if failed or errored: self.stream.write(", ")
537
self.stream.write("known_failure_count=%d" %
538
result.known_failure_count)
489
539
self.stream.writeln(")")
491
self.stream.writeln("OK")
541
if result.known_failure_count:
542
self.stream.writeln("OK (known_failures=%d)" %
543
result.known_failure_count)
545
self.stream.writeln("OK")
492
546
if result.skip_count > 0:
493
547
skipped = result.skip_count
494
548
self.stream.writeln('%d test%s skipped' %
495
549
(skipped, skipped != 1 and "s" or ""))
550
if result.unsupported:
551
for feature, count in sorted(result.unsupported.items()):
552
self.stream.writeln("Missing feature '%s' skipped %d tests." %
496
554
result.report_cleaning_up()
497
555
# This is still a little bogus,
498
556
# but only a little. Folk not using our testrunner will
545
603
"""Indicates that a test was intentionally skipped, rather than failing."""
606
class KnownFailure(AssertionError):
607
"""Indicates that a test failed in a precisely expected manner.
609
Such failures dont block the whole test suite from passing because they are
610
indicators of partially completed code or of future work. We have an
611
explicit error for them so that we can ensure that they are always visible:
612
KnownFailures are always shown in the output of bzr selftest.
616
class UnavailableFeature(Exception):
617
"""A feature required for this test was not available.
619
The feature should be used to construct the exception.
548
623
class CommandFailed(Exception):
793
868
excName = str(excClass)
794
869
raise self.failureException, "%s not raised" % excName
871
def assertRaises(self, excClass, func, *args, **kwargs):
872
"""Assert that a callable raises a particular exception.
874
:param excClass: As for the except statement, this may be either an
875
exception class, or a tuple of classes.
877
Returns the exception so that you can examine it.
880
func(*args, **kwargs)
884
if getattr(excClass,'__name__', None) is not None:
885
excName = excClass.__name__
888
excName = str(excClass)
889
raise self.failureException, "%s not raised" % excName
796
891
def assertIs(self, left, right, message=None):
797
892
if not (left is right):
798
893
if message is not None:
970
1065
def _restoreHooks(self):
971
1066
bzrlib.branch.Branch.hooks = self._preserved_hooks
1068
def knownFailure(self, reason):
1069
"""This test has failed for some known reason."""
1070
raise KnownFailure(reason)
1072
def run(self, result=None):
1073
if result is None: result = self.defaultTestResult()
1074
for feature in getattr(self, '_test_needs_features', []):
1075
if not feature.available():
1076
result.startTest(self)
1077
if getattr(result, 'addNotSupported', None):
1078
result.addNotSupported(self, feature)
1080
result.addSuccess(self)
1081
result.stopTest(self)
1083
return unittest.TestCase.run(self, result)
973
1085
def tearDown(self):
974
1086
self._runCleanups()
975
1087
unittest.TestCase.tearDown(self)
1045
1157
"""Shortcut that splits cmd into words, runs, and returns stdout"""
1046
1158
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
1160
def requireFeature(self, feature):
1161
"""This test requires a specific feature is available.
1163
:raises UnavailableFeature: When feature is not available.
1165
if not feature.available():
1166
raise UnavailableFeature(feature)
1048
1168
def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
1049
1169
working_dir=None):
1050
1170
"""Invoke bzr and return (stdout, stderr).
1383
1503
this_tree=wt_to)
1384
1504
wt_to.add_parent_tree_id(branch_from.last_revision())
1506
def reduceLockdirTimeout(self):
1507
"""Reduce the default lock timeout for the duration of the test, so that
1508
if LockContention occurs during a test, it does so quickly.
1510
Tests that expect to provoke LockContention errors should call this.
1512
orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
1514
bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
1515
self.addCleanup(resetTimeout)
1516
bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
1387
1518
BzrTestBase = TestCase
1412
1543
# execution. Variables that the parameteriser sets need to be
1413
1544
# ones that are not set by setUp, or setUp will trash them.
1414
1545
super(TestCaseWithMemoryTransport, self).__init__(methodName)
1415
self.transport_server = default_transport
1546
self.vfs_transport_factory = default_transport
1547
self.transport_server = None
1416
1548
self.transport_readonly_server = None
1549
self.__vfs_server = None
1418
1551
def get_transport(self):
1419
1552
"""Return a writeable transport for the test scratch space"""
1447
1580
if self.transport_readonly_server is None:
1448
1581
# readonly decorator requested
1449
1582
# bring up the server
1451
1583
self.__readonly_server = ReadonlyServer()
1452
self.__readonly_server.setUp(self.__server)
1584
self.__readonly_server.setUp(self.get_vfs_only_server())
1454
1586
self.__readonly_server = self.create_transport_readonly_server()
1455
self.__readonly_server.setUp()
1587
self.__readonly_server.setUp(self.get_vfs_only_server())
1456
1588
self.addCleanup(self.__readonly_server.tearDown)
1457
1589
return self.__readonly_server
1480
1612
For TestCaseWithMemoryTransport this is always a MemoryServer, and there
1481
1613
is no means to override it.
1615
if self.__vfs_server is None:
1616
self.__vfs_server = MemoryServer()
1617
self.__vfs_server.setUp()
1618
self.addCleanup(self.__vfs_server.tearDown)
1619
return self.__vfs_server
1621
def get_server(self):
1622
"""Get the read/write server instance.
1624
This is useful for some tests with specific servers that need
1627
This is built from the self.transport_server factory. If that is None,
1628
then the self.get_vfs_server is returned.
1483
1630
if self.__server is None:
1484
self.__server = MemoryServer()
1485
self.__server.setUp()
1631
if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
1632
return self.get_vfs_only_server()
1634
# bring up a decorated means of access to the vfs only server.
1635
self.__server = self.transport_server()
1637
self.__server.setUp(self.get_vfs_only_server())
1638
except TypeError, e:
1639
# This should never happen; the try:Except here is to assist
1640
# developers having to update code rather than seeing an
1641
# uninformative TypeError.
1642
raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
1486
1643
self.addCleanup(self.__server.tearDown)
1487
1644
return self.__server
1489
def get_url(self, relpath=None):
1646
def _adjust_url(self, base, relpath):
1490
1647
"""Get a URL (or maybe a path) for the readwrite transport.
1492
1649
This will either be backed by '.' or to an equivalent non-file based
1508
1664
base += urlutils.escape(relpath)
1667
def get_url(self, relpath=None):
1668
"""Get a URL (or maybe a path) for the readwrite transport.
1670
This will either be backed by '.' or to an equivalent non-file based
1672
relpath provides for clients to get a path relative to the base url.
1673
These should only be downwards relative, not upwards.
1675
base = self.get_server().get_url()
1676
return self._adjust_url(base, relpath)
1678
def get_vfs_only_url(self, relpath=None):
1679
"""Get a URL (or maybe a path for the plain old vfs transport.
1681
This will never be a smart protocol.
1682
:param relpath: provides for clients to get a path relative to the base
1683
url. These should only be downwards relative, not upwards.
1685
base = self.get_vfs_only_server().get_url()
1686
return self._adjust_url(base, relpath)
1511
1688
def _make_test_root(self):
1512
1689
if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1735
1913
readwrite one must both define get_url() as resolving to os.getcwd().
1738
def create_transport_server(self):
1739
"""Create a transport server from class defined at init.
1741
This is mostly a hook for daughter classes.
1743
return self.transport_server()
1745
def get_server(self):
1916
def get_vfs_only_server(self):
1746
1917
"""See TestCaseWithMemoryTransport.
1748
1919
This is useful for some tests with specific servers that need
1751
if self.__server is None:
1752
self.__server = self.create_transport_server()
1753
self.__server.setUp()
1754
self.addCleanup(self.__server.tearDown)
1755
return self.__server
1922
if self.__vfs_server is None:
1923
self.__vfs_server = self.vfs_transport_factory()
1924
self.__vfs_server.setUp()
1925
self.addCleanup(self.__vfs_server.tearDown)
1926
return self.__vfs_server
1757
1928
def make_branch_and_tree(self, relpath, format=None):
1758
1929
"""Create a branch on the transport and a tree locally.
1760
1931
If the transport is not a LocalTransport, the Tree can't be created on
1761
the transport. In that case the working tree is created in the local
1762
directory, and the returned tree's branch and repository will also be
1765
This will fail if the original default transport for this test
1766
case wasn't backed by the working directory, as the branch won't
1767
be on disk for us to open it.
1932
the transport. In that case if the vfs_transport_factory is
1933
LocalURLServer the working tree is created in the local
1934
directory backing the transport, and the returned tree's branch and
1935
repository will also be accessed locally. Otherwise a lightweight
1936
checkout is created and returned.
1769
1938
:param format: The BzrDirFormat.
1770
1939
:returns: the WorkingTree.
1778
1947
return b.bzrdir.create_workingtree()
1779
1948
except errors.NotLocalUrl:
1780
1949
# We can only make working trees locally at the moment. If the
1781
# transport can't support them, then reopen the branch on a local
1782
# transport, and create the working tree there.
1784
# Possibly we should instead keep
1785
# the non-disk-backed branch and create a local checkout?
1786
bd = bzrdir.BzrDir.open(relpath)
1787
return bd.create_workingtree()
1950
# transport can't support them, then we keep the non-disk-backed
1951
# branch and create a local checkout.
1952
if self.vfs_transport_factory is LocalURLServer:
1953
# the branch is colocated on disk, we cannot create a checkout.
1954
# hopefully callers will expect this.
1955
local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
1956
return local_controldir.create_workingtree()
1958
return b.create_checkout(relpath, lightweight=True)
1789
1960
def assertIsDirectory(self, relpath, transport):
1790
1961
"""Assert that relpath within transport is a directory.
2002
2173
'bzrlib.tests.test_ssh_transport',
2003
2174
'bzrlib.tests.test_status',
2004
2175
'bzrlib.tests.test_store',
2176
'bzrlib.tests.test_strace',
2005
2177
'bzrlib.tests.test_subsume',
2006
2178
'bzrlib.tests.test_symbol_versioning',
2007
2179
'bzrlib.tests.test_tag',
2094
2266
print 'delete directory:', i
2095
2267
shutil.rmtree(i)
2270
class Feature(object):
2271
"""An operating system Feature."""
2274
self._available = None
2276
def available(self):
2277
"""Is the feature available?
2279
:return: True if the feature is available.
2281
if self._available is None:
2282
self._available = self._probe()
2283
return self._available
2286
"""Implement this method in concrete features.
2288
:return: True if the feature is available.
2290
raise NotImplementedError
2293
if getattr(self, 'feature_name', None):
2294
return self.feature_name()
2295
return self.__class__.__name__