/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_selftest.py

  • Committer: Jelmer Vernooij
  • Date: 2018-05-06 11:48:54 UTC
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@jelmer.uk-20180506114854-h4qd9ojaqy8wxjsd
Move .mailmap to root.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
import gc
20
20
import doctest
21
 
from functools import reduce
22
 
from io import BytesIO, TextIOWrapper
23
21
import os
24
22
import signal
25
23
import sys
64
62
from ..bzr import (
65
63
    groupcompress_repo,
66
64
    )
67
 
from ..git import (
68
 
    workingtree as git_workingtree,
69
 
    )
70
65
from ..sixish import (
71
 
    PY3,
72
66
    StringIO,
73
67
    text_type,
74
68
    )
103
97
            "text", "plain", {"charset": "utf8"})))
104
98
        self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
105
99
        self.assertThat(self.get_log(),
106
 
                        DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
 
100
            DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
107
101
 
108
102
 
109
103
class TestTreeShape(tests.TestCaseInTempDir):
162
156
        for module in modules:
163
157
            try:
164
158
                permutation_count += len(reduce(getattr,
165
 
                                                (module
166
 
                                                 + ".get_test_permutations").split('.')[1:],
167
 
                                                __import__(module))())
 
159
                    (module + ".get_test_permutations").split('.')[1:],
 
160
                     __import__(module))())
168
161
            except errors.DependencyNotPresent:
169
162
                pass
170
163
        scenarios = transport_test_permutations()
244
237
                   ("(d)", repository.format_registry.get(
245
238
                    b'Bazaar repository format 2a (needs bzr 1.16 or later)\n'))]
246
239
        no_vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
247
 
                                                None)
 
240
            None)
248
241
        vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
249
 
                                             vfs_transport_factory="vfs")
 
242
            vfs_transport_factory="vfs")
250
243
        # no_vfs generate scenarios without vfs_transport_factory
251
244
        expected = [
252
245
            ('RemoteRepositoryFormat(c)',
284
277
        input_test = TestTestScenarioApplication("test_apply_scenario")
285
278
        # setup two adapted tests
286
279
        adapted_test1 = apply_scenario(input_test,
287
 
                                       ("new id",
288
 
                                        {"bzrdir_format": "bzr_format",
289
 
                                         "repository_format": "repo_fmt",
290
 
                                         "transport_server": "transport_server",
291
 
                                         "transport_readonly_server": "readonly-server"}))
 
280
            ("new id",
 
281
            {"bzrdir_format":"bzr_format",
 
282
             "repository_format":"repo_fmt",
 
283
             "transport_server":"transport_server",
 
284
             "transport_readonly_server":"readonly-server"}))
292
285
        adapted_test2 = apply_scenario(input_test,
293
 
                                       ("new id 2", {"bzrdir_format": None}))
 
286
            ("new id 2", {"bzrdir_format":None}))
294
287
        # input_test should have been altered.
295
288
        self.assertRaises(AttributeError, getattr, input_test, "bzrdir_format")
296
289
        # the new tests are mutually incompatible, ensuring it has
300
293
        self.assertEqual("repo_fmt", adapted_test1.repository_format)
301
294
        self.assertEqual("transport_server", adapted_test1.transport_server)
302
295
        self.assertEqual("readonly-server",
303
 
                         adapted_test1.transport_readonly_server)
 
296
            adapted_test1.transport_readonly_server)
304
297
        self.assertEqual(
305
298
            "breezy.tests.test_selftest.TestTestScenarioApplication."
306
299
            "test_apply_scenario(new id)",
350
343
                   workingtree_3.WorkingTreeFormat3(),
351
344
                   workingtree_4.WorkingTreeFormat6()]
352
345
        scenarios = make_scenarios(server1, server2, formats,
353
 
                                   remote_server='c', remote_readonly_server='d',
354
 
                                   remote_backing_server='e')
 
346
            remote_server='c', remote_readonly_server='d',
 
347
            remote_backing_server='e')
355
348
        self.assertEqual([
356
349
            ('WorkingTreeFormat4',
357
350
             {'bzrdir_format': formats[0]._matchingcontroldir,
404
397
        smart_readonly_server = test_server.ReadonlySmartTCPServer_for_testing
405
398
        mem_server = memory.MemoryServer
406
399
        formats = [workingtree_4.WorkingTreeFormat4(),
407
 
                   workingtree_3.WorkingTreeFormat3(), ]
 
400
                   workingtree_3.WorkingTreeFormat3(),]
408
401
        scenarios = make_scenarios(server1, server2, formats)
409
 
        self.assertEqual(9, len(scenarios))
 
402
        self.assertEqual(8, len(scenarios))
410
403
        default_wt_format = workingtree.format_registry.get_default()
411
404
        wt4_format = workingtree_4.WorkingTreeFormat4()
412
405
        wt5_format = workingtree_4.WorkingTreeFormat5()
413
406
        wt6_format = workingtree_4.WorkingTreeFormat6()
414
 
        git_wt_format = git_workingtree.GitWorkingTreeFormat()
415
407
        expected_scenarios = [
416
408
            ('WorkingTreeFormat4',
417
409
             {'bzrdir_format': formats[0]._matchingcontroldir,
426
418
              'transport_server': 'a',
427
419
              'workingtree_format': formats[1],
428
420
              '_workingtree_to_test_tree': return_parameter,
429
 
              }),
 
421
             }),
430
422
            ('WorkingTreeFormat6,remote',
431
423
             {'bzrdir_format': wt6_format._matchingcontroldir,
432
424
              'repo_is_remote': True,
435
427
              'vfs_transport_factory': mem_server,
436
428
              'workingtree_format': wt6_format,
437
429
              '_workingtree_to_test_tree': return_parameter,
438
 
              }),
 
430
             }),
439
431
            ('RevisionTree',
440
432
             {'_workingtree_to_test_tree': revision_tree_from_workingtree,
441
433
              'bzrdir_format': default_wt_format._matchingcontroldir,
442
434
              'transport_readonly_server': 'b',
443
435
              'transport_server': 'a',
444
436
              'workingtree_format': default_wt_format,
445
 
              }),
446
 
            ('GitRevisionTree',
447
 
             {'_workingtree_to_test_tree': revision_tree_from_workingtree,
448
 
              'bzrdir_format': git_wt_format._matchingcontroldir,
449
 
              'transport_readonly_server': 'b',
450
 
              'transport_server': 'a',
451
 
              'workingtree_format': git_wt_format,
452
 
              }
453
 
             ),
 
437
             }),
454
438
            ('DirStateRevisionTree,WT4',
455
439
             {'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
456
440
              'bzrdir_format': wt4_format._matchingcontroldir,
457
441
              'transport_readonly_server': 'b',
458
442
              'transport_server': 'a',
459
443
              'workingtree_format': wt4_format,
460
 
              }),
 
444
             }),
461
445
            ('DirStateRevisionTree,WT5',
462
446
             {'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
463
447
              'bzrdir_format': wt5_format._matchingcontroldir,
464
448
              'transport_readonly_server': 'b',
465
449
              'transport_server': 'a',
466
450
              'workingtree_format': wt5_format,
467
 
              }),
 
451
             }),
468
452
            ('PreviewTree',
469
453
             {'_workingtree_to_test_tree': preview_tree_pre,
470
454
              'bzrdir_format': default_wt_format._matchingcontroldir,
477
461
              'transport_readonly_server': 'b',
478
462
              'transport_server': 'a',
479
463
              'workingtree_format': default_wt_format}),
480
 
            ]
 
464
             ]
481
465
        self.assertEqual(expected_scenarios, scenarios)
482
466
 
483
467
 
509
493
        format1 = WorkingTreeFormat4()
510
494
        format2 = WorkingTreeFormat3()
511
495
        formats = [("1", str, format1, format2, "converter1"),
512
 
                   ("2", int, format2, format1, "converter2")]
 
496
            ("2", int, format2, format1, "converter2")]
513
497
        scenarios = make_scenarios(server1, server2, formats)
514
498
        self.assertEqual(2, len(scenarios))
515
499
        expected_scenarios = [
550
534
        self.build_tree(["foo"])
551
535
        real = os.lstat("foo")
552
536
        fake = _FakeStat(real.st_size, real.st_mtime, real.st_ctime,
553
 
                         real.st_dev, real.st_ino, real.st_mode)
 
537
            real.st_dev, real.st_ino, real.st_mode)
554
538
        self.assertEqualStat(real, fake)
555
539
 
556
540
    def test_assertEqualStat_notequal(self):
557
541
        self.build_tree(["foo", "longname"])
558
542
        self.assertRaises(AssertionError, self.assertEqualStat,
559
 
                          os.lstat("foo"), os.lstat("longname"))
 
543
            os.lstat("foo"), os.lstat("longname"))
560
544
 
561
545
    def test_assertPathExists(self):
562
546
        self.assertPathExists('.')
616
600
        self.assertFalse(osutils.lexists('dir'))
617
601
        self.assertIsInstance(tree, memorytree.MemoryTree)
618
602
        self.assertEqual(format.repository_format.__class__,
619
 
                         tree.branch.repository._format.__class__)
 
603
            tree.branch.repository._format.__class__)
620
604
 
621
605
    def test_make_branch_builder(self):
622
606
        builder = self.make_branch_builder('dir')
640
624
                         the_branch.repository._format.__class__)
641
625
        self.assertEqual(repo_format.get_format_string(),
642
626
                         self.get_transport().get_bytes(
643
 
            'dir/.bzr/repository/format'))
 
627
                            'dir/.bzr/repository/format'))
644
628
 
645
629
    def test_make_branch_builder_with_format_name(self):
646
630
        builder = self.make_branch_builder('dir', format='knit')
653
637
                         the_branch.repository._format.__class__)
654
638
        self.assertEqual(b'Bazaar-NG Knit Repository Format 1',
655
639
                         self.get_transport().get_bytes(
656
 
                             'dir/.bzr/repository/format'))
 
640
                            'dir/.bzr/repository/format'))
657
641
 
658
642
    def test_dangling_locks_cause_failures(self):
659
643
        class TestDanglingLock(tests.TestCaseWithMemoryTransport):
711
695
        self.build_tree(['a_dir/', 'a_file'], transport=t)
712
696
        self.assertIsDirectory('a_dir', t)
713
697
        self.assertRaises(AssertionError, self.assertIsDirectory, 'a_file', t)
714
 
        self.assertRaises(
715
 
            AssertionError, self.assertIsDirectory, 'not_here', t)
 
698
        self.assertRaises(AssertionError, self.assertIsDirectory, 'not_here', t)
716
699
 
717
700
    def test_make_branch_builder(self):
718
701
        builder = self.make_branch_builder('dir')
756
739
        self.requireFeature(features.lsprof_feature)
757
740
        terminal = testtools.testresult.doubles.ExtendedTestResult()
758
741
        result = tests.ProfileResult(terminal)
759
 
 
760
742
        class Sample(tests.TestCase):
761
743
            def a(self):
762
744
                self.sample_function()
763
 
 
764
745
            def sample_function(self):
765
746
                pass
766
747
        test = Sample("a")
786
767
        class ShortDelayTestCase(tests.TestCase):
787
768
            def test_short_delay(self):
788
769
                time.sleep(0.003)
789
 
 
790
770
            def test_short_benchmark(self):
791
771
                self.time(time.sleep, 0.003)
