~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_selftest.py

  • Committer: Martin
  • Date: 2011-04-15 21:22:57 UTC
  • mto: This revision was merged to the branch mainline in revision 5797.
  • Revision ID: gzlist@googlemail.com-20110415212257-jgtovwwp4be7egd9
Add release notes

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
"""Tests for the test framework."""
18
18
 
19
19
from cStringIO import StringIO
20
 
from doctest import ELLIPSIS
 
20
import doctest
21
21
import os
22
22
import signal
23
23
import sys
42
42
from bzrlib import (
43
43
    branchbuilder,
44
44
    bzrdir,
45
 
    debug,
46
45
    errors,
47
46
    lockdir,
48
47
    memorytree,
56
55
    )
57
56
from bzrlib.repofmt import (
58
57
    groupcompress_repo,
59
 
    pack_repo,
60
 
    weaverepo,
61
58
    )
62
59
from bzrlib.symbol_versioning import (
63
60
    deprecated_function,
68
65
    features,
69
66
    test_lsprof,
70
67
    test_server,
71
 
    test_sftp_transport,
72
68
    TestUtil,
73
69
    )
74
70
from bzrlib.trace import note, mutter
75
71
from bzrlib.transport import memory
76
 
from bzrlib.version import _get_bzr_source_tree
77
72
 
78
73
 
79
74
def _test_ids(test_suite):
92
87
            "text", "plain", {"charset": "utf8"})))
93
88
        self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
94
89
        self.assertThat(self.get_log(),
95
 
            DocTestMatches(u"...a test message\n", ELLIPSIS))
 
90
            DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
96
91
 
97
92
 
98
93
class TestUnicodeFilename(tests.TestCase):
343
338
        from bzrlib.tests.per_workingtree import make_scenarios
344
339
        server1 = "a"
345
340
        server2 = "b"
