~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_selftest.py

Abbreviate pack_stat struct format to '>6L'

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
from testtools import (
30
30
    ExtendedToOriginalDecorator,
31
31
    MultiTestResult,
 
32
    __version__ as testtools_version,
32
33
    )
33
34
from testtools.content import Content
34
35
from testtools.content_type import ContentType
36
37
    DocTestMatches,
37
38
    Equals,
38
39
    )
39
 
import testtools.tests.helpers
 
40
import testtools.testresult.doubles
40
41
 
41
42
import bzrlib
42
43
from bzrlib import (
43
44
    branchbuilder,
44
45
    bzrdir,
45
46
    errors,
 
47
    hooks,
46
48
    lockdir,
47
49
    memorytree,
48
50
    osutils,
92
94
            DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
93
95
 
94
96
 
95
 
class TestUnicodeFilename(tests.TestCase):
96
 
 
97
 
    def test_probe_passes(self):
98
 
        """UnicodeFilename._probe passes."""
99
 
        # We can't test much more than that because the behaviour depends
100
 
        # on the platform.
101
 
        tests.UnicodeFilename._probe()
102
 
 
103
 
 
104
97
class TestTreeShape(tests.TestCaseInTempDir):
105
98
 
106
99
    def test_unicode_paths(self):
107
 
        self.requireFeature(tests.UnicodeFilename)
 
100
        self.requireFeature(features.UnicodeFilenameFeature)
108
101
 
109
102
        filename = u'hell\u00d8'
110
103
        self.build_tree_contents([(filename, 'contents of hello')])
626
619
    def test_dangling_locks_cause_failures(self):
627
620
        class TestDanglingLock(tests.TestCaseWithMemoryTransport):
628
621
            def test_function(self):
629
 
                t = self.get_transport('.')
 
622
                t = self.get_transport_from_path('.')
630
623
                l = lockdir.LockDir(t, 'lock')
631
624
                l.create()
632
625
                l.attempt_lock()
652
645
        # for the server
653
646
        url = self.get_readonly_url()
654
647
        url2 = self.get_readonly_url('foo/bar')
655
 
        t = transport.get_transport(url)
656
 
        t2 = transport.get_transport(url2)
 
648
        t = transport.get_transport_from_url(url)
 
649
        t2 = transport.get_transport_from_url(url2)
657
650
        self.assertIsInstance(t, ReadonlyTransportDecorator)
658
651
        self.assertIsInstance(t2, ReadonlyTransportDecorator)
659
652
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
667
660
        url = self.get_readonly_url()
668
661
        url2 = self.get_readonly_url('foo/bar')
669
662
        # the transport returned may be any HttpTransportBase subclass
670
 
        t = transport.get_transport(url)
671
 
        t2 = transport.get_transport(url2)
 
663
        t = transport.get_transport_from_url(url)
 
664
        t2 = transport.get_transport_from_url(url2)
672
665
        self.assertIsInstance(t, HttpTransportBase)
673
666
        self.assertIsInstance(t2, HttpTransportBase)
674
667
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
712
705
class TestChrootedTest(tests.ChrootedTestCase):
713
706
 
714
707
    def test_root_is_root(self):
715
 
        t = transport.get_transport(self.get_readonly_url())
 
708
        t = transport.get_transport_from_url(self.get_readonly_url())
716
709
        url = t.base
717
710
        self.assertEqual(url, t.clone('..').base)
718
711
 
720
713
class TestProfileResult(tests.TestCase):
721
714
 
722
715
    def test_profiles_tests(self):
723
 
        self.requireFeature(test_lsprof.LSProfFeature)
724
 
        terminal = testtools.tests.helpers.ExtendedTestResult()
 
716
        self.requireFeature(features.lsprof_feature)
 
717
        terminal = testtools.testresult.doubles.ExtendedTestResult()
725
718
        result = tests.ProfileResult(terminal)
726
719
        class Sample(tests.TestCase):
727
720
            def a(self):
744
737
                descriptions=0,
745
738
                verbosity=1,
746
739
                )
747
 
        capture = testtools.tests.helpers.ExtendedTestResult()
 
740
        capture = testtools.testresult.doubles.ExtendedTestResult()
748
741
        test_case.run(MultiTestResult(result, capture))
749
742
        run_case = capture._events[0][1]