792
772
        self.check_timing(ShortDelayTestCase('test_short_delay'),
809
789
 
810
790
        This is used to exercise the test framework.
811
791
        """
812
 
        self.time(text_type, b'hello', errors='replace')
813
 
        self.time(text_type, b'world', errors='replace')
 
792
        self.time(unicode, 'hello', errors='replace')
 
793
        self.time(unicode, 'world', errors='replace')
814
794
 
815
795
    def test_lsprofiling(self):
816
796
        """Verbose test result prints lsprof statistics from test cases."""
840
820
        # and then repeated but with 'world', rather than 'hello'.
841
821
        # this should appear in the output stream of our test result.
842
822
        output = result_stream.getvalue()
843
 
        if PY3:
844
 
            self.assertContainsRe(output,
845
 
                                  r"LSProf output for <class 'str'>\(\(b'hello',\), {'errors': 'replace'}\)")
846
 
            self.assertContainsRe(output,
847
 
                                  r"LSProf output for <class 'str'>\(\(b'world',\), {'errors': 'replace'}\)")
848
 
        else:
849
 
            self.assertContainsRe(output,
850
 
                                  r"LSProf output for <type 'unicode'>\(\('hello',\), {'errors': 'replace'}\)")
851
 
            self.assertContainsRe(output,
852
 
                                  r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
853
 
        self.assertContainsRe(output,
854
 
                              r" *CallCount *Recursive *Total\(ms\) *Inline\(ms\) *module:lineno\(function\)\n")
855
 
        self.assertContainsRe(output,
856
 
                              r"( +1 +0 +0\.\d+ +0\.\d+ +<method 'disable' of '_lsprof\.Profiler' objects>\n)?")
 
823
        self.assertContainsRe(output,
 
824
            r"LSProf output for <type 'unicode'>\(\('hello',\), {'errors': 'replace'}\)")
 
825
        self.assertContainsRe(output,
 
826
            r" *CallCount *Recursive *Total\(ms\) *Inline\(ms\) *module:lineno\(function\)\n")
 
827
        self.assertContainsRe(output,
 
828
            r"( +1 +0 +0\.\d+ +0\.\d+ +<method 'disable' of '_lsprof\.Profiler' objects>\n)?")
 
829
        self.assertContainsRe(output,
 
830
            r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
857
831
 
858
832
    def test_uses_time_from_testtools(self):
859
833
        """Test case timings in verbose results should use testtools times"""
860
834
        import datetime
861
 
 
862
835
        class TimeAddedVerboseTestResult(tests.VerboseTestResult):
863
836
            def startTest(self, test):
864
837
                self.time(datetime.datetime.utcfromtimestamp(1.145))
865
838
                super(TimeAddedVerboseTestResult, self).startTest(test)
866
 
 
867
839
            def addSuccess(self, test):
868
840
                self.time(datetime.datetime.utcfromtimestamp(51.147))
869
841
                super(TimeAddedVerboseTestResult, self).addSuccess(test)
870
 
 
871
842
            def report_tests_starting(self): pass
872
843
        sio = StringIO()
873
844
        self.get_passing_test().run(TimeAddedVerboseTestResult(sio, 0, 2))
877
848
        """Using knownFailure should trigger several result actions."""
878
849
        class InstrumentedTestResult(tests.ExtendedTestResult):
879
850
            def stopTestRun(self): pass
880
 
 
881
851
            def report_tests_starting(self): pass
882
 
 
883
852
            def report_known_failure(self, test, err=None, details=None):
884
853
                self._call = test, 'known failure'
885
854
        result = InstrumentedTestResult(None, None, None, None)
886
 
 
887
855
        class Test(tests.TestCase):
888
856
            def test_function(self):
889
857
                self.knownFailure('failed!')
910
878
            )
911
879
        _get_test("test_xfail").run(result)
912
880
        self.assertContainsRe(result_stream.getvalue(),
913
 
                              "\n\\S+\\.test_xfail\\s+XFAIL\\s+\\d+ms\n"
914
 
                              "\\s*(?:Text attachment: )?reason"
915
 
                              "(?:\n-+\n|: {{{)"
916
 
                              "this_fails"
917
 
                              "(?:\n-+\n|}}}\n)")
 
881
            "\n\\S+\\.test_xfail\\s+XFAIL\\s+\\d+ms\n"
 
882
            "\\s*(?:Text attachment: )?reason"
 
883
            "(?:\n-+\n|: {{{)"
 
884
            "this_fails"
 
885
            "(?:\n-+\n|}}}\n)")
918
886
 
919
887
    def get_passing_test(self):
920
888
        """Return a test object that can't be run usefully."""
926
894
        """Test the behaviour of invoking addNotSupported."""
927
895
        class InstrumentedTestResult(tests.ExtendedTestResult):
928
896
            def stopTestRun(self): pass
929
 
 
930
897
            def report_tests_starting(self): pass
931
 
 
932
898
            def report_unsupported(self, test, feature):
933
899
                self._call = test, feature
934
900
        result = InstrumentedTestResult(None, None, None, None)
972
938
    def test_unavailable_exception(self):
973
939
        """An UnavailableFeature being raised should invoke addNotSupported."""
974
940
        class InstrumentedTestResult(tests.ExtendedTestResult):
975
 
            def stopTestRun(self):
976
 
                pass
977
 
 
978
 
            def report_tests_starting(self):
979
 
                pass
980
 
 
 
941
            def stopTestRun(self): pass
 
942
            def report_tests_starting(self): pass
981
943
            def addNotSupported(self, test, feature):
982
944
                self._call = test, feature
983
945
        result = InstrumentedTestResult(None, None, None, None)
984
946
        feature = features.Feature()
985
 
 
986
947
        class Test(tests.TestCase):
987
948
            def test_function(self):
988
949
                raise tests.UnavailableFeature(feature)
1021
982
        """Starting the first test should trigger startTests."""
1022
983
        class InstrumentedTestResult(tests.ExtendedTestResult):
1023
984
            calls = 0
1024
 
 
1025
 
            def startTests(self):
1026
 
                self.calls += 1
 
985
            def startTests(self): self.calls += 1
1027
986
        result = InstrumentedTestResult(None, None, None, None)
1028
 
 
1029
987
        def test_function():
1030
988
            pass
1031
989
        test = unittest.FunctionTestCase(test_function)
1036
994
        """With multiple tests startTests should still only be called once"""
1037
995
        class InstrumentedTestResult(tests.ExtendedTestResult):
1038
996
            calls = 0
1039
 
 
1040
 
            def startTests(self):
1041
 
                self.calls += 1
 
997
            def startTests(self): self.calls += 1
1042
998
        result = InstrumentedTestResult(None, None, None, None)
1043
999
        suite = unittest.TestSuite([
1044
1000
            unittest.FunctionTestCase(lambda: None),
1078
1034
                self.expectFailure('failed', self.assertTrue, False)
1079
1035
        test = unittest.TestSuite()
1080
1036
        test.addTest(Test("known_failure_test"))
1081
 
 
1082
1037
        def failing_test():
1083
1038
            raise AssertionError('foo')
1084
1039
        test.addTest(unittest.FunctionTestCase(failing_test))
1085
1040
        stream = StringIO()
1086
1041
        runner = tests.TextTestRunner(stream=stream)
1087
 
        self.run_test_runner(runner, test)
1088
 
        self.assertContainsRe(
1089
 
            stream.getvalue(),
 
1042
        result = self.run_test_runner(runner, test)
 
1043
        lines = stream.getvalue().splitlines()
 
1044
        self.assertContainsRe(stream.getvalue(),
1090
1045
            '(?sm)^brz selftest.*$'
1091
1046
            '.*'
1092
1047
            '^======================================================================\n'
1093
1048
            '^FAIL: failing_test\n'
1094
1049
            '^----------------------------------------------------------------------\n'
1095
1050
            'Traceback \\(most recent call last\\):\n'
1096
 
            '  .*'  # File .*, line .*, in failing_test' - but maybe not from .pyc
 
1051
            '  .*' # File .*, line .*, in failing_test' - but maybe not from .pyc
1097
1052
            '    raise AssertionError\\(\'foo\'\\)\n'
1098
1053
            '.*'
1099
1054
            '^----------------------------------------------------------------------\n'
1110
1065
        test = Test("known_failure_test")
1111
1066
        stream = StringIO()
1112
1067
        runner = tests.TextTestRunner(stream=stream)
1113
 
        self.run_test_runner(runner, test)
 
1068
        result = self.run_test_runner(runner, test)
1114
1069
        self.assertContainsRe(stream.getvalue(),
1115
 
                              '\n'
1116
 
                              '-*\n'
1117
 
                              'Ran 1 test in .*\n'
1118
 
                              '\n'
1119
 
                              'OK \\(known_failures=1\\)\n')
 
1070
            '\n'
 
1071
            '-*\n'
 
1072
            'Ran 1 test in .*\n'
 
1073
            '\n'
 
1074
            'OK \\(known_failures=1\\)\n')
1120
1075
 
1121
1076
    def test_unexpected_success_bad(self):
1122
1077
        class Test(tests.TestCase):
1123
1078
            def test_truth(self):
1124
1079
                self.expectFailure("No absolute truth", self.assertTrue, True)
1125
1080
        runner = tests.TextTestRunner(stream=StringIO())
1126
 
        self.run_test_runner(runner, Test("test_truth"))
 
1081
        result = self.run_test_runner(runner, Test("test_truth"))
1127
1082
        self.assertContainsRe(runner.stream.getvalue(),
1128
 
                              "=+\n"
1129
 
                              "FAIL: \\S+\\.test_truth\n"
1130
 
                              "-+\n"
1131
 
                              "(?:.*\n)*"
1132
 
                              "\\s*(?:Text attachment: )?reason"
1133
 
                              "(?:\n-+\n|: {{{)"
1134
 
                              "No absolute truth"
1135
 
                              "(?:\n-+\n|}}}\n)"
1136
 
                              "(?:.*\n)*"
1137
 
                              "-+\n"
1138
 
                              "Ran 1 test in .*\n"
1139
 
                              "\n"
1140
 
                              "FAILED \\(failures=1\\)\n\\Z")
 
1083
            "=+\n"
 
1084
            "FAIL: \\S+\\.test_truth\n"
 
1085
            "-+\n"
 
1086
            "(?:.*\n)*"
 
1087
            "\\s*(?:Text attachment: )?reason"
 
1088
            "(?:\n-+\n|: {{{)"
 
1089
            "No absolute truth"
 
1090
            "(?:\n-+\n|}}}\n)"
 
1091
            "(?:.*\n)*"
 
1092
            "-+\n"
 
1093
            "Ran 1 test in .*\n"
 
1094
            "\n"
 
1095
            "FAILED \\(failures=1\\)\n\\Z")
1141
1096
 
1142
1097
    def test_result_decorator(self):
1143
1098
        # decorate results
1144
1099
        calls = []
1145
 
 
1146
1100
        class LoggingDecorator(ExtendedToOriginalDecorator):
1147
1101
            def startTest(self, test):
1148
1102
                ExtendedToOriginalDecorator.startTest(self, test)
1149
1103
                calls.append('start')
1150
 
        test = unittest.FunctionTestCase(lambda: None)
 
1104
        test = unittest.FunctionTestCase(lambda:None)
1151
1105
        stream = StringIO()
1152
1106
        runner = tests.TextTestRunner(stream=stream,
1153
 
                                      result_decorators=[LoggingDecorator])
1154
 
        self.run_test_runner(runner, test)
 
1107
            result_decorators=[LoggingDecorator])
 
1108
        result = self.run_test_runner(runner, test)
1155
1109
        self.assertLength(1, calls)
1156
1110
 
1157
1111
    def test_skipped_test(self):
1168
1122
 
1169
1123
    def test_skipped_from_setup(self):
1170
1124
        calls = []
1171
 
 
1172
1125
        class SkippedSetupTest(tests.TestCase):
1173
1126
 
1174
1127
            def setUp(self):
1191
1144
 
1192
1145
    def test_skipped_from_test(self):
1193
1146
        calls = []
1194
 
 
1195
1147
        class SkippedTest(tests.TestCase):
1196
1148
 
1197
1149
            def setUp(self):
1225
1177
        self.assertTrue(result.wasSuccessful())
1226
1178
        self.assertTrue(result.wasStrictlySuccessful())
1227
1179
        self.assertContainsRe(out.getvalue(),
1228
 
                              r'(?m)not_applicable_test  * N/A')
 
1180
                r'(?m)not_applicable_test  * N/A')
1229
1181
        self.assertContainsRe(out.getvalue(),
1230
 
                              r'(?m)^    this test never runs')
 
1182
                r'(?m)^    this test never runs')
1231
1183
 
1232
1184
    def test_unsupported_features_listed(self):
1233
1185
        """When unsupported features are encountered they are detailed."""
1234
1186
        class Feature1(features.Feature):
1235
 
            def _probe(self):
1236
 
                return False
1237
 
 
 
1187
            def _probe(self): return False
1238
1188
        class Feature2(features.Feature):
1239
 
            def _probe(self):
1240
 
                return False
 
1189
            def _probe(self): return False
1241
1190
        # create sample tests
