180
192
self._formatTime(self._benchmarkTime),
181
193
self._elapsedTestTimeString())
183
return " %s" % self._elapsedTestTimeString()
195
return " %s" % self._elapsedTestTimeString()
185
197
def _formatTime(self, seconds):
186
198
"""Format seconds as milliseconds with leading spaces."""
187
return "%5dms" % (1000 * seconds)
199
# some benchmarks can take thousands of seconds to run, so we need 8
201
return "%8dms" % (1000 * seconds)
189
def _ellipsise_unimportant_words(self, a_string, final_width,
191
"""Add ellipses (sp?) for overly long strings.
193
:param keep_start: If true preserve the start of a_string rather
197
if len(a_string) > final_width:
198
result = a_string[:final_width-3] + '...'
202
if len(a_string) > final_width:
203
result = '...' + a_string[3-final_width:]
206
return result.ljust(final_width)
203
def _shortened_test_description(self, test):
205
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
208
208
def startTest(self, test):
209
209
unittest.TestResult.startTest(self, test)
210
# In a short description, the important words are in
211
# the beginning, but in an id, the important words are
213
SHOW_DESCRIPTIONS = False
215
if not self.showAll and self.dots and self.pb is not None:
218
final_width = osutils.terminal_width()
219
final_width = final_width - 15 - 8
221
if SHOW_DESCRIPTIONS:
222
what = test.shortDescription()
224
what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
227
if what.startswith('bzrlib.tests.'):
229
what = self._ellipsise_unimportant_words(what, final_width)
231
self.stream.write(what)
232
elif self.dots and self.pb is not None:
233
self.pb.update(what, self.testsRun - 1, None)
210
self.report_test_start(test)
235
211
self._recordTestStartTime()
237
213
def _recordTestStartTime(self):
289
247
self._bench_history.write("%s %s\n" % (
290
248
self._formatTime(self._benchmarkTime),
293
self.stream.writeln(' OK %s' % self._testTimeString())
294
for bench_called, stats in getattr(test, '_benchcalls', []):
295
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
296
stats.pprint(file=self.stream)
297
elif self.dots and self.pb is None:
298
self.stream.write('~')
300
self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
250
self.report_success(test)
302
251
unittest.TestResult.addSuccess(self, test)
304
253
def addSkipped(self, test, skip_excinfo):
305
254
self.extractBenchmarkTime(test)
307
print >>self.stream, ' SKIP %s' % self._testTimeString()
308
print >>self.stream, ' %s' % skip_excinfo[1]
309
elif self.dots and self.pb is None:
310
self.stream.write('S')
312
self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
255
self.report_skip(test, skip_excinfo)
314
256
# seems best to treat this as success from point-of-view of unittest
315
257
# -- it actually does nothing so it barely matters :)
336
278
self.stream.writeln(self.separator2)
337
279
self.stream.writeln("%s" % err)
284
def report_cleaning_up(self):
287
def report_success(self, test):
291
class TextTestResult(ExtendedTestResult):
292
"""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()
297
self.pb.show_pct = False
298
self.pb.show_spinner = False
299
self.pb.show_eta = False,
300
self.pb.show_count = False
301
self.pb.show_bar = False
303
def report_starting(self):
304
self.pb.update('[test 0/%d] starting...' % (self.num_tests))
306
def _progress_prefix_text(self):
307
a = '[%d' % self.count
308
if self.num_tests is not None:
309
a +='/%d' % self.num_tests
310
a += ' in %ds' % (time.time() - self._overall_start_time)
312
a += ', %d errors' % self.error_count
313
if self.failure_count:
314
a += ', %d failed' % self.failure_count
316
a += ', %d skipped' % self.skip_count
320
def report_test_start(self, test):
323
self._progress_prefix_text()
325
+ self._shortened_test_description(test))
327
def report_error(self, test, err):
328
self.error_count += 1
329
self.pb.note('ERROR: %s\n %s\n',
330
self._shortened_test_description(test),
334
def report_failure(self, test, err):
335
self.failure_count += 1
336
self.pb.note('FAIL: %s\n %s\n',
337
self._shortened_test_description(test),
341
def report_skip(self, test, skip_excinfo):
344
# at the moment these are mostly not things we can fix
345
# and so they just produce stipple; use the verbose reporter
348
# show test and reason for skip
349
self.pb.note('SKIP: %s\n %s\n',
350
self._shortened_test_description(test),
353
# since the class name was left behind in the still-visible
355
self.pb.note('SKIP: %s', skip_excinfo[1])
357
def report_cleaning_up(self):
358
self.pb.update('cleaning up...')
364
class VerboseTestResult(ExtendedTestResult):
365
"""Produce long output, with one line per test run plus times"""
367
def _ellipsize_to_right(self, a_string, final_width):
368
"""Truncate and pad a string, keeping the right hand side"""
369
if len(a_string) > final_width:
370
result = '...' + a_string[3-final_width:]
373
return result.ljust(final_width)
375
def report_starting(self):
376
self.stream.write('running %d tests...\n' % self.num_tests)
378
def report_test_start(self, test):
380
name = self._shortened_test_description(test)
381
# width needs space for 6 char status, plus 1 for slash, plus 2 10-char
382
# numbers, plus a trailing blank
383
self.stream.write(self._ellipsize_to_right(name,
384
osutils.terminal_width()-30))
387
def report_error(self, test, err):
388
self.error_count += 1
389
self.stream.writeln('ERROR %s\n %s'
390
% (self._testTimeString(), err[1]))
392
def report_failure(self, test, err):
393
self.failure_count += 1
394
self.stream.writeln(' FAIL %s\n %s'
395
% (self._testTimeString(), err[1]))
397
def report_success(self, test):
398
self.stream.writeln(' OK %s' % self._testTimeString())
399
for bench_called, stats in getattr(test, '_benchcalls', []):
400
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
401
stats.pprint(file=self.stream)
404
def report_skip(self, test, skip_excinfo):
405
print >>self.stream, ' SKIP %s' % self._testTimeString()
406
print >>self.stream, ' %s' % skip_excinfo[1]
340
409
class TextTestRunner(object):
341
410
stop_on_failure = False
574
649
raise AssertionError("value(s) %r not present in container %r" %
575
650
(missing, superlist))
577
def assertIs(self, left, right):
652
def assertListRaises(self, excClass, func, *args, **kwargs):
653
"""Fail unless excClass is raised when the iterator from func is used.
655
Many functions can return generators this makes sure
656
to wrap them in a list() call to make sure the whole generator
657
is run, and that the proper exception is raised.
660
list(func(*args, **kwargs))
664
if getattr(excClass,'__name__', None) is not None:
665
excName = excClass.__name__
667
excName = str(excClass)
668
raise self.failureException, "%s not raised" % excName
670
def assertIs(self, left, right, message=None):
578
671
if not (left is right):
579
raise AssertionError("%r is not %r." % (left, right))
672
if message is not None:
673
raise AssertionError(message)
675
raise AssertionError("%r is not %r." % (left, right))
677
def assertIsNot(self, left, right, message=None):
679
if message is not None:
680
raise AssertionError(message)
682
raise AssertionError("%r is %r." % (left, right))
581
684
def assertTransportMode(self, transport, path, mode):
582
685
"""Fail if a path does not have mode mode.
1108
1253
BzrTestBase = TestCase
1256
class TestCaseWithMemoryTransport(TestCase):
1257
"""Common test class for tests that do not need disk resources.
1259
Tests that need disk resources should derive from TestCaseWithTransport.
1261
TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
1263
For TestCaseWithMemoryTransport the test_home_dir is set to the name of
1264
a directory which does not exist. This serves to help ensure test isolation
1265
is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
1266
must exist. However, TestCaseWithMemoryTransport does not offer local
1267
file defaults for the transport in tests, nor does it obey the command line
1268
override, so tests that accidentally write to the common directory should
1276
def __init__(self, methodName='runTest'):
1277
# allow test parameterisation after test construction and before test
1278
# execution. Variables that the parameteriser sets need to be
1279
# ones that are not set by setUp, or setUp will trash them.
1280
super(TestCaseWithMemoryTransport, self).__init__(methodName)
1281
self.transport_server = default_transport
1282
self.transport_readonly_server = None
1284
def get_transport(self):
1285
"""Return a writeable transport for the test scratch space"""
1286
t = get_transport(self.get_url())
1287
self.assertFalse(t.is_readonly())
1290
def get_readonly_transport(self):
1291
"""Return a readonly transport for the test scratch space
1293
This can be used to test that operations which should only need
1294
readonly access in fact do not try to write.
1296
t = get_transport(self.get_readonly_url())
1297
self.assertTrue(t.is_readonly())
1300
def create_transport_readonly_server(self):
1301
"""Create a transport server from class defined at init.
1303
This is mostly a hook for daughter classes.
1305
return self.transport_readonly_server()
1307
def get_readonly_server(self):
1308
"""Get the server instance for the readonly transport
1310
This is useful for some tests with specific servers to do diagnostics.
1312
if self.__readonly_server is None:
1313
if self.transport_readonly_server is None:
1314
# readonly decorator requested
1315
# bring up the server
1317
self.__readonly_server = ReadonlyServer()
1318
self.__readonly_server.setUp(self.__server)
1320
self.__readonly_server = self.create_transport_readonly_server()
1321
self.__readonly_server.setUp()
1322
self.addCleanup(self.__readonly_server.tearDown)
1323
return self.__readonly_server
1325
def get_readonly_url(self, relpath=None):
1326
"""Get a URL for the readonly transport.
1328
This will either be backed by '.' or a decorator to the transport
1329
used by self.get_url()
1330
relpath provides for clients to get a path relative to the base url.
1331
These should only be downwards relative, not upwards.
1333
base = self.get_readonly_server().get_url()
1334
if relpath is not None:
1335
if not base.endswith('/'):
1337
base = base + relpath
1340
def get_server(self):
1341
"""Get the read/write server instance.
1343
This is useful for some tests with specific servers that need
1346
For TestCaseWithMemoryTransport this is always a MemoryServer, and there
1347
is no means to override it.
1349
if self.__server is None:
1350
self.__server = MemoryServer()
1351
self.__server.setUp()
1352
self.addCleanup(self.__server.tearDown)
1353
return self.__server
1355
def get_url(self, relpath=None):
1356
"""Get a URL (or maybe a path) for the readwrite transport.
1358
This will either be backed by '.' or to an equivalent non-file based
1360
relpath provides for clients to get a path relative to the base url.
1361
These should only be downwards relative, not upwards.
1363
base = self.get_server().get_url()
1364
if relpath is not None and relpath != '.':
1365
if not base.endswith('/'):
1367
# XXX: Really base should be a url; we did after all call
1368
# get_url()! But sometimes it's just a path (from
1369
# LocalAbspathServer), and it'd be wrong to append urlescaped data
1370
# to a non-escaped local path.
1371
if base.startswith('./') or base.startswith('/'):
1374
base += urlutils.escape(relpath)
1377
def _make_test_root(self):
1378
if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1382
root = u'test%04d.tmp' % i
1386
if e.errno == errno.EEXIST:
1391
# successfully created
1392
TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
1394
# make a fake bzr directory there to prevent any tests propagating
1395
# up onto the source directory's real branch
1396
bzrdir.BzrDir.create_standalone_workingtree(
1397
TestCaseWithMemoryTransport.TEST_ROOT)
1399
def makeAndChdirToTestDir(self):
1400
"""Create a temporary directories for this one test.
1402
This must set self.test_home_dir and self.test_dir and chdir to
1405
For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1407
os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1408
self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1409
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1411
def make_branch(self, relpath, format=None):
1412
"""Create a branch on the transport at relpath."""
1413
repo = self.make_repository(relpath, format=format)
1414
return repo.bzrdir.create_branch()
1416
def make_bzrdir(self, relpath, format=None):
1418
# might be a relative or absolute path
1419
maybe_a_url = self.get_url(relpath)
1420
segments = maybe_a_url.rsplit('/', 1)
1421
t = get_transport(maybe_a_url)
1422
if len(segments) > 1 and segments[-1] not in ('', '.'):
1425
except errors.FileExists:
1427
if isinstance(format, basestring):
1428
format = bzrdir.format_registry.make_bzrdir(format)
1429
elif format is None:
1430
format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
1431
return format.initialize_on_transport(t)
1432
except errors.UninitializableFormat:
1433
raise TestSkipped("Format %s is not initializable." % format)
1435
def make_repository(self, relpath, shared=False, format=None):
1436
"""Create a repository on our default transport at relpath."""
1437
made_control = self.make_bzrdir(relpath, format=format)
1438
return made_control.create_repository(shared=shared)
1440
def make_branch_and_memory_tree(self, relpath, format=None):
1441
"""Create a branch on the default transport and a MemoryTree for it."""
1442
b = self.make_branch(relpath, format=format)
1443
return memorytree.MemoryTree.create_on_branch(b)
1445
def overrideEnvironmentForTesting(self):
1446
os.environ['HOME'] = self.test_home_dir
1447
os.environ['APPDATA'] = self.test_home_dir
1450
super(TestCaseWithMemoryTransport, self).setUp()
1451
self._make_test_root()
1452
_currentdir = os.getcwdu()
1453
def _leaveDirectory():
1454
os.chdir(_currentdir)
1455
self.addCleanup(_leaveDirectory)
1456
self.makeAndChdirToTestDir()
1457
self.overrideEnvironmentForTesting()
1458
self.__readonly_server = None
1459
self.__server = None
1111
class TestCaseInTempDir(TestCase):
1462
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1112
1463
"""Derived class that runs a test within a temporary directory.
1114
1465
This is useful for tests that need to create a branch, etc.
1217
1542
elif line_endings == 'native':
1218
1543
end = os.linesep
1220
raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
1545
raise errors.BzrError(
1546
'Invalid line ending request %r' % line_endings)
1221
1547
content = "contents of %s%s" % (name.encode('utf-8'), end)
1222
# Technically 'put()' is the right command. However, put
1223
# uses an AtomicFile, which requires an extra rename into place
1224
# As long as the files didn't exist in the past, append() will
1225
# do the same thing as put()
1226
# On jam's machine, make_kernel_like_tree is:
1227
# put: 4.5-7.5s (averaging 6s)
1229
# put_non_atomic: 2.9-4.5s
1230
1548
transport.put_bytes_non_atomic(urlutils.escape(name), content)
1232
1550
def build_tree_contents(self, shape):
1233
1551
build_tree_contents(shape)
1553
def assertFileEqual(self, content, path):
1554
"""Fail if path does not contain 'content'."""
1555
self.failUnlessExists(path)
1556
# TODO: jam 20060427 Shouldn't this be 'rb'?
1557
self.assertEqualDiff(content, open(path, 'r').read())
1235
1559
def failUnlessExists(self, path):
1236
1560
"""Fail unless path, which may be abs or relative, exists."""
1237
self.failUnless(osutils.lexists(path))
1561
self.failUnless(osutils.lexists(path),path+" does not exist")
1239
1563
def failIfExists(self, path):
1240
1564
"""Fail if path, which may be abs or relative, exists."""
1241
self.failIf(osutils.lexists(path))
1243
def assertFileEqual(self, content, path):
1244
"""Fail if path does not contain 'content'."""
1245
self.failUnless(osutils.lexists(path))
1246
# TODO: jam 20060427 Shouldn't this be 'rb'?
1247
self.assertEqualDiff(content, open(path, 'r').read())
1565
self.failIf(osutils.lexists(path),path+" exists")
1250
1568
class TestCaseWithTransport(TestCaseInTempDir):
1261
1579
readwrite one must both define get_url() as resolving to os.getcwd().
1264
def __init__(self, methodName='testMethod'):
1265
super(TestCaseWithTransport, self).__init__(methodName)
1266
self.__readonly_server = None
1267
self.__server = None
1268
self.transport_server = default_transport
1269
self.transport_readonly_server = None
1271
def get_readonly_url(self, relpath=None):
1272
"""Get a URL for the readonly transport.
1274
This will either be backed by '.' or a decorator to the transport
1275
used by self.get_url()
1276
relpath provides for clients to get a path relative to the base url.
1277
These should only be downwards relative, not upwards.
1279
base = self.get_readonly_server().get_url()
1280
if relpath is not None:
1281
if not base.endswith('/'):
1283
base = base + relpath
1286
def get_readonly_server(self):
1287
"""Get the server instance for the readonly transport
1289
This is useful for some tests with specific servers to do diagnostics.
1291
if self.__readonly_server is None:
1292
if self.transport_readonly_server is None:
1293
# readonly decorator requested
1294
# bring up the server
1296
self.__readonly_server = ReadonlyServer()
1297
self.__readonly_server.setUp(self.__server)
1299
self.__readonly_server = self.transport_readonly_server()
1300
self.__readonly_server.setUp()
1301
self.addCleanup(self.__readonly_server.tearDown)
1302
return self.__readonly_server
1582
def create_transport_server(self):
1583
"""Create a transport server from class defined at init.
1585
This is mostly a hook for daughter classes.
1587
return self.transport_server()
1304
1589
def get_server(self):
1305
"""Get the read/write server instance.
1590
"""See TestCaseWithMemoryTransport.
1307
1592
This is useful for some tests with specific servers that need
1310
1595
if self.__server is None:
1311
self.__server = self.transport_server()
1596
self.__server = self.create_transport_server()
1312
1597
self.__server.setUp()
1313
1598
self.addCleanup(self.__server.tearDown)
1314
1599
return self.__server
1316
def get_url(self, relpath=None):
1317
"""Get a URL (or maybe a path) for the readwrite transport.
1319
This will either be backed by '.' or to an equivalent non-file based
1321
relpath provides for clients to get a path relative to the base url.
1322
These should only be downwards relative, not upwards.
1324
base = self.get_server().get_url()
1325
if relpath is not None and relpath != '.':
1326
if not base.endswith('/'):
1328
# XXX: Really base should be a url; we did after all call
1329
# get_url()! But sometimes it's just a path (from
1330
# LocalAbspathServer), and it'd be wrong to append urlescaped data
1331
# to a non-escaped local path.
1332
if base.startswith('./') or base.startswith('/'):
1335
base += urlutils.escape(relpath)
1338
def get_transport(self):
1339
"""Return a writeable transport for the test scratch space"""
1340
t = get_transport(self.get_url())
1341
self.assertFalse(t.is_readonly())
1344
def get_readonly_transport(self):
1345
"""Return a readonly transport for the test scratch space
1347
This can be used to test that operations which should only need
1348
readonly access in fact do not try to write.
1350
t = get_transport(self.get_readonly_url())
1351
self.assertTrue(t.is_readonly())
1354
def make_branch(self, relpath, format=None):
1355
"""Create a branch on the transport at relpath."""
1356
repo = self.make_repository(relpath, format=format)
1357
return repo.bzrdir.create_branch()
1359
def make_bzrdir(self, relpath, format=None):
1361
# might be a relative or absolute path
1362
maybe_a_url = self.get_url(relpath)
1363
segments = maybe_a_url.rsplit('/', 1)
1364
t = get_transport(maybe_a_url)
1365
if len(segments) > 1 and segments[-1] not in ('', '.'):
1368
except errors.FileExists:
1371
format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
1372
return format.initialize_on_transport(t)
1373
except errors.UninitializableFormat:
1374
raise TestSkipped("Format %s is not initializable." % format)
1376
def make_repository(self, relpath, shared=False, format=None):
1377
"""Create a repository on our default transport at relpath."""
1378
made_control = self.make_bzrdir(relpath, format=format)
1379
return made_control.create_repository(shared=shared)
1381
def make_branch_and_memory_tree(self, relpath):
1382
"""Create a branch on the default transport and a MemoryTree for it."""
1383
b = self.make_branch(relpath)
1384
return memorytree.MemoryTree.create_on_branch(b)
1386
1601
def make_branch_and_tree(self, relpath, format=None):
1387
1602
"""Create a branch on the transport and a tree locally.
1680
def sort_suite_by_re(suite, pattern):
1683
filter_re = re.compile(pattern)
1684
for test in iter_suite_tests(suite):
1685
if filter_re.search(test.id()):
1689
return TestUtil.TestSuite(first + second)
1461
1692
def run_suite(suite, name='test', verbose=False, pattern=".*",
1462
1693
stop_on_failure=False, keep_output=False,
1463
transport=None, lsprof_timed=None, bench_history=None):
1464
TestCaseInTempDir._TEST_NAME = name
1694
transport=None, lsprof_timed=None, bench_history=None,
1695
matching_tests_first=None):
1465
1696
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1471
pb = progress.ProgressBar()
1472
1701
runner = TextTestRunner(stream=sys.stdout,
1473
1702
descriptions=0,
1474
1703
verbosity=verbosity,
1475
1704
keep_output=keep_output,
1477
1705
bench_history=bench_history)
1478
1706
runner.stop_on_failure=stop_on_failure
1479
1707
if pattern != '.*':
1480
suite = filter_suite_by_re(suite, pattern)
1708
if matching_tests_first:
1709
suite = sort_suite_by_re(suite, pattern)
1711
suite = filter_suite_by_re(suite, pattern)
1481
1712
result = runner.run(suite)
1482
1713
return result.wasSuccessful()
1529
1763
'bzrlib.tests.test_bundle',
1530
1764
'bzrlib.tests.test_bzrdir',
1531
1765
'bzrlib.tests.test_cache_utf8',
1532
'bzrlib.tests.test_command',
1766
'bzrlib.tests.test_commands',
1533
1767
'bzrlib.tests.test_commit',
1534
1768
'bzrlib.tests.test_commit_merge',
1535
1769
'bzrlib.tests.test_config',
1536
1770
'bzrlib.tests.test_conflicts',
1537
1771
'bzrlib.tests.test_decorators',
1772
'bzrlib.tests.test_delta',
1538
1773
'bzrlib.tests.test_diff',
1539
1774
'bzrlib.tests.test_doc_generate',
1540
1775
'bzrlib.tests.test_errors',
1541
1776
'bzrlib.tests.test_escaped_store',
1542
1777
'bzrlib.tests.test_fetch',
1543
1778
'bzrlib.tests.test_ftp_transport',
1779
'bzrlib.tests.test_generate_docs',
1780
'bzrlib.tests.test_generate_ids',
1781
'bzrlib.tests.test_globbing',
1544
1782
'bzrlib.tests.test_gpg',
1545
1783
'bzrlib.tests.test_graph',
1546
1784
'bzrlib.tests.test_hashcache',