750
743
        timed_string = result._testTimeString(run_case)
781
774
 
782
775
    def test_lsprofiling(self):
783
776
        """Verbose test result prints lsprof statistics from test cases."""
784
 
        self.requireFeature(test_lsprof.LSProfFeature)
 
777
        self.requireFeature(features.lsprof_feature)
785
778
        result_stream = StringIO()
786
779
        result = bzrlib.tests.VerboseTestResult(
787
780
            result_stream,
832
825
        self.assertEndsWith(sio.getvalue(), "OK    50002ms\n")
833
826
 
834
827
    def test_known_failure(self):
835
 
        """A KnownFailure being raised should trigger several result actions."""
 
828
        """Using knownFailure should trigger several result actions."""
836
829
        class InstrumentedTestResult(tests.ExtendedTestResult):
837
830
            def stopTestRun(self): pass
838
831
            def report_tests_starting(self): pass
841
834
        result = InstrumentedTestResult(None, None, None, None)
842
835
        class Test(tests.TestCase):
843
836
            def test_function(self):
844
 
                raise tests.KnownFailure('failed!')
 
837
                self.knownFailure('failed!')
845
838
        test = Test("test_function")
846
839
        test.run(result)
847
840
        # it should invoke 'report_known_failure'.
863
856
            descriptions=0,
864
857
            verbosity=2,
865
858
            )
866
 
        test = self.get_passing_test()
867
 
        result.startTest(test)
868
 
        prefix = len(result_stream.getvalue())
869
 
        # the err parameter has the shape:
870
 
        # (class, exception object, traceback)
871
 
        # KnownFailures dont get their tracebacks shown though, so we
872
 
        # can skip that.
873
 
        err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
874
 
        result.report_known_failure(test, err)
875
 
        output = result_stream.getvalue()[prefix:]
876
 
        lines = output.splitlines()
877
 
        self.assertContainsRe(lines[0], r'XFAIL *\d+ms$')
878
 
        if sys.version_info > (2, 7):
879
 
            self.expectFailure("_ExpectedFailure on 2.7 loses the message",
880
 
                self.assertNotEqual, lines[1], '    ')
881
 
        self.assertEqual(lines[1], '    foo')
882
 
        self.assertEqual(2, len(lines))
 
859
        _get_test("test_xfail").run(result)
 
860
        self.assertContainsRe(result_stream.getvalue(),
 
861
            "\n\\S+\\.test_xfail\\s+XFAIL\\s+\\d+ms\n"
 
862
            "\\s*(?:Text attachment: )?reason"
 
863
            "(?:\n-+\n|: {{{)"
 
864
            "this_fails"
 
865
            "(?:\n-+\n|}}}\n)")
883
866
 
884
867
    def get_passing_test(self):
885
868
        """Return a test object that can't be run usefully."""
896
879
                self._call = test, feature
897
880
        result = InstrumentedTestResult(None, None, None, None)
898
881
        test = SampleTestCase('_test_pass')
899
 
        feature = tests.Feature()
 
882
        feature = features.Feature()
900
883
        result.startTest(test)
901
884
        result.addNotSupported(test, feature)
902
885
        # it should invoke 'report_unsupported'.
921
904
            verbosity=2,
922
905
            )
923
906
        test = self.get_passing_test()
924
 
        feature = tests.Feature()
 
907
        feature = features.Feature()
925
908
        result.startTest(test)
926
909
        prefix = len(result_stream.getvalue())
927
910
        result.report_unsupported(test, feature)
940
923
            def addNotSupported(self, test, feature):
941
924
                self._call = test, feature
942
925
        result = InstrumentedTestResult(None, None, None, None)
943
 
        feature = tests.Feature()
 
926
        feature = features.Feature()
944
927
        class Test(tests.TestCase):
945
928
            def test_function(self):
946
929
                raise tests.UnavailableFeature(feature)
965
948
    def test_strict_with_known_failure(self):
966
949
        result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
967
950
                                             verbosity=1)
968
 
        test = self.get_passing_test()
969
 
        err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
970
 
        result.addExpectedFailure(test, err)
 
951
        test = _get_test("test_xfail")
 
952
        test.run(result)
971
953
        self.assertFalse(result.wasStrictlySuccessful())
972
954
        self.assertEqual(None, result._extractBenchmarkTime(test))
973
955
 