1242
1191
        test1 = SampleTestCase('_test_pass')
1243
1192
        test1._test_needs_features = [Feature1()]
1248
1197
        test.addTest(test2)
1249
1198
        stream = StringIO()
1250
1199
        runner = tests.TextTestRunner(stream=stream)
1251
 
        self.run_test_runner(runner, test)
 
1200
        result = self.run_test_runner(runner, test)
1252
1201
        lines = stream.getvalue().splitlines()
1253
1202
        self.assertEqual([
1254
1203
            'OK',
1266
1215
        stream = StringIO()
1267
1216
        runner = tests.TextTestRunner(stream=stream, verbosity=2)
1268
1217
        # Need to use the CountingDecorator as that's what sets num_tests
1269
 
        self.run_test_runner(runner, tests.CountingDecorator(suite))
 
1218
        result = self.run_test_runner(runner, tests.CountingDecorator(suite))
1270
1219
        self.assertStartsWith(stream.getvalue(), "running 2 tests")
1271
1220
 
1272
1221
    def test_startTestRun(self):
1273
1222
        """run should call result.startTestRun()"""
1274
1223
        calls = []
1275
 
 
1276
1224
        class LoggingDecorator(ExtendedToOriginalDecorator):
1277
1225
            def startTestRun(self):
1278
1226
                ExtendedToOriginalDecorator.startTestRun(self)
1279
1227
                calls.append('startTestRun')
1280
 
        test = unittest.FunctionTestCase(lambda: None)
 
1228
        test = unittest.FunctionTestCase(lambda:None)
1281
1229
        stream = StringIO()
1282
1230
        runner = tests.TextTestRunner(stream=stream,
1283
 
                                      result_decorators=[LoggingDecorator])
1284
 
        self.run_test_runner(runner, test)
 
1231
            result_decorators=[LoggingDecorator])
 
1232
        result = self.run_test_runner(runner, test)
1285
1233
        self.assertLength(1, calls)
1286
1234
 
1287
1235
    def test_stopTestRun(self):
1288
1236
        """run should call result.stopTestRun()"""
1289
1237
        calls = []
1290
 
 
1291
1238
        class LoggingDecorator(ExtendedToOriginalDecorator):
1292
1239
            def stopTestRun(self):
1293
1240
                ExtendedToOriginalDecorator.stopTestRun(self)
1294
1241
                calls.append('stopTestRun')
1295
 
        test = unittest.FunctionTestCase(lambda: None)
 
1242
        test = unittest.FunctionTestCase(lambda:None)
1296
1243
        stream = StringIO()
1297
1244
        runner = tests.TextTestRunner(stream=stream,
1298
 
                                      result_decorators=[LoggingDecorator])
1299
 
        self.run_test_runner(runner, test)
 
1245
            result_decorators=[LoggingDecorator])
 
1246
        result = self.run_test_runner(runner, test)
1300
1247
        self.assertLength(1, calls)
1301
1248
 
1302
1249
    def test_unicode_test_output_on_ascii_stream(self):
1305
1252
            def test_log_unicode(self):
1306
1253
                self.log(u"\u2606")
1307
1254
                self.fail("Now print that log!")
1308
 
        if PY3:
1309
 
            bio = BytesIO()
1310
 
            out = TextIOWrapper(bio, 'ascii', 'backslashreplace')
1311
 
        else:
1312
 
            bio = out = StringIO()
 
1255
        out = StringIO()
1313
1256
        self.overrideAttr(osutils, "get_terminal_encoding",
1314
 
                          lambda trace=False: "ascii")
1315
 
        self.run_test_runner(
1316
 
            tests.TextTestRunner(stream=out),
 
1257
            lambda trace=False: "ascii")
 
1258
        result = self.run_test_runner(tests.TextTestRunner(stream=out),
1317
1259
            FailureWithUnicode("test_log_unicode"))
1318
 
        out.flush()
1319
 
        self.assertContainsRe(bio.getvalue(),
1320
 
                              b"(?:Text attachment: )?log"
1321
 
                              b"(?:\n-+\n|: {{{)"
1322
 
                              b"\\d+\\.\\d+  \\\\u2606"
1323
 
                              b"(?:\n-+\n|}}}\n)")
 
1260
        self.assertContainsRe(out.getvalue(),
 
1261
            "(?:Text attachment: )?log"
 
1262
            "(?:\n-+\n|: {{{)"
 
1263
            "\\d+\\.\\d+  \\\\u2606"
 
1264
            "(?:\n-+\n|}}}\n)")
1324
1265
 
1325
1266
 
1326
1267
class SampleTestCase(tests.TestCase):
1328
1269
    def _test_pass(self):
1329
1270
        pass
1330
1271
 
1331
 
 
1332
1272
class _TestException(Exception):
1333
1273
    pass
1334
1274
 
1351
1291
    def test_assertLength_shows_sequence_in_failure(self):
1352
1292
        a_list = [1, 2, 3]
1353
1293
        exception = self.assertRaises(AssertionError, self.assertLength, 2,
1354
 
                                      a_list)
 
1294
            a_list)
1355
1295
        self.assertEqual('Incorrect length: wanted 2, got 3 for [1, 2, 3]',
1356
 
                         exception.args[0])
 
1296
            exception.args[0])
1357
1297
 
1358
1298
    def test_base_setUp_not_called_causes_failure(self):
1359
1299
        class TestCaseWithBrokenSetUp(tests.TestCase):
1360
1300
            def setUp(self):
1361
 
                pass  # does not call TestCase.setUp
1362
 
 
 
1301
                pass # does not call TestCase.setUp
1363
1302
            def test_foo(self):
1364
1303
                pass
1365
1304
        test = TestCaseWithBrokenSetUp('test_foo')
1371
1310
    def test_base_tearDown_not_called_causes_failure(self):
1372
1311
        class TestCaseWithBrokenTearDown(tests.TestCase):
1373
1312
            def tearDown(self):
1374
 
                pass  # does not call TestCase.tearDown
1375
 
 
 
1313
                pass # does not call TestCase.tearDown
1376
1314
            def test_foo(self):
1377
1315
                pass
1378
1316
        test = TestCaseWithBrokenTearDown('test_foo')
