/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 bzrlib/tests/test_selftest.py

  • Committer: Aaron Bentley
  • Date: 2009-09-29 04:40:55 UTC
  • mfrom: (4717 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4718.
  • Revision ID: aaron@aaronbentley.com-20090929044055-e9jtpmz6eyut711h
Merged bzr.dev into fix_get_mtime.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
from cStringIO import StringIO
20
20
import os
 
21
import signal
21
22
import sys
22
23
import time
23
24
import unittest
37
38
    repository,
38
39
    symbol_versioning,
39
40
    tests,
 
41
    transport,
40
42
    workingtree,
41
43
    )
42
44
from bzrlib.repofmt import (
50
52
    deprecated_method,
51
53
    )
52
54
from bzrlib.tests import (
 
55
    SubUnitFeature,
53
56
    test_lsprof,
54
57
    test_sftp_transport,
55
58
    TestUtil,
574
577
                         self.get_transport().get_bytes(
575
578
                            'dir/.bzr/repository/format'))
576
579
 
577
 
    def test_safety_net(self):
578
 
        """No test should modify the safety .bzr directory.
579
 
 
580
 
        We just test that the _check_safety_net private method raises
581
 
        AssertionError, it's easier than building a test suite with the same
582
 
        test.
583
 
        """
584
 
        # Oops, a commit in the current directory (i.e. without local .bzr
585
 
        # directory) will crawl up the hierarchy to find a .bzr directory.
586
 
        self.run_bzr(['commit', '-mfoo', '--unchanged'])
587
 
        # But we have a safety net in place.
588
 
        self.assertRaises(AssertionError, self._check_safety_net)
589
 
 
590
580
    def test_dangling_locks_cause_failures(self):
591
581
        class TestDanglingLock(tests.TestCaseWithMemoryTransport):
592
582
            def test_function(self):
685
675
        self.assertEqual(url, t.clone('..').base)
686
676
 
687
677
 
 
678
class TestProfileResult(tests.TestCase):
 
679
 
 
680
    def test_profiles_tests(self):
 
681
        self.requireFeature(test_lsprof.LSProfFeature)
 
682
        terminal = unittest.TestResult()
 
683
        result = tests.ProfileResult(terminal)
 
684
        class Sample(tests.TestCase):
 
685
            def a(self):
 
686
                self.sample_function()
 
687
            def sample_function(self):
 
688
                pass
 
689
        test = Sample("a")
 
690
        test.attrs_to_keep = test.attrs_to_keep + ('_benchcalls',)
 
691
        test.run(result)
 
692
        self.assertLength(1, test._benchcalls)
 
693
        # We must be able to unpack it as the test reporting code wants
 
694
        (_, _, _), stats = test._benchcalls[0]
 
695
        self.assertTrue(callable(stats.pprint))
 
696
 
 
697
 
688
698
class TestTestResult(tests.TestCase):
689
699
 
690
700
    def check_timing(self, test_case, expected_re):
717
727
        self.check_timing(ShortDelayTestCase('test_short_delay'),
718
728
                          r"^ +[0-9]+ms$")
719
729
 
 
730
    def _patch_get_bzr_source_tree(self):
 
731
        # Reading from the actual source tree breaks isolation, but we don't
 
732
        # want to assume that thats *all* that would happen.
 
733
        def _get_bzr_source_tree():
 
734
            return None
 
735
        orig_get_bzr_source_tree = bzrlib.version._get_bzr_source_tree
 
736
        bzrlib.version._get_bzr_source_tree = _get_bzr_source_tree
 
737
        def restore():
 
738
            bzrlib.version._get_bzr_source_tree = orig_get_bzr_source_tree
 
739
        self.addCleanup(restore)
 
740
 
720
741
    def test_assigned_benchmark_file_stores_date(self):
 
742
        self._patch_get_bzr_source_tree()
721
743
        output = StringIO()