1005
987
        self.assertEquals(2, result.count)
1006
988
 
1007
989
 
1008
 
class TestUnicodeFilenameFeature(tests.TestCase):
1009
 
 
1010
 
    def test_probe_passes(self):
1011
 
        """UnicodeFilenameFeature._probe passes."""
1012
 
        # We can't test much more than that because the behaviour depends
1013
 
        # on the platform.
1014
 
        tests.UnicodeFilenameFeature._probe()
1015
 
 
1016
 
 
1017
990
class TestRunner(tests.TestCase):
1018
991
 
1019
992
    def dummy_test(self):
1045
1018
        test = unittest.TestSuite()
1046
1019
        test.addTest(Test("known_failure_test"))
1047
1020
        def failing_test():
1048
 
            self.fail('foo')
 
1021
            raise AssertionError('foo')
1049
1022
        test.addTest(unittest.FunctionTestCase(failing_test))
1050
1023
        stream = StringIO()
1051
1024
        runner = tests.TextTestRunner(stream=stream)
1059
1032
            '^----------------------------------------------------------------------\n'
1060
1033
            'Traceback \\(most recent call last\\):\n'
1061
1034
            '  .*' # File .*, line .*, in failing_test' - but maybe not from .pyc
1062
 
            '    self.fail\\(\'foo\'\\)\n'
 
1035
            '    raise AssertionError\\(\'foo\'\\)\n'
1063
1036
            '.*'
1064
1037
            '^----------------------------------------------------------------------\n'
1065
1038
            '.*'
1071
1044
        # the final output.
1072
1045
        class Test(tests.TestCase):
1073
1046
            def known_failure_test(self):
1074
 
                self.expectFailure('failed', self.assertTrue, False)
 
1047
                self.knownFailure("Never works...")
1075
1048
        test = Test("known_failure_test")
1076
1049
        stream = StringIO()
1077
1050
        runner = tests.TextTestRunner(stream=stream)
1083
1056
            '\n'
1084
1057
            'OK \\(known_failures=1\\)\n')
1085
1058
 
 
1059
    def test_unexpected_success_bad(self):
 
1060
        class Test(tests.TestCase):
 
1061
            def test_truth(self):
 
1062
                self.expectFailure("No absolute truth", self.assertTrue, True)
 
1063
        runner = tests.TextTestRunner(stream=StringIO())
 
1064
        result = self.run_test_runner(runner, Test("test_truth"))
 
1065
        if testtools_version[:3] <= (0, 9, 11):
 
1066
            self.assertContainsRe(runner.stream.getvalue(),
 
1067
                "=+\n"
 
1068
                "FAIL: \\S+\.test_truth\n"
 
1069
                "-+\n"
 
1070
                "(?:.*\n)*"
 
1071
                "No absolute truth\n"
 
1072
                "(?:.*\n)*"
 
1073
                "-+\n"
 
1074
                "Ran 1 test in .*\n"
 
1075
                "\n"
 
1076
                "FAILED \\(failures=1\\)\n\\Z")
 
1077
        else:
 
1078
            self.assertContainsRe(runner.stream.getvalue(),
 
1079
                "=+\n"
 
1080
                "FAIL: \\S+\.test_truth\n"
 
1081
                "-+\n"
 
1082
                "Empty attachments:\n"
 
1083
                "  log\n"
 
1084
                "\n"
 
1085
                "reason: {{{No absolute truth}}}\n"
 
1086
                "-+\n"
 
1087
                "Ran 1 test in .*\n"
 
1088
                "\n"
 
1089
                "FAILED \\(failures=1\\)\n\\Z")
 
1090
 
1086
1091
    def test_result_decorator(self):
1087
1092
        # decorate results
1088
1093
        calls = []
1172
1177
 
1173
1178
    def test_unsupported_features_listed(self):
1174
1179
        """When unsupported features are encountered they are detailed."""
1175
 
        class Feature1(tests.Feature):
 
1180
        class Feature1(features.Feature):
1176
1181
            def _probe(self): return False
1177
 
        class Feature2(tests.Feature):
 
1182
        class Feature2(features.Feature):
1178
1183
            def _probe(self): return False
1179
1184
        # create sample tests
1180
1185
        test1 = SampleTestCase('_test_pass')
1246
1251
            lambda trace=False: "ascii")