1403
1341
        """
1404
1342
        self.change_selftest_debug_flags({'allow_debug'})
1405
1343
        breezy.debug.debug_flags = {'a-flag'}
1406
 
 
1407
1344
        class TestThatRecordsFlags(tests.TestCase):
1408
1345
            def test_foo(nested_self):
1409
1346
                self.flags = set(breezy.debug.debug_flags)
1454
1391
        self.change_selftest_debug_flags({'allow_debug'})
1455
1392
        # Now run a test that modifies debug.debug_flags.
1456
1393
        breezy.debug.debug_flags = {'original-state'}
1457
 
 
1458
1394
        class TestThatModifiesFlags(tests.TestCase):
1459
1395
            def test_foo(self):
1460
1396
                breezy.debug.debug_flags = {'modified'}
1503
1439
        self.time(time.sleep, 0.007)
1504
1440
 
1505
1441
    def test_time_creates_benchmark_in_result(self):
1506
 
        """The TestCase.time() method accumulates a benchmark time."""
 
1442
        """Test that the TestCase.time() method accumulates a benchmark time."""
1507
1443
        sample_test = TestTestCase("method_that_times_a_bit_twice")
1508
1444
        output_stream = StringIO()
1509
1445
        result = breezy.tests.VerboseTestResult(
1520
1456
        # Note this test won't fail with hooks that the core library doesn't
1521
1457
        # use - but it trigger with a plugin that adds hooks, so its still a
1522
1458
        # useful warning in that case.
1523
 
        self.assertEqual(breezy.branch.BranchHooks(),
1524
 
                         breezy.branch.Branch.hooks)
 
1459
        self.assertEqual(breezy.branch.BranchHooks(), breezy.branch.Branch.hooks)
1525
1460
        self.assertEqual(
1526
1461
            breezy.bzr.smart.server.SmartServerHooks(),
1527
1462
            breezy.bzr.smart.server.SmartTCPServer.hooks)
1551
1486
        self.assertRaises(tests.KnownFailure, self.knownFailure, "A Failure")
1552
1487
 
1553
1488
    def test_open_bzrdir_safe_roots(self):
1554
 
        # even a memory transport should fail to open when its url isn't
 
1489
        # even a memory transport should fail to open when its url isn't 
1555
1490
        # permitted.
1556
1491
        # Manually set one up (TestCase doesn't and shouldn't provide magic
1557
1492
        # machinery)
1561
1496
        t = transport.get_transport_from_url(transport_server.get_url())
1562
1497
        controldir.ControlDir.create(t.base)
1563
1498
        self.assertRaises(errors.BzrError,
1564
 
                          controldir.ControlDir.open_from_transport, t)
 
1499
            controldir.ControlDir.open_from_transport, t)
1565
1500
        # But if we declare this as safe, we can open the bzrdir.
1566
1501
        self.permit_url(t.base)
1567
1502
        self._bzr_selftest_roots.append(t.base)
1570
1505
    def test_requireFeature_available(self):
1571
1506
        """self.requireFeature(available) is a no-op."""
1572
1507
        class Available(features.Feature):
1573
 
            def _probe(self):
1574
 
                return True
 
1508
            def _probe(self):return True
1575
1509
        feature = Available()
1576
1510
        self.requireFeature(feature)
1577
1511
 
1578
1512
    def test_requireFeature_unavailable(self):
1579
1513
        """self.requireFeature(unavailable) raises UnavailableFeature."""
1580
1514
        class Unavailable(features.Feature):
1581
 
            def _probe(self):
1582
 
                return False
 
1515
            def _probe(self):return False
1583
1516
        feature = Unavailable()
1584
1517
        self.assertRaises(tests.UnavailableFeature,
1585
1518
                          self.requireFeature, feature)
1591
1524
    def test_run_enabled_unittest_result(self):
1592
1525
        """Test we revert to regular behaviour when the test is enabled."""
1593
1526
        test = SampleTestCase('_test_pass')
1594
 
 
1595
1527
        class EnabledFeature(object):
1596
1528
            def available(self):
1597
1529
                return True
1603
1535
        self.assertEqual([], result.failures)
1604
1536
 
1605
1537
    def test_run_disabled_unittest_result(self):
1606
 
        """Test our compatibility for disabled tests with unittest results."""
 
1538
        """Test our compatability for disabled tests with unittest results."""
1607
1539
        test = SampleTestCase('_test_pass')
1608
 
 
1609
1540
        class DisabledFeature(object):
1610
1541
            def available(self):
1611
1542
                return False
1619
1550
    def test_run_disabled_supporting_result(self):
1620
1551
        """Test disabled tests behaviour with support aware results."""
1621
1552
        test = SampleTestCase('_test_pass')
1622
 
 
1623
1553
        class DisabledFeature(object):
1624
1554
            def __eq__(self, other):
1625
1555
                return isinstance(other, DisabledFeature)
1626
 
 
1627
1556
            def available(self):
1628
1557
                return False
1629
1558
        the_feature = DisabledFeature()
1630
1559
        test._test_needs_features = [the_feature]
1631
 
 
1632
1560
        class InstrumentedTestResult(unittest.TestResult):
1633
1561
            def __init__(self):
1634
1562
                unittest.TestResult.__init__(self)
1635
1563
                self.calls = []
1636
 
 
1637
1564
            def startTest(self, test):
1638
1565
                self.calls.append(('startTest', test))
1639
 
 
1640
1566
            def stopTest(self, test):
1641
1567
                self.calls.append(('stopTest', test))
1642
 
 
1643
1568
            def addNotSupported(self, test, feature):
1644
1569
                self.calls.append(('addNotSupported', test, feature))
1645
1570
        result = InstrumentedTestResult()
1658
1583
        self.assertEqual([], self._bzr_selftest_roots)
1659
1584
        self.start_server(transport_server)
1660
1585
        self.assertSubset([transport_server.get_url()],
1661
 
                          self._bzr_selftest_roots)
 
1586
            self._bzr_selftest_roots)
1662
1587
 
1663
1588
    def test_assert_list_raises_on_generator(self):
1664
1589
        def generator_which_will_raise():
1696
1621
            raise _NotTestException()
1697
1622
 
1698
1623
        # Wrong exceptions are not intercepted
1699
 
        self.assertRaises(
1700
 
            _NotTestException,
 
1624
        self.assertRaises(_NotTestException,
1701
1625
            self.assertListRaises, _TestException, wrong_exception)
1702
 
        self.assertRaises(
1703
 
            _NotTestException,
 
1626
        self.assertRaises(_NotTestException,
1704
1627
            self.assertListRaises, _TestException, wrong_exception_generator)
1705
1628
 
1706
1629
    def test_assert_list_raises_no_exception(self):
1712
1635
            yield 2
1713
1636
 
1714
1637
        self.assertRaises(AssertionError,
1715
 
                          self.assertListRaises, _TestException, success)
 
1638
            self.assertListRaises, _TestException, success)
1716
1639
 
1717
 
        self.assertRaises(
1718
 
            AssertionError,
 
1640
        self.assertRaises(AssertionError,
1719
1641
            self.assertListRaises, _TestException, success_generator)
1720
1642
 
1721
1643
    def _run_successful_test(self, test):
1725
1647
        return result
1726
1648
 
1727
1649
    def test_overrideAttr_without_value(self):
1728
 
        self.test_attr = 'original'  # Define a test attribute
1729
 
        obj = self  # Make 'obj' visible to the embedded test
1730
 
 
 
1650
        self.test_attr = 'original' # Define a test attribute
 
1651
        obj = self # Make 'obj' visible to the embedded test
1731
1652
        class Test(tests.TestCase):
1732
1653
 
1733
1654
            def setUp(self):
1744
1665
        self.assertEqual('original', obj.test_attr)
1745
1666
 
1746
1667
    def test_overrideAttr_with_value(self):
1747
 
        self.test_attr = 'original'  # Define a test attribute
1748
 
        obj = self  # Make 'obj' visible to the embedded test
1749
 
 
 
1668
        self.test_attr = 'original' # Define a test attribute
 
1669
        obj = self # Make 'obj' visible to the embedded test
1750
1670
        class Test(tests.TestCase):
1751
1671
 
1752
1672
            def setUp(self):
1762
1682
 
1763
1683
    def test_overrideAttr_with_no_existing_value_and_value(self):
1764
1684
        # Do not define the test_attribute
1765
 
        obj = self  # Make 'obj' visible to the embedded test
1766
 
 
 
1685
        obj = self # Make 'obj' visible to the embedded test
1767
1686
        class Test(tests.TestCase):
1768
1687
 
1769
1688
            def setUp(self):
1779
1698
 
1780
1699
    def test_overrideAttr_with_no_existing_value_and_no_value(self):
1781
1700
        # Do not define the test_attribute
1782
 
        obj = self  # Make 'obj' visible to the embedded test
1783
 
 
 
1701
        obj = self # Make 'obj' visible to the embedded test
1784
1702
        class Test(tests.TestCase):
1785
1703
 
1786
1704
            def setUp(self):
1799
1717
        calls = self.recordCalls(
1800
1718
            test_selftest, '_add_numbers')
1801
1719
        self.assertEqual(test_selftest._add_numbers(2, 10),
1802
 
                         12)
 
1720
            12)
1803
1721
        self.assertEqual(calls, [((2, 10), {})])
1804
1722
 
1805
1723
 
1810
1728
class _MissingFeature(features.Feature):
1811
1729
    def _probe(self):
1812
1730
        return False
1813
 
 
1814
 
 
1815
1731
missing_feature = _MissingFeature()
1816
1732
 
1817
1733
 
1854
1770
    return ExampleTests(name)
1855
1771
 
1856
1772
 
 
1773
def _get_skip_reasons(result):
 
1774
    # GZ 2017-06-06: Newer testtools doesn't have this, uses detail instead
 
1775
    return result.skip_reasons
 
1776
 
 
1777
 
1857
1778
class TestTestCaseLogDetails(tests.TestCase):
1858
1779
 
1859
1780
    def _run_test(self, test_name):
1867
1788
        self.assertEqual(1, len(result.failures))
1868
1789
        result_content = result.failures[0][1]
1869
1790
        self.assertContainsRe(result_content,
1870
 
                              '(?m)^(?:Text attachment: )?log(?:$|: )')
 
1791
            '(?m)^(?:Text attachment: )?log(?:$|: )')
1871
1792
        self.assertContainsRe(result_content, 'this was a failing test')
1872
1793
 
1873
1794
    def test_error_has_log(self):
1875
1796
        self.assertEqual(1, len(result.errors))
1876
1797
        result_content = result.errors[0][1]
1877
1798
        self.assertContainsRe(result_content,
1878
 
                              '(?m)^(?:Text attachment: )?log(?:$|: )')
 
1799
            '(?m)^(?:Text attachment: )?log(?:$|: )')
1879
1800
        self.assertContainsRe(result_content, 'this test errored')
1880
1801
 
1881
1802
    def test_skip_has_no_log(self):
1882
1803
        result = self._run_test('test_skip')
1883
 
        reasons = result.skip_reasons
 
1804
        reasons = _get_skip_reasons(result)
1884
1805
        self.assertEqual({'reason'}, set(reasons))
1885
1806
        skips = reasons['reason']
1886
1807
        self.assertEqual(1, len(skips))
1891
1812
        # testtools doesn't know about addNotSupported, so it just gets
1892
1813
        # considered as a skip
1893
1814
        result = self._run_test('test_missing_feature')
1894
 
        reasons = result.skip_reasons
 
1815
        reasons = _get_skip_reasons(result)
1895
1816
        self.assertEqual({str(missing_feature)}, set(reasons))
1896
1817
        skips = reasons[str(missing_feature)]
1897
1818
        self.assertEqual(1, len(skips))
1903
1824
        self.assertEqual(1, len(result.expectedFailures))
1904
1825
        result_content = result.expectedFailures[0][1]
1905
1826
        self.assertNotContainsRe(result_content,
1906
 
                                 '(?m)^(?:Text attachment: )?log(?:$|: )')
 
1827
            '(?m)^(?:Text attachment: )?log(?:$|: )')
1907
1828
        self.assertNotContainsRe(result_content, 'test with expected failure')
1908
1829
 
1909
1830
    def test_unexpected_success_has_log(self):
1984
1905
        self.assertIsInstance(2, int)
1985
1906
        self.assertIsInstance(u'', (str, text_type))
1986
1907
        e = self.assertRaises(AssertionError, self.assertIsInstance, None, int)
1987
 
        self.assertIn(
1988
 
            str(e),
1989
 
            ["None is an instance of <type 'NoneType'> rather than "
1990
 
             "<type 'int'>",
1991
 
             "None is an instance of <class 'NoneType'> rather than "
1992
 
             "<class 'int'>"])
 
1908
        self.assertEqual(str(e),
 
1909
            "None is an instance of <type 'NoneType'> rather than <type 'int'>")
1993
1910
        self.assertRaises(AssertionError, self.assertIsInstance, 23.3, int)
1994
1911
        e = self.assertRaises(AssertionError,
1995
 
                              self.assertIsInstance, None, int,
1996
 
                              "it's just not")
1997
 
        if PY3:
1998
 
            self.assertEqual(
1999
 
                str(e),
2000
 
                "None is an instance of <class 'NoneType'> rather "
2001
 
                "than <class 'int'>: it's just not")
2002
 
        else:
2003
 
            self.assertEqual(
2004
 
                str(e),
2005
 
                "None is an instance of <type 'NoneType'> "
2006
 
                "rather than <type 'int'>: it's just not")
 
1912
            self.assertIsInstance, None, int, "it's just not")
 
1913
        self.assertEqual(str(e),
 
1914
            "None is an instance of <type 'NoneType'> rather than <type 'int'>"
 
1915
            ": it's just not")
2007
1916
 
2008
1917
    def test_assertEndsWith(self):
2009
1918
        self.assertEndsWith('foo', 'oo')
2013
1922
        e = self.assertRaises(AssertionError,
2014
1923
                              self.assertEqualDiff, '', '\n')
2015
1924
        self.assertEqual(str(e),
2016
 
                         # Don't blink ! The '+' applies to the second string
2017
 
                         'first string is missing a final newline.\n+ \n')
 
1925
                          # Don't blink ! The '+' applies to the second string
 
1926
                          'first string is missing a final newline.\n+ \n')
2018
1927
        e = self.assertRaises(AssertionError,
2019
1928
                              self.assertEqualDiff, '\n', '')
2020
1929
        self.assertEqual(str(e),
2021
 
                         # Don't blink ! The '-' applies to the second string
2022
 
                         'second string is missing a final newline.\n- \n')
 
1930
                          # Don't blink ! The '-' applies to the second string
 
1931
                          'second string is missing a final newline.\n- \n')
2023
1932
 
2024
1933
 
2025
1934
class TestDeprecations(tests.TestCase):
2028
1937
        sample_object = ApplyDeprecatedHelper()
2029
1938
        # calling an undeprecated callable raises an assertion
2030
1939
        self.assertRaises(AssertionError, self.applyDeprecated,
2031
 
                          deprecated_in((0, 11, 0)),
2032
 
                          sample_object.sample_normal_method)
 
1940
            deprecated_in((0, 11, 0)),
 
1941
            sample_object.sample_normal_method)
2033
1942
        self.assertRaises(AssertionError, self.applyDeprecated,
2034
 
                          deprecated_in((0, 11, 0)),
2035
 
                          sample_undeprecated_function, "a param value")
 
1943
            deprecated_in((0, 11, 0)),
 
1944
            sample_undeprecated_function, "a param value")
2036
1945
        # calling a deprecated callable (function or method) with the wrong
2037
1946
        # expected deprecation fails.
2038
1947
        self.assertRaises(AssertionError, self.applyDeprecated,
2039
 
                          deprecated_in((0, 10, 0)),
2040
 
                          sample_object.sample_deprecated_method,
2041
 
                          "a param value")
 
1948
            deprecated_in((0, 10, 0)),
 
1949
            sample_object.sample_deprecated_method, "a param value")
2042
1950
        self.assertRaises(AssertionError, self.applyDeprecated,
2043
 
                          deprecated_in((0, 10, 0)),
2044
 
                          sample_deprecated_function)
 
1951
            deprecated_in((0, 10, 0)),
 
1952
            sample_deprecated_function)
2045
1953
        # calling a deprecated callable (function or method) with the right
2046
1954
        # expected deprecation returns the functions result.
2047
 
        self.assertEqual(
2048
 
            "a param value",
2049
 
            self.applyDeprecated(
2050
 
                deprecated_in((0, 11, 0)),
2051
 
                sample_object.sample_deprecated_method, "a param value"))
 
1955
        self.assertEqual("a param value",
 
1956
            self.applyDeprecated(deprecated_in((0, 11, 0)),
 
1957
            sample_object.sample_deprecated_method, "a param value"))
2052
1958
        self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 11, 0)),
2053
 
                                                 sample_deprecated_function))
 
1959
            sample_deprecated_function))
2054
1960
        # calling a nested deprecation with the wrong deprecation version
2055
1961
        # fails even if a deeper nested function was deprecated with the
2056
1962
        # supplied version.
2057
 
        self.assertRaises(
2058
 
            AssertionError, self.applyDeprecated,
 
1963
        self.assertRaises(AssertionError, self.applyDeprecated,
2059
1964
            deprecated_in((0, 11, 0)), sample_object.sample_nested_deprecation)
2060
1965
        # calling a nested deprecation with the right deprecation value
2061
1966
        # returns the calls result.
2062
 
        self.assertEqual(
2063
 
            2, self.applyDeprecated(
2064
 
                deprecated_in((0, 10, 0)),
2065
 
                sample_object.sample_nested_deprecation))
 
1967
        self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 10, 0)),
 
1968
            sample_object.sample_nested_deprecation))
2066
1969
 
2067
1970
    def test_callDeprecated(self):
2068
1971
        def testfunc(be_deprecated, result=None):
2099
2002
 
2100
2003
    def test_make_branch_and_tree_with_format(self):
2101
2004
        # we should be able to supply a format to make_branch_and_tree
2102
 
        self.make_branch_and_tree(
2103
 
            'a', format=breezy.bzr.bzrdir.BzrDirMetaFormat1())
 
2005
        self.make_branch_and_tree('a', format=breezy.bzr.bzrdir.BzrDirMetaFormat1())
2104
2006
        self.assertIsInstance(breezy.controldir.ControlDir.open('a')._format,
2105
2007
                              breezy.bzr.bzrdir.BzrDirMetaFormat1)
2106
2008
 
2120
2022
        base = tree.controldir.root_transport.base
2121
2023
        self.assertStartsWith(base, 'file://')
2122
2024
        self.assertEqual(tree.controldir.root_transport,
2123
 
                         tree.branch.controldir.root_transport)
 
2025
                tree.branch.controldir.root_transport)
2124
2026
        self.assertEqual(tree.controldir.root_transport,
2125
 
                         tree.branch.repository.controldir.root_transport)
 
2027
                tree.branch.repository.controldir.root_transport)
2126
2028
 
2127
2029
 
2128
2030
class SelfTestHelper(object):
2129
2031
 
2130
2032
    def run_selftest(self, **kwargs):
2131
2033
        """Run selftest returning its output."""
2132
 
        if PY3:
2133
 
            bio = BytesIO()
2134
 
            output = TextIOWrapper(bio, 'utf-8')
2135
 
        else:
2136
 
            bio = output = StringIO()
 
2034
        output = StringIO()
2137
2035
        old_transport = breezy.tests.default_transport
2138
2036
        old_root = tests.TestCaseWithMemoryTransport.TEST_ROOT
2139
2037
        tests.TestCaseWithMemoryTransport.TEST_ROOT = None
2142
2040
        finally:
2143
2041
            breezy.tests.default_transport = old_transport
2144
2042
            tests.TestCaseWithMemoryTransport.TEST_ROOT = old_root
2145
 
        if PY3:
2146
 
            output.flush()
2147
 
            output.detach()
2148
 
        bio.seek(0)
2149
 
        return bio
 
2043
        output.seek(0)
 
2044
        return output
2150
2045
 
2151
2046
 
2152
2047
class TestSelftest(tests.TestCase, SelfTestHelper):
2153
2048
    """Tests of breezy.tests.selftest."""
2154
2049
 
2155
 
    def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(
2156
 
            self):
 
2050
    def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(self):
2157
2051
        factory_called = []
2158
 
 
2159
2052
        def factory():
2160
2053
            factory_called.append(True)
2161
2054
            return TestUtil.TestSuite()
2162
2055
        out = StringIO()
2163
2056
        err = StringIO()
2164
2057
        self.apply_redirected(out, err, None, breezy.tests.selftest,
2165
 
                              test_suite_factory=factory)
 
2058
            test_suite_factory=factory)
2166
2059
        self.assertEqual([True], factory_called)
2167
2060
 
2168
2061
    def factory(self):
2169
2062
        """A test suite factory."""
2170
2063
        class Test(tests.TestCase):
2171
 
            def id(self):
2172
 
                return __name__ + ".Test." + self._testMethodName
2173
 
 
2174
2064
            def a(self):
2175
2065
                pass
2176
 
 
2177
2066
            def b(self):
2178
2067
                pass
2179
 
 
2180
 
            def c(telf):
 
2068
            def c(self):
2181
2069
                pass
2182
2070
        return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
2183
2071
 
2184
2072
    def test_list_only(self):
2185
2073
        output = self.run_selftest(test_suite_factory=self.factory,
2186
 
                                   list_only=True)
 
2074
            list_only=True)
2187
2075
        self.assertEqual(3, len(output.readlines()))
2188
2076
 
2189
2077
    def test_list_only_filtered(self):
2190
2078
        output = self.run_selftest(test_suite_factory=self.factory,
2191
 
                                   list_only=True, pattern="Test.b")
2192
 
        self.assertEndsWith(output.getvalue(), b"Test.b\n")
 
2079
            list_only=True, pattern="Test.b")
 
2080
        self.assertEndsWith(output.getvalue(), "Test.b\n")
2193
2081
        self.assertLength(1, output.readlines())
2194
2082
 
2195
2083
    def test_list_only_excludes(self):
2196
2084
        output = self.run_selftest(test_suite_factory=self.factory,
2197
 
                                   list_only=True, exclude_pattern="Test.b")
2198
 
        self.assertNotContainsRe(b"Test.b", output.getvalue())
 
2085
            list_only=True, exclude_pattern="Test.b")
 
2086
        self.assertNotContainsRe("Test.b", output.getvalue())
2199
2087
        self.assertLength(2, output.readlines())
2200
2088
 
2201
2089
    def test_lsprof_tests(self):
2202
2090
        self.requireFeature(features.lsprof_feature)
2203
2091
        results = []
2204
 
 
2205
2092
        class Test(object):
2206
2093
            def __call__(test, result):
2207
2094
                test.run(result)
2208
 
 
2209
2095
            def run(test, result):
2210
2096
                results.append(result)
2211
 
 
2212
2097
            def countTestCases(self):
2213
2098
                return 1
2214
2099
        self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
2218
2103
    def test_random(self):
2219
2104
        # test randomising by listing a number of tests.
2220
2105
        output_123 = self.run_selftest(test_suite_factory=self.factory,
2221
 
                                       list_only=True, random_seed="123")
 
2106
            list_only=True, random_seed="123")
2222
2107
        output_234 = self.run_selftest(test_suite_factory=self.factory,
2223
 
                                       list_only=True, random_seed="234")
 
2108
            list_only=True, random_seed="234")
2224
2109
        self.assertNotEqual(output_123, output_234)
2225
2110
        # "Randominzing test order..\n\n
2226
2111
        self.assertLength(5, output_123.readlines())
2229
2114
    def test_random_reuse_is_same_order(self):
2230
2115
        # test randomising by listing a number of tests.
2231
2116
        expected = self.run_selftest(test_suite_factory=self.factory,
2232
 
                                     list_only=True, random_seed="123")
 
2117
            list_only=True, random_seed="123")
2233
2118
        repeated = self.run_selftest(test_suite_factory=self.factory,
2234
 
                                     list_only=True, random_seed="123")
 
2119
            list_only=True, random_seed="123")
2235
2120
        self.assertEqual(expected.getvalue(), repeated.getvalue())
2236
2121
 
2237
2122
    def test_runner_class(self):
2247
2132
 
2248
2133
    def test_starting_with_single_argument(self):
2249
2134
        output = self.run_selftest(test_suite_factory=self.factory,
2250
 
                                   starting_with=[
2251
 
                                       'breezy.tests.test_selftest.Test.a'],
2252
 
                                   list_only=True)
2253
 
        self.assertEqual(b'breezy.tests.test_selftest.Test.a\n',
2254
 
                         output.getvalue())
 
2135
            starting_with=['breezy.tests.test_selftest.Test.a'],
 
2136
            list_only=True)
 
2137
        self.assertEqual('breezy.tests.test_selftest.Test.a\n',
 
2138
            output.getvalue())
2255
2139
 
2256
2140
    def test_starting_with_multiple_argument(self):
2257
 
        output = self.run_selftest(
2258
 
            test_suite_factory=self.factory,
 
2141
        output = self.run_selftest(test_suite_factory=self.factory,
2259
2142
            starting_with=['breezy.tests.test_selftest.Test.a',
2260
 
                           'breezy.tests.test_selftest.Test.b'],
 
2143
                'breezy.tests.test_selftest.Test.b'],
2261
2144
            list_only=True)
2262
 
        self.assertEqual(b'breezy.tests.test_selftest.Test.a\n'
2263
 
                         b'breezy.tests.test_selftest.Test.b\n',
2264
 
                         output.getvalue())
 
2145
        self.assertEqual('breezy.tests.test_selftest.Test.a\n'
 
2146
            'breezy.tests.test_selftest.Test.b\n',
 
2147
            output.getvalue())
2265
2148
 
2266
2149
    def check_transport_set(self, transport_server):
2267
2150
        captured_transport = []
2268
 
 
2269
2151
        def seen_transport(a_transport):
2270
2152
            captured_transport.append(a_transport)
2271
 
 
2272
2153
        class Capture(tests.TestCase):
2273
2154
            def a(self):
2274
2155
                seen_transport(breezy.tests.default_transport)
2275
 
 
2276
2156
        def factory():
2277
2157
            return TestUtil.TestSuite([Capture("a")])
2278
 
        self.run_selftest(transport=transport_server,
2279
 
                          test_suite_factory=factory)
 
2158
        self.run_selftest(transport=transport_server, test_suite_factory=factory)
2280
2159
        self.assertEqual(transport_server, captured_transport[0])
2281
2160
 
2282
2161
    def test_transport_sftp(self):
2293
2172
 
2294
2173
    def test_load_list(self):
2295
2174
        # Provide a list with one test - this test.
2296
 
        test_id_line = b'%s\n' % self.id().encode('ascii')
 
2175
        test_id_line = b'%s\n' % self.id()
2297
2176
        self.build_tree_contents([('test.list', test_id_line)])
2298
2177
        # And generate a list of the tests in  the suite.
2299
2178
        stream = self.run_selftest(load_list='test.list', list_only=True)
2302
2181
    def test_load_unknown(self):
2303
2182
        # Provide a list with one test - this test.
2304
2183
        # And generate a list of the tests in  the suite.
2305
 
        self.assertRaises(errors.NoSuchFile, self.run_selftest,
2306
 
                          load_list='missing file name', list_only=True)
 
2184
        err = self.assertRaises(errors.NoSuchFile, self.run_selftest,
 
2185
            load_list='missing file name', list_only=True)
2307
2186
 
2308
2187
 
2309
2188
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2312
2191
 
2313
2192
    def run_subunit_stream(self, test_name):
2314
2193
        from subunit import ProtocolTestCase
2315
 
 
2316
2194
        def factory():
2317
2195
            return TestUtil.TestSuite([_get_test(test_name)])
2318
2196
        stream = self.run_selftest(
2327
2205
    def test_fail_has_log(self):
2328
2206
        content, result = self.run_subunit_stream('test_fail')
2329
2207
        self.assertEqual(1, len(result.failures))
2330
 
        self.assertContainsRe(content, b'(?m)^log$')
2331
 
        self.assertContainsRe(content, b'this test will fail')
 
2208
        self.assertContainsRe(content, '(?m)^log$')
 
2209
        self.assertContainsRe(content, 'this test will fail')
2332
2210
 
2333
2211
    def test_error_has_log(self):
2334
2212
        content, result = self.run_subunit_stream('test_error')
2335
 
        self.assertContainsRe(content, b'(?m)^log$')
2336
 
        self.assertContainsRe(content, b'this test errored')
 
2213
        self.assertContainsRe(content, '(?m)^log$')
 
2214
        self.assertContainsRe(content, 'this test errored')
2337
2215
 
2338
2216
    def test_skip_has_no_log(self):
2339
2217
        content, result = self.run_subunit_stream('test_skip')
2340
 
        self.assertNotContainsRe(content, b'(?m)^log$')
2341
 
        self.assertNotContainsRe(content, b'this test will be skipped')
2342
 
        reasons = result.skip_reasons
 
2218
        self.assertNotContainsRe(content, '(?m)^log$')
 
2219
        self.assertNotContainsRe(content, 'this test will be skipped')
 
2220
        reasons = _get_skip_reasons(result)
2343
2221
        self.assertEqual({'reason'}, set(reasons))
2344
2222
        skips = reasons['reason']
2345
2223
        self.assertEqual(1, len(skips))
2346
 
        # test = skips[0]
 
2224
        test = skips[0]
2347
2225
        # RemotedTestCase doesn't preserve the "details"
2348
 
        # self.assertFalse('log' in test.getDetails())
 
2226
        ## self.assertFalse('log' in test.getDetails())
2349
2227
 
2350
2228
    def test_missing_feature_has_no_log(self):
2351
2229
        content, result = self.run_subunit_stream('test_missing_feature')
2352
 
        self.assertNotContainsRe(content, b'(?m)^log$')
2353
 
        self.assertNotContainsRe(content, b'missing the feature')
2354
 
        reasons = result.skip_reasons
 
2230
        self.assertNotContainsRe(content, '(?m)^log$')
 
2231
        self.assertNotContainsRe(content, 'missing the feature')
 
2232
        reasons = _get_skip_reasons(result)
2355
2233
        self.assertEqual({'_MissingFeature\n'}, set(reasons))
2356
2234
        skips = reasons['_MissingFeature\n']
2357
2235
        self.assertEqual(1, len(skips))
2358
 
        # test = skips[0]
 
2236
        test = skips[0]
2359
2237
        # RemotedTestCase doesn't preserve the "details"
2360
 
        # self.assertFalse('log' in test.getDetails())
 
2238
        ## self.assertFalse('log' in test.getDetails())
2361
2239
 
2362
2240
    def test_xfail_has_no_log(self):
2363
2241
        content, result = self.run_subunit_stream('test_xfail')
2364
 
        self.assertNotContainsRe(content, b'(?m)^log$')
2365
 
        self.assertNotContainsRe(content, b'test with expected failure')
 
2242
        self.assertNotContainsRe(content, '(?m)^log$')
 
2243
        self.assertNotContainsRe(content, 'test with expected failure')
2366
2244
        self.assertEqual(1, len(result.expectedFailures))
2367
2245
        result_content = result.expectedFailures[0][1]
2368
2246
        self.assertNotContainsRe(result_content,
2369
 
                                 '(?m)^(?:Text attachment: )?log(?:$|: )')
 
2247
            '(?m)^(?:Text attachment: )?log(?:$|: )')
2370
2248
        self.assertNotContainsRe(result_content, 'test with expected failure')
2371
2249
 
2372
2250
    def test_unexpected_success_has_log(self):
2373
2251
        content, result = self.run_subunit_stream('test_unexpected_success')
2374
 
        self.assertContainsRe(content, b'(?m)^log$')
2375
 
        self.assertContainsRe(content, b'test with unexpected success')
 
2252
        self.assertContainsRe(content, '(?m)^log$')
 
2253
        self.assertContainsRe(content, 'test with unexpected success')
 
2254
        # GZ 2011-05-18: Old versions of subunit treat unexpected success as a
 
2255
        #                success, if a min version check is added remove this
 
2256
        from subunit import TestProtocolClient as _Client
 
2257
        if _Client.addUnexpectedSuccess.__func__ is _Client.addSuccess.__func__:
 
2258
            self.expectFailure('subunit treats "unexpectedSuccess"'
 
2259
                               ' as a plain success',
 
2260
                self.assertEqual, 1, len(result.unexpectedSuccesses))
2376
2261
        self.assertEqual(1, len(result.unexpectedSuccesses))
2377
 
        # test = result.unexpectedSuccesses[0]
 
2262
        test = result.unexpectedSuccesses[0]
2378
2263
        # RemotedTestCase doesn't preserve the "details"
2379
 
        # self.assertTrue('log' in test.getDetails())
 
2264
        ## self.assertTrue('log' in test.getDetails())
2380
2265
 
2381
2266
    def test_success_has_no_log(self):
2382
2267
        content, result = self.run_subunit_stream('test_success')
2383
2268
        self.assertEqual(1, result.testsRun)
2384
 
        self.assertNotContainsRe(content, b'(?m)^log$')
2385
 
        self.assertNotContainsRe(content, b'this test succeeds')
 
2269
        self.assertNotContainsRe(content, '(?m)^log$')
 
2270
        self.assertNotContainsRe(content, 'this test succeeds')
2386
2271
 
2387
2272
 
2388
2273
class TestRunBzr(tests.TestCase):
2389
2274
 
2390
 
    result = 0
2391
2275
    out = ''
2392
2276
    err = ''
2393
2277
 
2394
 
    def _run_bzr_core(self, argv, encoding=None, stdin=None,
2395
 
                      stdout=None, stderr=None, working_dir=None):
 
2278
    def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None,
 
2279
                         working_dir=None):
2396
2280
        """Override _run_bzr_core to test how it is invoked by run_bzr.
