2610
2598
self.assertEqual('bzr: interrupted\n', result[1])
2613
class TestFeature(tests.TestCase):
2615
def test_caching(self):
2616
"""Feature._probe is called by the feature at most once."""
2617
class InstrumentedFeature(tests.Feature):
2619
super(InstrumentedFeature, self).__init__()
2622
self.calls.append('_probe')
2624
feature = InstrumentedFeature()
2626
self.assertEqual(['_probe'], feature.calls)
2628
self.assertEqual(['_probe'], feature.calls)
2630
def test_named_str(self):
2631
"""Feature.__str__ should thunk to feature_name()."""
2632
class NamedFeature(tests.Feature):
2633
def feature_name(self):
2635
feature = NamedFeature()
2636
self.assertEqual('symlinks', str(feature))
2638
def test_default_str(self):
2639
"""Feature.__str__ should default to __class__.__name__."""
2640
class NamedFeature(tests.Feature):
2642
feature = NamedFeature()
2643
self.assertEqual('NamedFeature', str(feature))
2646
class TestUnavailableFeature(tests.TestCase):
2648
def test_access_feature(self):
2649
feature = tests.Feature()
2650
exception = tests.UnavailableFeature(feature)
2651
self.assertIs(feature, exception.args[0])
2654
simple_thunk_feature = tests._CompatabilityThunkFeature(
2655
deprecated_in((2, 1, 0)),
2656
'bzrlib.tests.test_selftest',
2657
'simple_thunk_feature','UnicodeFilename',
2658
replacement_module='bzrlib.tests'
2661
class Test_CompatibilityFeature(tests.TestCase):
2663
def test_does_thunk(self):
2664
res = self.callDeprecated(
2665
['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
2666
' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
2667
simple_thunk_feature.available)
2668
self.assertEqual(tests.UnicodeFilename.available(), res)
2671
class TestModuleAvailableFeature(tests.TestCase):
2673
def test_available_module(self):
2674
feature = tests.ModuleAvailableFeature('bzrlib.tests')
2675
self.assertEqual('bzrlib.tests', feature.module_name)
2676
self.assertEqual('bzrlib.tests', str(feature))
2677
self.assertTrue(feature.available())
2678
self.assertIs(tests, feature.module)
2680
def test_unavailable_module(self):
2681
feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
2682
self.assertEqual('bzrlib.no_such_module_exists', str(feature))
2683
self.assertFalse(feature.available())
2684
self.assertIs(None, feature.module)
2687
2601
class TestSelftestFiltering(tests.TestCase):
2689
2603
def setUp(self):
3301
3214
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3217
class TestPostMortemDebugging(tests.TestCase):
3218
"""Check post mortem debugging works when tests fail or error"""
3220
class TracebackRecordingResult(tests.ExtendedTestResult):
3222
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3223
self.postcode = None
3224
def _post_mortem(self, tb=None):
3225
"""Record the code object at the end of the current traceback"""
3226
tb = tb or sys.exc_info()[2]
3229
while next is not None:
3232
self.postcode = tb.tb_frame.f_code
3233
def report_error(self, test, err):
3235
def report_failure(self, test, err):
3238
def test_location_unittest_error(self):
3239
"""Needs right post mortem traceback with erroring unittest case"""
3240
class Test(unittest.TestCase):
3243
result = self.TracebackRecordingResult()
3245
self.assertEqual(result.postcode, Test.runTest.func_code)
3247
def test_location_unittest_failure(self):
3248
"""Needs right post mortem traceback with failing unittest case"""
3249
class Test(unittest.TestCase):
3251
raise self.failureException
3252
result = self.TracebackRecordingResult()
3254
self.assertEqual(result.postcode, Test.runTest.func_code)
3256
def test_location_bt_error(self):
3257
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3258
class Test(tests.TestCase):
3259
def test_error(self):
3261
result = self.TracebackRecordingResult()
3262
Test("test_error").run(result)
3263
self.assertEqual(result.postcode, Test.test_error.func_code)
3265
def test_location_bt_failure(self):
3266
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3267
class Test(tests.TestCase):
3268
def test_failure(self):
3269
raise self.failureException
3270
result = self.TracebackRecordingResult()
3271
Test("test_failure").run(result)
3272
self.assertEqual(result.postcode, Test.test_failure.func_code)
3274
def test_env_var_triggers_post_mortem(self):
3275
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3277
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3278
post_mortem_calls = []
3279
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3280
self.overrideEnv('BZR_TEST_PDB', None)
3281
result._post_mortem(1)
3282
self.overrideEnv('BZR_TEST_PDB', 'on')
3283
result._post_mortem(2)
3284
self.assertEqual([2], post_mortem_calls)
3304
3287
class TestRunSuite(tests.TestCase):
3306
3289
def test_runner_class(self):
3317
3300
self.verbosity)
3318
3301
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3319
3302
self.assertLength(1, calls)
3305
class _Selftest(object):
3306
"""Mixin for tests needing full selftest output"""
3308
def _inject_stream_into_subunit(self, stream):
3309
"""To be overridden by subclasses that run tests out of process"""
3311
def _run_selftest(self, **kwargs):
3313
self._inject_stream_into_subunit(sio)
3314
tests.selftest(stream=sio, stop_on_failure=False, **kwargs)
3315
return sio.getvalue()
3318
class _ForkedSelftest(_Selftest):
3319
"""Mixin for tests needing full selftest output with forked children"""
3321
_test_needs_features = [features.subunit]
3323
def _inject_stream_into_subunit(self, stream):
3324
"""Monkey-patch subunit so the extra output goes to stream not stdout
3326
Some APIs need rewriting so this kind of bogus hackery can be replaced
3327
by passing the stream param from run_tests down into ProtocolTestCase.
3329
from subunit import ProtocolTestCase
3330
_original_init = ProtocolTestCase.__init__
3331
def _init_with_passthrough(self, *args, **kwargs):
3332
_original_init(self, *args, **kwargs)
3333
self._passthrough = stream
3334
self.overrideAttr(ProtocolTestCase, "__init__", _init_with_passthrough)
3336
def _run_selftest(self, **kwargs):
3337
# GZ 2011-05-26: Add a PosixSystem feature so this check can go away
3338
if getattr(os, "fork", None) is None:
3339
raise tests.TestNotApplicable("Platform doesn't support forking")
3340
# Make sure the fork code is actually invoked by claiming two cores
3341
self.overrideAttr(osutils, "local_concurrency", lambda: 2)
3342
kwargs.setdefault("suite_decorators", []).append(tests.fork_decorator)
3343
return super(_ForkedSelftest, self)._run_selftest(**kwargs)
3346
class TestParallelFork(_ForkedSelftest, tests.TestCase):
3347
"""Check operation of --parallel=fork selftest option"""
3349
def test_error_in_child_during_fork(self):
3350
"""Error in a forked child during test setup should get reported"""
3351
class Test(tests.TestCase):
3352
def testMethod(self):
3354
# We don't care what, just break something that a child will run
3355
self.overrideAttr(tests, "workaround_zealous_crypto_random", None)
3356
out = self._run_selftest(test_suite_factory=Test)
3357
# Lines from the tracebacks of the two child processes may be mixed
3358
# together due to the way subunit parses and forwards the streams,
3359
# so permit extra lines between each part of the error output.
3360
self.assertContainsRe(out,
3363
".+ in fork_for_tests\n"
3365
"\s*workaround_zealous_crypto_random\(\)\n"
3370
class TestUncollectedWarnings(_Selftest, tests.TestCase):
3371
"""Check a test case still alive after being run emits a warning"""
3373
class Test(tests.TestCase):
3374
def test_pass(self):
3376
def test_self_ref(self):
3377
self.also_self = self.test_self_ref
3378
def test_skip(self):
3379
self.skip("Don't need")
3381
def _get_suite(self):
3382
return TestUtil.TestSuite([
3383
self.Test("test_pass"),
3384
self.Test("test_self_ref"),
3385
self.Test("test_skip"),
3388
def _run_selftest_with_suite(self, **kwargs):
3389
old_flags = tests.selftest_debug_flags
3390
tests.selftest_debug_flags = old_flags.union(["uncollected_cases"])
3391
gc_on = gc.isenabled()
3395
output = self._run_selftest(test_suite_factory=self._get_suite,
3400
tests.selftest_debug_flags = old_flags
3401
self.assertNotContainsRe(output, "Uncollected test case.*test_pass")
3402
self.assertContainsRe(output, "Uncollected test case.*test_self_ref")
3405
def test_testsuite(self):
3406
self._run_selftest_with_suite()
3408
def test_pattern(self):
3409
out = self._run_selftest_with_suite(pattern="test_(?:pass|self_ref)$")
3410
self.assertNotContainsRe(out, "test_skip")
3412
def test_exclude_pattern(self):
3413
out = self._run_selftest_with_suite(exclude_pattern="test_skip$")
3414
self.assertNotContainsRe(out, "test_skip")
3416
def test_random_seed(self):
3417
self._run_selftest_with_suite(random_seed="now")
3419
def test_matching_tests_first(self):
3420
self._run_selftest_with_suite(matching_tests_first=True,
3421
pattern="test_self_ref$")
3423
def test_starting_with_and_exclude(self):
3424
out = self._run_selftest_with_suite(starting_with=["bt."],
3425
exclude_pattern="test_skip$")
3426
self.assertNotContainsRe(out, "test_skip")
3428
def test_additonal_decorator(self):
3429
out = self._run_selftest_with_suite(
3430
suite_decorators=[tests.TestDecorator])
3433
class TestUncollectedWarningsSubunit(TestUncollectedWarnings):
3434
"""Check warnings from tests staying alive are emitted with subunit"""
3436
_test_needs_features = [features.subunit]
3438
def _run_selftest_with_suite(self, **kwargs):
3439
return TestUncollectedWarnings._run_selftest_with_suite(self,
3440
runner_class=tests.SubUnitBzrRunner, **kwargs)
3443
class TestUncollectedWarningsForked(_ForkedSelftest, TestUncollectedWarnings):
3444
"""Check warnings from tests staying alive are emitted when forking"""
3447
class TestEnvironHandling(tests.TestCase):
3449
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3450
self.assertFalse('MYVAR' in os.environ)
3451
self.overrideEnv('MYVAR', '42')
3452
# We use an embedded test to make sure we fix the _captureVar bug
3453
class Test(tests.TestCase):
3455
# The first call save the 42 value
3456
self.overrideEnv('MYVAR', None)
3457
self.assertEquals(None, os.environ.get('MYVAR'))
3458
# Make sure we can call it twice
3459
self.overrideEnv('MYVAR', None)
3460
self.assertEquals(None, os.environ.get('MYVAR'))
3462
result = tests.TextTestResult(output, 0, 1)
3463
Test('test_me').run(result)
3464
if not result.wasStrictlySuccessful():
3465
self.fail(output.getvalue())
3466
# We get our value back
3467
self.assertEquals('42', os.environ.get('MYVAR'))
3470
class TestIsolatedEnv(tests.TestCase):
3471
"""Test isolating tests from os.environ.
3473
Since we use tests that are already isolated from os.environ a bit of care
3474
should be taken when designing the tests to avoid bootstrap side-effects.
3475
The tests start an already clean os.environ which allow doing valid
3476
assertions about which variables are present or not and design tests around
3480
class ScratchMonkey(tests.TestCase):
3485
def test_basics(self):
3486
# Make sure we know the definition of BZR_HOME: not part of os.environ
3487
# for tests.TestCase.
3488
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3489
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3490
# Being part of isolated_environ, BZR_HOME should not appear here
3491
self.assertFalse('BZR_HOME' in os.environ)
3492
# Make sure we know the definition of LINES: part of os.environ for
3494
self.assertTrue('LINES' in tests.isolated_environ)
3495
self.assertEquals('25', tests.isolated_environ['LINES'])
3496
self.assertEquals('25', os.environ['LINES'])
3498
def test_injecting_unknown_variable(self):
3499
# BZR_HOME is known to be absent from os.environ
3500
test = self.ScratchMonkey('test_me')
3501
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3502
self.assertEquals('foo', os.environ['BZR_HOME'])
3503
tests.restore_os_environ(test)
3504
self.assertFalse('BZR_HOME' in os.environ)
3506
def test_injecting_known_variable(self):
3507
test = self.ScratchMonkey('test_me')
3508
# LINES is known to be present in os.environ
3509
tests.override_os_environ(test, {'LINES': '42'})
3510
self.assertEquals('42', os.environ['LINES'])
3511
tests.restore_os_environ(test)
3512
self.assertEquals('25', os.environ['LINES'])
3514
def test_deleting_variable(self):
3515
test = self.ScratchMonkey('test_me')
3516
# LINES is known to be present in os.environ
3517
tests.override_os_environ(test, {'LINES': None})
3518
self.assertTrue('LINES' not in os.environ)
3519
tests.restore_os_environ(test)
3520
self.assertEquals('25', os.environ['LINES'])
3523
class TestDocTestSuiteIsolation(tests.TestCase):
3524
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3526
Since tests.TestCase alreay provides an isolation from os.environ, we use
3527
the clean environment as a base for testing. To precisely capture the
3528
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3531
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3532
not `os.environ` so each test overrides it to suit its needs.
3536
def get_doctest_suite_for_string(self, klass, string):
3537
class Finder(doctest.DocTestFinder):
3539
def find(*args, **kwargs):
3540
test = doctest.DocTestParser().get_doctest(
3541
string, {}, 'foo', 'foo.py', 0)
3544
suite = klass(test_finder=Finder())
3547
def run_doctest_suite_for_string(self, klass, string):
3548
suite = self.get_doctest_suite_for_string(klass, string)
3550
result = tests.TextTestResult(output, 0, 1)
3552
return result, output
3554
def assertDocTestStringSucceds(self, klass, string):
3555
result, output = self.run_doctest_suite_for_string(klass, string)
3556
if not result.wasStrictlySuccessful():
3557
self.fail(output.getvalue())
3559
def assertDocTestStringFails(self, klass, string):
3560
result, output = self.run_doctest_suite_for_string(klass, string)
3561
if result.wasStrictlySuccessful():
3562
self.fail(output.getvalue())
3564
def test_injected_variable(self):
3565
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3568
>>> os.environ['LINES']
3571
# doctest.DocTestSuite fails as it sees '25'
3572
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3573
# tests.DocTestSuite sees '42'
3574
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3576
def test_deleted_variable(self):
3577
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3580
>>> os.environ.get('LINES')
3582
# doctest.DocTestSuite fails as it sees '25'
3583
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3584
# tests.DocTestSuite sees None
3585
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3588
class TestSelftestExcludePatterns(tests.TestCase):
3591
super(TestSelftestExcludePatterns, self).setUp()
3592
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3594
def suite_factory(self, keep_only=None, starting_with=None):
3595
"""A test suite factory with only a few tests."""
3596
class Test(tests.TestCase):
3598
# We don't need the full class path
3599
return self._testMethodName
3606
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3608
def assertTestList(self, expected, *selftest_args):
3609
# We rely on setUp installing the right test suite factory so we can
3610
# test at the command level without loading the whole test suite
3611
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3612
actual = out.splitlines()
3613
self.assertEquals(expected, actual)
3615
def test_full_list(self):
3616
self.assertTestList(['a', 'b', 'c'])
3618
def test_single_exclude(self):
3619
self.assertTestList(['b', 'c'], '-x', 'a')
3621
def test_mutiple_excludes(self):
3622
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3625
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3627
_test_needs_features = [features.subunit]
3630
super(TestCounterHooks, self).setUp()
3631
class Test(tests.TestCase):
3634
super(Test, self).setUp()
3635
self.hooks = hooks.Hooks()
3636
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3637
self.install_counter_hook(self.hooks, 'myhook')
3642
def run_hook_once(self):
3643
for hook in self.hooks['myhook']:
3646
self.test_class = Test
3648
def assertHookCalls(self, expected_calls, test_name):
3649
test = self.test_class(test_name)
3650
result = unittest.TestResult()
3652
self.assertTrue(hasattr(test, '_counters'))
3653
self.assertTrue(test._counters.has_key('myhook'))
3654
self.assertEquals(expected_calls, test._counters['myhook'])
3656
def test_no_hook(self):
3657
self.assertHookCalls(0, 'no_hook')
3659
def test_run_hook_once(self):
3660
tt = features.testtools
3661
if tt.module.__version__ < (0, 9, 8):
3662
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3663
self.assertHookCalls(1, 'run_hook_once')