1247
1252
        result = self.run_test_runner(tests.TextTestRunner(stream=out),
1248
1253
            FailureWithUnicode("test_log_unicode"))
1249
 
        self.assertContainsRe(out.getvalue(),
1250
 
            "Text attachment: log\n"
1251
 
            "-+\n"
1252
 
            "\d+\.\d+  \\\\u2606\n"
1253
 
            "-+\n")
 
1254
        if testtools_version[:3] > (0, 9, 11):
 
1255
            self.assertContainsRe(out.getvalue(), "log: {{{\d+\.\d+  \\\\u2606}}}")
 
1256
        else:
 
1257
            self.assertContainsRe(out.getvalue(),
 
1258
                "Text attachment: log\n"
 
1259
                "-+\n"
 
1260
                "\d+\.\d+  \\\\u2606\n"
 
1261
                "-+\n")
1254
1262
 
1255
1263
 
1256
1264
class SampleTestCase(tests.TestCase):
1457
1465
 
1458
1466
        Each self.time() call is individually and separately profiled.
1459
1467
        """
1460
 
        self.requireFeature(test_lsprof.LSProfFeature)
 
1468
        self.requireFeature(features.lsprof_feature)
1461
1469
        # overrides the class member with an instance member so no cleanup
1462
1470
        # needed.
1463
1471
        self._gather_lsprof_in_benchmarks = True
1482
1490
        transport_server = memory.MemoryServer()
1483
1491
        transport_server.start_server()
1484
1492
        self.addCleanup(transport_server.stop_server)
1485
 
        t = transport.get_transport(transport_server.get_url())
 
1493
        t = transport.get_transport_from_url(transport_server.get_url())
1486
1494
        bzrdir.BzrDir.create(t.base)
1487
1495
        self.assertRaises(errors.BzrError,
1488
1496
            bzrdir.BzrDir.open_from_transport, t)
1493
1501
 
1494
1502
    def test_requireFeature_available(self):
1495
1503
        """self.requireFeature(available) is a no-op."""
1496
 
        class Available(tests.Feature):
 
1504
        class Available(features.Feature):
1497
1505
            def _probe(self):return True
1498
1506
        feature = Available()
1499
1507
        self.requireFeature(feature)
1500
1508
 
1501
1509
    def test_requireFeature_unavailable(self):
1502
1510
        """self.requireFeature(unavailable) raises UnavailableFeature."""
1503
 
        class Unavailable(tests.Feature):
 
1511
        class Unavailable(features.Feature):
1504
1512
            def _probe(self):return False
1505
1513
        feature = Unavailable()
1506
1514
        self.assertRaises(tests.UnavailableFeature,
1665
1673
        test.run(unittest.TestResult())
1666
1674
        self.assertEqual('original', obj.test_attr)
1667
1675
 
1668
 
 
1669
 
class _MissingFeature(tests.Feature):
 
1676
    def test_recordCalls(self):
 
1677
        from bzrlib.tests import test_selftest
 
1678
        calls = self.recordCalls(
 
1679
            test_selftest, '_add_numbers')
 
1680
        self.assertEqual(test_selftest._add_numbers(2, 10),
 
1681
            12)
 
1682
        self.assertEquals(calls, [((2, 10), {})])
 
1683
 
 
1684
 
 
1685
def _add_numbers(a, b):
 
1686
    return a + b
 
1687
 
 
1688
 
 
1689
class _MissingFeature(features.Feature):
1670
1690
    def _probe(self):
1671
1691
        return False
1672
1692
missing_feature = _MissingFeature()
1723
1743
        result = self._run_test('test_fail')
1724
1744
        self.assertEqual(1, len(result.failures))
1725
1745
        result_content = result.failures[0][1]
1726
 
        self.assertContainsRe(result_content, 'Text attachment: log')
 
1746
        if testtools_version < (0, 9, 12):
 
1747
            self.assertContainsRe(result_content, 'Text attachment: log')
1727
1748
        self.assertContainsRe(result_content, 'this was a failing test')
1728
1749
 
1729
1750
    def test_error_has_log(self):
1730
1751
        result = self._run_test('test_error')
1731
1752
        self.assertEqual(1, len(result.errors))
1732
1753
        result_content = result.errors[0][1]
1733
 
        self.assertContainsRe(result_content, 'Text attachment: log')
 
1754
        if testtools_version < (0, 9, 12):
 
1755
            self.assertContainsRe(result_content, 'Text attachment: log')
1734
1756
        self.assertContainsRe(result_content, 'this test errored')
1735
1757
 
1736
1758
    def test_skip_has_no_log(self):
2018
2040
        self.assertLength(2, output.readlines())
2019
2041
 
2020
2042
    def test_lsprof_tests(self):
2021
 
        self.requireFeature(test_lsprof.LSProfFeature)
2022
 
        calls = []
 
2043
        self.requireFeature(features.lsprof_feature)
 
2044
        results = []
2023
2045
        class Test(object):
2024
2046
            def __call__(test, result):
2025
2047
                test.run(result)
2026
2048
            def run(test, result):
2027
 
                self.assertIsInstance(result, ExtendedToOriginalDecorator)
2028
 
                calls.append("called")
 
2049
                results.append(result)
2029
2050
            def countTestCases(self):
2030
2051
                return 1
2031
2052
        self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
2032
 
        self.assertLength(1, calls)
 
2053
        self.assertLength(1, results)
 
2054
        self.assertIsInstance(results.pop(), ExtendedToOriginalDecorator)
2033
2055
 
2034
2056
    def test_random(self):
2035
2057
        # test randomising by listing a number of tests.
2177
2199
        content, result = self.run_subunit_stream('test_unexpected_success')
2178
2200
        self.assertContainsRe(content, '(?m)^log$')
2179
2201
        self.assertContainsRe(content, 'test with unexpected success')
2180
 
        self.expectFailure('subunit treats "unexpectedSuccess"'
2181
 
                           ' as a plain success',
2182
 
            self.assertEqual, 1, len(result.unexpectedSuccesses))
 
2202
        # GZ 2011-05-18: Old versions of subunit treat unexpected success as a
 
2203
        #                success, if a min version check is added remove this
 
2204
        from subunit import TestProtocolClient as _Client
 
2205
        if _Client.addUnexpectedSuccess.im_func is _Client.addSuccess.im_func:
 
2206
            self.expectFailure('subunit treats "unexpectedSuccess"'
 
2207
                               ' as a plain success',
 
2208
                self.assertEqual, 1, len(result.unexpectedSuccesses))
2183
2209
        self.assertEqual(1, len(result.unexpectedSuccesses))
2184
2210
        test = result.unexpectedSuccesses[0]
2185
2211
        # RemotedTestCase doesn't preserve the "details"
2483
2509
 
2484
2510
 
2485
2511
class TestStartBzrSubProcess(tests.TestCase):
 
2512
    """Stub test start_bzr_subprocess."""
2486
2513
 
2487
 
    def check_popen_state(self):
2488
 
        """Replace to make assertions when popen is called."""
 
2514
    def _subprocess_log_cleanup(self):
 
2515
        """Inhibits the base version as we don't produce a log file."""
