270
205
if not re.search(needle_re, haystack):
271
206
raise AssertionError('pattern "%s" not found in "%s"'
272
207
% (needle_re, haystack))
274
def AssertSubset(self, sublist, superlist):
275
"""Assert that every entry in sublist is present in superlist."""
277
for entry in sublist:
278
if entry not in superlist:
279
missing.append(entry)
281
raise AssertionError("value(s) %r not present in container %r" %
282
(missing, superlist))
284
def _startLogFile(self):
285
"""Send bzr and test log messages to a temporary file.
287
The file is removed as the test is torn down.
209
def _enable_file_logging(self):
289
210
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
290
encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
291
self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
292
bzrlib.trace.enable_test_log(self._log_file)
212
self._log_file = os.fdopen(fileno, 'w+')
214
hdlr = logging.StreamHandler(self._log_file)
215
hdlr.setLevel(logging.DEBUG)
216
hdlr.setFormatter(logging.Formatter('%(levelname)8s %(message)s'))
217
logging.getLogger('').addHandler(hdlr)
218
logging.getLogger('').setLevel(logging.DEBUG)
219
self._log_hdlr = hdlr
220
debug('opened log file %s', name)
293
222
self._log_file_name = name
294
self.addCleanup(self._finishLogFile)
296
def _finishLogFile(self):
297
"""Finished with the log file.
299
Read contents into memory, close, and delete.
301
bzrlib.trace.disable_test_log()
302
self._log_file.seek(0)
303
self._log_contents = self._log_file.read()
225
os.environ['HOME'] = self.oldenv
226
if os.environ.get('BZREMAIL') is not None:
227
del os.environ['BZREMAIL']
228
if self.bzr_email is not None:
229
os.environ['BZREMAIL'] = self.bzr_email
230
if os.environ.get('EMAIL') is not None:
231
del os.environ['EMAIL']
232
if self.email is not None:
233
os.environ['EMAIL'] = self.email
234
logging.getLogger('').removeHandler(self._log_hdlr)
235
bzrlib.trace.enable_default_logging()
236
logging.debug('%s teardown', self.id())
304
237
self._log_file.close()
305
os.remove(self._log_file_name)
306
self._log_file = self._log_file_name = None
308
def addCleanup(self, callable):
309
"""Arrange to run a callable when this case is torn down.
311
Callables are run in the reverse of the order they are registered,
312
ie last-in first-out.
314
if callable in self._cleanups:
315
raise ValueError("cleanup function %r already registered on %s"
317
self._cleanups.append(callable)
319
def _cleanEnvironment(self):
322
'APPDATA': os.getcwd(),
327
self.addCleanup(self._restoreEnvironment)
328
for name, value in new_env.iteritems():
329
self._captureVar(name, value)
332
def _captureVar(self, name, newvalue):
333
"""Set an environment variable, preparing it to be reset when finished."""
334
self.__old_env[name] = os.environ.get(name, None)
336
if name in os.environ:
339
os.environ[name] = newvalue
342
def _restoreVar(name, value):
344
if name in os.environ:
347
os.environ[name] = value
349
def _restoreEnvironment(self):
350
for name, value in self.__old_env.iteritems():
351
self._restoreVar(name, value)
355
238
unittest.TestCase.tearDown(self)
357
def _runCleanups(self):
358
"""Run registered cleanup functions.
360
This should only be called from TestCase.tearDown.
362
for cleanup_fn in reversed(self._cleanups):
365
240
def log(self, *args):
368
243
def _get_log(self):
369
244
"""Return as a string the log for this test"""
370
245
if self._log_file_name:
371
246
return open(self._log_file_name).read()
373
return self._log_contents
374
# TODO: Delete the log after it's been read in
376
def capture(self, cmd, retcode=0):
250
def capture(self, cmd):
377
251
"""Shortcut that splits cmd into words, runs, and returns stdout"""
378
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
252
return self.run_bzr_captured(cmd.split())[0]
380
254
def run_bzr_captured(self, argv, retcode=0):
381
"""Invoke bzr and return (stdout, stderr).
255
"""Invoke bzr and return (result, stdout, stderr).
383
257
Useful for code that wants to check the contents of the
384
258
output, the way error messages are presented, etc.
538
411
os.mkdir(os.path.join(TestCaseInTempDir.TEST_ROOT, '.bzr'))
541
super(TestCaseInTempDir, self).setUp()
542
414
self._make_test_root()
543
_currentdir = os.getcwdu()
544
short_id = self.id().replace('bzrlib.tests.', '') \
415
self._currentdir = os.getcwdu()
416
short_id = self.id().replace('bzrlib.selftest.', '') \
545
417
.replace('__main__.', '')
546
418
self.test_dir = os.path.join(self.TEST_ROOT, short_id)
547
419
os.mkdir(self.test_dir)
548
420
os.chdir(self.test_dir)
549
os.environ['HOME'] = self.test_dir
550
def _leaveDirectory():
551
os.chdir(_currentdir)
552
self.addCleanup(_leaveDirectory)
421
super(TestCaseInTempDir, self).setUp()
554
def build_tree(self, shape, line_endings='native'):
424
os.chdir(self._currentdir)
425
super(TestCaseInTempDir, self).tearDown()
427
def build_tree(self, shape):
555
428
"""Build a test tree according to a pattern.
557
430
shape is a sequence of file specifications. If the final
558
431
character is '/', a directory is created.
560
433
This doesn't add anything to a branch.
561
:param line_endings: Either 'binary' or 'native'
562
in binary mode, exact contents are written
563
in native mode, the line endings match the
564
default platform endings.
566
435
# XXX: It's OK to just create them using forward slashes on windows?
567
436
for name in shape:
568
self.assert_(isinstance(name, basestring))
437
assert isinstance(name, basestring)
569
438
if name[-1] == '/':
570
439
os.mkdir(name[:-1])
572
if line_endings == 'binary':
574
elif line_endings == 'native':
577
raise BzrError('Invalid line ending request %r' % (line_endings,))
578
442
print >>f, "contents of", name
581
445
def build_tree_contents(self, shape):
582
build_tree_contents(shape)
446
bzrlib.selftest.build_tree_contents(shape)
584
448
def failUnlessExists(self, path):
585
449
"""Fail unless path, which may be abs or relative, exists."""
586
self.failUnless(bzrlib.osutils.lexists(path))
588
def assertFileEqual(self, content, path):
589
"""Fail if path does not contain 'content'."""
590
self.failUnless(bzrlib.osutils.lexists(path))
591
self.assertEqualDiff(content, open(path, 'r').read())
450
self.failUnless(osutils.lexists(path))
453
class MetaTestLog(TestCase):
454
def test_logging(self):
455
"""Test logs are captured when a test fails."""
456
logging.info('an info message')
457
warning('something looks dodgy...')
458
logging.debug('hello, test is running')
594
462
def filter_suite_by_re(suite, pattern):
463
result = TestUtil.TestSuite()
596
464
filter_re = re.compile(pattern)
597
465
for test in iter_suite_tests(suite):
598
466
if filter_re.search(test.id()):
625
493
return result.wasSuccessful()
628
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
496
def selftest(verbose=False, pattern=".*", stop_on_failure=True):
630
497
"""Run the whole test suite under the enhanced runner"""
631
498
return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern,
632
stop_on_failure=stop_on_failure, keep_output=keep_output)
499
stop_on_failure=stop_on_failure)
635
502
def test_suite():
636
503
"""Build and return TestSuite for the whole program."""
504
import bzrlib.store, bzrlib.inventory, bzrlib.branch
505
import bzrlib.osutils, bzrlib.merge3, bzrlib.plugin
637
506
from doctest import DocTestSuite
639
global MODULES_TO_DOCTEST
508
global MODULES_TO_TEST, MODULES_TO_DOCTEST
642
'bzrlib.tests.test_ancestry',
643
'bzrlib.tests.test_annotate',
644
'bzrlib.tests.test_api',
645
'bzrlib.tests.test_bad_files',
646
'bzrlib.tests.test_branch',
647
'bzrlib.tests.test_command',
648
'bzrlib.tests.test_commit',
649
'bzrlib.tests.test_commit_merge',
650
'bzrlib.tests.test_config',
651
'bzrlib.tests.test_conflicts',
652
'bzrlib.tests.test_diff',
653
'bzrlib.tests.test_fetch',
654
'bzrlib.tests.test_gpg',
655
'bzrlib.tests.test_graph',
656
'bzrlib.tests.test_hashcache',
657
'bzrlib.tests.test_http',
658
'bzrlib.tests.test_identitymap',
659
'bzrlib.tests.test_inv',
660
'bzrlib.tests.test_log',
661
'bzrlib.tests.test_merge',
662
'bzrlib.tests.test_merge3',
663
'bzrlib.tests.test_merge_core',
664
'bzrlib.tests.test_missing',
665
'bzrlib.tests.test_msgeditor',
666
'bzrlib.tests.test_nonascii',
667
'bzrlib.tests.test_options',
668
'bzrlib.tests.test_parent',
669
'bzrlib.tests.test_plugins',
670
'bzrlib.tests.test_remove',
671
'bzrlib.tests.test_revision',
672
'bzrlib.tests.test_revision_info',
673
'bzrlib.tests.test_revisionnamespaces',
674
'bzrlib.tests.test_revprops',
675
'bzrlib.tests.test_reweave',
676
'bzrlib.tests.test_rio',
677
'bzrlib.tests.test_sampler',
678
'bzrlib.tests.test_selftest',
679
'bzrlib.tests.test_setup',
680
'bzrlib.tests.test_sftp',
681
'bzrlib.tests.test_smart_add',
682
'bzrlib.tests.test_source',
683
'bzrlib.tests.test_status',
684
'bzrlib.tests.test_store',
685
'bzrlib.tests.test_testament',
686
'bzrlib.tests.test_trace',
687
'bzrlib.tests.test_transactions',
688
'bzrlib.tests.test_transport',
689
'bzrlib.tests.test_tsort',
690
'bzrlib.tests.test_ui',
691
'bzrlib.tests.test_uncommit',
692
'bzrlib.tests.test_upgrade',
693
'bzrlib.tests.test_weave',
694
'bzrlib.tests.test_whitebox',
695
'bzrlib.tests.test_workingtree',
696
'bzrlib.tests.test_xml',
511
['bzrlib.selftest.MetaTestLog',
512
'bzrlib.selftest.testgpg',
513
'bzrlib.selftest.testidentitymap',
514
'bzrlib.selftest.testinv',
515
'bzrlib.selftest.test_ancestry',
516
'bzrlib.selftest.test_commit',
517
'bzrlib.selftest.test_commit_merge',
518
'bzrlib.selftest.testconfig',
519
'bzrlib.selftest.versioning',
520
'bzrlib.selftest.testmerge3',
521
'bzrlib.selftest.testmerge',
522
'bzrlib.selftest.testhashcache',
523
'bzrlib.selftest.teststatus',
524
'bzrlib.selftest.testlog',
525
'bzrlib.selftest.testrevisionnamespaces',
526
'bzrlib.selftest.testbranch',
527
'bzrlib.selftest.testrevision',
528
'bzrlib.selftest.test_revision_info',
529
'bzrlib.selftest.test_merge_core',
530
'bzrlib.selftest.test_smart_add',
531
'bzrlib.selftest.test_bad_files',
532
'bzrlib.selftest.testdiff',
533
'bzrlib.selftest.test_parent',
534
'bzrlib.selftest.test_xml',
535
'bzrlib.selftest.test_weave',
536
'bzrlib.selftest.testfetch',
537
'bzrlib.selftest.whitebox',
538
'bzrlib.selftest.teststore',
539
'bzrlib.selftest.blackbox',
540
'bzrlib.selftest.testsampler',
541
'bzrlib.selftest.testtransactions',
542
'bzrlib.selftest.testtransport',
543
'bzrlib.selftest.testgraph',
544
'bzrlib.selftest.testworkingtree',
545
'bzrlib.selftest.test_upgrade',
546
'bzrlib.selftest.test_conflicts',
547
'bzrlib.selftest.testtestament',
548
'bzrlib.selftest.testannotate',
549
'bzrlib.selftest.testrevprops',
550
'bzrlib.selftest.testoptions',
699
print '%10s: %s' % ('bzr', os.path.realpath(sys.argv[0]))
700
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
553
for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,
554
bzrlib.osutils, bzrlib.commands, bzrlib.merge3):
555
if m not in MODULES_TO_DOCTEST:
556
MODULES_TO_DOCTEST.append(m)
558
TestCase.BZRPATH = os.path.join(os.path.realpath(os.path.dirname(bzrlib.__path__[0])), 'bzr')
559
print '%-30s %s' % ('bzr binary', TestCase.BZRPATH)
702
561
suite = TestSuite()
703
# python2.4's TestLoader.loadTestsFromNames gives very poor
704
# errors if it fails to load a named module - no indication of what's
705
# actually wrong, just "no such module". We should probably override that
706
# class, but for the moment just load them ourselves. (mbp 20051202)
707
loader = TestLoader()
708
for mod_name in testmod_names:
709
mod = _load_module_by_name(mod_name)
710
suite.addTest(loader.loadTestsFromModule(mod))
711
for package in packages_to_test():
712
suite.addTest(package.test_suite())
562
suite.addTest(TestLoader().loadTestsFromNames(testmod_names))
713
563
for m in MODULES_TO_TEST:
714
suite.addTest(loader.loadTestsFromModule(m))
564
suite.addTest(TestLoader().loadTestsFromModule(m))
715
565
for m in (MODULES_TO_DOCTEST):
716
566
suite.addTest(DocTestSuite(m))
717
for name, plugin in bzrlib.plugin.all_plugins().items():
718
if hasattr(plugin, 'test_suite'):
719
suite.addTest(plugin.test_suite())
567
for p in bzrlib.plugin.all_plugins:
568
if hasattr(p, 'test_suite'):
569
suite.addTest(p.test_suite())
723
def _load_module_by_name(mod_name):
724
parts = mod_name.split('.')
725
module = __import__(mod_name)
727
# for historical reasons python returns the top-level module even though
728
# it loads the submodule; we need to walk down to get the one we want.
730
module = getattr(module, parts.pop(0))