208
222
def startTest(self, test):
209
223
unittest.TestResult.startTest(self, test)
210
224
self.report_test_start(test)
225
test.number = self.count
211
226
self._recordTestStartTime()
213
228
def _recordTestStartTime(self):
214
229
"""Record that a test has started."""
215
230
self._start_time = time.time()
232
def _cleanupLogFile(self, test):
233
# We can only do this if we have one of our TestCases, not if
235
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
236
if setKeepLogfile is not None:
217
239
def addError(self, test, err):
240
self.extractBenchmarkTime(test)
241
self._cleanupLogFile(test)
218
242
if isinstance(err[1], TestSkipped):
219
return self.addSkipped(test, err)
243
return self.addSkipped(test, err)
244
elif isinstance(err[1], UnavailableFeature):
245
return self.addNotSupported(test, err[1].args[0])
220
246
unittest.TestResult.addError(self, test, err)
221
# We can only do this if we have one of our TestCases, not if
223
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
224
if setKeepLogfile is not None:
226
self.extractBenchmarkTime(test)
247
self.error_count += 1
227
248
self.report_error(test, err)
228
249
if self.stop_early:
231
252
def addFailure(self, test, err):
253
self._cleanupLogFile(test)
254
self.extractBenchmarkTime(test)
255
if isinstance(err[1], KnownFailure):
256
return self.addKnownFailure(test, err)
232
257
unittest.TestResult.addFailure(self, test, err)
233
# We can only do this if we have one of our TestCases, not if
235
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
236
if setKeepLogfile is not None:
238
self.extractBenchmarkTime(test)
258
self.failure_count += 1
239
259
self.report_failure(test, err)
240
260
if self.stop_early:
263
def addKnownFailure(self, test, err):
264
self.known_failure_count += 1
265
self.report_known_failure(test, err)
267
def addNotSupported(self, test, feature):
268
self.unsupported.setdefault(str(feature), 0)
269
self.unsupported[str(feature)] += 1
270
self.report_unsupported(test, feature)
243
272
def addSuccess(self, test):
244
273
self.extractBenchmarkTime(test)
245
274
if self._bench_history is not None:
267
295
def printErrorList(self, flavour, errors):
268
296
for test, err in errors:
269
297
self.stream.writeln(self.separator1)
270
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
298
self.stream.write("%s: " % flavour)
299
if self.use_numbered_dirs:
300
self.stream.write('#%d ' % test.number)
301
self.stream.writeln(self.getDescription(test))
271
302
if getattr(test, '_get_log', None) is not None:
272
303
print >>self.stream
273
304
print >>self.stream, \
291
322
class TextTestResult(ExtendedTestResult):
292
323
"""Displays progress and results of tests in text form"""
294
def __init__(self, *args, **kw):
295
ExtendedTestResult.__init__(self, *args, **kw)
296
self.pb = self.ui.nested_progress_bar()
325
def __init__(self, stream, descriptions, verbosity,
329
use_numbered_dirs=False,
331
ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
332
bench_history, num_tests, use_numbered_dirs)
334
self.pb = self.ui.nested_progress_bar()
335
self._supplied_pb = False
338
self._supplied_pb = True
297
339
self.pb.show_pct = False
298
340
self.pb.show_spinner = False
299
self.pb.show_eta = False,
341
self.pb.show_eta = False,
300
342
self.pb.show_count = False
301
343
self.pb.show_bar = False
325
371
+ self._shortened_test_description(test))
373
def _test_description(self, test):
374
if self.use_numbered_dirs:
375
return '#%d %s' % (self.count,
376
self._shortened_test_description(test))
378
return self._shortened_test_description(test)
327
380
def report_error(self, test, err):
328
self.error_count += 1
329
381
self.pb.note('ERROR: %s\n %s\n',
330
self._shortened_test_description(test),
382
self._test_description(test),
334
386
def report_failure(self, test, err):
335
self.failure_count += 1
336
387
self.pb.note('FAIL: %s\n %s\n',
337
self._shortened_test_description(test),
388
self._test_description(test),
392
def report_known_failure(self, test, err):
393
self.pb.note('XFAIL: %s\n%s\n',
394
self._test_description(test), err[1])
341
396
def report_skip(self, test, skip_excinfo):
342
397
self.skip_count += 1
380
439
name = self._shortened_test_description(test)
381
440
# width needs space for 6 char status, plus 1 for slash, plus 2 10-char
382
441
# numbers, plus a trailing blank
383
self.stream.write(self._ellipsize_to_right(name,
384
osutils.terminal_width()-30))
442
# when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
443
if self.use_numbered_dirs:
444
self.stream.write('%5d ' % self.count)
445
self.stream.write(self._ellipsize_to_right(name,
446
osutils.terminal_width()-36))
448
self.stream.write(self._ellipsize_to_right(name,
449
osutils.terminal_width()-30))
385
450
self.stream.flush()
452
def _error_summary(self, err):
454
if self.use_numbered_dirs:
456
return '%s%s' % (indent, err[1])
387
458
def report_error(self, test, err):
388
self.error_count += 1
389
self.stream.writeln('ERROR %s\n %s'
390
% (self._testTimeString(), err[1]))
459
self.stream.writeln('ERROR %s\n%s'
460
% (self._testTimeString(),
461
self._error_summary(err)))
392
463
def report_failure(self, test, err):
393
self.failure_count += 1
394
self.stream.writeln(' FAIL %s\n %s'
395
% (self._testTimeString(), err[1]))
464
self.stream.writeln(' FAIL %s\n%s'
465
% (self._testTimeString(),
466
self._error_summary(err)))
468
def report_known_failure(self, test, err):
469
self.stream.writeln('XFAIL %s\n%s'
470
% (self._testTimeString(),
471
self._error_summary(err)))
397
473
def report_success(self, test):
398
474
self.stream.writeln(' OK %s' % self._testTimeString())
399
475
for bench_called, stats in getattr(test, '_benchcalls', []):
400
476
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
401
477
stats.pprint(file=self.stream)
478
# flush the stream so that we get smooth output. This verbose mode is
479
# used to show the output in PQM.
402
480
self.stream.flush()
404
482
def report_skip(self, test, skip_excinfo):
405
print >>self.stream, ' SKIP %s' % self._testTimeString()
406
print >>self.stream, ' %s' % skip_excinfo[1]
484
self.stream.writeln(' SKIP %s\n%s'
485
% (self._testTimeString(),
486
self._error_summary(skip_excinfo)))
488
def report_unsupported(self, test, feature):
489
"""test cannot be run because feature is missing."""
490
self.stream.writeln("NODEP %s\n The feature '%s' is not available."
491
%(self._testTimeString(), feature))
409
495
class TextTestRunner(object):
434
525
bench_history=self._bench_history,
435
526
num_tests=test.countTestCases(),
527
use_numbered_dirs=self.use_numbered_dirs,
437
529
result.stop_early = self.stop_on_failure
438
530
result.report_starting()
532
if self.verbosity >= 2:
533
self.stream.writeln("Listing tests only ...\n")
535
for t in iter_suite_tests(test):
536
self.stream.writeln("%s" % (t.id()))
538
actionTaken = "Listed"
541
run = result.testsRun
440
543
stopTime = time.time()
441
544
timeTaken = stopTime - startTime
442
545
result.printErrors()
443
546
self.stream.writeln(result.separator2)
444
run = result.testsRun
445
self.stream.writeln("Ran %d test%s in %.3fs" %
446
(run, run != 1 and "s" or "", timeTaken))
547
self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
548
run, run != 1 and "s" or "", timeTaken))
447
549
self.stream.writeln()
448
550
if not result.wasSuccessful():
449
551
self.stream.write("FAILED (")
454
556
if failed: self.stream.write(", ")
455
557
self.stream.write("errors=%d" % errored)
558
if result.known_failure_count:
559
if failed or errored: self.stream.write(", ")
560
self.stream.write("known_failure_count=%d" %
561
result.known_failure_count)
456
562
self.stream.writeln(")")
458
self.stream.writeln("OK")
564
if result.known_failure_count:
565
self.stream.writeln("OK (known_failures=%d)" %
566
result.known_failure_count)
568
self.stream.writeln("OK")
569
if result.skip_count > 0:
570
skipped = result.skip_count
571
self.stream.writeln('%d test%s skipped' %
572
(skipped, skipped != 1 and "s" or ""))
573
if result.unsupported:
574
for feature, count in sorted(result.unsupported.items()):
575
self.stream.writeln("Missing feature '%s' skipped %d tests." %
459
577
result.report_cleaning_up()
460
578
# This is still a little bogus,
461
579
# but only a little. Folk not using our testrunner will
500
618
"""Indicates that a test was intentionally skipped, rather than failing."""
621
class KnownFailure(AssertionError):
622
"""Indicates that a test failed in a precisely expected manner.
624
Such failures dont block the whole test suite from passing because they are
625
indicators of partially completed code or of future work. We have an
626
explicit error for them so that we can ensure that they are always visible:
627
KnownFailures are always shown in the output of bzr selftest.
631
class UnavailableFeature(Exception):
632
"""A feature required for this test was not available.
634
The feature should be used to construct the exception.
503
638
class CommandFailed(Exception):
530
665
return setattr(self._cstring, name, val)
668
class TestUIFactory(ui.CLIUIFactory):
669
"""A UI Factory for testing.
671
Hide the progress bar but emit note()s.
673
Allows get_password to be tested without real tty attached.
680
super(TestUIFactory, self).__init__()
681
if stdin is not None:
682
# We use a StringIOWrapper to be able to test various
683
# encodings, but the user is still responsible to
684
# encode the string and to set the encoding attribute
685
# of StringIOWrapper.
686
self.stdin = StringIOWrapper(stdin)
688
self.stdout = sys.stdout
692
self.stderr = sys.stderr
697
"""See progress.ProgressBar.clear()."""
699
def clear_term(self):
700
"""See progress.ProgressBar.clear_term()."""
702
def clear_term(self):
703
"""See progress.ProgressBar.clear_term()."""
706
"""See progress.ProgressBar.finished()."""
708
def note(self, fmt_string, *args, **kwargs):
709
"""See progress.ProgressBar.note()."""
710
self.stdout.write((fmt_string + "\n") % args)
712
def progress_bar(self):
715
def nested_progress_bar(self):
718
def update(self, message, count=None, total=None):
719
"""See progress.ProgressBar.update()."""
721
def get_non_echoed_password(self, prompt):
722
"""Get password from stdin without trying to handle the echo mode"""
724
self.stdout.write(prompt)
725
password = self.stdin.readline()
728
if password[-1] == '\n':
729
password = password[:-1]
533
733
class TestCase(unittest.TestCase):
534
734
"""Base class for bzr unit tests.
569
769
self._startLogFile()
570
770
self._benchcalls = []
571
771
self._benchtime = None
774
def _clear_hooks(self):
775
# prevent hooks affecting tests
777
import bzrlib.smart.server
778
self._preserved_hooks = {
779
bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
780
bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
782
self.addCleanup(self._restoreHooks)
783
# this list of hooks must be kept in sync with the defaults
785
bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
786
bzrlib.smart.server.SmartTCPServer.hooks = \
787
bzrlib.smart.server.SmartServerHooks()
573
789
def _silenceUI(self):
574
790
"""Turn off UI for duration of test"""
575
791
# by default the UI is off; tests can turn it on if they want it.
576
saved = bzrlib.ui.ui_factory
792
saved = ui.ui_factory
578
bzrlib.ui.ui_factory = saved
579
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
794
ui.ui_factory = saved
795
ui.ui_factory = ui.SilentUIFactory()
580
796
self.addCleanup(_restore)
582
798
def _ndiff_strings(self, a, b):
594
810
charjunk=lambda x: False)
595
811
return ''.join(difflines)
813
def assertEqual(self, a, b, message=''):
817
except UnicodeError, e:
818
# If we can't compare without getting a UnicodeError, then
819
# obviously they are different
820
mutter('UnicodeError: %s', e)
823
raise AssertionError("%snot equal:\na = %s\nb = %s\n"
825
pformat(a, indent=4), pformat(b, indent=4)))
827
assertEquals = assertEqual
597
829
def assertEqualDiff(self, a, b, message=None):
598
830
"""Assert two texts are equal, if not raise an exception.
661
893
excName = str(excClass)
662
894
raise self.failureException, "%s not raised" % excName
664
def assertIs(self, left, right):
896
def assertRaises(self, excClass, func, *args, **kwargs):
897
"""Assert that a callable raises a particular exception.
899
:param excClass: As for the except statement, this may be either an
900
exception class, or a tuple of classes.
902
Returns the exception so that you can examine it.
905
func(*args, **kwargs)
909
if getattr(excClass,'__name__', None) is not None:
910
excName = excClass.__name__
913
excName = str(excClass)
914
raise self.failureException, "%s not raised" % excName
916
def assertIs(self, left, right, message=None):
665
917
if not (left is right):
666
raise AssertionError("%r is not %r." % (left, right))
918
if message is not None:
919
raise AssertionError(message)
921
raise AssertionError("%r is not %r." % (left, right))
923
def assertIsNot(self, left, right, message=None):
925
if message is not None:
926
raise AssertionError(message)
928
raise AssertionError("%r is %r." % (left, right))
668
930
def assertTransportMode(self, transport, path, mode):
669
931
"""Fail if a path does not have mode mode.
683
945
self.fail("%r is an instance of %s rather than %s" % (
684
946
obj, obj.__class__, kls))
948
def expectFailure(self, reason, assertion, *args, **kwargs):
949
"""Invoke a test, expecting it to fail for the given reason.
951
This is for assertions that ought to succeed, but currently fail.
952
(The failure is *expected* but not *wanted*.) Please be very precise
953
about the failure you're expecting. If a new bug is introduced,
954
AssertionError should be raised, not KnownFailure.
956
Frequently, expectFailure should be followed by an opposite assertion.
959
Intended to be used with a callable that raises AssertionError as the
960
'assertion' parameter. args and kwargs are passed to the 'assertion'.
962
Raises KnownFailure if the test fails. Raises AssertionError if the
967
self.expectFailure('Math is broken', self.assertNotEqual, 54,
969
self.assertEqual(42, dynamic_val)
971
This means that a dynamic_val of 54 will cause the test to raise
972
a KnownFailure. Once math is fixed and the expectFailure is removed,
973
only a dynamic_val of 42 will allow the test to pass. Anything other
974
than 54 or 42 will cause an AssertionError.
977
assertion(*args, **kwargs)
978
except AssertionError:
979
raise KnownFailure(reason)
981
self.fail('Unexpected success. Should have failed: %s' % reason)
686
983
def _capture_warnings(self, a_callable, *args, **kwargs):
687
984
"""A helper for callDeprecated and applyDeprecated.
825
1122
for name, value in self.__old_env.iteritems():
826
1123
osutils.set_or_unset_env(name, value)
1125
def _restoreHooks(self):
1126
for klass, hooks in self._preserved_hooks.items():
1127
setattr(klass, 'hooks', hooks)
1129
def knownFailure(self, reason):
1130
"""This test has failed for some known reason."""
1131
raise KnownFailure(reason)
1133
def run(self, result=None):
1134
if result is None: result = self.defaultTestResult()
1135
for feature in getattr(self, '_test_needs_features', []):
1136
if not feature.available():
1137
result.startTest(self)
1138
if getattr(result, 'addNotSupported', None):
1139
result.addNotSupported(self, feature)
1141
result.addSuccess(self)
1142
result.stopTest(self)
1144
return unittest.TestCase.run(self, result)
828
1146
def tearDown(self):
829
1147
self._runCleanups()
830
1148
unittest.TestCase.tearDown(self)
890
1218
"""Shortcut that splits cmd into words, runs, and returns stdout"""
891
1219
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
1221
def requireFeature(self, feature):
1222
"""This test requires a specific feature is available.
1224
:raises UnavailableFeature: When feature is not available.
1226
if not feature.available():
1227
raise UnavailableFeature(feature)
893
1229
def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
894
1230
working_dir=None):
895
1231
"""Invoke bzr and return (stdout, stderr).
929
1263
handler.setLevel(logging.INFO)
930
1264
logger = logging.getLogger('')
931
1265
logger.addHandler(handler)
932
old_ui_factory = bzrlib.ui.ui_factory
933
bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
936
bzrlib.ui.ui_factory.stdin = stdin
1266
old_ui_factory = ui.ui_factory
1267
ui.ui_factory = TestUIFactory(stdin=stdin, stdout=stdout, stderr=stderr)
939
1270
if working_dir is not None:
944
1275
saved_debug_flags = frozenset(debug.debug_flags)
945
1276
debug.debug_flags.clear()
947
result = self.apply_redirected(stdin, stdout, stderr,
1278
result = self.apply_redirected(ui.ui_factory.stdin,
948
1280
bzrlib.commands.run_bzr_catch_errors,
951
1283
debug.debug_flags.update(saved_debug_flags)
953
1285
logger.removeHandler(handler)
954
bzrlib.ui.ui_factory = old_ui_factory
1286
ui.ui_factory = old_ui_factory
955
1287
if cwd is not None:
976
1309
where it may be useful for debugging. See also run_captured.
978
1311
:param stdin: A string to be used as stdin for the command.
1312
:param retcode: The status code the command should return
1313
:param working_dir: The directory to run the command in
980
1315
retcode = kwargs.pop('retcode', 0)
981
1316
encoding = kwargs.pop('encoding', None)
982
1317
stdin = kwargs.pop('stdin', None)
983
1318
working_dir = kwargs.pop('working_dir', None)
984
return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
985
stdin=stdin, working_dir=working_dir)
1319
error_regexes = kwargs.pop('error_regexes', [])
1321
out, err = self.run_bzr_captured(args, retcode=retcode,
1322
encoding=encoding, stdin=stdin, working_dir=working_dir)
1324
for regex in error_regexes:
1325
self.assertContainsRe(err, regex)
987
1329
def run_bzr_decode(self, *args, **kwargs):
988
1330
if 'encoding' in kwargs:
1015
1357
'commit', '--strict', '-m', 'my commit comment')
1017
1359
kwargs.setdefault('retcode', 3)
1018
out, err = self.run_bzr(*args, **kwargs)
1019
for regex in error_regexes:
1020
self.assertContainsRe(err, regex)
1360
out, err = self.run_bzr(error_regexes=error_regexes, *args, **kwargs)
1021
1361
return out, err
1023
1363
def run_bzr_subprocess(self, *args, **kwargs):
1230
1570
this_tree=wt_to)
1231
1571
wt_to.add_parent_tree_id(branch_from.last_revision())
1573
def reduceLockdirTimeout(self):
1574
"""Reduce the default lock timeout for the duration of the test, so that
1575
if LockContention occurs during a test, it does so quickly.
1577
Tests that expect to provoke LockContention errors should call this.
1579
orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
1581
bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
1582
self.addCleanup(resetTimeout)
1583
bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
1234
1585
BzrTestBase = TestCase
1259
1610
# execution. Variables that the parameteriser sets need to be
1260
1611
# ones that are not set by setUp, or setUp will trash them.
1261
1612
super(TestCaseWithMemoryTransport, self).__init__(methodName)
1262
self.transport_server = default_transport
1613
self.vfs_transport_factory = default_transport
1614
self.transport_server = None
1263
1615
self.transport_readonly_server = None
1265
def failUnlessExists(self, path):
1266
"""Fail unless path, which may be abs or relative, exists."""
1267
self.failUnless(osutils.lexists(path))
1269
def failIfExists(self, path):
1270
"""Fail if path, which may be abs or relative, exists."""
1271
self.failIf(osutils.lexists(path))
1616
self.__vfs_server = None
1273
1618
def get_transport(self):
1274
1619
"""Return a writeable transport for the test scratch space"""
1275
1620
t = get_transport(self.get_url())
1302
1647
if self.transport_readonly_server is None:
1303
1648
# readonly decorator requested
1304
1649
# bring up the server
1306
1650
self.__readonly_server = ReadonlyServer()
1307
self.__readonly_server.setUp(self.__server)
1651
self.__readonly_server.setUp(self.get_vfs_only_server())
1309
1653
self.__readonly_server = self.create_transport_readonly_server()
1310
self.__readonly_server.setUp()
1654
self.__readonly_server.setUp(self.get_vfs_only_server())
1311
1655
self.addCleanup(self.__readonly_server.tearDown)
1312
1656
return self.__readonly_server
1335
1679
For TestCaseWithMemoryTransport this is always a MemoryServer, and there
1336
1680
is no means to override it.
1682
if self.__vfs_server is None:
1683
self.__vfs_server = MemoryServer()
1684
self.__vfs_server.setUp()
1685
self.addCleanup(self.__vfs_server.tearDown)
1686
return self.__vfs_server
1688
def get_server(self):
1689
"""Get the read/write server instance.
1691
This is useful for some tests with specific servers that need
1694
This is built from the self.transport_server factory. If that is None,
1695
then the self.get_vfs_server is returned.
1338
1697
if self.__server is None:
1339
self.__server = MemoryServer()
1340
self.__server.setUp()
1698
if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
1699
return self.get_vfs_only_server()
1701
# bring up a decorated means of access to the vfs only server.
1702
self.__server = self.transport_server()
1704
self.__server.setUp(self.get_vfs_only_server())
1705
except TypeError, e:
1706
# This should never happen; the try:Except here is to assist
1707
# developers having to update code rather than seeing an
1708
# uninformative TypeError.
1709
raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
1341
1710
self.addCleanup(self.__server.tearDown)
1342
1711
return self.__server
1344
def get_url(self, relpath=None):
1713
def _adjust_url(self, base, relpath):
1345
1714
"""Get a URL (or maybe a path) for the readwrite transport.
1347
1716
This will either be backed by '.' or to an equivalent non-file based
1363
1731
base += urlutils.escape(relpath)
1734
def get_url(self, relpath=None):
1735
"""Get a URL (or maybe a path) for the readwrite transport.
1737
This will either be backed by '.' or to an equivalent non-file based
1739
relpath provides for clients to get a path relative to the base url.
1740
These should only be downwards relative, not upwards.
1742
base = self.get_server().get_url()
1743
return self._adjust_url(base, relpath)
1745
def get_vfs_only_url(self, relpath=None):
1746
"""Get a URL (or maybe a path for the plain old vfs transport.
1748
This will never be a smart protocol.
1749
:param relpath: provides for clients to get a path relative to the base
1750
url. These should only be downwards relative, not upwards.
1752
base = self.get_vfs_only_server().get_url()
1753
return self._adjust_url(base, relpath)
1366
1755
def _make_test_root(self):
1367
1756
if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1475
1868
For TestCaseInTempDir we create a temporary directory based on the test
1476
1869
name and then create two subdirs - test and home under it.
1871
if self.use_numbered_dirs: # strongly recommended on Windows
1872
# due the path length limitation (260 ch.)
1873
candidate_dir = '%s/%dK/%05d' % (self.TEST_ROOT,
1874
int(self.number/1000),
1876
os.makedirs(candidate_dir)
1877
self.test_home_dir = candidate_dir + '/home'
1878
os.mkdir(self.test_home_dir)
1879
self.test_dir = candidate_dir + '/work'
1880
os.mkdir(self.test_dir)
1881
os.chdir(self.test_dir)
1882
# put name of test inside
1883
f = file(candidate_dir + '/name', 'w')
1478
1888
# shorten the name, to avoid test failures due to path length
1479
1889
short_id = self.id().replace('bzrlib.tests.', '') \
1480
1890
.replace('__main__.', '')[-100:]
1529
1939
elif line_endings == 'native':
1530
1940
end = os.linesep
1532
raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
1942
raise errors.BzrError(
1943
'Invalid line ending request %r' % line_endings)
1533
1944
content = "contents of %s%s" % (name.encode('utf-8'), end)
1534
# Technically 'put()' is the right command. However, put
1535
# uses an AtomicFile, which requires an extra rename into place
1536
# As long as the files didn't exist in the past, append() will
1537
# do the same thing as put()
1538
# On jam's machine, make_kernel_like_tree is:
1539
# put: 4.5-7.5s (averaging 6s)
1541
# put_non_atomic: 2.9-4.5s
1542
1945
transport.put_bytes_non_atomic(urlutils.escape(name), content)
1544
1947
def build_tree_contents(self, shape):
1547
1950
def assertFileEqual(self, content, path):
1548
1951
"""Fail if path does not contain 'content'."""
1549
self.failUnless(osutils.lexists(path))
1952
self.failUnlessExists(path)
1550
1953
# TODO: jam 20060427 Shouldn't this be 'rb'?
1551
self.assertEqualDiff(content, open(path, 'r').read())
1959
self.assertEqualDiff(content, s)
1961
def failUnlessExists(self, path):
1962
"""Fail unless path or paths, which may be abs or relative, exist."""
1963
if not isinstance(path, basestring):
1965
self.failUnlessExists(p)
1967
self.failUnless(osutils.lexists(path),path+" does not exist")
1969
def failIfExists(self, path):
1970
"""Fail if path or paths, which may be abs or relative, exist."""
1971
if not isinstance(path, basestring):
1973
self.failIfExists(p)
1975
self.failIf(osutils.lexists(path),path+" exists")
1977
def assertInWorkingTree(self,path,root_path='.',tree=None):
1978
"""Assert whether path or paths are in the WorkingTree"""
1980
tree = workingtree.WorkingTree.open(root_path)
1981
if not isinstance(path, basestring):
1983
self.assertInWorkingTree(p,tree=tree)
1985
self.assertIsNot(tree.path2id(path), None,
1986
path+' not in working tree.')
1988
def assertNotInWorkingTree(self,path,root_path='.',tree=None):
1989
"""Assert whether path or paths are not in the WorkingTree"""
1991
tree = workingtree.WorkingTree.open(root_path)
1992
if not isinstance(path, basestring):
1994
self.assertNotInWorkingTree(p,tree=tree)
1996
self.assertIs(tree.path2id(path), None, path+' in working tree.')
1554
1999
class TestCaseWithTransport(TestCaseInTempDir):
1565
2010
readwrite one must both define get_url() as resolving to os.getcwd().
1568
def create_transport_server(self):
1569
"""Create a transport server from class defined at init.
1571
This is mostly a hook for daughter classes.
1573
return self.transport_server()
1575
def get_server(self):
2013
def get_vfs_only_server(self):
1576
2014
"""See TestCaseWithMemoryTransport.
1578
2016
This is useful for some tests with specific servers that need
1581
if self.__server is None:
1582
self.__server = self.create_transport_server()
1583
self.__server.setUp()
1584
self.addCleanup(self.__server.tearDown)
1585
return self.__server
2019
if self.__vfs_server is None:
2020
self.__vfs_server = self.vfs_transport_factory()
2021
self.__vfs_server.setUp()
2022
self.addCleanup(self.__vfs_server.tearDown)
2023
return self.__vfs_server
1587
2025
def make_branch_and_tree(self, relpath, format=None):
1588
2026
"""Create a branch on the transport and a tree locally.
1590
2028
If the transport is not a LocalTransport, the Tree can't be created on
1591
the transport. In that case the working tree is created in the local
1592
directory, and the returned tree's branch and repository will also be
1595
This will fail if the original default transport for this test
1596
case wasn't backed by the working directory, as the branch won't
1597
be on disk for us to open it.
2029
the transport. In that case if the vfs_transport_factory is
2030
LocalURLServer the working tree is created in the local
2031
directory backing the transport, and the returned tree's branch and
2032
repository will also be accessed locally. Otherwise a lightweight
2033
checkout is created and returned.
1599
2035
:param format: The BzrDirFormat.
1600
2036
:returns: the WorkingTree.
1608
2044
return b.bzrdir.create_workingtree()
1609
2045
except errors.NotLocalUrl:
1610
2046
# We can only make working trees locally at the moment. If the
1611
# transport can't support them, then reopen the branch on a local
1612
# transport, and create the working tree there.
1614
# Possibly we should instead keep
1615
# the non-disk-backed branch and create a local checkout?
1616
bd = bzrdir.BzrDir.open(relpath)
1617
return bd.create_workingtree()
2047
# transport can't support them, then we keep the non-disk-backed
2048
# branch and create a local checkout.
2049
if self.vfs_transport_factory is LocalURLServer:
2050
# the branch is colocated on disk, we cannot create a checkout.
2051
# hopefully callers will expect this.
2052
local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2053
return local_controldir.create_workingtree()
2055
return b.create_checkout(relpath, lightweight=True)
1619
2057
def assertIsDirectory(self, relpath, transport):
1620
2058
"""Assert that relpath within transport is a directory.
1631
2069
self.fail("path %s is not a directory; has mode %#o"
1632
2070
% (relpath, mode))
2072
def assertTreesEqual(self, left, right):
2073
"""Check that left and right have the same content and properties."""
2074
# we use a tree delta to check for equality of the content, and we
2075
# manually check for equality of other things such as the parents list.
2076
self.assertEqual(left.get_parent_ids(), right.get_parent_ids())
2077
differences = left.changes_from(right)
2078
self.assertFalse(differences.has_changed(),
2079
"Trees %r and %r are different: %r" % (left, right, differences))
1634
2081
def setUp(self):
1635
2082
super(TestCaseWithTransport, self).setUp()
1636
self.__server = None
2083
self.__vfs_server = None
1639
2086
class ChrootedTestCase(TestCaseWithTransport):
1651
2098
def setUp(self):
1652
2099
super(ChrootedTestCase, self).setUp()
1653
if not self.transport_server == MemoryServer:
2100
if not self.vfs_transport_factory == MemoryServer:
1654
2101
self.transport_readonly_server = HttpServer
1657
def filter_suite_by_re(suite, pattern):
1658
result = TestUtil.TestSuite()
2104
def filter_suite_by_re(suite, pattern, exclude_pattern=None,
2105
random_order=False):
2106
"""Create a test suite by filtering another one.
2108
:param suite: the source suite
2109
:param pattern: pattern that names must match
2110
:param exclude_pattern: pattern that names must not match, if any
2111
:param random_order: if True, tests in the new suite will be put in
2113
:returns: the newly created suite
2115
return sort_suite_by_re(suite, pattern, exclude_pattern,
2116
random_order, False)
2119
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
2120
random_order=False, append_rest=True):
2121
"""Create a test suite by sorting another one.
2123
:param suite: the source suite
2124
:param pattern: pattern that names must match in order to go
2125
first in the new suite
2126
:param exclude_pattern: pattern that names must not match, if any
2127
:param random_order: if True, tests in the new suite will be put in
2129
:param append_rest: if False, pattern is a strict filter and not
2130
just an ordering directive
2131
:returns: the newly created suite
1659
2135
filter_re = re.compile(pattern)
2136
if exclude_pattern is not None:
2137
exclude_re = re.compile(exclude_pattern)
1660
2138
for test in iter_suite_tests(suite):
1661
if filter_re.search(test.id()):
1662
result.addTest(test)
2140
if exclude_pattern is None or not exclude_re.search(test_id):
2141
if filter_re.search(test_id):
2146
random.shuffle(first)
2147
random.shuffle(second)
2148
return TestUtil.TestSuite(first + second)
1666
2151
def run_suite(suite, name='test', verbose=False, pattern=".*",
1667
2152
stop_on_failure=False, keep_output=False,
1668
transport=None, lsprof_timed=None, bench_history=None):
2153
transport=None, lsprof_timed=None, bench_history=None,
2154
matching_tests_first=None,
2158
exclude_pattern=None,
2160
use_numbered_dirs = bool(numbered_dirs)
1669
2162
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2163
if numbered_dirs is not None:
2164
TestCaseInTempDir.use_numbered_dirs = use_numbered_dirs
1675
2170
descriptions=0,
1676
2171
verbosity=verbosity,
1677
2172
keep_output=keep_output,
1678
bench_history=bench_history)
2173
bench_history=bench_history,
2174
use_numbered_dirs=use_numbered_dirs,
2175
list_only=list_only,
1679
2177
runner.stop_on_failure=stop_on_failure
1681
suite = filter_suite_by_re(suite, pattern)
2178
# Initialise the random number generator and display the seed used.
2179
# We convert the seed to a long to make it reuseable across invocations.
2180
random_order = False
2181
if random_seed is not None:
2183
if random_seed == "now":
2184
random_seed = long(time.time())
2186
# Convert the seed to a long if we can
2188
random_seed = long(random_seed)
2191
runner.stream.writeln("Randomizing test order using seed %s\n" %
2193
random.seed(random_seed)
2194
# Customise the list of tests if requested
2195
if pattern != '.*' or exclude_pattern is not None or random_order:
2196
if matching_tests_first:
2197
suite = sort_suite_by_re(suite, pattern, exclude_pattern,
2200
suite = filter_suite_by_re(suite, pattern, exclude_pattern,
1682
2202
result = runner.run(suite)
1683
2203
return result.wasSuccessful()
1710
2235
stop_on_failure=stop_on_failure, keep_output=keep_output,
1711
2236
transport=transport,
1712
2237
lsprof_timed=lsprof_timed,
1713
bench_history=bench_history)
2238
bench_history=bench_history,
2239
matching_tests_first=matching_tests_first,
2240
numbered_dirs=numbered_dirs,
2241
list_only=list_only,
2242
random_seed=random_seed,
2243
exclude_pattern=exclude_pattern)
1715
2245
default_transport = old_transport
1728
2258
'bzrlib.tests.test_atomicfile',
1729
2259
'bzrlib.tests.test_bad_files',
1730
2260
'bzrlib.tests.test_branch',
2261
'bzrlib.tests.test_bugtracker',
1731
2262
'bzrlib.tests.test_bundle',
1732
2263
'bzrlib.tests.test_bzrdir',
1733
2264
'bzrlib.tests.test_cache_utf8',
1737
2268
'bzrlib.tests.test_config',
1738
2269
'bzrlib.tests.test_conflicts',
1739
2270
'bzrlib.tests.test_decorators',
2271
'bzrlib.tests.test_delta',
1740
2272
'bzrlib.tests.test_diff',
1741
'bzrlib.tests.test_doc_generate',
2273
'bzrlib.tests.test_dirstate',
1742
2274
'bzrlib.tests.test_errors',
1743
2275
'bzrlib.tests.test_escaped_store',
2276
'bzrlib.tests.test_extract',
1744
2277
'bzrlib.tests.test_fetch',
1745
2278
'bzrlib.tests.test_ftp_transport',
2279
'bzrlib.tests.test_generate_docs',
1746
2280
'bzrlib.tests.test_generate_ids',
1747
2281
'bzrlib.tests.test_globbing',
1748
2282
'bzrlib.tests.test_gpg',
1749
2283
'bzrlib.tests.test_graph',
1750
2284
'bzrlib.tests.test_hashcache',
2285
'bzrlib.tests.test_help',
1751
2286
'bzrlib.tests.test_http',
1752
2287
'bzrlib.tests.test_http_response',
2288
'bzrlib.tests.test_https_ca_bundle',
1753
2289
'bzrlib.tests.test_identitymap',
1754
2290
'bzrlib.tests.test_ignores',
1755
2291
'bzrlib.tests.test_inv',
1763
2299
'bzrlib.tests.test_merge',
1764
2300
'bzrlib.tests.test_merge3',
1765
2301
'bzrlib.tests.test_merge_core',
2302
'bzrlib.tests.test_merge_directive',
1766
2303
'bzrlib.tests.test_missing',
1767
2304
'bzrlib.tests.test_msgeditor',
1768
2305
'bzrlib.tests.test_nonascii',
1769
2306
'bzrlib.tests.test_options',
1770
2307
'bzrlib.tests.test_osutils',
2308
'bzrlib.tests.test_osutils_encodings',
1771
2309
'bzrlib.tests.test_patch',
1772
2310
'bzrlib.tests.test_patches',
1773
2311
'bzrlib.tests.test_permissions',
1775
2313
'bzrlib.tests.test_progress',
1776
2314
'bzrlib.tests.test_reconcile',
1777
2315
'bzrlib.tests.test_registry',
2316
'bzrlib.tests.test_remote',
1778
2317
'bzrlib.tests.test_repository',
1779
2318
'bzrlib.tests.test_revert',
1780
2319
'bzrlib.tests.test_revision',
1785
2324
'bzrlib.tests.test_selftest',
1786
2325
'bzrlib.tests.test_setup',
1787
2326
'bzrlib.tests.test_sftp_transport',
2327
'bzrlib.tests.test_smart',
1788
2328
'bzrlib.tests.test_smart_add',
1789
2329
'bzrlib.tests.test_smart_transport',
1790
2330
'bzrlib.tests.test_source',
2331
'bzrlib.tests.test_ssh_transport',
1791
2332
'bzrlib.tests.test_status',
1792
2333
'bzrlib.tests.test_store',
2334
'bzrlib.tests.test_strace',
2335
'bzrlib.tests.test_subsume',
1793
2336
'bzrlib.tests.test_symbol_versioning',
2337
'bzrlib.tests.test_tag',
1794
2338
'bzrlib.tests.test_testament',
1795
2339
'bzrlib.tests.test_textfile',
1796
2340
'bzrlib.tests.test_textmerge',
2341
'bzrlib.tests.test_timestamp',
1797
2342
'bzrlib.tests.test_trace',
1798
2343
'bzrlib.tests.test_transactions',
1799
2344
'bzrlib.tests.test_transform',
1837
2383
for name, plugin in bzrlib.plugin.all_plugins().items():
1838
2384
if getattr(plugin, 'test_suite', None) is not None:
1839
suite.addTest(plugin.test_suite())
2385
default_encoding = sys.getdefaultencoding()
2387
plugin_suite = plugin.test_suite()
2388
except ImportError, e:
2389
bzrlib.trace.warning(
2390
'Unable to test plugin "%s": %s', name, e)
2392
suite.addTest(plugin_suite)
2393
if default_encoding != sys.getdefaultencoding():
2394
bzrlib.trace.warning(
2395
'Plugin "%s" tried to reset default encoding to: %s', name,
2396
sys.getdefaultencoding())
2398
sys.setdefaultencoding(default_encoding)
1863
2432
if os.path.isdir(i) and re_dir.match(i):
1865
2434
print 'delete directory:', i
2438
class Feature(object):
2439
"""An operating system Feature."""
2442
self._available = None
2444
def available(self):
2445
"""Is the feature available?
2447
:return: True if the feature is available.
2449
if self._available is None:
2450
self._available = self._probe()
2451
return self._available
2454
"""Implement this method in concrete features.
2456
:return: True if the feature is available.
2458
raise NotImplementedError
2461
if getattr(self, 'feature_name', None):
2462
return self.feature_name()
2463
return self.__class__.__name__