2489
2516
 
2490
2517
    def _popen(self, *args, **kwargs):
2491
 
        """Record the command that is run, so that we can ensure it is correct"""
 
2518
        """Override the base version to record the command that is run.
 
2519
 
 
2520
        From there we can ensure it is correct without spawning a real process.
 
2521
        """
2492
2522
        self.check_popen_state()
2493
2523
        self._popen_args = args
2494
2524
        self._popen_kwargs = kwargs
2495
2525
        raise _DontSpawnProcess()
2496
2526
 
 
2527
    def check_popen_state(self):
 
2528
        """Replace to make assertions when popen is called."""
 
2529
 
2497
2530
    def test_run_bzr_subprocess_no_plugins(self):
2498
2531
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
2499
2532
        command = self._popen_args[0]
2503
2536
 
2504
2537
    def test_allow_plugins(self):
2505
2538
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2506
 
            allow_plugins=True)
 
2539
                          allow_plugins=True)
2507
2540
        command = self._popen_args[0]
2508
2541
        self.assertEqual([], command[2:])
2509
2542
 
2514
2547
            self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2515
2548
        self.check_popen_state = check_environment
2516
2549
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2517
 
            env_changes={'EXISTANT_ENV_VAR':'set variable'})
 
2550
                          env_changes={'EXISTANT_ENV_VAR':'set variable'})
2518
2551
        # not set in theparent
2519
2552
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2520
2553
 
2526
2559
        os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2527
2560
        self.check_popen_state = check_environment
