338
333
def test_scenarios(self):
339
334
# check that constructor parameters are passed through to the adapted
341
from .per_workingtree import make_scenarios
336
from bzrlib.tests.per_workingtree import make_scenarios
344
formats = [workingtree_4.WorkingTreeFormat4(),
345
workingtree_3.WorkingTreeFormat3(),
346
workingtree_4.WorkingTreeFormat6()]
347
scenarios = make_scenarios(server1, server2, formats,
348
remote_server='c', remote_readonly_server='d',
349
remote_backing_server='e')
339
formats = [workingtree.WorkingTreeFormat2(),
340
workingtree.WorkingTreeFormat3(),]
341
scenarios = make_scenarios(server1, server2, formats)
350
342
self.assertEqual([
351
('WorkingTreeFormat4',
352
{'bzrdir_format': formats[0]._matchingcontroldir,
343
('WorkingTreeFormat2',
344
{'bzrdir_format': formats[0]._matchingbzrdir,
353
345
'transport_readonly_server': 'b',
354
346
'transport_server': 'a',
355
347
'workingtree_format': formats[0]}),
356
348
('WorkingTreeFormat3',
357
{'bzrdir_format': formats[1]._matchingcontroldir,
358
'transport_readonly_server': 'b',
359
'transport_server': 'a',
360
'workingtree_format': formats[1]}),
361
('WorkingTreeFormat6',
362
{'bzrdir_format': formats[2]._matchingcontroldir,
363
'transport_readonly_server': 'b',
364
'transport_server': 'a',
365
'workingtree_format': formats[2]}),
366
('WorkingTreeFormat6,remote',
367
{'bzrdir_format': formats[2]._matchingcontroldir,
368
'repo_is_remote': True,
369
'transport_readonly_server': 'd',
370
'transport_server': 'c',
371
'vfs_transport_factory': 'e',
372
'workingtree_format': formats[2]}),
349
{'bzrdir_format': formats[1]._matchingbzrdir,
350
'transport_readonly_server': 'b',
351
'transport_server': 'a',
352
'workingtree_format': formats[1]})],
376
356
class TestTreeScenarios(tests.TestCase):
378
358
def test_scenarios(self):
379
359
# the tree implementation scenario generator is meant to setup one
380
# instance for each working tree format, one additional instance
360
# instance for each working tree format, and one additional instance
381
361
# that will use the default wt format, but create a revision tree for
382
# the tests, and one more that uses the default wt format as a
383
# lightweight checkout of a remote repository. This means that the wt
384
# ones should have the workingtree_to_test_tree attribute set to
385
# 'return_parameter' and the revision one set to
386
# revision_tree_from_workingtree.
362
# the tests. this means that the wt ones should have the
363
# workingtree_to_test_tree attribute set to 'return_parameter' and the
364
# revision one set to revision_tree_from_workingtree.
388
from .per_tree import (
366
from bzrlib.tests.per_tree import (
389
367
_dirstate_tree_from_workingtree,
391
369
preview_tree_pre,
398
smart_server = test_server.SmartTCPServer_for_testing
399
smart_readonly_server = test_server.ReadonlySmartTCPServer_for_testing
400
mem_server = memory.MemoryServer
401
formats = [workingtree_4.WorkingTreeFormat4(),
402
workingtree_3.WorkingTreeFormat3(), ]
376
formats = [workingtree.WorkingTreeFormat2(),
377
workingtree.WorkingTreeFormat3(),]
403
378
scenarios = make_scenarios(server1, server2, formats)
404
self.assertEqual(9, len(scenarios))
405
default_wt_format = workingtree.format_registry.get_default()
406
wt4_format = workingtree_4.WorkingTreeFormat4()
407
wt5_format = workingtree_4.WorkingTreeFormat5()
408
wt6_format = workingtree_4.WorkingTreeFormat6()
409
git_wt_format = git_workingtree.GitWorkingTreeFormat()
379
self.assertEqual(7, len(scenarios))
380
default_wt_format = workingtree.WorkingTreeFormat4._default_format
381
wt4_format = workingtree.WorkingTreeFormat4()
382
wt5_format = workingtree.WorkingTreeFormat5()
410
383
expected_scenarios = [
411
('WorkingTreeFormat4',
412
{'bzrdir_format': formats[0]._matchingcontroldir,
384
('WorkingTreeFormat2',
385
{'bzrdir_format': formats[0]._matchingbzrdir,
413
386
'transport_readonly_server': 'b',
414
387
'transport_server': 'a',
415
388
'workingtree_format': formats[0],
416
389
'_workingtree_to_test_tree': return_parameter,
418
391
('WorkingTreeFormat3',
419
{'bzrdir_format': formats[1]._matchingcontroldir,
392
{'bzrdir_format': formats[1]._matchingbzrdir,
420
393
'transport_readonly_server': 'b',
421
394
'transport_server': 'a',
422
395
'workingtree_format': formats[1],
423
396
'_workingtree_to_test_tree': return_parameter,
425
('WorkingTreeFormat6,remote',
426
{'bzrdir_format': wt6_format._matchingcontroldir,
427
'repo_is_remote': True,
428
'transport_readonly_server': smart_readonly_server,
429
'transport_server': smart_server,
430
'vfs_transport_factory': mem_server,
431
'workingtree_format': wt6_format,
432
'_workingtree_to_test_tree': return_parameter,
435
399
{'_workingtree_to_test_tree': revision_tree_from_workingtree,
436
'bzrdir_format': default_wt_format._matchingcontroldir,
400
'bzrdir_format': default_wt_format._matchingbzrdir,
437
401
'transport_readonly_server': 'b',
438
402
'transport_server': 'a',
439
403
'workingtree_format': default_wt_format,
442
{'_workingtree_to_test_tree': revision_tree_from_workingtree,
443
'bzrdir_format': git_wt_format._matchingcontroldir,
444
'transport_readonly_server': 'b',
445
'transport_server': 'a',
446
'workingtree_format': git_wt_format,
449
405
('DirStateRevisionTree,WT4',
450
406
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
451
'bzrdir_format': wt4_format._matchingcontroldir,
407
'bzrdir_format': wt4_format._matchingbzrdir,
452
408
'transport_readonly_server': 'b',
453
409
'transport_server': 'a',
454
410
'workingtree_format': wt4_format,
456
412
('DirStateRevisionTree,WT5',
457
413
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
458
'bzrdir_format': wt5_format._matchingcontroldir,
414
'bzrdir_format': wt5_format._matchingbzrdir,
459
415
'transport_readonly_server': 'b',
460
416
'transport_server': 'a',
461
417
'workingtree_format': wt5_format,
464
420
{'_workingtree_to_test_tree': preview_tree_pre,
465
'bzrdir_format': default_wt_format._matchingcontroldir,
421
'bzrdir_format': default_wt_format._matchingbzrdir,
466
422
'transport_readonly_server': 'b',
467
423
'transport_server': 'a',
468
424
'workingtree_format': default_wt_format}),
469
425
('PreviewTreePost',
470
426
{'_workingtree_to_test_tree': preview_tree_post,
471
'bzrdir_format': default_wt_format._matchingcontroldir,
427
'bzrdir_format': default_wt_format._matchingbzrdir,
472
428
'transport_readonly_server': 'b',
473
429
'transport_server': 'a',
474
430
'workingtree_format': default_wt_format}),
476
432
self.assertEqual(expected_scenarios, scenarios)
598
548
tree = self.make_branch_and_memory_tree('dir')
599
549
# Guard against regression into MemoryTransport leaking
600
550
# files to disk instead of keeping them in memory.
601
self.assertFalse(osutils.lexists('dir'))
551
self.failIf(osutils.lexists('dir'))
602
552
self.assertIsInstance(tree, memorytree.MemoryTree)
604
554
def test_make_branch_and_memory_tree_with_format(self):
605
555
"""make_branch_and_memory_tree should accept a format option."""
606
556
format = bzrdir.BzrDirMetaFormat1()
607
format.repository_format = repository.format_registry.get_default()
557
format.repository_format = weaverepo.RepositoryFormat7()
608
558
tree = self.make_branch_and_memory_tree('dir', format=format)
609
559
# Guard against regression into MemoryTransport leaking
610
560
# files to disk instead of keeping them in memory.
611
self.assertFalse(osutils.lexists('dir'))
561
self.failIf(osutils.lexists('dir'))
612
562
self.assertIsInstance(tree, memorytree.MemoryTree)
613
563
self.assertEqual(format.repository_format.__class__,
614
tree.branch.repository._format.__class__)
564
tree.branch.repository._format.__class__)
616
566
def test_make_branch_builder(self):
617
567
builder = self.make_branch_builder('dir')
618
568
self.assertIsInstance(builder, branchbuilder.BranchBuilder)
619
569
# Guard against regression into MemoryTransport leaking
620
570
# files to disk instead of keeping them in memory.
621
self.assertFalse(osutils.lexists('dir'))
571
self.failIf(osutils.lexists('dir'))
623
573
def test_make_branch_builder_with_format(self):
624
574
# Use a repo layout that doesn't conform to a 'named' layout, to ensure
625
575
# that the format objects are used.
626
576
format = bzrdir.BzrDirMetaFormat1()
627
repo_format = repository.format_registry.get_default()
577
repo_format = weaverepo.RepositoryFormat7()
628
578
format.repository_format = repo_format
629
579
builder = self.make_branch_builder('dir', format=format)
630
580
the_branch = builder.get_branch()
631
581
# Guard against regression into MemoryTransport leaking
632
582
# files to disk instead of keeping them in memory.
633
self.assertFalse(osutils.lexists('dir'))
583
self.failIf(osutils.lexists('dir'))
634
584
self.assertEqual(format.repository_format.__class__,
635
585
the_branch.repository._format.__class__)
636
586
self.assertEqual(repo_format.get_format_string(),
637
587
self.get_transport().get_bytes(
638
'dir/.bzr/repository/format'))
588
'dir/.bzr/repository/format'))
640
590
def test_make_branch_builder_with_format_name(self):
641
591
builder = self.make_branch_builder('dir', format='knit')
642
592
the_branch = builder.get_branch()
643
593
# Guard against regression into MemoryTransport leaking
644
594
# files to disk instead of keeping them in memory.
645
self.assertFalse(osutils.lexists('dir'))
646
dir_format = controldir.format_registry.make_controldir('knit')
595
self.failIf(osutils.lexists('dir'))
596
dir_format = bzrdir.format_registry.make_bzrdir('knit')
647
597
self.assertEqual(dir_format.repository_format.__class__,
648
598
the_branch.repository._format.__class__)
649
self.assertEqual(b'Bazaar-NG Knit Repository Format 1',
599
self.assertEqual('Bazaar-NG Knit Repository Format 1',
650
600
self.get_transport().get_bytes(
651
'dir/.bzr/repository/format'))
601
'dir/.bzr/repository/format'))
653
603
def test_dangling_locks_cause_failures(self):
654
604
class TestDanglingLock(tests.TestCaseWithMemoryTransport):
655
605
def test_function(self):
656
t = self.get_transport_from_path('.')
606
t = self.get_transport('.')
657
607
l = lockdir.LockDir(t, 'lock')
661
611
result = test.run()
662
612
total_failures = result.errors + result.failures
663
613
if self._lock_check_thorough:
664
self.assertEqual(1, len(total_failures))
614
self.assertLength(1, total_failures)
666
616
# When _lock_check_thorough is disabled, then we don't trigger a
668
self.assertEqual(0, len(total_failures))
618
self.assertLength(0, total_failures)
671
621
class TestTestCaseWithTransport(tests.TestCaseWithTransport):
672
622
"""Tests for the convenience functions TestCaseWithTransport introduces."""
674
624
def test_get_readonly_url_none(self):
675
from ..transport.readonly import ReadonlyTransportDecorator
625
from bzrlib.transport.readonly import ReadonlyTransportDecorator
676
626
self.vfs_transport_factory = memory.MemoryServer
677
627
self.transport_readonly_server = None
678
628
# calling get_readonly_transport() constructs a decorator on the url
680
630
url = self.get_readonly_url()
681
631
url2 = self.get_readonly_url('foo/bar')
682
t = transport.get_transport_from_url(url)
683
t2 = transport.get_transport_from_url(url2)
684
self.assertIsInstance(t, ReadonlyTransportDecorator)
685
self.assertIsInstance(t2, ReadonlyTransportDecorator)
632
t = transport.get_transport(url)
633
t2 = transport.get_transport(url2)
634
self.failUnless(isinstance(t, ReadonlyTransportDecorator))
635
self.failUnless(isinstance(t2, ReadonlyTransportDecorator))
686
636
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
688
638
def test_get_readonly_url_http(self):
689
from .http_server import HttpServer
690
from ..transport.http import HttpTransport
639
from bzrlib.tests.http_server import HttpServer
640
from bzrlib.transport.http import HttpTransportBase
691
641
self.transport_server = test_server.LocalURLServer
692
642
self.transport_readonly_server = HttpServer
693
643
# calling get_readonly_transport() gives us a HTTP server instance.
694
644
url = self.get_readonly_url()
695
645
url2 = self.get_readonly_url('foo/bar')
696
646
# the transport returned may be any HttpTransportBase subclass
697
t = transport.get_transport_from_url(url)
698
t2 = transport.get_transport_from_url(url2)
699
self.assertIsInstance(t, HttpTransport)
700
self.assertIsInstance(t2, HttpTransport)
647
t = transport.get_transport(url)
648
t2 = transport.get_transport(url2)
649
self.failUnless(isinstance(t, HttpTransportBase))
650
self.failUnless(isinstance(t2, HttpTransportBase))
701
651
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
703
653
def test_is_directory(self):
792
741
r"^ +[0-9]+ms\*$")
794
743
def test_unittest_reporting_unittest_class(self):
795
# getting the time from a non-breezy test works ok
744
# getting the time from a non-bzrlib test works ok
796
745
class ShortDelayTestCase(unittest.TestCase):
797
746
def test_short_delay(self):
798
747
time.sleep(0.003)
799
748
self.check_timing(ShortDelayTestCase('test_short_delay'),
751
def _patch_get_bzr_source_tree(self):
752
# Reading from the actual source tree breaks isolation, but we don't
753
# want to assume that thats *all* that would happen.
754
self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', lambda: None)
756
def test_assigned_benchmark_file_stores_date(self):
757
self._patch_get_bzr_source_tree()
759
result = bzrlib.tests.TextTestResult(self._log_file,
764
output_string = output.getvalue()
765
# if you are wondering about the regexp please read the comment in
766
# test_bench_history (bzrlib.tests.test_selftest.TestRunner)
767
# XXX: what comment? -- Andrew Bennetts
768
self.assertContainsRe(output_string, "--date [0-9.]+")
770
def test_benchhistory_records_test_times(self):
771
self._patch_get_bzr_source_tree()
772
result_stream = StringIO()
773
result = bzrlib.tests.TextTestResult(
777
bench_history=result_stream
780
# we want profile a call and check that its test duration is recorded
781
# make a new test instance that when run will generate a benchmark
782
example_test_case = TestTestResult("_time_hello_world_encoding")
783
# execute the test, which should succeed and record times
784
example_test_case.run(result)
785
lines = result_stream.getvalue().splitlines()
786
self.assertEqual(2, len(lines))
787
self.assertContainsRe(lines[1],
788
" *[0-9]+ms bzrlib.tests.test_selftest.TestTestResult"
789
"._time_hello_world_encoding")
802
791
def _time_hello_world_encoding(self):
803
792
"""Profile two sleep calls
805
794
This is used to exercise the test framework.
807
self.time(str, b'hello', errors='replace')
808
self.time(str, b'world', errors='replace')
796
self.time(unicode, 'hello', errors='replace')
797
self.time(unicode, 'world', errors='replace')
810
799
def test_lsprofiling(self):
811
800
"""Verbose test result prints lsprof statistics from test cases."""
812
self.requireFeature(features.lsprof_feature)
801
self.requireFeature(test_lsprof.LSProfFeature)
813
802
result_stream = StringIO()
814
result = breezy.tests.VerboseTestResult(
803
result = bzrlib.tests.VerboseTestResult(
804
unittest._WritelnDecorator(result_stream),
836
825
# this should appear in the output stream of our test result.
837
826
output = result_stream.getvalue()
838
827
self.assertContainsRe(output,
839
r"LSProf output for <class 'str'>\(\(b'hello',\), {'errors': 'replace'}\)")
840
self.assertContainsRe(output,
841
r"LSProf output for <class 'str'>\(\(b'world',\), {'errors': 'replace'}\)")
842
self.assertContainsRe(output,
843
r" *CallCount *Recursive *Total\(ms\) *Inline\(ms\) *module:lineno\(function\)\n")
844
self.assertContainsRe(output,
845
r"( +1 +0 +0\.\d+ +0\.\d+ +<method 'disable' of '_lsprof\.Profiler' objects>\n)?")
847
def test_uses_time_from_testtools(self):
848
"""Test case timings in verbose results should use testtools times"""
851
class TimeAddedVerboseTestResult(tests.VerboseTestResult):
852
def startTest(self, test):
853
self.time(datetime.datetime.utcfromtimestamp(1.145))
854
super(TimeAddedVerboseTestResult, self).startTest(test)
856
def addSuccess(self, test):
857
self.time(datetime.datetime.utcfromtimestamp(51.147))
858
super(TimeAddedVerboseTestResult, self).addSuccess(test)
860
def report_tests_starting(self): pass
862
self.get_passing_test().run(TimeAddedVerboseTestResult(sio, 0, 2))
863
self.assertEndsWith(sio.getvalue(), "OK 50002ms\n")
828
r"LSProf output for <type 'unicode'>\(\('hello',\), {'errors': 'replace'}\)")
829
self.assertContainsRe(output,
830
r" *CallCount *Recursive *Total\(ms\) *Inline\(ms\) *module:lineno\(function\)\n")
831
self.assertContainsRe(output,
832
r"( +1 +0 +0\.\d+ +0\.\d+ +<method 'disable' of '_lsprof\.Profiler' objects>\n)?")
833
self.assertContainsRe(output,
834
r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
865
836
def test_known_failure(self):
866
"""Using knownFailure should trigger several result actions."""
837
"""A KnownFailure being raised should trigger several result actions."""
867
838
class InstrumentedTestResult(tests.ExtendedTestResult):
868
839
def stopTestRun(self): pass
870
def report_tests_starting(self): pass
840
def startTests(self): pass
841
def report_test_start(self, test): pass
872
842
def report_known_failure(self, test, err=None, details=None):
873
843
self._call = test, 'known failure'
874
844
result = InstrumentedTestResult(None, None, None, None)
876
845
class Test(tests.TestCase):
877
846
def test_function(self):
878
self.knownFailure('failed!')
847
raise tests.KnownFailure('failed!')
879
848
test = Test("test_function")
881
850
# it should invoke 'report_known_failure'.
1249
def test_verbose_test_count(self):
1250
"""A verbose test run reports the right test count at the start"""
1251
suite = TestUtil.TestSuite([
1252
unittest.FunctionTestCase(lambda:None),
1253
unittest.FunctionTestCase(lambda:None)])
1254
self.assertEqual(suite.countTestCases(), 2)
1256
runner = tests.TextTestRunner(stream=stream, verbosity=2)
1257
# Need to use the CountingDecorator as that's what sets num_tests
1258
self.run_test_runner(runner, tests.CountingDecorator(suite))
1259
self.assertStartsWith(stream.getvalue(), "running 2 tests")
1191
def _patch_get_bzr_source_tree(self):
1192
# Reading from the actual source tree breaks isolation, but we don't
1193
# want to assume that thats *all* that would happen.
1194
self._get_source_tree_calls = []
1196
self._get_source_tree_calls.append("called")
1198
self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', new_get)
1200
def test_bench_history(self):
1201
# tests that the running the benchmark passes bench_history into
1202
# the test result object. We can tell that happens if
1203
# _get_bzr_source_tree is called.
1204
self._patch_get_bzr_source_tree()
1205
test = TestRunner('dummy_test')
1207
runner = tests.TextTestRunner(stream=self._log_file,
1208
bench_history=output)
1209
result = self.run_test_runner(runner, test)
1210
output_string = output.getvalue()
1211
self.assertContainsRe(output_string, "--date [0-9.]+")
1212
self.assertLength(1, self._get_source_tree_calls)
1261
1214
def test_startTestRun(self):
1262
1215
"""run should call result.startTestRun()"""
1265
class LoggingDecorator(ExtendedToOriginalDecorator):
1217
class LoggingDecorator(tests.ForwardingResult):
1266
1218
def startTestRun(self):
1267
ExtendedToOriginalDecorator.startTestRun(self)
1219
tests.ForwardingResult.startTestRun(self)
1268
1220
calls.append('startTestRun')
1269
test = unittest.FunctionTestCase(lambda: None)
1221
test = unittest.FunctionTestCase(lambda:None)
1270
1222
stream = StringIO()
1271
1223
runner = tests.TextTestRunner(stream=stream,
1272
result_decorators=[LoggingDecorator])
1273
self.run_test_runner(runner, test)
1224
result_decorators=[LoggingDecorator])
1225
result = self.run_test_runner(runner, test)
1274
1226
self.assertLength(1, calls)
1276
1228
def test_stopTestRun(self):
1277
1229
"""run should call result.stopTestRun()"""
1280
class LoggingDecorator(ExtendedToOriginalDecorator):
1231
class LoggingDecorator(tests.ForwardingResult):
1281
1232
def stopTestRun(self):
1282
ExtendedToOriginalDecorator.stopTestRun(self)
1233
tests.ForwardingResult.stopTestRun(self)
1283
1234
calls.append('stopTestRun')
1284
test = unittest.FunctionTestCase(lambda: None)
1235
test = unittest.FunctionTestCase(lambda:None)
1285
1236
stream = StringIO()
1286
1237
runner = tests.TextTestRunner(stream=stream,
1287
result_decorators=[LoggingDecorator])
1288
self.run_test_runner(runner, test)
1238
result_decorators=[LoggingDecorator])
1239
result = self.run_test_runner(runner, test)
1289
1240
self.assertLength(1, calls)
1291
def test_unicode_test_output_on_ascii_stream(self):
1292
"""Showing results should always succeed even on an ascii console"""
1293
class FailureWithUnicode(tests.TestCase):
1294
def test_log_unicode(self):
1296
self.fail("Now print that log!")
1298
out = TextIOWrapper(bio, 'ascii', 'backslashreplace')
1299
self.overrideAttr(osutils, "get_terminal_encoding",
1300
lambda trace=False: "ascii")
1301
self.run_test_runner(
1302
tests.TextTestRunner(stream=out),
1303
FailureWithUnicode("test_log_unicode"))
1305
self.assertContainsRe(bio.getvalue(),
1306
b"(?:Text attachment: )?log"
1308
b"\\d+\\.\\d+ \\\\u2606"
1309
b"(?:\n-+\n|}}}\n)")
1312
1243
class SampleTestCase(tests.TestCase):
1314
1245
def _test_pass(self):
1318
1248
class _TestException(Exception):
1322
1252
class TestTestCase(tests.TestCase):
1323
"""Tests that test the core breezy TestCase."""
1253
"""Tests that test the core bzrlib TestCase."""
1325
1255
def test_assertLength_matches_empty(self):
1726
1631
obj.test_attr = 'modified'
1727
1632
self.assertEqual('modified', obj.test_attr)
1729
self._run_successful_test(Test('test_value'))
1634
test = Test('test_value')
1635
test.run(unittest.TestResult())
1730
1636
self.assertEqual('original', obj.test_attr)
1732
1638
def test_overrideAttr_with_value(self):
1733
self.test_attr = 'original' # Define a test attribute
1734
obj = self # Make 'obj' visible to the embedded test
1639
self.test_attr = 'original' # Define a test attribute
1640
obj = self # Make 'obj' visible to the embedded test
1736
1641
class Test(tests.TestCase):
1738
1643
def setUp(self):
1739
super(Test, self).setUp()
1644
tests.TestCase.setUp(self)
1740
1645
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1742
1647
def test_value(self):
1743
1648
self.assertEqual('original', self.orig)
1744
1649
self.assertEqual('modified', obj.test_attr)
1746
self._run_successful_test(Test('test_value'))
1651
test = Test('test_value')
1652
test.run(unittest.TestResult())
1747
1653
self.assertEqual('original', obj.test_attr)
1749
def test_overrideAttr_with_no_existing_value_and_value(self):
1750
# Do not define the test_attribute
1751
obj = self # Make 'obj' visible to the embedded test
1753
class Test(tests.TestCase):
1756
tests.TestCase.setUp(self)
1757
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1759
def test_value(self):
1760
self.assertEqual(tests._unitialized_attr, self.orig)
1761
self.assertEqual('modified', obj.test_attr)
1763
self._run_successful_test(Test('test_value'))
1764
self.assertRaises(AttributeError, getattr, obj, 'test_attr')
1766
def test_overrideAttr_with_no_existing_value_and_no_value(self):
1767
# Do not define the test_attribute
1768
obj = self # Make 'obj' visible to the embedded test
1770
class Test(tests.TestCase):
1773
tests.TestCase.setUp(self)
1774
self.orig = self.overrideAttr(obj, 'test_attr')
1776
def test_value(self):
1777
self.assertEqual(tests._unitialized_attr, self.orig)
1778
self.assertRaises(AttributeError, getattr, obj, 'test_attr')
1780
self._run_successful_test(Test('test_value'))
1781
self.assertRaises(AttributeError, getattr, obj, 'test_attr')
1783
def test_recordCalls(self):
1784
from breezy.tests import test_selftest
1785
calls = self.recordCalls(
1786
test_selftest, '_add_numbers')
1787
self.assertEqual(test_selftest._add_numbers(2, 10),
1789
self.assertEqual(calls, [((2, 10), {})])
1792
def _add_numbers(a, b):
1796
class _MissingFeature(features.Feature):
1801
missing_feature = _MissingFeature()
1804
def _get_test(name):
1805
"""Get an instance of a specific example test.
1807
We protect this in a function so that they don't auto-run in the test
1811
class ExampleTests(tests.TestCase):
1813
def test_fail(self):
1814
mutter('this was a failing test')
1815
self.fail('this test will fail')
1817
def test_error(self):
1818
mutter('this test errored')
1819
raise RuntimeError('gotcha')
1821
def test_missing_feature(self):
1822
mutter('missing the feature')
1823
self.requireFeature(missing_feature)
1825
def test_skip(self):
1826
mutter('this test will be skipped')
1827
raise tests.TestSkipped('reason')
1829
def test_success(self):
1830
mutter('this test succeeds')
1832
def test_xfail(self):
1833
mutter('test with expected failure')
1834
self.knownFailure('this_fails')
1836
def test_unexpected_success(self):
1837
mutter('test with unexpected success')
1838
self.expectFailure('should_fail', lambda: None)
1840
return ExampleTests(name)
1843
class TestTestCaseLogDetails(tests.TestCase):
1845
def _run_test(self, test_name):
1846
test = _get_test(test_name)
1847
result = testtools.TestResult()
1851
def test_fail_has_log(self):
1852
result = self._run_test('test_fail')
1853
self.assertEqual(1, len(result.failures))
1854
result_content = result.failures[0][1]
1855
self.assertContainsRe(result_content,
1856
'(?m)^(?:Text attachment: )?log(?:$|: )')
1857
self.assertContainsRe(result_content, 'this was a failing test')
1859
def test_error_has_log(self):
1860
result = self._run_test('test_error')
1861
self.assertEqual(1, len(result.errors))
1862
result_content = result.errors[0][1]
1863
self.assertContainsRe(result_content,
1864
'(?m)^(?:Text attachment: )?log(?:$|: )')
1865
self.assertContainsRe(result_content, 'this test errored')
1867
def test_skip_has_no_log(self):
1868
result = self._run_test('test_skip')
1869
reasons = result.skip_reasons
1870
self.assertEqual({'reason'}, set(reasons))
1871
skips = reasons['reason']
1872
self.assertEqual(1, len(skips))
1874
self.assertFalse('log' in test.getDetails())
1876
def test_missing_feature_has_no_log(self):
1877
# testtools doesn't know about addNotSupported, so it just gets
1878
# considered as a skip
1879
result = self._run_test('test_missing_feature')
1880
reasons = result.skip_reasons
1881
self.assertEqual({str(missing_feature)}, set(reasons))
1882
skips = reasons[str(missing_feature)]
1883
self.assertEqual(1, len(skips))
1885
self.assertFalse('log' in test.getDetails())
1887
def test_xfail_has_no_log(self):
1888
result = self._run_test('test_xfail')
1889
self.assertEqual(1, len(result.expectedFailures))
1890
result_content = result.expectedFailures[0][1]
1891
self.assertNotContainsRe(result_content,
1892
'(?m)^(?:Text attachment: )?log(?:$|: )')
1893
self.assertNotContainsRe(result_content, 'test with expected failure')
1895
def test_unexpected_success_has_log(self):
1896
result = self._run_test('test_unexpected_success')
1897
self.assertEqual(1, len(result.unexpectedSuccesses))
1898
# Inconsistency, unexpectedSuccesses is a list of tests,
1899
# expectedFailures is a list of reasons?
1900
test = result.unexpectedSuccesses[0]
1901
details = test.getDetails()
1902
self.assertTrue('log' in details)
1905
class TestTestCloning(tests.TestCase):
1906
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1908
def test_cloned_testcase_does_not_share_details(self):
1909
"""A TestCase cloned with clone_test does not share mutable attributes
1910
such as details or cleanups.
1912
class Test(tests.TestCase):
1914
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1915
orig_test = Test('test_foo')
1916
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1917
orig_test.run(unittest.TestResult())
1918
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1919
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1921
def test_double_apply_scenario_preserves_first_scenario(self):
1922
"""Applying two levels of scenarios to a test preserves the attributes
1923
added by both scenarios.
1925
class Test(tests.TestCase):
1928
test = Test('test_foo')
1929
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1930
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1931
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1932
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1933
all_tests = list(tests.iter_suite_tests(suite))
1934
self.assertLength(4, all_tests)
1935
all_xys = sorted((t.x, t.y) for t in all_tests)
1936
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1939
1656
# NB: Don't delete this; it's not actually from 0.11!
1940
1657
@deprecated_function(deprecated_in((0, 11, 0)))
2008
1719
sample_object = ApplyDeprecatedHelper()
2009
1720
# calling an undeprecated callable raises an assertion
2010
1721
self.assertRaises(AssertionError, self.applyDeprecated,
2011
deprecated_in((0, 11, 0)),
2012
sample_object.sample_normal_method)
1722
deprecated_in((0, 11, 0)),
1723
sample_object.sample_normal_method)
2013
1724
self.assertRaises(AssertionError, self.applyDeprecated,
2014
deprecated_in((0, 11, 0)),
2015
sample_undeprecated_function, "a param value")
1725
deprecated_in((0, 11, 0)),
1726
sample_undeprecated_function, "a param value")
2016
1727
# calling a deprecated callable (function or method) with the wrong
2017
1728
# expected deprecation fails.
2018
1729
self.assertRaises(AssertionError, self.applyDeprecated,
2019
deprecated_in((0, 10, 0)),
2020
sample_object.sample_deprecated_method,
1730
deprecated_in((0, 10, 0)),
1731
sample_object.sample_deprecated_method, "a param value")
2022
1732
self.assertRaises(AssertionError, self.applyDeprecated,
2023
deprecated_in((0, 10, 0)),
2024
sample_deprecated_function)
1733
deprecated_in((0, 10, 0)),
1734
sample_deprecated_function)
2025
1735
# calling a deprecated callable (function or method) with the right
2026
1736
# expected deprecation returns the functions result.
2029
self.applyDeprecated(
2030
deprecated_in((0, 11, 0)),
2031
sample_object.sample_deprecated_method, "a param value"))
1737
self.assertEqual("a param value",
1738
self.applyDeprecated(deprecated_in((0, 11, 0)),
1739
sample_object.sample_deprecated_method, "a param value"))
2032
1740
self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 11, 0)),
2033
sample_deprecated_function))
1741
sample_deprecated_function))
2034
1742
# calling a nested deprecation with the wrong deprecation version
2035
1743
# fails even if a deeper nested function was deprecated with the
2036
1744
# supplied version.
2038
AssertionError, self.applyDeprecated,
1745
self.assertRaises(AssertionError, self.applyDeprecated,
2039
1746
deprecated_in((0, 11, 0)), sample_object.sample_nested_deprecation)
2040
1747
# calling a nested deprecation with the right deprecation value
2041
1748
# returns the calls result.
2043
2, self.applyDeprecated(
2044
deprecated_in((0, 10, 0)),
2045
sample_object.sample_nested_deprecation))
1749
self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 10, 0)),
1750
sample_object.sample_nested_deprecation))
2047
1752
def test_callDeprecated(self):
2048
1753
def testfunc(be_deprecated, result=None):
2097
1804
self.transport_server = test_server.FakeVFATServer
2098
1805
self.assertFalse(self.get_url('t1').startswith('file://'))
2099
1806
tree = self.make_branch_and_tree('t1')
2100
base = tree.controldir.root_transport.base
1807
base = tree.bzrdir.root_transport.base
2101
1808
self.assertStartsWith(base, 'file://')
2102
self.assertEqual(tree.controldir.root_transport,
2103
tree.branch.controldir.root_transport)
2104
self.assertEqual(tree.controldir.root_transport,
2105
tree.branch.repository.controldir.root_transport)
2108
class SelfTestHelper(object):
1809
self.assertEquals(tree.bzrdir.root_transport,
1810
tree.branch.bzrdir.root_transport)
1811
self.assertEquals(tree.bzrdir.root_transport,
1812
tree.branch.repository.bzrdir.root_transport)
1815
class SelfTestHelper:
2110
1817
def run_selftest(self, **kwargs):
2111
1818
"""Run selftest returning its output."""
2113
output = TextIOWrapper(bio, 'utf-8')
2114
old_transport = breezy.tests.default_transport
1820
old_transport = bzrlib.tests.default_transport
2115
1821
old_root = tests.TestCaseWithMemoryTransport.TEST_ROOT
2116
1822
tests.TestCaseWithMemoryTransport.TEST_ROOT = None
2118
1824
self.assertEqual(True, tests.selftest(stream=output, **kwargs))
2120
breezy.tests.default_transport = old_transport
1826
bzrlib.tests.default_transport = old_transport
2121
1827
tests.TestCaseWithMemoryTransport.TEST_ROOT = old_root
2128
1832
class TestSelftest(tests.TestCase, SelfTestHelper):
2129
"""Tests of breezy.tests.selftest."""
1833
"""Tests of bzrlib.tests.selftest."""
2131
def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(
1835
def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(self):
2133
1836
factory_called = []
2136
1838
factory_called.append(True)
2137
1839
return TestUtil.TestSuite()
2138
1840
out = StringIO()
2139
1841
err = StringIO()
2140
self.apply_redirected(out, err, None, breezy.tests.selftest,
2141
test_suite_factory=factory)
1842
self.apply_redirected(out, err, None, bzrlib.tests.selftest,
1843
test_suite_factory=factory)
2142
1844
self.assertEqual([True], factory_called)
2144
1846
def factory(self):
2145
1847
"""A test suite factory."""
2146
1848
class Test(tests.TestCase):
2148
return __name__ + ".Test." + self._testMethodName
2158
1855
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
2160
1857
def test_list_only(self):
2161
1858
output = self.run_selftest(test_suite_factory=self.factory,
2163
1860
self.assertEqual(3, len(output.readlines()))
2165
1862
def test_list_only_filtered(self):
2166
1863
output = self.run_selftest(test_suite_factory=self.factory,
2167
list_only=True, pattern="Test.b")
2168
self.assertEndsWith(output.getvalue(), b"Test.b\n")
1864
list_only=True, pattern="Test.b")
1865
self.assertEndsWith(output.getvalue(), "Test.b\n")
2169
1866
self.assertLength(1, output.readlines())
2171
1868
def test_list_only_excludes(self):
2172
1869
output = self.run_selftest(test_suite_factory=self.factory,
2173
list_only=True, exclude_pattern="Test.b")
2174
self.assertNotContainsRe(b"Test.b", output.getvalue())
1870
list_only=True, exclude_pattern="Test.b")
1871
self.assertNotContainsRe("Test.b", output.getvalue())
2175
1872
self.assertLength(2, output.readlines())
2177
1874
def test_lsprof_tests(self):
2178
self.requireFeature(features.lsprof_feature)
1875
self.requireFeature(test_lsprof.LSProfFeature)
2181
1877
class Test(object):
2182
1878
def __call__(test, result):
2183
1879
test.run(result)
2185
1880
def run(test, result):
2186
results.append(result)
1881
self.assertIsInstance(result, tests.ForwardingResult)
1882
calls.append("called")
2188
1883
def countTestCases(self):
2190
1885
self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
2191
self.assertLength(1, results)
2192
self.assertIsInstance(results.pop(), ExtendedToOriginalDecorator)
1886
self.assertLength(1, calls)
2194
1888
def test_random(self):
2195
1889
# test randomising by listing a number of tests.
2196
1890
output_123 = self.run_selftest(test_suite_factory=self.factory,
2197
list_only=True, random_seed="123")
1891
list_only=True, random_seed="123")
2198
1892
output_234 = self.run_selftest(test_suite_factory=self.factory,
2199
list_only=True, random_seed="234")
1893
list_only=True, random_seed="234")
2200
1894
self.assertNotEqual(output_123, output_234)
2201
1895
# "Randominzing test order..\n\n
2202
1896
self.assertLength(5, output_123.readlines())
2278
1965
def test_load_unknown(self):
2279
1966
# Provide a list with one test - this test.
2280
1967
# And generate a list of the tests in the suite.
2281
self.assertRaises(errors.NoSuchFile, self.run_selftest,
2282
load_list='missing file name', list_only=True)
2285
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2287
_test_needs_features = [features.subunit]
2289
def run_subunit_stream(self, test_name):
2290
from subunit import ProtocolTestCase
2293
return TestUtil.TestSuite([_get_test(test_name)])
2294
stream = self.run_selftest(
2295
runner_class=tests.SubUnitBzrRunnerv1,
2296
test_suite_factory=factory)
2297
test = ProtocolTestCase(stream)
2298
result = testtools.TestResult()
2300
content = stream.getvalue()
2301
return content, result
2303
def test_fail_has_log(self):
2304
content, result = self.run_subunit_stream('test_fail')
2305
self.assertEqual(1, len(result.failures))
2306
self.assertContainsRe(content, b'(?m)^log$')
2307
self.assertContainsRe(content, b'this test will fail')
2309
def test_error_has_log(self):
2310
content, result = self.run_subunit_stream('test_error')
2311
self.assertContainsRe(content, b'(?m)^log$')
2312
self.assertContainsRe(content, b'this test errored')
2314
def test_skip_has_no_log(self):
2315
content, result = self.run_subunit_stream('test_skip')
2316
self.assertNotContainsRe(content, b'(?m)^log$')
2317
self.assertNotContainsRe(content, b'this test will be skipped')
2318
reasons = result.skip_reasons
2319
self.assertEqual({'reason'}, set(reasons))
2320
skips = reasons['reason']
2321
self.assertEqual(1, len(skips))
2323
# RemotedTestCase doesn't preserve the "details"
2324
# self.assertFalse('log' in test.getDetails())
2326
def test_missing_feature_has_no_log(self):
2327
content, result = self.run_subunit_stream('test_missing_feature')
2328
self.assertNotContainsRe(content, b'(?m)^log$')
2329
self.assertNotContainsRe(content, b'missing the feature')
2330
reasons = result.skip_reasons
2331
self.assertEqual({'_MissingFeature\n'}, set(reasons))
2332
skips = reasons['_MissingFeature\n']
2333
self.assertEqual(1, len(skips))
2335
# RemotedTestCase doesn't preserve the "details"
2336
# self.assertFalse('log' in test.getDetails())
2338
def test_xfail_has_no_log(self):
2339
content, result = self.run_subunit_stream('test_xfail')
2340
self.assertNotContainsRe(content, b'(?m)^log$')
2341
self.assertNotContainsRe(content, b'test with expected failure')
2342
self.assertEqual(1, len(result.expectedFailures))
2343
result_content = result.expectedFailures[0][1]
2344
self.assertNotContainsRe(result_content,
2345
'(?m)^(?:Text attachment: )?log(?:$|: )')
2346
self.assertNotContainsRe(result_content, 'test with expected failure')
2348
def test_unexpected_success_has_log(self):
2349
content, result = self.run_subunit_stream('test_unexpected_success')
2350
self.assertContainsRe(content, b'(?m)^log$')
2351
self.assertContainsRe(content, b'test with unexpected success')
2352
self.assertEqual(1, len(result.unexpectedSuccesses))
2353
# test = result.unexpectedSuccesses[0]
2354
# RemotedTestCase doesn't preserve the "details"
2355
# self.assertTrue('log' in test.getDetails())
2357
def test_success_has_no_log(self):
2358
content, result = self.run_subunit_stream('test_success')
2359
self.assertEqual(1, result.testsRun)
2360
self.assertNotContainsRe(content, b'(?m)^log$')
2361
self.assertNotContainsRe(content, b'this test succeeds')
1968
err = self.assertRaises(errors.NoSuchFile, self.run_selftest,
1969
load_list='missing file name', list_only=True)
2364
1972
class TestRunBzr(tests.TestCase):
2370
def _run_bzr_core(self, argv, encoding=None, stdin=None,
2371
stdout=None, stderr=None, working_dir=None):
1977
def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None,
2372
1979
"""Override _run_bzr_core to test how it is invoked by run_bzr.
2374
1981
Attempts to run bzr from inside this class don't actually run it.
2548
2171
self.next_subprocess = process
2550
2173
result = self.run_bzr_subprocess(*args, **kwargs)
2551
except BaseException:
2552
2175
self.next_subprocess = None
2553
for key, expected in expected_args.items():
2176
for key, expected in expected_args.iteritems():
2554
2177
self.assertEqual(expected, self.subprocess_calls[-1][key])
2557
2180
self.next_subprocess = None
2558
for key, expected in expected_args.items():
2181
for key, expected in expected_args.iteritems():
2559
2182
self.assertEqual(expected, self.subprocess_calls[-1][key])
2562
2185
def test_run_bzr_subprocess(self):
2563
2186
"""The run_bzr_helper_external command behaves nicely."""
2564
self.assertRunBzrSubprocess({'process_args': ['--version']},
2565
StubProcess(), '--version')
2566
self.assertRunBzrSubprocess({'process_args': ['--version']},
2567
StubProcess(), ['--version'])
2187
self.assertRunBzrSubprocess({'process_args':['--version']},
2188
StubProcess(), '--version')
2189
self.assertRunBzrSubprocess({'process_args':['--version']},
2190
StubProcess(), ['--version'])
2568
2191
# retcode=None disables retcode checking
2569
result = self.assertRunBzrSubprocess(
2570
{}, StubProcess(retcode=3), '--version', retcode=None)
2571
result = self.assertRunBzrSubprocess(
2572
{}, StubProcess(out="is free software"), '--version')
2192
result = self.assertRunBzrSubprocess({},
2193
StubProcess(retcode=3), '--version', retcode=None)
2194
result = self.assertRunBzrSubprocess({},
2195
StubProcess(out="is free software"), '--version')
2573
2196
self.assertContainsRe(result[0], 'is free software')
2574
2197
# Running a subcommand that is missing errors
2575
2198
self.assertRaises(AssertionError, self.assertRunBzrSubprocess,
2576
{'process_args': ['--versionn']
2577
}, StubProcess(retcode=3),
2199
{'process_args':['--versionn']}, StubProcess(retcode=3),
2579
2201
# Unless it is told to expect the error from the subprocess
2580
result = self.assertRunBzrSubprocess(
2581
{}, StubProcess(retcode=3), '--versionn', retcode=3)
2202
result = self.assertRunBzrSubprocess({},
2203
StubProcess(retcode=3), '--versionn', retcode=3)
2582
2204
# Or to ignore retcode checking
2583
result = self.assertRunBzrSubprocess(
2584
{}, StubProcess(err="unknown command", retcode=3),
2585
'--versionn', retcode=None)
2205
result = self.assertRunBzrSubprocess({},
2206
StubProcess(err="unknown command", retcode=3), '--versionn',
2586
2208
self.assertContainsRe(result[1], 'unknown command')
2588
2210
def test_env_change_passes_through(self):
2589
2211
self.assertRunBzrSubprocess(
2590
{'env_changes': {'new': 'value', 'changed': 'newvalue', 'deleted': None}},
2212
{'env_changes':{'new':'value', 'changed':'newvalue', 'deleted':None}},
2591
2213
StubProcess(), '',
2592
env_changes={'new': 'value', 'changed': 'newvalue', 'deleted': None})
2214
env_changes={'new':'value', 'changed':'newvalue', 'deleted':None})
2594
2216
def test_no_working_dir_passed_as_None(self):
2595
2217
self.assertRunBzrSubprocess({'working_dir': None}, StubProcess(), '')
2597
2219
def test_no_working_dir_passed_through(self):
2598
2220
self.assertRunBzrSubprocess({'working_dir': 'dir'}, StubProcess(), '',
2601
2223
def test_run_bzr_subprocess_no_plugins(self):
2602
2224
self.assertRunBzrSubprocess({'allow_plugins': False},
2605
2227
def test_allow_plugins(self):
2606
2228
self.assertRunBzrSubprocess({'allow_plugins': True},
2607
StubProcess(), '', allow_plugins=True)
2229
StubProcess(), '', allow_plugins=True)
2610
2232
class TestFinishBzrSubprocess(TestWithFakedStartBzrSubprocess):
2640
2262
class TestStartBzrSubProcess(tests.TestCase):
2641
"""Stub test start_bzr_subprocess."""
2643
def _subprocess_log_cleanup(self):
2644
"""Inhibits the base version as we don't produce a log file."""
2264
def check_popen_state(self):
2265
"""Replace to make assertions when popen is called."""
2646
2267
def _popen(self, *args, **kwargs):
2647
"""Override the base version to record the command that is run.
2649
From there we can ensure it is correct without spawning a real process.
2268
"""Record the command that is run, so that we can ensure it is correct"""
2651
2269
self.check_popen_state()
2652
2270
self._popen_args = args
2653
2271
self._popen_kwargs = kwargs
2654
2272
raise _DontSpawnProcess()
2656
def check_popen_state(self):
2657
"""Replace to make assertions when popen is called."""
2659
2274
def test_run_bzr_subprocess_no_plugins(self):
2660
2275
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
2661
2276
command = self._popen_args[0]
2662
2277
self.assertEqual(sys.executable, command[0])
2663
self.assertEqual(self.get_brz_path(), command[1])
2278
self.assertEqual(self.get_bzr_path(), command[1])
2664
2279
self.assertEqual(['--no-plugins'], command[2:])
2666
2281
def test_allow_plugins(self):
2667
2282
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2669
2284
command = self._popen_args[0]
2670
2285
self.assertEqual([], command[2:])
2672
2287
def test_set_env(self):
2673
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2288
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2674
2289
# set in the child
2676
2290
def check_environment():
2677
2291
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2678
2292
self.check_popen_state = check_environment
2679
2293
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2680
env_changes={'EXISTANT_ENV_VAR': 'set variable'})
2294
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2681
2295
# not set in theparent
2682
2296
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2684
2298
def test_run_bzr_subprocess_env_del(self):
2685
2299
"""run_bzr_subprocess can remove environment variables too."""
2686
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2300
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2688
2301
def check_environment():
2689
2302
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2690
2303
os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2691
2304
self.check_popen_state = check_environment
2692
2305
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2693
env_changes={'EXISTANT_ENV_VAR': None})
2306
env_changes={'EXISTANT_ENV_VAR':None})
2694
2307
# Still set in parent
2695
2308
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2696
2309
del os.environ['EXISTANT_ENV_VAR']
2698
2311
def test_env_del_missing(self):
2699
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2312
self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
2701
2313
def check_environment():
2702
2314
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2703
2315
self.check_popen_state = check_environment
2704
2316
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2705
env_changes={'NON_EXISTANT_ENV_VAR': None})
2317
env_changes={'NON_EXISTANT_ENV_VAR':None})
2707
2319
def test_working_dir(self):
2708
2320
"""Test that we can specify the working dir for the child"""
2321
orig_getcwd = osutils.getcwd
2322
orig_chdir = os.chdir
2711
2324
def chdir(path):
2712
2325
chdirs.append(path)
2713
self.overrideAttr(os, 'chdir', chdir)
2717
self.overrideAttr(osutils, 'getcwd', getcwd)
2718
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2330
osutils.getcwd = getcwd
2332
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2335
osutils.getcwd = orig_getcwd
2337
os.chdir = orig_chdir
2720
2338
self.assertEqual(['foo', 'current'], chdirs)
2722
def test_get_brz_path_with_cwd_breezy(self):
2723
self.get_source_path = lambda: ""
2724
self.overrideAttr(os.path, "isfile", lambda path: True)
2725
self.assertEqual(self.get_brz_path(), "brz")
2728
2341
class TestActuallyStartBzrSubprocess(tests.TestCaseWithTransport):
2729
2342
"""Tests that really need to do things with an external bzr."""
2735
2348
self.disable_missing_extensions_warning()
2736
2349
process = self.start_bzr_subprocess(['wait-until-signalled'],
2737
2350
skip_if_plan_to_signal=True)
2738
self.assertEqual(b'running\n', process.stdout.readline())
2351
self.assertEqual('running\n', process.stdout.readline())
2739
2352
result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT,
2741
self.assertEqual(b'', result[0])
2742
self.assertEqual(b'brz: interrupted\n', result[1])
2354
self.assertEqual('', result[0])
2355
self.assertEqual('bzr: interrupted\n', result[1])
2358
class TestFeature(tests.TestCase):
2360
def test_caching(self):
2361
"""Feature._probe is called by the feature at most once."""
2362
class InstrumentedFeature(tests.Feature):
2364
super(InstrumentedFeature, self).__init__()
2367
self.calls.append('_probe')
2369
feature = InstrumentedFeature()
2371
self.assertEqual(['_probe'], feature.calls)
2373
self.assertEqual(['_probe'], feature.calls)
2375
def test_named_str(self):
2376
"""Feature.__str__ should thunk to feature_name()."""
2377
class NamedFeature(tests.Feature):
2378
def feature_name(self):
2380
feature = NamedFeature()
2381
self.assertEqual('symlinks', str(feature))
2383
def test_default_str(self):
2384
"""Feature.__str__ should default to __class__.__name__."""
2385
class NamedFeature(tests.Feature):
2387
feature = NamedFeature()
2388
self.assertEqual('NamedFeature', str(feature))
2391
class TestUnavailableFeature(tests.TestCase):
2393
def test_access_feature(self):
2394
feature = tests.Feature()
2395
exception = tests.UnavailableFeature(feature)
2396
self.assertIs(feature, exception.args[0])
2399
simple_thunk_feature = tests._CompatabilityThunkFeature(
2400
deprecated_in((2, 1, 0)),
2401
'bzrlib.tests.test_selftest',
2402
'simple_thunk_feature','UnicodeFilename',
2403
replacement_module='bzrlib.tests'
2406
class Test_CompatibilityFeature(tests.TestCase):
2408
def test_does_thunk(self):
2409
res = self.callDeprecated(
2410
['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
2411
' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
2412
simple_thunk_feature.available)
2413
self.assertEqual(tests.UnicodeFilename.available(), res)
2416
class TestModuleAvailableFeature(tests.TestCase):
2418
def test_available_module(self):
2419
feature = tests.ModuleAvailableFeature('bzrlib.tests')
2420
self.assertEqual('bzrlib.tests', feature.module_name)
2421
self.assertEqual('bzrlib.tests', str(feature))
2422
self.assertTrue(feature.available())
2423
self.assertIs(tests, feature.module)
2425
def test_unavailable_module(self):
2426
feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
2427
self.assertEqual('bzrlib.no_such_module_exists', str(feature))
2428
self.assertFalse(feature.available())
2429
self.assertIs(None, feature.module)
2745
2432
class TestSelftestFiltering(tests.TestCase):
2747
2434
def setUp(self):
2748
super(TestSelftestFiltering, self).setUp()
2435
tests.TestCase.setUp(self)
2749
2436
self.suite = TestUtil.TestSuite()
2750
2437
self.loader = TestUtil.TestLoader()
2751
2438
self.suite.addTest(self.loader.loadTestsFromModule(
2752
sys.modules['breezy.tests.test_selftest']))
2439
sys.modules['bzrlib.tests.test_selftest']))
2753
2440
self.all_names = _test_ids(self.suite)
2755
2442
def test_condition_id_re(self):
2756
test_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2757
'test_condition_id_re')
2443
test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2444
'test_condition_id_re')
2758
2445
filtered_suite = tests.filter_suite_by_condition(
2759
2446
self.suite, tests.condition_id_re('test_condition_id_re'))
2760
2447
self.assertEqual([test_name], _test_ids(filtered_suite))
2762
2449
def test_condition_id_in_list(self):
2763
test_names = ['breezy.tests.test_selftest.TestSelftestFiltering.'
2450
test_names = ['bzrlib.tests.test_selftest.TestSelftestFiltering.'
2764
2451
'test_condition_id_in_list']
2765
2452
id_list = tests.TestIdList(test_names)
2766
2453
filtered_suite = tests.filter_suite_by_condition(
2803
2490
self.all_names = _test_ids(self.suite)
2804
2491
filtered_suite = tests.exclude_tests_by_re(self.suite,
2805
2492
'exclude_tests_by_re')
2806
excluded_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2807
'test_exclude_tests_by_re')
2493
excluded_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2494
'test_exclude_tests_by_re')
2808
2495
self.assertEqual(len(self.all_names) - 1,
2809
filtered_suite.countTestCases())
2496
filtered_suite.countTestCases())
2810
2497
self.assertFalse(excluded_name in _test_ids(filtered_suite))
2811
2498
remaining_names = list(self.all_names)
2812
2499
remaining_names.remove(excluded_name)
2813
2500
self.assertEqual(remaining_names, _test_ids(filtered_suite))
2815
2502
def test_filter_suite_by_condition(self):
2816
test_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2817
'test_filter_suite_by_condition')
2818
filtered_suite = tests.filter_suite_by_condition(
2819
self.suite, lambda x: x.id() == test_name)
2503
test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2504
'test_filter_suite_by_condition')
2505
filtered_suite = tests.filter_suite_by_condition(self.suite,
2506
lambda x:x.id() == test_name)
2820
2507
self.assertEqual([test_name], _test_ids(filtered_suite))
2822
2509
def test_filter_suite_by_re(self):
2823
2510
filtered_suite = tests.filter_suite_by_re(self.suite,
2824
2511
'test_filter_suite_by_r')
2825
2512
filtered_names = _test_ids(filtered_suite)
2827
filtered_names, ['breezy.tests.test_selftest.'
2828
'TestSelftestFiltering.test_filter_suite_by_re'])
2513
self.assertEqual(filtered_names, ['bzrlib.tests.test_selftest.'
2514
'TestSelftestFiltering.test_filter_suite_by_re'])
2830
2516
def test_filter_suite_by_id_list(self):
2831
test_list = ['breezy.tests.test_selftest.'
2517
test_list = ['bzrlib.tests.test_selftest.'
2832
2518
'TestSelftestFiltering.test_filter_suite_by_id_list']
2833
2519
filtered_suite = tests.filter_suite_by_id_list(
2834
2520
self.suite, tests.TestIdList(test_list))
2835
2521
filtered_names = _test_ids(filtered_suite)
2836
2522
self.assertEqual(
2837
2523
filtered_names,
2838
['breezy.tests.test_selftest.'
2524
['bzrlib.tests.test_selftest.'
2839
2525
'TestSelftestFiltering.test_filter_suite_by_id_list'])
2841
2527
def test_filter_suite_by_id_startswith(self):
2842
2528
# By design this test may fail if another test is added whose name also
2843
2529
# begins with one of the start value used.
2844
klass = 'breezy.tests.test_selftest.TestSelftestFiltering.'
2530
klass = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2845
2531
start1 = klass + 'test_filter_suite_by_id_starts'
2846
2532
start2 = klass + 'test_filter_suite_by_id_li'
2847
2533
test_list = [klass + 'test_filter_suite_by_id_list',
3095
2776
self.assertEqual([], test_list)
3097
2778
self.assertSubset([
3102
2783
def test_test_suite(self):
3103
2784
# test_suite() loads the entire test suite to operate. To avoid this
3104
2785
# overhead, and yet still be confident that things are happening,
3105
# we temporarily replace two functions used by test_suite with
2786
# we temporarily replace two functions used by test_suite with
3106
2787
# test doubles that supply a few sample tests to load, and check they
3110
2790
def testmod_names():
3111
2791
calls.append("testmod_names")
3113
'breezy.tests.blackbox.test_branch',
3114
'breezy.tests.per_transport',
3115
'breezy.tests.test_selftest',
2793
'bzrlib.tests.blackbox.test_branch',
2794
'bzrlib.tests.per_transport',
2795
'bzrlib.tests.test_selftest',
3117
2797
self.overrideAttr(tests, '_test_suite_testmod_names', testmod_names)
3119
2798
def doctests():
3120
2799
calls.append("modules_to_doctest")
3121
2800
if __doc__ is None:
3123
return ['breezy.timestamp']
2802
return ['bzrlib.timestamp']
3124
2803
self.overrideAttr(tests, '_test_suite_modules_to_doctest', doctests)
3125
2804
expected_test_list = [
3126
2805
# testmod_names
3127
'breezy.tests.blackbox.test_branch.TestBranch.test_branch',
3128
('breezy.tests.per_transport.TransportTests'
2806
'bzrlib.tests.blackbox.test_branch.TestBranch.test_branch',
2807
('bzrlib.tests.per_transport.TransportTests'
3129
2808
'.test_abspath(LocalTransport,LocalURLServer)'),
3130
'breezy.tests.test_selftest.TestTestSuite.test_test_suite',
2809
'bzrlib.tests.test_selftest.TestTestSuite.test_test_suite',
3131
2810
# plugins can't be tested that way since selftest may be run with
2813
if __doc__ is not None:
2814
expected_test_list.extend([
2815
# modules_to_doctest
2816
'bzrlib.timestamp.format_highres_date',
3134
2818
suite = tests.test_suite()
3135
self.assertEqual({"testmod_names", "modules_to_doctest"}, set(calls))
2819
self.assertEqual(set(["testmod_names", "modules_to_doctest"]),
3136
2821
self.assertSubset(expected_test_list, _test_ids(suite))
3138
2823
def test_test_suite_list_and_start(self):
3139
# We cannot test this at the same time as the main load, because we
3140
# want to know that starting_with == None works. So a second load is
3141
# incurred - note that the starting_with parameter causes a partial
3142
# load rather than a full load so this test should be pretty quick.
3144
'breezy.tests.test_selftest.TestTestSuite.test_test_suite']
2824
# We cannot test this at the same time as the main load, because we want
2825
# to know that starting_with == None works. So a second load is
2826
# incurred - note that the starting_with parameter causes a partial load
2827
# rather than a full load so this test should be pretty quick.
2828
test_list = ['bzrlib.tests.test_selftest.TestTestSuite.test_test_suite']
3145
2829
suite = tests.test_suite(test_list,
3146
['breezy.tests.test_selftest.TestTestSuite'])
3147
# test_test_suite_list_and_start is not included
3148
self.assertEqual(test_list, _test_ids(suite))
2830
['bzrlib.tests.test_selftest.TestTestSuite'])
2831
# test_test_suite_list_and_start is not included
2832
self.assertEquals(test_list, _test_ids(suite))
3151
2835
class TestLoadTestIdList(tests.TestCaseInTempDir):
3257
2941
def test_resolve_prefix(self):
3258
2942
tpr = self._get_registry()
3259
2943
tpr.register('bar', 'bb.aa.rr')
3260
self.assertEqual('bb.aa.rr', tpr.resolve_alias('bar'))
2944
self.assertEquals('bb.aa.rr', tpr.resolve_alias('bar'))
3262
2946
def test_resolve_unknown_alias(self):
3263
2947
tpr = self._get_registry()
3264
self.assertRaises(errors.CommandError,
2948
self.assertRaises(errors.BzrCommandError,
3265
2949
tpr.resolve_alias, 'I am not a prefix')
3267
2951
def test_predefined_prefixes(self):
3268
2952
tpr = tests.test_prefix_alias_registry
3269
self.assertEqual('breezy', tpr.resolve_alias('breezy'))
3270
self.assertEqual('breezy.doc', tpr.resolve_alias('bd'))
3271
self.assertEqual('breezy.utils', tpr.resolve_alias('bu'))
3272
self.assertEqual('breezy.tests', tpr.resolve_alias('bt'))
3273
self.assertEqual('breezy.tests.blackbox', tpr.resolve_alias('bb'))
3274
self.assertEqual('breezy.plugins', tpr.resolve_alias('bp'))
3277
class TestThreadLeakDetection(tests.TestCase):
3278
"""Ensure when tests leak threads we detect and report it"""
3280
class LeakRecordingResult(tests.ExtendedTestResult):
3282
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3285
def _report_thread_leak(self, test, leaks, alive):
3286
self.leaks.append((test, leaks))
3288
def test_testcase_without_addCleanups(self):
3289
"""Check old TestCase instances don't break with leak detection"""
3290
class Test(unittest.TestCase):
3293
result = self.LeakRecordingResult()
3295
result.startTestRun()
3297
result.stopTestRun()
3298
self.assertEqual(result._tests_leaking_threads_count, 0)
3299
self.assertEqual(result.leaks, [])
3301
def test_thread_leak(self):
3302
"""Ensure a thread that outlives the running of a test is reported
3304
Uses a thread that blocks on an event, and is started by the inner
3305
test case. As the thread outlives the inner case's run, it should be
3306
detected as a leak, but the event is then set so that the thread can
3307
be safely joined in cleanup so it's not leaked for real.
3309
event = threading.Event()
3310
thread = threading.Thread(name="Leaker", target=event.wait)
3312
class Test(tests.TestCase):
3313
def test_leak(self):
3315
result = self.LeakRecordingResult()
3316
test = Test("test_leak")
3317
self.addCleanup(thread.join)
3318
self.addCleanup(event.set)
3319
result.startTestRun()
3321
result.stopTestRun()
3322
self.assertEqual(result._tests_leaking_threads_count, 1)
3323
self.assertEqual(result._first_thread_leaker_id, test.id())
3324
self.assertEqual(result.leaks, [(test, {thread})])
3325
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3327
def test_multiple_leaks(self):
3328
"""Check multiple leaks are blamed on the test cases at fault
3330
Same concept as the previous test, but has one inner test method that
3331
leaks two threads, and one that doesn't leak at all.
3333
event = threading.Event()
3334
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3335
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3336
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3338
class Test(tests.TestCase):
3339
def test_first_leak(self):
3342
def test_second_no_leak(self):
3345
def test_third_leak(self):
3348
result = self.LeakRecordingResult()
3349
first_test = Test("test_first_leak")
3350
third_test = Test("test_third_leak")
3351
self.addCleanup(thread_a.join)
3352
self.addCleanup(thread_b.join)
3353
self.addCleanup(thread_c.join)
3354
self.addCleanup(event.set)
3355
result.startTestRun()
3357
[first_test, Test("test_second_no_leak"), third_test]
3359
result.stopTestRun()
3360
self.assertEqual(result._tests_leaking_threads_count, 2)
3361
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3362
self.assertEqual(result.leaks, [
3363
(first_test, {thread_b}),
3364
(third_test, {thread_a, thread_c})])
3365
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3368
class TestPostMortemDebugging(tests.TestCase):
3369
"""Check post mortem debugging works when tests fail or error"""
3371
class TracebackRecordingResult(tests.ExtendedTestResult):
3373
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3374
self.postcode = None
3376
def _post_mortem(self, tb=None):
3377
"""Record the code object at the end of the current traceback"""
3378
tb = tb or sys.exc_info()[2]
3381
while next is not None:
3384
self.postcode = tb.tb_frame.f_code
3386
def report_error(self, test, err):
3389
def report_failure(self, test, err):
3392
def test_location_unittest_error(self):
3393
"""Needs right post mortem traceback with erroring unittest case"""
3394
class Test(unittest.TestCase):
3397
result = self.TracebackRecordingResult()
3399
self.assertEqual(result.postcode, Test.runTest.__code__)
3401
def test_location_unittest_failure(self):
3402
"""Needs right post mortem traceback with failing unittest case"""
3403
class Test(unittest.TestCase):
3405
raise self.failureException
3406
result = self.TracebackRecordingResult()
3408
self.assertEqual(result.postcode, Test.runTest.__code__)
3410
def test_location_bt_error(self):
3411
"""Needs right post mortem traceback with erroring breezy.tests case"""
3412
class Test(tests.TestCase):
3413
def test_error(self):
3415
result = self.TracebackRecordingResult()
3416
Test("test_error").run(result)
3417
self.assertEqual(result.postcode, Test.test_error.__code__)
3419
def test_location_bt_failure(self):
3420
"""Needs right post mortem traceback with failing breezy.tests case"""
3421
class Test(tests.TestCase):
3422
def test_failure(self):
3423
raise self.failureException
3424
result = self.TracebackRecordingResult()
3425
Test("test_failure").run(result)
3426
self.assertEqual(result.postcode, Test.test_failure.__code__)
3428
def test_env_var_triggers_post_mortem(self):
3429
"""Check pdb.post_mortem is called iff BRZ_TEST_PDB is set"""
3431
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3432
post_mortem_calls = []
3433
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3434
self.overrideEnv('BRZ_TEST_PDB', None)
3435
result._post_mortem(1)
3436
self.overrideEnv('BRZ_TEST_PDB', 'on')
3437
result._post_mortem(2)
3438
self.assertEqual([2], post_mortem_calls)
2953
self.assertEquals('bzrlib', tpr.resolve_alias('bzrlib'))
2954
self.assertEquals('bzrlib.doc', tpr.resolve_alias('bd'))
2955
self.assertEquals('bzrlib.utils', tpr.resolve_alias('bu'))
2956
self.assertEquals('bzrlib.tests', tpr.resolve_alias('bt'))
2957
self.assertEquals('bzrlib.tests.blackbox', tpr.resolve_alias('bb'))
2958
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3441
2961
class TestRunSuite(tests.TestCase):
3455
2974
self.verbosity)
3456
2975
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3457
2976
self.assertLength(1, calls)
3460
class _Selftest(object):
3461
"""Mixin for tests needing full selftest output"""
3463
def _inject_stream_into_subunit(self, stream):
3464
"""To be overridden by subclasses that run tests out of process"""
3466
def _run_selftest(self, **kwargs):
3468
sio = TextIOWrapper(bio, 'utf-8')
3469
self._inject_stream_into_subunit(bio)
3470
tests.selftest(stream=sio, stop_on_failure=False, **kwargs)
3472
return bio.getvalue()
3475
class _ForkedSelftest(_Selftest):
3476
"""Mixin for tests needing full selftest output with forked children"""
3478
_test_needs_features = [features.subunit]
3480
def _inject_stream_into_subunit(self, stream):
3481
"""Monkey-patch subunit so the extra output goes to stream not stdout
3483
Some APIs need rewriting so this kind of bogus hackery can be replaced
3484
by passing the stream param from run_tests down into ProtocolTestCase.
3486
from subunit import ProtocolTestCase
3487
_original_init = ProtocolTestCase.__init__
3489
def _init_with_passthrough(self, *args, **kwargs):
3490
_original_init(self, *args, **kwargs)
3491
self._passthrough = stream
3492
self.overrideAttr(ProtocolTestCase, "__init__", _init_with_passthrough)
3494
def _run_selftest(self, **kwargs):
3495
# GZ 2011-05-26: Add a PosixSystem feature so this check can go away
3496
if getattr(os, "fork", None) is None:
3497
raise tests.TestNotApplicable("Platform doesn't support forking")
3498
# Make sure the fork code is actually invoked by claiming two cores
3499
self.overrideAttr(osutils, "local_concurrency", lambda: 2)
3500
kwargs.setdefault("suite_decorators", []).append(tests.fork_decorator)
3501
return super(_ForkedSelftest, self)._run_selftest(**kwargs)
3504
class TestParallelFork(_ForkedSelftest, tests.TestCase):
3505
"""Check operation of --parallel=fork selftest option"""
3507
def test_error_in_child_during_fork(self):
3508
"""Error in a forked child during test setup should get reported"""
3509
class Test(tests.TestCase):
3510
def testMethod(self):
3512
# We don't care what, just break something that a child will run
3513
self.overrideAttr(tests, "workaround_zealous_crypto_random", None)
3514
out = self._run_selftest(test_suite_factory=Test)
3515
# Lines from the tracebacks of the two child processes may be mixed
3516
# together due to the way subunit parses and forwards the streams,
3517
# so permit extra lines between each part of the error output.
3518
self.assertContainsRe(out,
3521
b".+ in fork_for_tests\n"
3523
b"\\s*workaround_zealous_crypto_random\\(\\)\n"
3528
class TestUncollectedWarnings(_Selftest, tests.TestCase):
3529
"""Check a test case still alive after being run emits a warning"""
3531
class Test(tests.TestCase):
3532
def test_pass(self):
3535
def test_self_ref(self):
3536
self.also_self = self.test_self_ref
3538
def test_skip(self):
3539
self.skipTest("Don't need")
3541
def _get_suite(self):
3542
return TestUtil.TestSuite([
3543
self.Test("test_pass"),
3544
self.Test("test_self_ref"),
3545
self.Test("test_skip"),
3548
def _run_selftest_with_suite(self, **kwargs):
3549
old_flags = tests.selftest_debug_flags
3550
tests.selftest_debug_flags = old_flags.union(["uncollected_cases"])
3551
gc_on = gc.isenabled()
3555
output = self._run_selftest(test_suite_factory=self._get_suite,
3560
tests.selftest_debug_flags = old_flags
3561
self.assertNotContainsRe(output, b"Uncollected test case.*test_pass")
3562
self.assertContainsRe(output, b"Uncollected test case.*test_self_ref")
3565
def test_testsuite(self):
3566
self._run_selftest_with_suite()
3568
def test_pattern(self):
3569
out = self._run_selftest_with_suite(pattern="test_(?:pass|self_ref)$")
3570
self.assertNotContainsRe(out, b"test_skip")
3572
def test_exclude_pattern(self):
3573
out = self._run_selftest_with_suite(exclude_pattern="test_skip$")
3574
self.assertNotContainsRe(out, b"test_skip")
3576
def test_random_seed(self):
3577
self._run_selftest_with_suite(random_seed="now")
3579
def test_matching_tests_first(self):
3580
self._run_selftest_with_suite(matching_tests_first=True,
3581
pattern="test_self_ref$")
3583
def test_starting_with_and_exclude(self):
3584
out = self._run_selftest_with_suite(starting_with=["bt."],
3585
exclude_pattern="test_skip$")
3586
self.assertNotContainsRe(out, b"test_skip")
3588
def test_additonal_decorator(self):
3589
self._run_selftest_with_suite(suite_decorators=[tests.TestDecorator])
3592
class TestUncollectedWarningsSubunit(TestUncollectedWarnings):
3593
"""Check warnings from tests staying alive are emitted with subunit"""
3595
_test_needs_features = [features.subunit]
3597
def _run_selftest_with_suite(self, **kwargs):
3598
return TestUncollectedWarnings._run_selftest_with_suite(
3599
self, runner_class=tests.SubUnitBzrRunnerv1, **kwargs)
3602
class TestUncollectedWarningsForked(_ForkedSelftest, TestUncollectedWarnings):
3603
"""Check warnings from tests staying alive are emitted when forking"""
3606
class TestEnvironHandling(tests.TestCase):
3608
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3609
self.assertFalse('MYVAR' in os.environ)
3610
self.overrideEnv('MYVAR', '42')
3611
# We use an embedded test to make sure we fix the _captureVar bug
3613
class Test(tests.TestCase):
3615
# The first call save the 42 value
3616
self.overrideEnv('MYVAR', None)
3617
self.assertEqual(None, os.environ.get('MYVAR'))
3618
# Make sure we can call it twice
3619
self.overrideEnv('MYVAR', None)
3620
self.assertEqual(None, os.environ.get('MYVAR'))
3622
result = tests.TextTestResult(output, 0, 1)
3623
Test('test_me').run(result)
3624
if not result.wasStrictlySuccessful():
3625
self.fail(output.getvalue())
3626
# We get our value back
3627
self.assertEqual('42', os.environ.get('MYVAR'))
3630
class TestIsolatedEnv(tests.TestCase):
3631
"""Test isolating tests from os.environ.
3633
Since we use tests that are already isolated from os.environ a bit of care
3634
should be taken when designing the tests to avoid bootstrap side-effects.
3635
The tests start an already clean os.environ which allow doing valid
3636
assertions about which variables are present or not and design tests around
3640
class ScratchMonkey(tests.TestCase):
3645
def test_basics(self):
3646
# Make sure we know the definition of BRZ_HOME: not part of os.environ
3647
# for tests.TestCase.
3648
self.assertTrue('BRZ_HOME' in tests.isolated_environ)
3649
self.assertEqual(None, tests.isolated_environ['BRZ_HOME'])
3650
# Being part of isolated_environ, BRZ_HOME should not appear here
3651
self.assertFalse('BRZ_HOME' in os.environ)
3652
# Make sure we know the definition of LINES: part of os.environ for
3654
self.assertTrue('LINES' in tests.isolated_environ)
3655
self.assertEqual('25', tests.isolated_environ['LINES'])
3656
self.assertEqual('25', os.environ['LINES'])
3658
def test_injecting_unknown_variable(self):
3659
# BRZ_HOME is known to be absent from os.environ
3660
test = self.ScratchMonkey('test_me')
3661
tests.override_os_environ(test, {'BRZ_HOME': 'foo'})
3662
self.assertEqual('foo', os.environ['BRZ_HOME'])
3663
tests.restore_os_environ(test)
3664
self.assertFalse('BRZ_HOME' in os.environ)
3666
def test_injecting_known_variable(self):
3667
test = self.ScratchMonkey('test_me')
3668
# LINES is known to be present in os.environ
3669
tests.override_os_environ(test, {'LINES': '42'})
3670
self.assertEqual('42', os.environ['LINES'])
3671
tests.restore_os_environ(test)
3672
self.assertEqual('25', os.environ['LINES'])
3674
def test_deleting_variable(self):
3675
test = self.ScratchMonkey('test_me')
3676
# LINES is known to be present in os.environ
3677
tests.override_os_environ(test, {'LINES': None})
3678
self.assertTrue('LINES' not in os.environ)
3679
tests.restore_os_environ(test)
3680
self.assertEqual('25', os.environ['LINES'])
3683
class TestDocTestSuiteIsolation(tests.TestCase):
3684
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3686
Since tests.TestCase alreay provides an isolation from os.environ, we use
3687
the clean environment as a base for testing. To precisely capture the
3688
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3691
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3692
not `os.environ` so each test overrides it to suit its needs.
3696
def get_doctest_suite_for_string(self, klass, string):
3697
class Finder(doctest.DocTestFinder):
3699
def find(*args, **kwargs):
3700
test = doctest.DocTestParser().get_doctest(
3701
string, {}, 'foo', 'foo.py', 0)
3704
suite = klass(test_finder=Finder())
3707
def run_doctest_suite_for_string(self, klass, string):
3708
suite = self.get_doctest_suite_for_string(klass, string)
3710
result = tests.TextTestResult(output, 0, 1)
3712
return result, output
3714
def assertDocTestStringSucceds(self, klass, string):
3715
result, output = self.run_doctest_suite_for_string(klass, string)
3716
if not result.wasStrictlySuccessful():
3717
self.fail(output.getvalue())
3719
def assertDocTestStringFails(self, klass, string):
3720
result, output = self.run_doctest_suite_for_string(klass, string)
3721
if result.wasStrictlySuccessful():
3722
self.fail(output.getvalue())
3724
def test_injected_variable(self):
3725
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3728
>>> os.environ['LINES']
3731
# doctest.DocTestSuite fails as it sees '25'
3732
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3733
# tests.DocTestSuite sees '42'
3734
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3736
def test_deleted_variable(self):
3737
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3740
>>> os.environ.get('LINES')
3742
# doctest.DocTestSuite fails as it sees '25'
3743
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3744
# tests.DocTestSuite sees None
3745
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3748
class TestSelftestExcludePatterns(tests.TestCase):
3751
super(TestSelftestExcludePatterns, self).setUp()
3752
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3754
def suite_factory(self, keep_only=None, starting_with=None):
3755
"""A test suite factory with only a few tests."""
3756
class Test(tests.TestCase):
3758
# We don't need the full class path
3759
return self._testMethodName
3769
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3771
def assertTestList(self, expected, *selftest_args):
3772
# We rely on setUp installing the right test suite factory so we can
3773
# test at the command level without loading the whole test suite
3774
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3775
actual = out.splitlines()
3776
self.assertEqual(expected, actual)
3778
def test_full_list(self):
3779
self.assertTestList(['a', 'b', 'c'])
3781
def test_single_exclude(self):
3782
self.assertTestList(['b', 'c'], '-x', 'a')
3784
def test_mutiple_excludes(self):
3785
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3788
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3790
_test_needs_features = [features.subunit]
3793
super(TestCounterHooks, self).setUp()
3795
class Test(tests.TestCase):
3798
super(Test, self).setUp()
3799
self.hooks = hooks.Hooks()
3800
self.hooks.add_hook('myhook', 'Foo bar blah', (2, 4))
3801
self.install_counter_hook(self.hooks, 'myhook')
3806
def run_hook_once(self):
3807
for hook in self.hooks['myhook']:
3810
self.test_class = Test
3812
def assertHookCalls(self, expected_calls, test_name):
3813
test = self.test_class(test_name)
3814
result = unittest.TestResult()
3816
self.assertTrue(hasattr(test, '_counters'))
3817
self.assertTrue('myhook' in test._counters)
3818
self.assertEqual(expected_calls, test._counters['myhook'])
3820
def test_no_hook(self):
3821
self.assertHookCalls(0, 'no_hook')
3823
def test_run_hook_once(self):
3824
tt = features.testtools
3825
if tt.module.__version__ < (0, 9, 8):
3826
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3827
self.assertHookCalls(1, 'run_hook_once')