2397
2281
 
2398
2282
        Attempts to run bzr from inside this class don't actually run it.
2401
2285
        only need to test that it passes the right parameters to run_bzr.
2402
2286
        """
2403
2287
        self.argv = list(argv)
 
2288
        self.retcode = retcode
2404
2289
        self.encoding = encoding
2405
2290
        self.stdin = stdin
2406
2291
        self.working_dir = working_dir
2407
 
        stdout.write(self.out)
2408
 
        stderr.write(self.err)
2409
 
        return self.result
 
2292
        return self.retcode, self.out, self.err
2410
2293
 
2411
2294
    def test_run_bzr_error(self):
2412
2295
        self.out = "It sure does!\n"
2413
 
        self.result = 34
2414
2296
        out, err = self.run_bzr_error(['^$'], ['rocks'], retcode=34)
2415
2297
        self.assertEqual(['rocks'], self.argv)
 
2298
        self.assertEqual(34, self.retcode)
2416
2299
        self.assertEqual('It sure does!\n', out)
2417
2300
        self.assertEqual(out, self.out)
2418
2301
        self.assertEqual('', err)
2421
2304
    def test_run_bzr_error_regexes(self):
2422
2305
        self.out = ''
2423
2306
        self.err = "bzr: ERROR: foobarbaz is not versioned"
2424
 
        self.result = 3
2425
2307
        out, err = self.run_bzr_error(
2426
2308
            ["bzr: ERROR: foobarbaz is not versioned"],
2427
2309
            ['file-id', 'foobarbaz'])
2429
2311
    def test_encoding(self):
2430
2312
        """Test that run_bzr passes encoding to _run_bzr_core"""
2431
2313
        self.run_bzr('foo bar')
2432
 
        self.assertEqual(osutils.get_user_encoding(), self.encoding)
 
2314
        self.assertEqual(None, self.encoding)
2433
2315
        self.assertEqual(['foo', 'bar'], self.argv)
2434
2316
 
2435
2317
        self.run_bzr('foo bar', encoding='baz')
2436
2318
        self.assertEqual('baz', self.encoding)
2437
2319
        self.assertEqual(['foo', 'bar'], self.argv)
2438
2320
 
 
2321
    def test_retcode(self):
 
2322
        """Test that run_bzr passes retcode to _run_bzr_core"""
 
2323
        # Default is retcode == 0
 
2324
        self.run_bzr('foo bar')
 
2325
        self.assertEqual(0, self.retcode)
 
2326
        self.assertEqual(['foo', 'bar'], self.argv)
 
2327
 
 
2328
        self.run_bzr('foo bar', retcode=1)
 
2329
        self.assertEqual(1, self.retcode)
 
2330
        self.assertEqual(['foo', 'bar'], self.argv)
 
2331
 
 
2332
        self.run_bzr('foo bar', retcode=None)
 
2333
        self.assertEqual(None, self.retcode)
 
2334
        self.assertEqual(['foo', 'bar'], self.argv)
 
2335
 
 
2336
        self.run_bzr(['foo', 'bar'], retcode=3)
 
2337
        self.assertEqual(3, self.retcode)
 
2338
        self.assertEqual(['foo', 'bar'], self.argv)
 
2339
 
2439
2340
    def test_stdin(self):
2440
2341
        # test that the stdin keyword to run_bzr is passed through to
2441
2342
        # _run_bzr_core as-is. We do this by overriding
2530
2431
 
2531
2432
class StubProcess(object):
2532
2433
    """A stub process for testing run_bzr_subprocess."""
2533
 
 
 
2434
    
2534
2435
    def __init__(self, out="", err="", retcode=0):
2535
2436
        self.out = out
2536
2437
        self.err = err
2552
2453
                             working_dir=None,
2553
2454
                             allow_plugins=False):
2554
2455
        """capture what run_bzr_subprocess tries to do."""
2555
 
        self.subprocess_calls.append(
2556
 
            {'process_args': process_args,
2557
 
             'env_changes': env_changes,
2558
 
             'skip_if_plan_to_signal': skip_if_plan_to_signal,
2559
 
             'working_dir': working_dir, 'allow_plugins': allow_plugins})
 
2456
        self.subprocess_calls.append({'process_args':process_args,
 
2457
            'env_changes':env_changes,
 
2458
            'skip_if_plan_to_signal':skip_if_plan_to_signal,
 
2459
            'working_dir':working_dir, 'allow_plugins':allow_plugins})
2560
2460
        return self.next_subprocess
2561
2461
 
2562
2462
 
2572
2472
        self.next_subprocess = process
2573
2473
        try:
2574
2474
            result = self.run_bzr_subprocess(*args, **kwargs)
2575
 
        except BaseException:
 
2475
        except:
2576
2476
            self.next_subprocess = None
2577
2477
            for key, expected in expected_args.items():
2578
2478
                self.assertEqual(expected, self.subprocess_calls[-1][key])
2585
2485
 
2586
2486
    def test_run_bzr_subprocess(self):
2587
2487
        """The run_bzr_helper_external command behaves nicely."""
2588
 
        self.assertRunBzrSubprocess({'process_args': ['--version']},
2589
 
                                    StubProcess(), '--version')
2590
 
        self.assertRunBzrSubprocess({'process_args': ['--version']},
2591
 
                                    StubProcess(), ['--version'])
 
2488
        self.assertRunBzrSubprocess({'process_args':['--version']},
 
2489
            StubProcess(), '--version')
 
2490
        self.assertRunBzrSubprocess({'process_args':['--version']},
 
2491
            StubProcess(), ['--version'])
2592
2492
        # retcode=None disables retcode checking
2593
 
        result = self.assertRunBzrSubprocess(
2594
 
            {}, StubProcess(retcode=3), '--version', retcode=None)
2595
 
        result = self.assertRunBzrSubprocess(
2596
 
            {}, StubProcess(out="is free software"), '--version')
 
2493
        result = self.assertRunBzrSubprocess({},
 
2494
            StubProcess(retcode=3), '--version', retcode=None)
 
2495
        result = self.assertRunBzrSubprocess({},
 
2496
            StubProcess(out="is free software"), '--version')
2597
2497
        self.assertContainsRe(result[0], 'is free software')
2598
2498
        # Running a subcommand that is missing errors
2599
2499
        self.assertRaises(AssertionError, self.assertRunBzrSubprocess,
2600
 
                          {'process_args': ['--versionn']
2601
 
                           }, StubProcess(retcode=3),
2602
 
                          '--versionn')
 
2500
            {'process_args':['--versionn']}, StubProcess(retcode=3),
 
2501
            '--versionn')
2603
2502
        # Unless it is told to expect the error from the subprocess
2604
 
        result = self.assertRunBzrSubprocess(
2605
 
            {}, StubProcess(retcode=3), '--versionn', retcode=3)
 
2503
        result = self.assertRunBzrSubprocess({},
 
2504
            StubProcess(retcode=3), '--versionn', retcode=3)
2606
2505
        # Or to ignore retcode checking
2607
 
        result = self.assertRunBzrSubprocess(
2608
 
            {}, StubProcess(err="unknown command", retcode=3),
2609
 
            '--versionn', retcode=None)
 
2506
        result = self.assertRunBzrSubprocess({},
 
2507
            StubProcess(err="unknown command", retcode=3), '--versionn',
 
2508
            retcode=None)
2610
2509
        self.assertContainsRe(result[1], 'unknown command')
2611
2510
 
2612
2511
    def test_env_change_passes_through(self):
2613
2512
        self.assertRunBzrSubprocess(
2614
 
            {'env_changes': {'new': 'value', 'changed': 'newvalue', 'deleted': None}},
 
2513
            {'env_changes':{'new':'value', 'changed':'newvalue', 'deleted':None}},
2615
2514
            StubProcess(), '',
2616
 
            env_changes={'new': 'value', 'changed': 'newvalue', 'deleted': None})
 
2515
            env_changes={'new':'value', 'changed':'newvalue', 'deleted':None})
2617
2516
 
2618
2517
    def test_no_working_dir_passed_as_None(self):
2619
2518
        self.assertRunBzrSubprocess({'working_dir': None}, StubProcess(), '')
2620
2519
 
2621
2520
    def test_no_working_dir_passed_through(self):
2622
2521
        self.assertRunBzrSubprocess({'working_dir': 'dir'}, StubProcess(), '',
2623
 
                                    working_dir='dir')
 
2522
            working_dir='dir')
2624
2523
 
2625
2524
    def test_run_bzr_subprocess_no_plugins(self):
2626
2525
        self.assertRunBzrSubprocess({'allow_plugins': False},
2627
 
                                    StubProcess(), '')
 
2526
            StubProcess(), '')
2628
2527
 
2629
2528
    def test_allow_plugins(self):
2630
2529
        self.assertRunBzrSubprocess({'allow_plugins': True},
2631
 
                                    StubProcess(), '', allow_plugins=True)
 
2530
            StubProcess(), '', allow_plugins=True)
2632
2531
 
2633
2532
 
2634
2533
class TestFinishBzrSubprocess(TestWithFakedStartBzrSubprocess):
2696
2595
    def test_set_env(self):
2697
2596
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2698
2597
        # set in the child
2699
 
 
2700
2598
        def check_environment():
2701
2599
            self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2702
2600
        self.check_popen_state = check_environment
2703
2601
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2704
 
                          env_changes={'EXISTANT_ENV_VAR': 'set variable'})
 
2602
                          env_changes={'EXISTANT_ENV_VAR':'set variable'})
2705
2603
        # not set in theparent
2706
2604
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2707
2605
 
2708
2606
    def test_run_bzr_subprocess_env_del(self):
2709
2607
        """run_bzr_subprocess can remove environment variables too."""
2710
2608
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2711
 
 
2712
2609
        def check_environment():
2713
2610
            self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2714
2611
        os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2715
2612
        self.check_popen_state = check_environment
2716
2613
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2717
 
                          env_changes={'EXISTANT_ENV_VAR': None})
 
2614
                          env_changes={'EXISTANT_ENV_VAR':None})
2718
2615
        # Still set in parent
2719
2616
        self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2720
2617
        del os.environ['EXISTANT_ENV_VAR']
2721
2618
 
2722
2619
    def test_env_del_missing(self):
2723
2620
        self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2724
 
 
2725
2621
        def check_environment():
2726
2622
            self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2727
2623
        self.check_popen_state = check_environment
2728
2624
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2729
 
                          env_changes={'NON_EXISTANT_ENV_VAR': None})
 
2625
                          env_changes={'NON_EXISTANT_ENV_VAR':None})
2730
2626
 
2731
2627
    def test_working_dir(self):
2732
2628
        """Test that we can specify the working dir for the child"""
 
2629
        orig_getcwd = osutils.getcwd
 
2630
        orig_chdir = os.chdir
2733
2631
        chdirs = []
2734
 
 
2735
2632
        def chdir(path):
2736
2633
            chdirs.append(path)
2737
2634
        self.overrideAttr(os, 'chdir', chdir)
2738
 
 
2739
2635
        def getcwd():
2740
2636
            return 'current'
2741
2637
        self.overrideAttr(osutils, 'getcwd', getcwd)
2759
2655
        self.disable_missing_extensions_warning()
2760
2656
        process = self.start_bzr_subprocess(['wait-until-signalled'],
2761
2657
                                            skip_if_plan_to_signal=True)
2762
 
        self.assertEqual(b'running\n', process.stdout.readline())
 
2658
        self.assertEqual('running\n', process.stdout.readline())
2763
2659
        result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT,
2764
2660
                                            retcode=3)
2765
 
        self.assertEqual(b'', result[0])
2766
 
        self.assertEqual(b'brz: interrupted\n', result[1])
 
2661
        self.assertEqual('', result[0])
 
2662
        self.assertEqual('brz: interrupted\n', result[1])
2767
2663
 
2768
2664
 
2769
2665
class TestSelftestFiltering(tests.TestCase):
2778
2674
 
2779
2675
    def test_condition_id_re(self):
2780
2676
        test_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2781
 
                     'test_condition_id_re')
 
2677
            'test_condition_id_re')
2782
2678
        filtered_suite = tests.filter_suite_by_condition(
2783
2679
            self.suite, tests.condition_id_re('test_condition_id_re'))
2784
2680
        self.assertEqual([test_name], _test_ids(filtered_suite))
2797
2693
        klass = 'breezy.tests.test_selftest.TestSelftestFiltering.'
2798
2694
        start1 = klass + 'test_condition_id_starts'
2799
2695
        start2 = klass + 'test_condition_id_in'
2800
 
        test_names = [klass + 'test_condition_id_in_list',
 
2696
        test_names = [ klass + 'test_condition_id_in_list',
2801
2697
                      klass + 'test_condition_id_startswith',
2802
 
                      ]
 
2698
                     ]
2803
2699
        filtered_suite = tests.filter_suite_by_condition(
2804
2700
            self.suite, tests.condition_id_startswith([start1, start2]))
2805
2701
        self.assertEqual(test_names, _test_ids(filtered_suite))
2813
2709
 
2814
2710
    def test_exclude_tests_by_condition(self):
2815
2711
        excluded_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2816
 
                         'test_exclude_tests_by_condition')
2817
 
        filtered_suite = tests.exclude_tests_by_condition(
2818
 
            self.suite, lambda x: x.id() == excluded_name)
 
2712
            'test_exclude_tests_by_condition')
 
2713
        filtered_suite = tests.exclude_tests_by_condition(self.suite,
 
2714
            lambda x:x.id() == excluded_name)
2819
2715
        self.assertEqual(len(self.all_names) - 1,
2820
 
                         filtered_suite.countTestCases())
 
2716
            filtered_suite.countTestCases())
2821
2717
        self.assertFalse(excluded_name in _test_ids(filtered_suite))
2822
2718
        remaining_names = list(self.all_names)
2823
2719
        remaining_names.remove(excluded_name)
2828
2724
        filtered_suite = tests.exclude_tests_by_re(self.suite,
2829
2725
                                                   'exclude_tests_by_re')
2830
2726
        excluded_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2831
 
                         'test_exclude_tests_by_re')
 
2727
            'test_exclude_tests_by_re')
2832
2728
        self.assertEqual(len(self.all_names) - 1,
2833
 
                         filtered_suite.countTestCases())
 
2729
            filtered_suite.countTestCases())
2834
2730
        self.assertFalse(excluded_name in _test_ids(filtered_suite))
2835
2731
        remaining_names = list(self.all_names)
2836
2732
        remaining_names.remove(excluded_name)
2838
2734
 
2839
2735
    def test_filter_suite_by_condition(self):
2840
2736
        test_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2841
 
                     'test_filter_suite_by_condition')
2842
 
        filtered_suite = tests.filter_suite_by_condition(
2843
 
            self.suite, lambda x: x.id() == test_name)
 
2737
            'test_filter_suite_by_condition')
 
2738
        filtered_suite = tests.filter_suite_by_condition(self.suite,
 
2739
            lambda x:x.id() == test_name)
2844
2740
        self.assertEqual([test_name], _test_ids(filtered_suite))
2845
2741
 
2846
2742
    def test_filter_suite_by_re(self):
2847
2743
        filtered_suite = tests.filter_suite_by_re(self.suite,
2848
2744
                                                  'test_filter_suite_by_r')
2849
2745
        filtered_names = _test_ids(filtered_suite)
2850
 
        self.assertEqual(
2851
 
            filtered_names, ['breezy.tests.test_selftest.'
2852
 
                             'TestSelftestFiltering.test_filter_suite_by_re'])
 
2746
        self.assertEqual(filtered_names, ['breezy.tests.test_selftest.'
 
2747
            'TestSelftestFiltering.test_filter_suite_by_re'])
2853
2748
 
2854
2749
    def test_filter_suite_by_id_list(self):
2855
2750
        test_list = ['breezy.tests.test_selftest.'
2880
2775
 
2881
2776
    def test_preserve_input(self):
2882
2777
        # NB: Surely this is something in the stdlib to do this?
2883
 
        self.assertIs(self.suite, tests.preserve_input(self.suite))
2884
 
        self.assertEqual("@#$", tests.preserve_input("@#$"))
 
2778
        self.assertTrue(self.suite is tests.preserve_input(self.suite))
 
2779
        self.assertTrue("@#$" is tests.preserve_input("@#$"))
2885
2780
 
2886
2781
    def test_randomize_suite(self):
2887
2782
        randomized_suite = tests.randomize_suite(self.suite)
2903
2798
        condition = tests.condition_id_re('test_filter_suite_by_r')
2904
2799
        split_suite = tests.split_suite_by_condition(self.suite, condition)
2905
2800
        filtered_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2906
 
                         'test_filter_suite_by_re')
 
2801
            'test_filter_suite_by_re')
2907
2802
        self.assertEqual([filtered_name], _test_ids(split_suite[0]))
2908
2803
        self.assertFalse(filtered_name in _test_ids(split_suite[1]))
2909
2804
        remaining_names = list(self.all_names)
2915
2810
        split_suite = tests.split_suite_by_re(self.suite,
2916
2811
                                              'test_filter_suite_by_r')
2917
2812
        filtered_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2918
 
                         'test_filter_suite_by_re')
 
2813
            'test_filter_suite_by_re')
2919
2814
        self.assertEqual([filtered_name], _test_ids(split_suite[0]))
2920
2815
        self.assertFalse(filtered_name in _test_ids(split_suite[1]))
2921
2816
        remaining_names = list(self.all_names)
2964
2859
        self.permit_url(url)
2965
2860
        out, err = self.run_bzr(["log", "%s/nonexistantpath" % url], retcode=3)
2966
2861
        self.assertEqual(out, '')
2967
 
        self.assertContainsRe(
2968
 
            err, 'brz: ERROR: Not a branch: ".*nonexistantpath/".\n')
 
2862
        self.assertContainsRe(err,
 
2863
            'brz: ERROR: Not a branch: ".*nonexistantpath/".\n')
2969
2864
 
2970
2865
 
2971
2866
class TestTestLoader(tests.TestCase):
2975
2870
        """Gets a TestLoader and a module with one test in it."""
2976
2871
        loader = TestUtil.TestLoader()
2977
2872
        module = {}
2978
 
 
2979
2873
        class Stub(tests.TestCase):
2980
2874
            def test_foo(self):
2981
2875
                pass
2982
 
 
2983
2876
        class MyModule(object):
2984
2877
            pass
2985
2878
        MyModule.a_class = Stub
2989
2882
 
2990
2883
    def test_module_no_load_tests_attribute_loads_classes(self):
2991
2884
        loader, module = self._get_loader_and_module()
2992
 
        self.assertEqual(1, loader.loadTestsFromModule(
2993
 
            module).countTestCases())
 
2885
        self.assertEqual(1, loader.loadTestsFromModule(module).countTestCases())
2994
2886
 
2995
2887
    def test_module_load_tests_attribute_gets_called(self):
2996
2888
        loader, module = self._get_loader_and_module()
2997
 
 
2998
2889
        def load_tests(loader, standard_tests, pattern):
2999
2890
            result = loader.suiteClass()
3000
2891
            for test in tests.iter_suite_tests(standard_tests):
3010
2901
        loader = TestUtil.TestLoader()
3011
2902
        suite = loader.loadTestsFromModuleName('breezy.tests.test_sampler')
3012
2903
        self.assertEqual(['breezy.tests.test_sampler.DemoTest.test_nothing'],
3013
 
                         _test_ids(suite))
 
2904
                          _test_ids(suite))
3014
2905
 
3015
2906
    def test_load_tests_from_module_name_with_bogus_module_name(self):
3016
2907
        loader = TestUtil.TestLoader()
3033
2924
 
3034
2925
        suite = TestUtil.TestSuite()
3035
2926
        for id in test_id_list:
3036
 
            t = Stub('test_foo')
 
2927
            t  = Stub('test_foo')
3037
2928
            t.id = _create_test_id(id)
3038
2929
            suite.addTest(t)
3039
2930
        return suite
3087
2978
        dupes = loader.suiteClass()
3088
2979
        for test in tests.iter_suite_tests(suite):
3089
2980
            dupes.addTest(test)
3090
 
            dupes.addTest(test)  # Add it again
 
2981
            dupes.addTest(test) # Add it again
3091
2982
 
3092
 
        test_list = ['breezy.tests.test_sampler.DemoTest.test_nothing', ]
 
2983
        test_list = ['breezy.tests.test_sampler.DemoTest.test_nothing',]
3093
2984
        not_found, duplicates = tests.suite_matches_id_list(
3094
2985
            dupes, test_list)
3095
2986
        self.assertEqual([], not_found)
3096
2987
        self.assertEqual(['breezy.tests.test_sampler.DemoTest.test_nothing'],
3097
 
                         duplicates)
 
2988
                          duplicates)
3098
2989
 
3099
2990
 
3100
2991
class TestTestSuite(tests.TestCase):
3126
3017
    def test_test_suite(self):
3127
3018
        # test_suite() loads the entire test suite to operate. To avoid this
3128
3019
        # overhead, and yet still be confident that things are happening,
3129
 
        # we temporarily replace two functions used by test_suite with
 
3020
        # we temporarily replace two functions used by test_suite with 
3130
3021
        # test doubles that supply a few sample tests to load, and check they
3131
3022
        # are loaded.
3132
3023
        calls = []
3133
 
 
3134
3024
        def testmod_names():
3135
3025
            calls.append("testmod_names")
3136
3026
            return [
3139
3029
                'breezy.tests.test_selftest',
3140
3030
                ]
3141
3031
        self.overrideAttr(tests, '_test_suite_testmod_names', testmod_names)
3142
 
 
3143
3032
        def doctests():
3144
3033
            calls.append("modules_to_doctest")
3145
3034
            if __doc__ is None:
3155
3044
            # plugins can't be tested that way since selftest may be run with
3156
3045
            # --no-plugins
3157
3046
            ]
3158
 
        if __doc__ is not None and not PY3:
 
3047
        if __doc__ is not None:
3159
3048
            expected_test_list.extend([
3160
3049
                # modules_to_doctest
3161
3050
                'breezy.timestamp.format_highres_date',
3162
3051
                ])
3163
3052
        suite = tests.test_suite()
3164
 
        if PY3:
3165
 
            self.assertEqual({"testmod_names"}, set(calls))
3166
 
        else:
3167
 
            self.assertEqual({"testmod_names", "modules_to_doctest"},
3168
 
                             set(calls))
 
3053
        self.assertEqual({"testmod_names", "modules_to_doctest"},
 
3054
            set(calls))
3169
3055
        self.assertSubset(expected_test_list, _test_ids(suite))
3170
3056
 
3171
3057
    def test_test_suite_list_and_start(self):
3172
 
        # We cannot test this at the same time as the main load, because we
3173
 
        # want to know that starting_with == None works. So a second load is
3174
 
        # incurred - note that the starting_with parameter causes a partial
3175
 
        # load rather than a full load so this test should be pretty quick.
3176
 
        test_list = [
3177
 
            'breezy.tests.test_selftest.TestTestSuite.test_test_suite']
 
3058
        # We cannot test this at the same time as the main load, because we want
 
3059
        # to know that starting_with == None works. So a second load is
 
3060
        # incurred - note that the starting_with parameter causes a partial load
 
3061
        # rather than a full load so this test should be pretty quick.
 
3062
        test_list = ['breezy.tests.test_selftest.TestTestSuite.test_test_suite']
3178
3063
        suite = tests.test_suite(test_list,
3179
3064
                                 ['breezy.tests.test_selftest.TestTestSuite'])
3180
 
        # test_test_suite_list_and_start is not included
 
3065
        # test_test_suite_list_and_start is not included 
3181
3066
        self.assertEqual(test_list, _test_ids(suite))
3182
3067
 
3183
3068
 
3257
3142
        self.assertEqual(test_list, _test_ids(suite))
3258
3143
 
3259
3144
    def test_exclude_tests(self):
 
3145
        test_list = ['bogus']
3260
3146
        loader = self._create_loader('bogus')
3261
3147
 
3262
3148
        suite = loader.loadTestsFromModuleName('breezy.tests.test_sampler')
3280
3166
        tpr.register('bar', 'bBB.aAA.rRR')
3281
3167
        self.assertEqual('bbb.aaa.rrr', tpr.get('bar'))
3282
3168
        self.assertThat(self.get_log(),
3283
 
                        DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
3284
 
                                       doctest.ELLIPSIS))
 
3169
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
 
3170
                           doctest.ELLIPSIS))
3285
3171
 
3286
3172
    def test_get_unknown_prefix(self):
3287
3173
        tpr = self._get_registry()
3314
3200
        def __init__(self):
3315
3201
            tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3316
3202
            self.leaks = []
3317
 
 
3318
3203
        def _report_thread_leak(self, test, leaks, alive):
3319
3204
            self.leaks.append((test, leaks))
3320
3205
 
3330
3215
        result.stopTestRun()
3331
3216
        self.assertEqual(result._tests_leaking_threads_count, 0)
3332
3217
        self.assertEqual(result.leaks, [])
3333
 
 
 
3218
        
3334
3219
    def test_thread_leak(self):
3335
3220
        """Ensure a thread that outlives the running of a test is reported