2528
2561
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2529
 
            env_changes={'EXISTANT_ENV_VAR':None})
 
2562
                          env_changes={'EXISTANT_ENV_VAR':None})
2530
2563
        # Still set in parent
2531
2564
        self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2532
2565
        del os.environ['EXISTANT_ENV_VAR']
2537
2570
            self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2538
2571
        self.check_popen_state = check_environment
2539
2572
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2540
 
            env_changes={'NON_EXISTANT_ENV_VAR':None})
 
2573
                          env_changes={'NON_EXISTANT_ENV_VAR':None})
2541
2574
 
2542
2575
    def test_working_dir(self):
2543
2576
        """Test that we can specify the working dir for the child"""
2546
2579
        chdirs = []
2547
2580
        def chdir(path):
2548
2581
            chdirs.append(path)
2549
 
        os.chdir = chdir
2550
 
        try:
2551
 
            def getcwd():
2552
 
                return 'current'
2553
 
            osutils.getcwd = getcwd
2554
 
            try:
2555
 
                self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2556
 
                    working_dir='foo')
2557
 
            finally:
2558
 
                osutils.getcwd = orig_getcwd
2559
 
        finally:
2560
 
            os.chdir = orig_chdir
 
2582
        self.overrideAttr(os, 'chdir', chdir)
 
2583
        def getcwd():
 
2584
            return 'current'
 
2585
        self.overrideAttr(osutils, 'getcwd', getcwd)
 
2586
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2587
                          working_dir='foo')
2561
2588
        self.assertEqual(['foo', 'current'], chdirs)
2562
2589
 
2563
2590
    def test_get_bzr_path_with_cwd_bzrlib(self):
2583
2610
        self.assertEqual('bzr: interrupted\n', result[1])
2584
2611
 
2585
2612
 
2586
 
class TestFeature(tests.TestCase):
2587
 
 
2588
 
    def test_caching(self):
2589
 
        """Feature._probe is called by the feature at most once."""
2590
 
        class InstrumentedFeature(tests.Feature):
2591
 
            def __init__(self):
2592
 
                super(InstrumentedFeature, self).__init__()
2593
 
                self.calls = []
2594
 
            def _probe(self):
2595
 
                self.calls.append('_probe')
2596
 
                return False
2597
 
        feature = InstrumentedFeature()
2598
 
        feature.available()
2599
 
        self.assertEqual(['_probe'], feature.calls)
2600
 
        feature.available()
2601
 
        self.assertEqual(['_probe'], feature.calls)
2602
 
 
2603
 
    def test_named_str(self):
2604
 
        """Feature.__str__ should thunk to feature_name()."""
2605
 
        class NamedFeature(tests.Feature):
2606
 
            def feature_name(self):
2607
 
                return 'symlinks'
2608
 
        feature = NamedFeature()
2609
 
        self.assertEqual('symlinks', str(feature))
2610
 
 
2611
 
    def test_default_str(self):
2612
 
        """Feature.__str__ should default to __class__.__name__."""
2613
 
        class NamedFeature(tests.Feature):
2614
 
            pass
2615
 
        feature = NamedFeature()
2616
 
        self.assertEqual('NamedFeature', str(feature))
2617
 
 
2618
 
 
2619
 
class TestUnavailableFeature(tests.TestCase):
2620
 
 
2621
 
    def test_access_feature(self):
2622
 
        feature = tests.Feature()
2623
 
        exception = tests.UnavailableFeature(feature)
2624
 
        self.assertIs(feature, exception.args[0])
2625
 
 
2626
 
 
2627
 
simple_thunk_feature = tests._CompatabilityThunkFeature(
2628
 
    deprecated_in((2, 1, 0)),
2629
 
    'bzrlib.tests.test_selftest',
2630
 
    'simple_thunk_feature','UnicodeFilename',
2631
 
    replacement_module='bzrlib.tests'
2632
 
    )
2633
 
 
2634
 
class Test_CompatibilityFeature(tests.TestCase):
2635
 
 
2636
 
    def test_does_thunk(self):