722
744
        result = bzrlib.tests.TextTestResult(self._log_file,
723
745
                                        descriptions=0,
731
753
        self.assertContainsRe(output_string, "--date [0-9.]+")
732
754
 
733
755
    def test_benchhistory_records_test_times(self):
 
756
        self._patch_get_bzr_source_tree()
734
757
        result_stream = StringIO()
735
758
        result = bzrlib.tests.TextTestResult(
736
759
            self._log_file,
798
821
    def test_known_failure(self):
799
822
        """A KnownFailure being raised should trigger several result actions."""
800
823
        class InstrumentedTestResult(tests.ExtendedTestResult):
801
 
            def done(self): pass
 
824
            def stopTestRun(self): pass
802
825
            def startTests(self): pass
803
826
            def report_test_start(self, test): pass
804
827
            def report_known_failure(self, test, err):
852
875
    def test_add_not_supported(self):
853
876
        """Test the behaviour of invoking addNotSupported."""
854
877
        class InstrumentedTestResult(tests.ExtendedTestResult):
855
 
            def done(self): pass
 
878
            def stopTestRun(self): pass
856
879
            def startTests(self): pass
857
880
            def report_test_start(self, test): pass
858
881
            def report_unsupported(self, test, feature):
896
919
    def test_unavailable_exception(self):
897
920
        """An UnavailableFeature being raised should invoke addNotSupported."""
898
921
        class InstrumentedTestResult(tests.ExtendedTestResult):
899
 
            def done(self): pass
 
922
            def stopTestRun(self): pass
900
923
            def startTests(self): pass
901
924
            def report_test_start(self, test): pass
902
925
            def addNotSupported(self, test, feature):
979
1002
        because of our use of global state.
980
1003
        """
981
1004
        old_root = tests.TestCaseInTempDir.TEST_ROOT
 
1005
        old_leak = tests.TestCase._first_thread_leaker_id
982
1006
        try:
983
1007
            tests.TestCaseInTempDir.TEST_ROOT = None
 
1008
            tests.TestCase._first_thread_leaker_id = None
984
1009
            return testrunner.run(test)
985
1010
        finally:
986
1011
            tests.TestCaseInTempDir.TEST_ROOT = old_root
 
1012
            tests.TestCase._first_thread_leaker_id = old_leak
987
1013
 
988
1014
    def test_known_failure_failed_run(self):
989
1015
        # run a test that generates a known failure which should be printed in
1029
1055
            '\n'
1030
1056
            'OK \\(known_failures=1\\)\n')
1031
1057
 
 
1058
    def test_result_decorator(self):
 
1059
        # decorate results
 
1060
        calls = []
 
1061
        class LoggingDecorator(tests.ForwardingResult):
 
1062
            def startTest(self, test):
 
1063
                tests.ForwardingResult.startTest(self, test)
 
1064
                calls.append('start')
 
1065
        test = unittest.FunctionTestCase(lambda:None)
 
1066
        stream = StringIO()
 
1067
        runner = tests.TextTestRunner(stream=stream,
 
1068
            result_decorators=[LoggingDecorator])
 
1069
        result = self.run_test_runner(runner, test)
 
1070
        self.assertLength(1, calls)
 
1071
 
1032
1072
    def test_skipped_test(self):
1033
1073
        # run a test that is skipped, and check the suite as a whole still
1034
1074
        # succeeds.
1101
1141
        self.assertContainsRe(out.getvalue(),
1102
1142
                r'(?m)^    this test never runs')
1103
1143
 
1104
 
    def test_not_applicable_demo(self):
1105
 
        # just so you can see it in the test output
1106
 
        raise tests.TestNotApplicable('this test is just a demonstation')
1107
 
 
1108
1144
    def test_unsupported_features_listed(self):
1109
1145
        """When unsupported features are encountered they are detailed."""
1110
1146
        class Feature1(tests.Feature):
1130
1166
            ],
1131
1167
            lines[-3:])
1132
1168
 
 
1169
    def _patch_get_bzr_source_tree(self):
 
1170
        # Reading from the actual source tree breaks isolation, but we don't
 
1171
        # want to assume that thats *all* that would happen.
 
1172
        self._get_source_tree_calls = []
 
1173
        def _get_bzr_source_tree():
 
1174
            self._get_source_tree_calls.append("called")
 
1175
            return None
 
1176
        orig_get_bzr_source_tree = bzrlib.version._get_bzr_source_tree
 
1177
        bzrlib.version._get_bzr_source_tree = _get_bzr_source_tree
 
1178
        def restore():
 
1179
            bzrlib.version._get_bzr_source_tree = orig_get_bzr_source_tree
 
1180
        self.addCleanup(restore)
 
1181
 
1133
1182
    def test_bench_history(self):
1134
 
        # tests that the running the benchmark produces a history file
1135
 
        # containing a timestamp and the revision id of the bzrlib source which
1136
 
        # was tested.
1137
 
        workingtree = _get_bzr_source_tree()
 
1183
        # tests that the running the benchmark passes bench_history into
 
1184
        # the test result object. We can tell that happens if
 
1185
        # _get_bzr_source_tree is called.
 
1186
        self._patch_get_bzr_source_tree()
1138
1187
        test = TestRunner('dummy_test')
1139
1188
        output = StringIO()
1140
1189
        runner = tests.TextTestRunner(stream=self._log_file,
1142
1191
        result = self.run_test_runner(runner, test)
1143
1192
        output_string = output.getvalue()
1144
1193
        self.assertContainsRe(output_string, "--date [0-9.]+")
1145
 
        if workingtree is not None:
1146
 
            revision_id = workingtree.get_parent_ids()[0]
1147
 
            self.assertEndsWith(output_string.rstrip(), revision_id)
 
1194
        self.assertLength(1, self._get_source_tree_calls)
1148
1195
 
1149
1196
    def assertLogDeleted(self, test):
1150
1197
        log = test._get_log()
1259
1306
        self.assertContainsRe(log, 'this will be kept')
1260
1307
        self.assertEqual(log, test._log_contents)
1261
1308
 
 
1309
    def test_startTestRun(self):
 
1310
        """run should call result.startTestRun()"""
 
1311
        calls = []
 
1312
        class LoggingDecorator(tests.ForwardingResult):
 
1313
            def startTestRun(self):
 
1314
                tests.ForwardingResult.startTestRun(self)
 
1315
                calls.append('startTestRun')
 
1316
        test = unittest.FunctionTestCase(lambda:None)
 
1317
        stream = StringIO()
 
1318
        runner = tests.TextTestRunner(stream=stream,
 
1319
            result_decorators=[LoggingDecorator])
 
1320
        result = self.run_test_runner(runner, test)
 
1321
        self.assertLength(1, calls)
 
1322
 
 
1323
    def test_stopTestRun(self):
 
1324
        """run should call result.stopTestRun()"""
 
1325
        calls = []
 
1326
        class LoggingDecorator(tests.ForwardingResult):
 
1327
            def stopTestRun(self):
 
1328
                tests.ForwardingResult.stopTestRun(self)
 
1329
                calls.append('stopTestRun')
 
1330
        test = unittest.FunctionTestCase(lambda:None)
 
1331
        stream = StringIO()
 
1332
        runner = tests.TextTestRunner(stream=stream,
 
1333
            result_decorators=[LoggingDecorator])
 
1334
        result = self.run_test_runner(runner, test)
 
1335
        self.assertLength(1, calls)
 
1336
 
1262
1337
 
1263
1338
class SampleTestCase(tests.TestCase):
1264
1339
 
1430
1505
        outer_test = TestTestCase("outer_child")
1431
1506
        result = self.make_test_result()
1432
1507
        outer_test.run(result)
 
1508
        self.addCleanup(osutils.delete_any, outer_test._log_file_name)
1433
1509
        self.assertEqual(original_trace, bzrlib.trace._trace_file)
1434
1510
 
1435
1511
    def method_that_times_a_bit_twice(self):
1478
1554
        self.assertEqual((time.sleep, (0.003,), {}), self._benchcalls[1][0])
1479
1555
        self.assertIsInstance(self._benchcalls[0][1], bzrlib.lsprof.Stats)
1480
1556
        self.assertIsInstance(self._benchcalls[1][1], bzrlib.lsprof.Stats)
 
1557
        del self._benchcalls[:]
1481
1558
 
1482
1559
    def test_knownFailure(self):
1483
1560
        """Self.knownFailure() should raise a KnownFailure exception."""
1484
1561
        self.assertRaises(tests.KnownFailure, self.knownFailure, "A Failure")
1485
1562
 
 
1563
    def test_open_bzrdir_safe_roots(self):
 
1564
        # even a memory transport should fail to open when its url isn't 
 
1565
        # permitted.
 
1566
        # Manually set one up (TestCase doesn't and shouldn't provide magic
 
1567
        # machinery)
 
1568
        transport_server = MemoryServer()
 
1569
        transport_server.setUp()
 
1570
        self.addCleanup(transport_server.tearDown)
 
1571
        t = transport.get_transport(transport_server.get_url())
 
1572
        bzrdir.BzrDir.create(t.base)
 
1573
        self.assertRaises(errors.BzrError,
 
1574
            bzrdir.BzrDir.open_from_transport, t)
 
1575
        # But if we declare this as safe, we can open the bzrdir.
 
1576
        self.permit_url(t.base)
 
1577
        self._bzr_selftest_roots.append(t.base)
 
1578
        bzrdir.BzrDir.open_from_transport(t)
 
1579
 
1486
1580
    def test_requireFeature_available(self):
1487
1581
        """self.requireFeature(available) is a no-op."""
1488
1582
        class Available(tests.Feature):
1555
1649
            ],
1556
1650
            result.calls)
1557
1651
 
 
1652
    def test_start_server_registers_url(self):
 
1653
        transport_server = MemoryServer()
 
1654
        # A little strict, but unlikely to be changed soon.
 
1655
        self.assertEqual([], self._bzr_selftest_roots)
 
1656
        self.start_server(transport_server)
 
1657
        self.assertSubset([transport_server.get_url()],
 
1658
            self._bzr_selftest_roots)
 
1659
 
1558
1660
    def test_assert_list_raises_on_generator(self):
1559
1661
        def generator_which_will_raise():
1560
1662
            # This will not raise until after the first yield
1658
1760
        self.assertEndsWith('foo', 'oo')
1659
1761
        self.assertRaises(AssertionError, self.assertEndsWith, 'o', 'oo')
1660
1762
 
 
1763
    def test_assertEqualDiff(self):
 
1764
        e = self.assertRaises(AssertionError,
 
1765
                              self.assertEqualDiff, '', '\n')
 
1766
        self.assertEquals(str(e),
 
1767
                          # Don't blink ! The '+' applies to the second string
 
1768
                          'first string is missing a final newline.\n+ \n')
 
1769
        e = self.assertRaises(AssertionError,
 
1770
                              self.assertEqualDiff, '\n', '')
 
1771
        self.assertEquals(str(e),
 
1772
                          # Don't blink ! The '-' applies to the second string
 
1773
                          'second string is missing a final newline.\n- \n')
 
1774
 
 
1775
 
 
1776
class TestDeprecations(tests.TestCase):
 
1777
 
1661
1778
    def test_applyDeprecated_not_deprecated(self):
1662
1779
        sample_object = ApplyDeprecatedHelper()
1663
1780
        # calling an undeprecated callable raises an assertion
1740
1857
        tree = self.make_branch_and_memory_tree('a')
1741
1858
        self.assertIsInstance(tree, bzrlib.memorytree.MemoryTree)
1742
1859
 
1743
 
 
1744
 
class TestSFTPMakeBranchAndTree(test_sftp_transport.TestCaseWithSFTPServer):
1745
 
 
1746
 
    def test_make_tree_for_sftp_branch(self):
1747
 
        """Transports backed by local directories create local trees."""
1748
 
 
 
1860
    def test_make_tree_for_local_vfs_backed_transport(self):
 
1861
        # make_branch_and_tree has to use local branch and repositories
 
1862
        # when the vfs transport and local disk are colocated, even if
 
1863
        # a different transport is in use for url generation.
 
1864
        from bzrlib.transport.fakevfat import FakeVFATServer
 
1865
        self.transport_server = FakeVFATServer
 
1866
        self.assertFalse(self.get_url('t1').startswith('file://'))
1749
1867
        tree = self.make_branch_and_tree('t1')
1750
1868
        base = tree.bzrdir.root_transport.base
1751
 
        self.failIf(base.startswith('sftp'),
1752
 
                'base %r is on sftp but should be local' % base)
 
1869
        self.assertStartsWith(base, 'file://')
1753
1870
        self.assertEquals(tree.bzrdir.root_transport,
1754
1871
                tree.branch.bzrdir.root_transport)
1755
1872
        self.assertEquals(tree.bzrdir.root_transport,
1756
1873
                tree.branch.repository.bzrdir.root_transport)
1757
1874
 
1758
1875
 
1759
 
class TestSelftest(tests.TestCase):
 
1876
class SelfTestHelper:
 
1877
 
 
1878
    def run_selftest(self, **kwargs):
 
1879
        """Run selftest returning its output."""
 
1880
        output = StringIO()
 
1881
        old_transport = bzrlib.tests.default_transport
 
1882
        old_root = tests.TestCaseWithMemoryTransport.TEST_ROOT
 
1883
        tests.TestCaseWithMemoryTransport.TEST_ROOT = None
 
1884
        try:
 
1885
            self.assertEqual(True, tests.selftest(stream=output, **kwargs))
 
1886
        finally:
 
1887
            bzrlib.tests.default_transport = old_transport
 
1888
            tests.TestCaseWithMemoryTransport.TEST_ROOT = old_root
 
1889
        output.seek(0)
 
1890
        return output
 
1891
 
 
1892
 
 
1893
class TestSelftest(tests.TestCase, SelfTestHelper):
1760
1894
    """Tests of bzrlib.tests.selftest."""
1761
1895
 
1762
1896
    def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(self):
1770
1904
            test_suite_factory=factory)
1771
1905
        self.assertEqual([True], factory_called)
1772
1906
 
 
1907
    def factory(self):
 
1908
        """A test suite factory."""
 
1909
        class Test(tests.TestCase):
 
1910
            def a(self):
 
1911
                pass
 
1912
            def b(self):
 
1913
                pass
 
1914
            def c(self):
 
1915
                pass
 
1916
        return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
 
1917
 
 
1918
    def test_list_only(self):
 
1919
        output = self.run_selftest(test_suite_factory=self.factory,
 
1920
            list_only=True)
 
1921
        self.assertEqual(3, len(output.readlines()))
 
1922
 
 
1923
    def test_list_only_filtered(self):
 
1924
        output = self.run_selftest(test_suite_factory=self.factory,
 
1925
            list_only=True, pattern="Test.b")
 
1926
        self.assertEndsWith(output.getvalue(), "Test.b\n")
 
1927
        self.assertLength(1, output.readlines())
 
1928
 
 
1929
    def test_list_only_excludes(self):
 
1930
        output = self.run_selftest(test_suite_factory=self.factory,
 
1931
            list_only=True, exclude_pattern="Test.b")
 
1932
        self.assertNotContainsRe("Test.b", output.getvalue())
 
1933
        self.assertLength(2, output.readlines())
 
1934
 
 
1935
    def test_lsprof_tests(self):
 
1936
        self.requireFeature(test_lsprof.LSProfFeature)
 
1937
        calls = []
 
1938
        class Test(object):
 
1939
            def __call__(test, result):
 
1940
                test.run(result)
 
1941
            def run(test, result):
 
1942
                self.assertIsInstance(result, tests.ForwardingResult)
 
1943
                calls.append("called")
 
1944
            def countTestCases(self):
 
1945
                return 1
 
1946
        self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
 
1947
        self.assertLength(1, calls)
 
1948
 
 
1949
    def test_random(self):
 
1950
        # test randomising by listing a number of tests.
 
1951
        output_123 = self.run_selftest(test_suite_factory=self.factory,
 
1952
            list_only=True, random_seed="123")
 
1953
        output_234 = self.run_selftest(test_suite_factory=self.factory,
 
1954
            list_only=True, random_seed="234")
 
1955
        self.assertNotEqual(output_123, output_234)
 
1956
        # "Randominzing test order..\n\n
 
1957
        self.assertLength(5, output_123.readlines())
 
1958
        self.assertLength(5, output_234.readlines())
 
1959
 
 
1960
    def test_random_reuse_is_same_order(self):
 
1961
        # test randomising by listing a number of tests.
 
1962
        expected = self.run_selftest(test_suite_factory=self.factory,
 
1963
            list_only=True, random_seed="123")
 
1964
        repeated = self.run_selftest(test_suite_factory=self.factory,
 
1965
            list_only=True, random_seed="123")
 
1966
        self.assertEqual(expected.getvalue(), repeated.getvalue())
 
1967
 
 
1968
    def test_runner_class(self):
 
1969
        self.requireFeature(SubUnitFeature)
 
1970
        from subunit import ProtocolTestCase
 
1971
        stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
 
1972
            test_suite_factory=self.factory)
 
1973
        test = ProtocolTestCase(stream)
 
1974
        result = unittest.TestResult()
 
1975
        test.run(result)
 
1976
        self.assertEqual(3, result.testsRun)
 
1977
 
 
1978
    def test_starting_with_single_argument(self):
 
1979
        output = self.run_selftest(test_suite_factory=self.factory,
 
1980
            starting_with=['bzrlib.tests.test_selftest.Test.a'],
 
1981
            list_only=True)
 
1982
        self.assertEqual('bzrlib.tests.test_selftest.Test.a\n',
 
1983
            output.getvalue())
 
1984
 
 
1985
    def test_starting_with_multiple_argument(self):
 
1986
        output = self.run_selftest(test_suite_factory=self.factory,
 
1987
            starting_with=['bzrlib.tests.test_selftest.Test.a',
 
1988
                'bzrlib.tests.test_selftest.Test.b'],
 
1989
            list_only=True)
 
1990
        self.assertEqual('bzrlib.tests.test_selftest.Test.a\n'
 
1991
            'bzrlib.tests.test_selftest.Test.b\n',
 
1992
            output.getvalue())
 
1993
 
 
1994
    def check_transport_set(self, transport_server):
 
1995
        captured_transport = []
 
1996
        def seen_transport(a_transport):
 
1997
            captured_transport.append(a_transport)
 
1998
        class Capture(tests.TestCase):
 
1999
            def a(self):
 
2000
                seen_transport(bzrlib.tests.default_transport)
 
2001
        def factory():
 
2002
            return TestUtil.TestSuite([Capture("a")])
 
2003
        self.run_selftest(transport=transport_server, test_suite_factory=factory)
 
2004
        self.assertEqual(transport_server, captured_transport[0])
 
2005
 
 
2006
    def test_transport_sftp(self):
 
2007
        try:
 
2008
            import bzrlib.transport.sftp
 
2009
        except errors.ParamikoNotPresent:
 
2010
            raise tests.TestSkipped("Paramiko not present")
 
2011
        self.check_transport_set(bzrlib.transport.sftp.SFTPAbsoluteServer)
 
2012
 
 
2013
    def test_transport_memory(self):
 
2014
        self.check_transport_set(bzrlib.transport.memory.MemoryServer)
 
2015
 
 
2016
 
 
2017
class TestSelftestWithIdList(tests.TestCaseInTempDir, SelfTestHelper):
 
2018
    # Does IO: reads test.list
 
2019
 
 
2020
    def test_load_list(self):
 
2021
        # Provide a list with one test - this test.
 
2022
        test_id_line = '%s\n' % self.id()
 
2023
        self.build_tree_contents([('test.list', test_id_line)])
 
2024
        # And generate a list of the tests in  the suite.
 
2025
        stream = self.run_selftest(load_list='test.list', list_only=True)
 
2026
        self.assertEqual(test_id_line, stream.getvalue())
 
2027
 
 
2028
    def test_load_unknown(self):
 
2029
        # Provide a list with one test - this test.
 
2030
        # And generate a list of the tests in  the suite.
 
2031
        err = self.assertRaises(errors.NoSuchFile, self.run_selftest,
 
2032
            load_list='missing file name', list_only=True)
 
2033
 
 
2034
 
 
2035
class TestRunBzr(tests.TestCase):
 
2036
 
 
2037
    out = ''
 
2038
    err = ''
 
2039
 
 
2040
    def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None,
 
2041
                         working_dir=None):
 
2042
        """Override _run_bzr_core to test how it is invoked by run_bzr.
 
2043
 
 
2044
        Attempts to run bzr from inside this class don't actually run it.
 
2045
 
 
2046
        We test how run_bzr actually invokes bzr in another location.  Here we
 
2047
        only need to test that it passes the right parameters to run_bzr.
 
2048
        """
 
2049
        self.argv = list(argv)
 
2050
        self.retcode = retcode
 
2051
        self.encoding = encoding
 
2052
        self.stdin = stdin
 
2053
        self.working_dir = working_dir
 
2054
        return self.retcode, self.out, self.err
 
2055
 
 
2056
    def test_run_bzr_error(self):
 
2057
        self.out = "It sure does!\n"
 
2058
        out, err = self.run_bzr_error(['^$'], ['rocks'], retcode=34)
 
2059
        self.assertEqual(['rocks'], self.argv)
 
2060
        self.assertEqual(34, self.retcode)
 
2061
        self.assertEqual('It sure does!\n', out)
 
2062
        self.assertEquals(out, self.out)
 
2063
        self.assertEqual('', err)
 
2064
        self.assertEquals(err, self.err)
 
2065
 
 
2066
    def test_run_bzr_error_regexes(self):
 
2067
        self.out = ''
 
2068
        self.err = "bzr: ERROR: foobarbaz is not versioned"
 
2069
        out, err = self.run_bzr_error(
 
2070
            ["bzr: ERROR: foobarbaz is not versioned"],
 
2071
            ['file-id', 'foobarbaz'])
 
2072
 
 
2073
    def test_encoding(self):
 
2074
        """Test that run_bzr passes encoding to _run_bzr_core"""
 
2075
        self.run_bzr('foo bar')
 
2076
        self.assertEqual(None, self.encoding)
 
2077
        self.assertEqual(['foo', 'bar'], self.argv)
 
2078
 
 
2079
        self.run_bzr('foo bar', encoding='baz')
 
2080
        self.assertEqual('baz', self.encoding)
 
2081
        self.assertEqual(['foo', 'bar'], self.argv)
 
2082
 
 
2083
    def test_retcode(self):
 
2084
        """Test that run_bzr passes retcode to _run_bzr_core"""
 
2085
        # Default is retcode == 0
 
2086
        self.run_bzr('foo bar')
 
2087
        self.assertEqual(0, self.retcode)
 
2088
        self.assertEqual(['foo', 'bar'], self.argv)
 
2089
 
 
2090
        self.run_bzr('foo bar', retcode=1)
 
2091
        self.assertEqual(1, self.retcode)
 
2092
        self.assertEqual(['foo', 'bar'], self.argv)
 
2093
 
 
2094
        self.run_bzr('foo bar', retcode=None)
 
2095
        self.assertEqual(None, self.retcode)
 
2096
        self.assertEqual(['foo', 'bar'], self.argv)
 
2097
 
 
2098
        self.run_bzr(['foo', 'bar'], retcode=3)
 
2099
        self.assertEqual(3, self.retcode)
 
2100
        self.assertEqual(['foo', 'bar'], self.argv)
 
2101
 
 
2102
    def test_stdin(self):
 
2103
        # test that the stdin keyword to run_bzr is passed through to
 
2104
        # _run_bzr_core as-is. We do this by overriding
 
2105
        # _run_bzr_core in this class, and then calling run_bzr,
 
2106
        # which is a convenience function for _run_bzr_core, so
 
2107
        # should invoke it.
 
2108
        self.run_bzr('foo bar', stdin='gam')
 
2109
        self.assertEqual('gam', self.stdin)
 
2110
        self.assertEqual(['foo', 'bar'], self.argv)
 
2111
 
 
2112
        self.run_bzr('foo bar', stdin='zippy')
 
2113
        self.assertEqual('zippy', self.stdin)
 
2114
        self.assertEqual(['foo', 'bar'], self.argv)
 
2115
 
 
2116
    def test_working_dir(self):
 
2117
        """Test that run_bzr passes working_dir to _run_bzr_core"""
 
2118
        self.run_bzr('foo bar')
 
2119
        self.assertEqual(None, self.working_dir)
 
2120
        self.assertEqual(['foo', 'bar'], self.argv)
 
2121
 
 
2122
        self.run_bzr('foo bar', working_dir='baz')
 
2123
        self.assertEqual('baz', self.working_dir)
 
2124
        self.assertEqual(['foo', 'bar'], self.argv)
 
2125
 
 
2126
    def test_reject_extra_keyword_arguments(self):
 
2127
        self.assertRaises(TypeError, self.run_bzr, "foo bar",
 
2128
                          error_regex=['error message'])
 
2129
 
 
2130
 
 
2131
class TestRunBzrCaptured(tests.TestCaseWithTransport):
 
2132
    # Does IO when testing the working_dir parameter.
 
2133
 
 
2134
    def apply_redirected(self, stdin=None, stdout=None, stderr=None,
 
2135
                         a_callable=None, *args, **kwargs):
 
2136
        self.stdin = stdin
 
2137
        self.factory_stdin = getattr(bzrlib.ui.ui_factory, "stdin", None)
 
2138
        self.factory = bzrlib.ui.ui_factory
 
2139
        self.working_dir = osutils.getcwd()
 
2140
        stdout.write('foo\n')
 
2141
        stderr.write('bar\n')
 
2142
        return 0
 
2143
 
 
2144
    def test_stdin(self):
 
2145
        # test that the stdin keyword to _run_bzr_core is passed through to
 
2146
        # apply_redirected as a StringIO. We do this by overriding
 
2147
        # apply_redirected in this class, and then calling _run_bzr_core,
 
2148
        # which calls apply_redirected.
 
2149
        self.run_bzr(['foo', 'bar'], stdin='gam')
 
2150
        self.assertEqual('gam', self.stdin.read())
 
2151
        self.assertTrue(self.stdin is self.factory_stdin)
 
2152
        self.run_bzr(['foo', 'bar'], stdin='zippy')
 
2153
        self.assertEqual('zippy', self.stdin.read())
 
2154
        self.assertTrue(self.stdin is self.factory_stdin)
 
2155
 
 
2156
    def test_ui_factory(self):
 
2157
        # each invocation of self.run_bzr should get its
 
2158
        # own UI factory, which is an instance of TestUIFactory,
 
2159
        # with stdin, stdout and stderr attached to the stdin,
 
2160
        # stdout and stderr of the invoked run_bzr
 
2161
        current_factory = bzrlib.ui.ui_factory
 
2162
        self.run_bzr(['foo'])
 
2163
        self.failIf(current_factory is self.factory)
 
2164
        self.assertNotEqual(sys.stdout, self.factory.stdout)
 
2165
        self.assertNotEqual(sys.stderr, self.factory.stderr)
 
2166
        self.assertEqual('foo\n', self.factory.stdout.getvalue())
 
2167
        self.assertEqual('bar\n', self.factory.stderr.getvalue())
 
2168
        self.assertIsInstance(self.factory, tests.TestUIFactory)
 
2169
 
 
2170
    def test_working_dir(self):
 
2171
        self.build_tree(['one/', 'two/'])
 
2172
        cwd = osutils.getcwd()
 
2173
 
 
2174
        # Default is to work in the current directory
 
2175
        self.run_bzr(['foo', 'bar'])
 
2176
        self.assertEqual(cwd, self.working_dir)
 
2177
 
 
2178
        self.run_bzr(['foo', 'bar'], working_dir=None)
 
2179
        self.assertEqual(cwd, self.working_dir)
 
2180
 
 
2181
        # The function should be run in the alternative directory
 
2182
        # but afterwards the current working dir shouldn't be changed
 
2183
        self.run_bzr(['foo', 'bar'], working_dir='one')
 
2184
        self.assertNotEqual(cwd, self.working_dir)
 
2185
        self.assertEndsWith(self.working_dir, 'one')
 
2186
        self.assertEqual(cwd, osutils.getcwd())
 
2187
 
 
2188
        self.run_bzr(['foo', 'bar'], working_dir='two')
 
2189
        self.assertNotEqual(cwd, self.working_dir)
 
2190
        self.assertEndsWith(self.working_dir, 'two')
 
2191
        self.assertEqual(cwd, osutils.getcwd())
 
2192
 
 
2193
 
 
2194
class StubProcess(object):
 
2195
    """A stub process for testing run_bzr_subprocess."""
 
2196
    
 
2197
    def __init__(self, out="", err="", retcode=0):
 
2198
        self.out = out
 
2199
        self.err = err
 
2200
        self.returncode = retcode
 
2201
 
 
2202
    def communicate(self):
 
2203
        return self.out, self.err
 
2204
 
 
2205
 
 
2206
class TestWithFakedStartBzrSubprocess(tests.TestCaseWithTransport):
 
2207
    """Base class for tests testing how we might run bzr."""
 
2208
 
 
2209
    def setUp(self):
 
2210
        tests.TestCaseWithTransport.setUp(self)
 
2211
        self.subprocess_calls = []
 
2212
 
 
2213
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
2214
                             skip_if_plan_to_signal=False,
 
2215
                             working_dir=None,
 
2216
                             allow_plugins=False):
 
2217
        """capture what run_bzr_subprocess tries to do."""
 
2218
        self.subprocess_calls.append({'process_args':process_args,
 
2219
            'env_changes':env_changes,
 
2220
            'skip_if_plan_to_signal':skip_if_plan_to_signal,
 
2221
            'working_dir':working_dir, 'allow_plugins':allow_plugins})
 
2222
        return self.next_subprocess
 
2223
 
 
2224
 
 
2225
class TestRunBzrSubprocess(TestWithFakedStartBzrSubprocess):
 
2226
 
 
2227
    def assertRunBzrSubprocess(self, expected_args, process, *args, **kwargs):
 
2228
        """Run run_bzr_subprocess with args and kwargs using a stubbed process.
 
2229
 
 
2230
        Inside TestRunBzrSubprocessCommands we use a stub start_bzr_subprocess
 
2231
        that will return static results. This assertion method populates those
 
2232
        results and also checks the arguments run_bzr_subprocess generates.
 
2233
        """
 
2234
        self.next_subprocess = process
 
2235
        try:
 
2236
            result = self.run_bzr_subprocess(*args, **kwargs)
 
2237
        except:
 
2238
            self.next_subprocess = None
 
2239
            for key, expected in expected_args.iteritems():
 
2240
                self.assertEqual(expected, self.subprocess_calls[-1][key])
 
2241
            raise
 
2242
        else:
 
2243
            self.next_subprocess = None
 
2244
            for key, expected in expected_args.iteritems():
 
2245
                self.assertEqual(expected, self.subprocess_calls[-1][key])
 
2246
            return result
 
2247
 
 
2248
    def test_run_bzr_subprocess(self):
 
2249
        """The run_bzr_helper_external command behaves nicely."""
 
2250
        self.assertRunBzrSubprocess({'process_args':['--version']},
 
2251
            StubProcess(), '--version')
 
2252
        self.assertRunBzrSubprocess({'process_args':['--version']},
 
2253
            StubProcess(), ['--version'])
 
2254
        # retcode=None disables retcode checking
 
2255
        result = self.assertRunBzrSubprocess({},
 
2256
            StubProcess(retcode=3), '--version', retcode=None)
 
2257
        result = self.assertRunBzrSubprocess({},
 
2258
            StubProcess(out="is free software"), '--version')
 
2259
        self.assertContainsRe(result[0], 'is free software')
 
2260
        # Running a subcommand that is missing errors
 
2261
        self.assertRaises(AssertionError, self.assertRunBzrSubprocess,
 
2262
            {'process_args':['--versionn']}, StubProcess(retcode=3),
 
2263
            '--versionn')
 
2264
        # Unless it is told to expect the error from the subprocess
 
2265
        result = self.assertRunBzrSubprocess({},
 
2266
            StubProcess(retcode=3), '--versionn', retcode=3)
 
2267
        # Or to ignore retcode checking
 
2268
        result = self.assertRunBzrSubprocess({},
 
2269
            StubProcess(err="unknown command", retcode=3), '--versionn',
 
2270
            retcode=None)
 
2271
        self.assertContainsRe(result[1], 'unknown command')
 
2272
 
 
2273
    def test_env_change_passes_through(self):
 
2274
        self.assertRunBzrSubprocess(
 
2275
            {'env_changes':{'new':'value', 'changed':'newvalue', 'deleted':None}},
 
2276
            StubProcess(), '',
 
2277
            env_changes={'new':'value', 'changed':'newvalue', 'deleted':None})
 
2278
 
 
2279
    def test_no_working_dir_passed_as_None(self):
 
2280
        self.assertRunBzrSubprocess({'working_dir': None}, StubProcess(), '')
 
2281
 
 
2282
    def test_no_working_dir_passed_through(self):
 
2283
        self.assertRunBzrSubprocess({'working_dir': 'dir'}, StubProcess(), '',
 
2284
            working_dir='dir')
 
2285
 
 
2286
    def test_run_bzr_subprocess_no_plugins(self):
 
2287
        self.assertRunBzrSubprocess({'allow_plugins': False},
 
2288
            StubProcess(), '')
 
2289
 
 
2290
    def test_allow_plugins(self):
 
2291
        self.assertRunBzrSubprocess({'allow_plugins': True},
 
2292
            StubProcess(), '', allow_plugins=True)
 
2293
 
 
2294
 
 
2295
class TestFinishBzrSubprocess(TestWithFakedStartBzrSubprocess):
 
2296
 
 
2297
    def test_finish_bzr_subprocess_with_error(self):
 
2298
        """finish_bzr_subprocess allows specification of the desired exit code.
 
2299
        """
 
2300
        process = StubProcess(err="unknown command", retcode=3)
 
2301
        result = self.finish_bzr_subprocess(process, retcode=3)
 
2302
        self.assertEqual('', result[0])
 
2303
        self.assertContainsRe(result[1], 'unknown command')
 
2304
 
 
2305
    def test_finish_bzr_subprocess_ignoring_retcode(self):
 
2306
        """finish_bzr_subprocess allows the exit code to be ignored."""
 
2307
        process = StubProcess(err="unknown command", retcode=3)
 
2308
        result = self.finish_bzr_subprocess(process, retcode=None)
 
2309
        self.assertEqual('', result[0])
 
2310
        self.assertContainsRe(result[1], 'unknown command')
 
2311
 
 
2312
    def test_finish_subprocess_with_unexpected_retcode(self):
 
2313
        """finish_bzr_subprocess raises self.failureException if the retcode is
 
2314
        not the expected one.
 
2315
        """
 
2316
        process = StubProcess(err="unknown command", retcode=3)
 
2317
        self.assertRaises(self.failureException, self.finish_bzr_subprocess,
 
2318
                          process)
 
2319
 
 
2320
 
 
2321
class _DontSpawnProcess(Exception):
 
2322
    """A simple exception which just allows us to skip unnecessary steps"""
 
2323
 
 
2324
 
 
2325
class TestStartBzrSubProcess(tests.TestCase):
 
2326
 
 
2327
    def check_popen_state(self):
 
2328
        """Replace to make assertions when popen is called."""
 
2329
 
 
2330
    def _popen(self, *args, **kwargs):
 
2331
        """Record the command that is run, so that we can ensure it is correct"""
 
2332
        self.check_popen_state()
 
2333
        self._popen_args = args
 
2334
        self._popen_kwargs = kwargs
 
2335
        raise _DontSpawnProcess()
 
2336
 
 
2337
    def test_run_bzr_subprocess_no_plugins(self):
 
2338
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
 
2339
        command = self._popen_args[0]
 
2340
        self.assertEqual(sys.executable, command[0])
 
2341
        self.assertEqual(self.get_bzr_path(), command[1])
 
2342
        self.assertEqual(['--no-plugins'], command[2:])
 
2343
 
 
2344
    def test_allow_plugins(self):
 
2345
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2346
            allow_plugins=True)
 
2347
        command = self._popen_args[0]
 
2348
        self.assertEqual([], command[2:])
 
2349
 
 
2350
    def test_set_env(self):
 
2351
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
 
2352
        # set in the child
 
2353
        def check_environment():
 
2354
            self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
 
2355
        self.check_popen_state = check_environment
 
2356
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2357
            env_changes={'EXISTANT_ENV_VAR':'set variable'})
 
2358
        # not set in theparent
 
2359
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
 
2360
 
 
2361
    def test_run_bzr_subprocess_env_del(self):
 
2362
        """run_bzr_subprocess can remove environment variables too."""
 
2363
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
 
2364
        def check_environment():
 
2365
            self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
 
2366
        os.environ['EXISTANT_ENV_VAR'] = 'set variable'
 
2367
        self.check_popen_state = check_environment
 
2368
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2369
            env_changes={'EXISTANT_ENV_VAR':None})
 
2370
        # Still set in parent
 
2371
        self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
 
2372
        del os.environ['EXISTANT_ENV_VAR']
 
2373
 
 
2374
    def test_env_del_missing(self):
 
2375
        self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
 
2376
        def check_environment():
 
2377
            self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
 
2378
        self.check_popen_state = check_environment
 
2379
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2380
            env_changes={'NON_EXISTANT_ENV_VAR':None})
 
2381
 
 
2382
    def test_working_dir(self):
 
2383
        """Test that we can specify the working dir for the child"""
 
2384
        orig_getcwd = osutils.getcwd
 
2385
        orig_chdir = os.chdir
 
2386
        chdirs = []
 
2387
        def chdir(path):
 
2388
            chdirs.append(path)
 
2389
        os.chdir = chdir
 
2390
        try:
 
2391
            def getcwd():
 
2392
                return 'current'
 
2393
            osutils.getcwd = getcwd
 
2394
            try:
 
2395
                self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2396
                    working_dir='foo')
 
2397
            finally:
 
2398
                osutils.getcwd = orig_getcwd
 
2399
        finally:
 
2400
            os.chdir = orig_chdir
 
2401
        self.assertEqual(['foo', 'current'], chdirs)
 
2402
 
 
2403
 
 
2404
class TestActuallyStartBzrSubprocess(tests.TestCaseWithTransport):
 
2405
    """Tests that really need to do things with an external bzr."""
 
2406
 
 
2407
    def test_start_and_stop_bzr_subprocess_send_signal(self):
 
2408
        """finish_bzr_subprocess raises self.failureException if the retcode is
 
2409
        not the expected one.
 
2410
        """
 
2411
        self.disable_missing_extensions_warning()
 
2412
        process = self.start_bzr_subprocess(['wait-until-signalled'],
 
2413
                                            skip_if_plan_to_signal=True)
 
2414
        self.assertEqual('running\n', process.stdout.readline())
 
2415
        result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT,
 
2416
                                            retcode=3)
 
2417
        self.assertEqual('', result[0])
 
2418
        self.assertEqual('bzr: interrupted\n', result[1])
 
2419
 
1773
2420
 
1774
2421
class TestKnownFailure(tests.TestCase):
1775
2422
 
1840
2487
        tests.TestCase.setUp(self)
1841
2488
        self.suite = TestUtil.TestSuite()
1842
2489
        self.loader = TestUtil.TestLoader()
1843
 
        self.suite.addTest(self.loader.loadTestsFromModuleNames([
1844
 
            'bzrlib.tests.test_selftest']))
 
2490
        self.suite.addTest(self.loader.loadTestsFromModule(
 
2491
            sys.modules['bzrlib.tests.test_selftest']))
1845
2492
        self.all_names = _test_ids(self.suite)
1846
2493
 
1847
2494
    def test_condition_id_re(self):
2025
2672
        # Running bzr in blackbox mode, normal/expected/user errors should be
2026
2673
        # caught in the regular way and turned into an error message plus exit
2027
2674
        # code.
2028
 
        out, err = self.run_bzr(["log", "/nonexistantpath"], retcode=3)
 
2675
        transport_server = MemoryServer()
 
2676
        transport_server.setUp()
 
2677
        self.addCleanup(transport_server.tearDown)
 
2678
        url = transport_server.get_url()
 
2679
        self.permit_url(url)
 
2680
        out, err = self.run_bzr(["log", "%s/nonexistantpath" % url], retcode=3)
2029
2681
        self.assertEqual(out, '')
2030
2682
        self.assertContainsRe(err,
2031
2683
            'bzr: ERROR: Not a branch: ".*nonexistantpath/".\n')
2157
2809
 
2158
2810
class TestTestSuite(tests.TestCase):
2159
2811
 
 
2812
    def test__test_suite_testmod_names(self):
 
2813
        # Test that a plausible list of test module names are returned
 
2814
        # by _test_suite_testmod_names.
 
2815
        test_list = tests._test_suite_testmod_names()
 
2816
        self.assertSubset([
 
2817
            'bzrlib.tests.blackbox',
 
2818
            'bzrlib.tests.per_transport',
 
2819
            'bzrlib.tests.test_selftest',
 
2820
            ],
 
2821
            test_list)
 
2822
 
 
2823
    def test__test_suite_modules_to_doctest(self):
 
2824
        # Test that a plausible list of modules to doctest is returned
 
2825
        # by _test_suite_modules_to_doctest.
 
2826
        test_list = tests._test_suite_modules_to_doctest()
 
2827
        self.assertSubset([
 
2828
            'bzrlib.timestamp',
 
2829
            ],
 
2830
            test_list)
 
2831
 
2160
2832
    def test_test_suite(self):
2161
 
        # This test is slow, so we do a single test with one test in each
2162
 
        # category
2163
 
        test_list = [
 
2833
        # test_suite() loads the entire test suite to operate. To avoid this
 
2834
        # overhead, and yet still be confident that things are happening,
 
2835
        # we temporarily replace two functions used by test_suite with 
 
2836
        # test doubles that supply a few sample tests to load, and check they
 
2837
        # are loaded.
 
2838
        calls = []
 
2839
        def _test_suite_testmod_names():
 
2840
            calls.append("testmod_names")
 
2841
            return [
 
2842
                'bzrlib.tests.blackbox.test_branch',
 
2843
                'bzrlib.tests.per_transport',
 
2844
                'bzrlib.tests.test_selftest',
 
2845
                ]
 
2846
        original_testmod_names = tests._test_suite_testmod_names
 
2847
        def _test_suite_modules_to_doctest():
 
2848
            calls.append("modules_to_doctest")
 
2849
            return ['bzrlib.timestamp']
 
2850
        orig_modules_to_doctest = tests._test_suite_modules_to_doctest
 
2851
        def restore_names():
 
2852
            tests._test_suite_testmod_names = original_testmod_names
 
2853
            tests._test_suite_modules_to_doctest = orig_modules_to_doctest
 
2854
        self.addCleanup(restore_names)
 
2855
        tests._test_suite_testmod_names = _test_suite_testmod_names
 
2856
        tests._test_suite_modules_to_doctest = _test_suite_modules_to_doctest
 
2857
        expected_test_list = [
2164
2858
            # testmod_names
2165
2859
            'bzrlib.tests.blackbox.test_branch.TestBranch.test_branch',
2166
2860
            ('bzrlib.tests.per_transport.TransportTests'
2171
2865
            # plugins can't be tested that way since selftest may be run with
2172
2866
            # --no-plugins
2173
2867
            ]
2174
 
        suite = tests.test_suite(test_list)
2175
 
        self.assertEquals(test_list, _test_ids(suite))
 
2868
        suite = tests.test_suite()
 
2869
        self.assertEqual(set(["testmod_names", "modules_to_doctest"]),
 
2870
            set(calls))
 
2871
        self.assertSubset(expected_test_list, _test_ids(suite))
2176
2872
 
2177
2873
    def test_test_suite_list_and_start(self):
 
2874
        # We cannot test this at the same time as the main load, because we want
 
2875
        # to know that starting_with == None works. So a second load is
 
2876
        # incurred - note that the starting_with parameter causes a partial load
 
2877
        # rather than a full load so this test should be pretty quick.
2178
2878
        test_list = ['bzrlib.tests.test_selftest.TestTestSuite.test_test_suite']
2179
2879
        suite = tests.test_suite(test_list,
2180
2880
                                 ['bzrlib.tests.test_selftest.TestTestSuite'])
2326
3026
                                                self.verbosity)
2327
3027
        tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
2328
3028
        self.assertLength(1, calls)
2329
 
 
2330
 
    def test_done(self):
2331
 
        """run_suite should call result.done()"""
2332
 
        self.calls = 0
2333
 
        def one_more_call(): self.calls += 1
2334
 
        def test_function():
2335
 
            pass
2336
 
        test = unittest.FunctionTestCase(test_function)
2337
 
        class InstrumentedTestResult(tests.ExtendedTestResult):
2338
 
            def done(self): one_more_call()
2339
 
        class MyRunner(tests.TextTestRunner):
2340
 
            def run(self, test):
2341
 
                return InstrumentedTestResult(self.stream, self.descriptions,
2342
 
                                              self.verbosity)
2343
 
        tests.run_suite(test, runner_class=MyRunner, stream=StringIO())
2344
 
        self.assertEquals(1, self.calls)