3336
3221
 
3341
3226
        """
3342
3227
        event = threading.Event()
3343
3228
        thread = threading.Thread(name="Leaker", target=event.wait)
3344
 
 
3345
3229
        class Test(tests.TestCase):
3346
3230
            def test_leak(self):
3347
3231
                thread.start()
3367
3251
        thread_a = threading.Thread(name="LeakerA", target=event.wait)
3368
3252
        thread_b = threading.Thread(name="LeakerB", target=event.wait)
3369
3253
        thread_c = threading.Thread(name="LeakerC", target=event.wait)
3370
 
 
3371
3254
        class Test(tests.TestCase):
3372
3255
            def test_first_leak(self):
3373
3256
                thread_b.start()
3374
 
 
3375
3257
            def test_second_no_leak(self):
3376
3258
                pass
3377
 
 
3378
3259
            def test_third_leak(self):
3379
3260
                thread_c.start()
3380
3261
                thread_a.start()
3405
3286
        def __init__(self):
3406
3287
            tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3407
3288
            self.postcode = None
3408
 
 
3409
3289
        def _post_mortem(self, tb=None):
3410
3290
            """Record the code object at the end of the current traceback"""
3411
3291
            tb = tb or sys.exc_info()[2]
3415
3295
                    tb = next
3416
3296
                    next = next.tb_next
3417
3297
                self.postcode = tb.tb_frame.f_code
3418
 
 
3419
3298
        def report_error(self, test, err):
3420
3299
            pass
3421
 
 
3422
3300
        def report_failure(self, test, err):
3423
3301
            pass
3424
3302
 
3480
3358
                pass
3481
3359
        suite = Stub("test_foo")
3482
3360
        calls = []
3483
 
 
3484
3361
        class MyRunner(tests.TextTestRunner):
3485
3362
            def run(self, test):
3486
3363
                calls.append(test)
3497
3374
        """To be overridden by subclasses that run tests out of process"""
3498
3375
 
3499
3376
    def _run_selftest(self, **kwargs):
3500
 
        if PY3:
3501
 
            bio = BytesIO()
3502
 
            sio = TextIOWrapper(bio, 'utf-8')
3503
 
        else:
3504
 
            sio = bio = StringIO()
3505
 
        self._inject_stream_into_subunit(bio)
 
3377
        sio = StringIO()
 
3378
        self._inject_stream_into_subunit(sio)
3506
3379
        tests.selftest(stream=sio, stop_on_failure=False, **kwargs)
3507
 
        sio.flush()
3508
 
        return bio.getvalue()
 
3380
        return sio.getvalue()
3509
3381
 
3510
3382
 
3511
3383
class _ForkedSelftest(_Selftest):
3521
3393
        """