2637
 
        res = self.callDeprecated(
2638
 
            ['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
2639
 
             ' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
2640
 
            simple_thunk_feature.available)
2641
 
        self.assertEqual(tests.UnicodeFilename.available(), res)
2642
 
 
2643
 
 
2644
 
class TestModuleAvailableFeature(tests.TestCase):
2645
 
 
2646
 
    def test_available_module(self):
2647
 
        feature = tests.ModuleAvailableFeature('bzrlib.tests')
2648
 
        self.assertEqual('bzrlib.tests', feature.module_name)
2649
 
        self.assertEqual('bzrlib.tests', str(feature))
2650
 
        self.assertTrue(feature.available())
2651
 
        self.assertIs(tests, feature.module)
2652
 
 
2653
 
    def test_unavailable_module(self):
2654
 
        feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
2655
 
        self.assertEqual('bzrlib.no_such_module_exists', str(feature))
2656
 
        self.assertFalse(feature.available())
2657
 
        self.assertIs(None, feature.module)
2658
 
 
2659
 
 
2660
2613
class TestSelftestFiltering(tests.TestCase):
2661
2614
 
2662
2615
    def setUp(self):
3500
3453
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
3501
3454
        # tests.DocTestSuite sees None
3502
3455
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
 
3456
 
 
3457
 
 
3458
class TestSelftestExcludePatterns(tests.TestCase):
 
3459
 
 
3460
    def setUp(self):
 
3461
        super(TestSelftestExcludePatterns, self).setUp()
 
3462
        self.overrideAttr(tests, 'test_suite', self.suite_factory)
 
3463
 
 
3464
    def suite_factory(self, keep_only=None, starting_with=None):
 
3465
        """A test suite factory with only a few tests."""
 
3466
        class Test(tests.TestCase):
 
3467
            def id(self):
 
3468
                # We don't need the full class path
 
3469
                return self._testMethodName
 
3470
            def a(self):
 
3471
                pass
 
3472
            def b(self):
 
3473
                pass
 
3474
            def c(self):
 
3475
                pass
 
3476
        return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
 
3477
 
 
3478
    def assertTestList(self, expected, *selftest_args):
 
3479
        # We rely on setUp installing the right test suite factory so we can
 
3480
        # test at the command level without loading the whole test suite
 
3481
        out, err = self.run_bzr(('selftest', '--list') + selftest_args)
 
3482
        actual = out.splitlines()
 
3483
        self.assertEquals(expected, actual)
 
3484
 
 
3485
    def test_full_list(self):
 
3486
        self.assertTestList(['a', 'b', 'c'])
 
3487
 
 
3488
    def test_single_exclude(self):
 
3489
        self.assertTestList(['b', 'c'], '-x', 'a')
 
3490
 
 
3491
    def test_mutiple_excludes(self):
 
3492
        self.assertTestList(['c'], '-x', 'a', '-x', 'b')
 
3493
 
 
3494
 
 
3495
class TestCounterHooks(tests.TestCase, SelfTestHelper):
 
3496
 
 
3497
    _test_needs_features = [features.subunit]
 
3498
 
 
3499
    def setUp(self):
 
3500
        super(TestCounterHooks, self).setUp()
 
3501
        class Test(tests.TestCase):
 
3502
 
 
3503
            def setUp(self):
 
3504
                super(Test, self).setUp()
 
3505
                self.hooks = hooks.Hooks()
 
3506
                self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
 
3507
                self.install_counter_hook(self.hooks, 'myhook')
 
3508
 
 
3509
            def no_hook(self):
 
3510
                pass
 
3511
 
 
3512
            def run_hook_once(self):
 
3513
                for hook in self.hooks['myhook']:
 
3514
                    hook(self)
 
3515
 
 
3516
        self.test_class = Test
 
3517
 
 
3518
    def assertHookCalls(self, expected_calls, test_name):
 
3519
        test = self.test_class(test_name)
 
3520
        result = unittest.TestResult()
 
3521
        test.run(result)
 
3522
        self.assertTrue(hasattr(test, '_counters'))
 
3523
        self.assertTrue(test._counters.has_key('myhook'))
 
3524
        self.assertEquals(expected_calls, test._counters['myhook'])
 
3525
 
 
3526
    def test_no_hook(self):
 
3527
        self.assertHookCalls(0, 'no_hook')
 
3528
 
 
3529
    def test_run_hook_once(self):
 
3530
        tt = features.testtools
 
3531
        if tt.module.__version__ < (0, 9, 8):
 
3532
            raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
 
3533
        self.assertHookCalls(1, 'run_hook_once')