346
 
        formats = [workingtree.WorkingTreeFormat2(),
 
341
        formats = [workingtree.WorkingTreeFormat4(),
347
342
                   workingtree.WorkingTreeFormat3(),]
348
343
        scenarios = make_scenarios(server1, server2, formats)
349
344
        self.assertEqual([
350
 
            ('WorkingTreeFormat2',
 
345
            ('WorkingTreeFormat4',
351
346
             {'bzrdir_format': formats[0]._matchingbzrdir,
352
347
              'transport_readonly_server': 'b',
353
348
              'transport_server': 'a',
380
375
            )
381
376
        server1 = "a"
382
377
        server2 = "b"
383
 
        formats = [workingtree.WorkingTreeFormat2(),
 
378
        formats = [workingtree.WorkingTreeFormat4(),
384
379
                   workingtree.WorkingTreeFormat3(),]
385
380
        scenarios = make_scenarios(server1, server2, formats)
386
381
        self.assertEqual(7, len(scenarios))
387
 
        default_wt_format = workingtree.WorkingTreeFormat4._default_format
 
382
        default_wt_format = workingtree.format_registry.get_default()
388
383
        wt4_format = workingtree.WorkingTreeFormat4()
389
384
        wt5_format = workingtree.WorkingTreeFormat5()
390
385
        expected_scenarios = [
391
 
            ('WorkingTreeFormat2',
 
386
            ('WorkingTreeFormat4',
392
387
             {'bzrdir_format': formats[0]._matchingbzrdir,
393
388
              'transport_readonly_server': 'b',
394
389
              'transport_server': 'a',
454
449
        # ones to add.
455
450
        from bzrlib.tests.per_tree import (
456
451
            return_parameter,
457
 
            revision_tree_from_workingtree
458
452
            )
459
453
        from bzrlib.tests.per_intertree import (
460
454
            make_scenarios,
461
455
            )
462
 
        from bzrlib.workingtree import WorkingTreeFormat2, WorkingTreeFormat3
 
456
        from bzrlib.workingtree import WorkingTreeFormat3, WorkingTreeFormat4
463
457
        input_test = TestInterTreeScenarios(
464
458
            "test_scenarios")
465
459
        server1 = "a"
466
460
        server2 = "b"
467
 
        format1 = WorkingTreeFormat2()
 
461
        format1 = WorkingTreeFormat4()
468
462
        format2 = WorkingTreeFormat3()
469
463
        formats = [("1", str, format1, format2, "converter1"),
470
464
            ("2", int, format2, format1, "converter2")]
561
555
    def test_make_branch_and_memory_tree_with_format(self):
562
556
        """make_branch_and_memory_tree should accept a format option."""
563
557
        format = bzrdir.BzrDirMetaFormat1()
564
 
        format.repository_format = weaverepo.RepositoryFormat7()
 
558
        format.repository_format = repository.format_registry.get_default()
565
559
        tree = self.make_branch_and_memory_tree('dir', format=format)
566
560
        # Guard against regression into MemoryTransport leaking
567
561
        # files to disk instead of keeping them in memory.
581
575
        # Use a repo layout that doesn't conform to a 'named' layout, to ensure
582
576
        # that the format objects are used.
583
577
        format = bzrdir.BzrDirMetaFormat1()
584
 
        repo_format = weaverepo.RepositoryFormat7()
 
578
        repo_format = repository.format_registry.get_default()
585
579
        format.repository_format = repo_format
586
580
        builder = self.make_branch_builder('dir', format=format)
587
581
        the_branch = builder.get_branch()
755
749
        self.check_timing(ShortDelayTestCase('test_short_delay'),
756
750
                          r"^ +[0-9]+ms$")
757
751
 
758
 
    def _patch_get_bzr_source_tree(self):
759
 
        # Reading from the actual source tree breaks isolation, but we don't
760
 
        # want to assume that thats *all* that would happen.
761
 
        self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', lambda: None)
762
 
 
763
 
    def test_assigned_benchmark_file_stores_date(self):
764
 
        self._patch_get_bzr_source_tree()
765
 
        output = StringIO()
766
 
        result = bzrlib.tests.TextTestResult(self._log_file,
767
 
                                        descriptions=0,
768
 
                                        verbosity=1,
769
 
                                        bench_history=output
770
 
                                        )
771
 
        output_string = output.getvalue()
772
 
        # if you are wondering about the regexp please read the comment in
773
 
        # test_bench_history (bzrlib.tests.test_selftest.TestRunner)
774
 
        # XXX: what comment?  -- Andrew Bennetts
775
 
        self.assertContainsRe(output_string, "--date [0-9.]+")
776
 
 
777
 
    def test_benchhistory_records_test_times(self):
778
 
        self._patch_get_bzr_source_tree()
779
 
        result_stream = StringIO()
780
 
        result = bzrlib.tests.TextTestResult(
781
 
            self._log_file,
782
 
            descriptions=0,
783
 
            verbosity=1,
784
 
            bench_history=result_stream
785
 
            )
786
 
 
787
 
        # we want profile a call and check that its test duration is recorded
788
 
        # make a new test instance that when run will generate a benchmark
789
 
        example_test_case = TestTestResult("_time_hello_world_encoding")
790
 
        # execute the test, which should succeed and record times
791
 
        example_test_case.run(result)
792
 
        lines = result_stream.getvalue().splitlines()
793
 
        self.assertEqual(2, len(lines))
794
 
        self.assertContainsRe(lines[1],
795
 
            " *[0-9]+ms bzrlib.tests.test_selftest.TestTestResult"
796
 
            "._time_hello_world_encoding")
797
 
 
798
752
    def _time_hello_world_encoding(self):
799
753
        """Profile two sleep calls
800
754
 
1219
1173
            ],
1220
1174
            lines[-3:])
1221
1175
 
1222
 
    def _patch_get_bzr_source_tree(self):
1223
 
        # Reading from the actual source tree breaks isolation, but we don't
1224
 
        # want to assume that thats *all* that would happen.
1225
 
        self._get_source_tree_calls = []
1226
 
        def new_get():
1227
 
            self._get_source_tree_calls.append("called")
1228
 
            return None
1229
 
        self.overrideAttr(bzrlib.version, '_get_bzr_source_tree',  new_get)
1230
 
 
1231
 
    def test_bench_history(self):
1232
 
        # tests that the running the benchmark passes bench_history into
1233
 
        # the test result object. We can tell that happens if
1234
 
        # _get_bzr_source_tree is called.
1235
 
        self._patch_get_bzr_source_tree()
1236
 
        test = TestRunner('dummy_test')
1237
 
        output = StringIO()
1238
 
        runner = tests.TextTestRunner(stream=self._log_file,
1239
 
                                      bench_history=output)
1240
 
        result = self.run_test_runner(runner, test)
1241
 
        output_string = output.getvalue()
1242
 
        self.assertContainsRe(output_string, "--date [0-9.]+")
1243
 
        self.assertLength(1, self._get_source_tree_calls)
1244
 
 
1245
1176
    def test_verbose_test_count(self):
1246
1177
        """A verbose test run reports the right test count at the start"""
1247
1178
        suite = TestUtil.TestSuite([
1282
1213
        result = self.run_test_runner(runner, test)
1283
1214
        self.assertLength(1, calls)
1284
1215
 
 
1216
    def test_unicode_test_output_on_ascii_stream(self):
 
1217
        """Showing results should always succeed even on an ascii console"""
 
1218
        class FailureWithUnicode(tests.TestCase):
 
1219
            def test_log_unicode(self):
 
1220
                self.log(u"\u2606")
 
1221
                self.fail("Now print that log!")
 
1222
        out = StringIO()
 
1223
        self.overrideAttr(osutils, "get_terminal_encoding",
 
1224
            lambda trace=False: "ascii")
 
1225
        result = self.run_test_runner(tests.TextTestRunner(stream=out),
 
1226
            FailureWithUnicode("test_log_unicode"))
 
1227
        self.assertContainsRe(out.getvalue(),
 
1228
            "Text attachment: log\n"
 
1229
            "-+\n"
 
1230
            "\d+\.\d+  \\\\u2606\n"
 
1231
            "-+\n")
 
1232
 
1285
1233
 
1286
1234
class SampleTestCase(tests.TestCase):
1287
1235
 
1475
1423
        # Note this test won't fail with hooks that the core library doesn't
1476
1424
        # use - but it trigger with a plugin that adds hooks, so its still a
1477
1425
        # useful warning in that case.
1478
 
        self.assertEqual(bzrlib.branch.BranchHooks(),
1479
 
            bzrlib.branch.Branch.hooks)
1480
 
        self.assertEqual(bzrlib.smart.server.SmartServerHooks(),
 
1426
        self.assertEqual(bzrlib.branch.BranchHooks(), bzrlib.branch.Branch.hooks)
 
1427
        self.assertEqual(
 
1428
            bzrlib.smart.server.SmartServerHooks(),
1481
1429
            bzrlib.smart.server.SmartTCPServer.hooks)
1482
 
        self.assertEqual(bzrlib.commands.CommandHooks(),
1483
 
            bzrlib.commands.Command.hooks)
 
1430
        self.assertEqual(
 
1431
            bzrlib.commands.CommandHooks(), bzrlib.commands.Command.hooks)
1484
1432
 
1485
1433
    def test__gather_lsprof_in_benchmarks(self):
1486
1434
        """When _gather_lsprof_in_benchmarks is on, accumulate profile data.
1964
1912
    def test_make_branch_and_tree_with_format(self):
1965
1913
        # we should be able to supply a format to make_branch_and_tree
1966
1914
        self.make_branch_and_tree('a', format=bzrlib.bzrdir.BzrDirMetaFormat1())
1967
 
        self.make_branch_and_tree('b', format=bzrlib.bzrdir.BzrDirFormat6())
1968
1915
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('a')._format,
1969
1916
                              bzrlib.bzrdir.BzrDirMetaFormat1)
1970
 
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('b')._format,
1971
 
                              bzrlib.bzrdir.BzrDirFormat6)
1972
1917
 
1973
1918
    def test_make_branch_and_memory_tree(self):
1974
1919
        # we should be able to get a new branch and a mutable tree from
3193
3138
        tpr.register('bar', 'bBB.aAA.rRR')
3194
3139
        self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
3195
3140
        self.assertThat(self.get_log(),
3196
 
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR", ELLIPSIS))
 
3141
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
 
3142
                           doctest.ELLIPSIS))
3197
3143
 
3198
3144
    def test_get_unknown_prefix(self):
3199
3145
        tpr = self._get_registry()
3234
3180
        class Test(unittest.TestCase):
3235
3181
            def runTest(self):
3236
3182
                pass
3237
 
            addCleanup = None # for when on Python 2.7 with native addCleanup
3238
3183
        result = self.LeakRecordingResult()
3239
3184
        test = Test()
3240
 
        self.assertIs(getattr(test, "addCleanup", None), None)
3241
3185
        result.startTestRun()
3242
3186
        test.run(result)
3243
3187
        result.stopTestRun()
3370
3314
        result = tests.ExtendedTestResult(StringIO(), 0, 1)
3371
3315
        post_mortem_calls = []
3372
3316
        self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3373
 
        self.addCleanup(osutils.set_or_unset_env, "BZR_TEST_PDB",
3374
 
            osutils.set_or_unset_env("BZR_TEST_PDB", None))
 
3317
        self.overrideEnv('BZR_TEST_PDB', None)
3375
3318
        result._post_mortem(1)
3376
 
        os.environ["BZR_TEST_PDB"] = "on"
 
3319
        self.overrideEnv('BZR_TEST_PDB', 'on')
3377
3320
        result._post_mortem(2)
3378
3321
        self.assertEqual([2], post_mortem_calls)
3379
3322
 
3394
3337
                                                self.verbosity)
3395
3338
        tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3396
3339
        self.assertLength(1, calls)
 
3340
 
 
3341
 
 
3342
class TestEnvironHandling(tests.TestCase):
 
3343
 
 
3344
    def test_overrideEnv_None_called_twice_doesnt_leak(self):
 
3345
        self.failIf('MYVAR' in os.environ)
 
3346
        self.overrideEnv('MYVAR', '42')
 
3347
        # We use an embedded test to make sure we fix the _captureVar bug
 
3348
        class Test(tests.TestCase):
 
3349
            def test_me(self):
 
3350
                # The first call save the 42 value
 
3351
                self.overrideEnv('MYVAR', None)
 
3352
                self.assertEquals(None, os.environ.get('MYVAR'))
 
3353
                # Make sure we can call it twice
 
3354
                self.overrideEnv('MYVAR', None)
 
3355
                self.assertEquals(None, os.environ.get('MYVAR'))
 
3356
        output = StringIO()
 
3357
        result = tests.TextTestResult(output, 0, 1)
 
3358
        Test('test_me').run(result)
 
3359
        if not result.wasStrictlySuccessful():
 
3360
            self.fail(output.getvalue())
 
3361
        # We get our value back
 
3362
        self.assertEquals('42', os.environ.get('MYVAR'))
 
3363
 
 
3364
 
 
3365
class TestIsolatedEnv(tests.TestCase):
 
3366
    """Test isolating tests from os.environ.
 
3367
 
 
3368
    Since we use tests that are already isolated from os.environ a bit of care
 
3369
    should be taken when designing the tests to avoid bootstrap side-effects.
 
3370
    The tests start an already clean os.environ which allow doing valid
 
3371
    assertions about which variables are present or not and design tests around
 
3372
    these assertions.
 
3373
    """
 
3374
 
 
3375
    class ScratchMonkey(tests.TestCase):
 
3376
 
 
3377
        def test_me(self):
 
3378
            pass
 
3379
 
 
3380
    def test_basics(self):
 
3381
        # Make sure we know the definition of BZR_HOME: not part of os.environ
 
3382
        # for tests.TestCase.
 
3383
        self.assertTrue('BZR_HOME' in tests.isolated_environ)
 
3384
        self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
 
3385
        # Being part of isolated_environ, BZR_HOME should not appear here
 
3386
        self.assertFalse('BZR_HOME' in os.environ)
 
3387
        # Make sure we know the definition of LINES: part of os.environ for
 
3388
        # tests.TestCase
 
3389
        self.assertTrue('LINES' in tests.isolated_environ)
 
3390
        self.assertEquals('25', tests.isolated_environ['LINES'])
 
3391
        self.assertEquals('25', os.environ['LINES'])
 
3392
 
 
3393
    def test_injecting_unknown_variable(self):
 
3394
        # BZR_HOME is known to be absent from os.environ
 
3395
        test = self.ScratchMonkey('test_me')
 
3396
        tests.override_os_environ(test, {'BZR_HOME': 'foo'})
 
3397
        self.assertEquals('foo', os.environ['BZR_HOME'])
 
3398
        tests.restore_os_environ(test)
 
3399
        self.assertFalse('BZR_HOME' in os.environ)
 
3400
 
 
3401
    def test_injecting_known_variable(self):
 
3402
        test = self.ScratchMonkey('test_me')
 
3403
        # LINES is known to be present in os.environ
 
3404
        tests.override_os_environ(test, {'LINES': '42'})
 
3405
        self.assertEquals('42', os.environ['LINES'])
 
3406
        tests.restore_os_environ(test)
 
3407
        self.assertEquals('25', os.environ['LINES'])
 
3408
 
 
3409
    def test_deleting_variable(self):
 
3410
        test = self.ScratchMonkey('test_me')
 
3411
        # LINES is known to be present in os.environ
 
3412
        tests.override_os_environ(test, {'LINES': None})
 
3413
        self.assertTrue('LINES' not in os.environ)
 
3414
        tests.restore_os_environ(test)
 
3415
        self.assertEquals('25', os.environ['LINES'])
 
3416
 
 
3417
 
 
3418
class TestDocTestSuiteIsolation(tests.TestCase):
 
3419
    """Test that `tests.DocTestSuite` isolates doc tests from os.environ.
 
3420
 
 
3421
    Since tests.TestCase alreay provides an isolation from os.environ, we use
 
3422
    the clean environment as a base for testing. To precisely capture the
 
3423
    isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
 
3424
    compare against.
 
3425
 
 
3426
    We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
 
3427
    not `os.environ` so each test overrides it to suit its needs.
 
3428
 
 
3429
    """
 
3430
 
 
3431
    def get_doctest_suite_for_string(self, klass, string):
 
3432
        class Finder(doctest.DocTestFinder):
 
3433
 
 
3434
            def find(*args, **kwargs):
 
3435
                test = doctest.DocTestParser().get_doctest(
 
3436
                    string, {}, 'foo', 'foo.py', 0)
 
3437
                return [test]
 
3438
 
 
3439
        suite = klass(test_finder=Finder())
 
3440
        return suite
 
3441
 
 
3442
    def run_doctest_suite_for_string(self, klass, string):
 
3443
        suite = self.get_doctest_suite_for_string(klass, string)
 
3444
        output = StringIO()
 
3445
        result = tests.TextTestResult(output, 0, 1)
 
3446
        suite.run(result)
 
3447
        return result, output
 
3448
 
 
3449
    def assertDocTestStringSucceds(self, klass, string):
 
3450
        result, output = self.run_doctest_suite_for_string(klass, string)
 
3451
        if not result.wasStrictlySuccessful():
 
3452
            self.fail(output.getvalue())
 
3453
 
 
3454
    def assertDocTestStringFails(self, klass, string):
 
3455
        result, output = self.run_doctest_suite_for_string(klass, string)
 
3456
        if result.wasStrictlySuccessful():
 
3457
            self.fail(output.getvalue())
 
3458
 
 
3459
    def test_injected_variable(self):
 
3460
        self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
 
3461
        test = """
 
3462
            >>> import os
 
3463
            >>> os.environ['LINES']
 
3464
            '42'
 
3465
            """
 
3466
        # doctest.DocTestSuite fails as it sees '25'
 
3467
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
 
3468
        # tests.DocTestSuite sees '42'
 
3469
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
 
3470
 
 
3471
    def test_deleted_variable(self):
 
3472
        self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
 
3473
        test = """
 
3474
            >>> import os
 
3475
            >>> os.environ.get('LINES')
 
3476
            """
 
3477
        # doctest.DocTestSuite fails as it sees '25'
 
3478
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
 
3479
        # tests.DocTestSuite sees None
 
3480
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)