3522
3394
        from subunit import ProtocolTestCase
3523
3395
        _original_init = ProtocolTestCase.__init__
3524
 
 
3525
3396
        def _init_with_passthrough(self, *args, **kwargs):
3526
3397
            _original_init(self, *args, **kwargs)
3527
3398
            self._passthrough = stream
3552
3423
        # together due to the way subunit parses and forwards the streams,
3553
3424
        # so permit extra lines between each part of the error output.
3554
3425
        self.assertContainsRe(out,
3555
 
                              b"Traceback.*:\n"
3556
 
                              b"(?:.*\n)*"
3557
 
                              b".+ in fork_for_tests\n"
3558
 
                              b"(?:.*\n)*"
3559
 
                              b"\\s*workaround_zealous_crypto_random\\(\\)\n"
3560
 
                              b"(?:.*\n)*"
3561
 
                              b"TypeError:")
 
3426
            "Traceback.*:\n"
 
3427
            "(?:.*\n)*"
 
3428
            ".+ in fork_for_tests\n"
 
3429
            "(?:.*\n)*"
 
3430
            "\\s*workaround_zealous_crypto_random\\(\\)\n"
 
3431
            "(?:.*\n)*"
 
3432
            "TypeError:")
3562
3433
 
3563
3434
 
3564
3435
class TestUncollectedWarnings(_Selftest, tests.TestCase):
3567
3438
    class Test(tests.TestCase):
3568
3439
        def test_pass(self):
3569
3440
            pass
3570
 
 
3571
3441
        def test_self_ref(self):
3572
3442
            self.also_self = self.test_self_ref
3573
 
 
3574
3443
        def test_skip(self):
3575
3444
            self.skipTest("Don't need")
3576
3445
 
3589
3458
            gc.disable()
3590
3459
        try:
3591
3460
            output = self._run_selftest(test_suite_factory=self._get_suite,
3592
 
                                        **kwargs)
 
3461
                **kwargs)
3593
3462
        finally:
3594
3463
            if gc_on:
3595
3464
                gc.enable()
3596
3465
            tests.selftest_debug_flags = old_flags
3597
 
        self.assertNotContainsRe(output, b"Uncollected test case.*test_pass")
3598
 
        self.assertContainsRe(output, b"Uncollected test case.*test_self_ref")
 
3466
        self.assertNotContainsRe(output, "Uncollected test case.*test_pass")
 
3467
        self.assertContainsRe(output, "Uncollected test case.*test_self_ref")
3599
3468
        return output
3600
3469
 
3601
3470
    def test_testsuite(self):
3603
3472
 
3604
3473
    def test_pattern(self):
3605
3474
        out = self._run_selftest_with_suite(pattern="test_(?:pass|self_ref)$")
3606
 
        self.assertNotContainsRe(out, b"test_skip")
 
3475
        self.assertNotContainsRe(out, "test_skip")
3607
3476
 
3608
3477
    def test_exclude_pattern(self):
3609
3478
        out = self._run_selftest_with_suite(exclude_pattern="test_skip$")
3610
 
        self.assertNotContainsRe(out, b"test_skip")
 
3479
        self.assertNotContainsRe(out, "test_skip")
3611
3480
 
3612
3481
    def test_random_seed(self):
3613
3482
        self._run_selftest_with_suite(random_seed="now")
3614
3483
 
3615
3484
    def test_matching_tests_first(self):
3616
3485
        self._run_selftest_with_suite(matching_tests_first=True,
3617
 
                                      pattern="test_self_ref$")
 
3486
            pattern="test_self_ref$")
3618
3487
 
3619
3488
    def test_starting_with_and_exclude(self):
3620
3489
        out = self._run_selftest_with_suite(starting_with=["bt."],
3621
 
                                            exclude_pattern="test_skip$")
3622
 
        self.assertNotContainsRe(out, b"test_skip")
 
3490
            exclude_pattern="test_skip$")
 
3491
        self.assertNotContainsRe(out, "test_skip")
3623
3492
 
3624
3493
    def test_additonal_decorator(self):
3625
 
        self._run_selftest_with_suite(suite_decorators=[tests.TestDecorator])
 
3494
        out = self._run_selftest_with_suite(
 
3495
            suite_decorators=[tests.TestDecorator])
3626
3496
 
3627
3497
 
3628
3498
class TestUncollectedWarningsSubunit(TestUncollectedWarnings):
3645
3515
        self.assertFalse('MYVAR' in os.environ)
3646
3516
        self.overrideEnv('MYVAR', '42')
3647
3517
        # We use an embedded test to make sure we fix the _captureVar bug
3648
 
 
3649
3518
        class Test(tests.TestCase):
3650
3519
            def test_me(self):
3651
3520
                # The first call save the 42 value
3793
3662
            def id(self):
3794
3663
                # We don't need the full class path
3795
3664
                return self._testMethodName
3796
 
 
3797
3665
            def a(self):
3798
3666
                pass
3799
 
 
3800
3667
            def b(self):
3801
3668
                pass
3802
 
 
3803
3669
            def c(self):
3804
3670
                pass
3805
3671
        return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3827
3693
 
3828
3694
    def setUp(self):
3829
3695
        super(TestCounterHooks, self).setUp()
3830
 
 
3831
3696
        class Test(tests.TestCase):
3832
3697
 
3833
3698
            def setUp(self):