~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_selftest.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-04-29 11:07:14 UTC
  • mfrom: (5813.1.1 realname-can-be-empty)
  • Revision ID: pqm@pqm.ubuntu.com-20110429110714-wr9f71ea9600lvb6
(jelmer) Allow realname to be empty in tests. (Jelmer Vernooij)

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):
111
106
 
112
107
        filename = u'hell\u00d8'
113
108
        self.build_tree_contents([(filename, 'contents of hello')])
114
 
        self.failUnlessExists(filename)
 
109
        self.assertPathExists(filename)
115
110
 
116
111
 
117
112
class TestClassesAvailable(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")]
516
510
        self.assertRaises(AssertionError, self.assertEqualStat,
517
511
            os.lstat("foo"), os.lstat("longname"))
518
512
 
 
513
    def test_failUnlessExists(self):
 
514
        """Deprecated failUnlessExists and failIfExists"""
 
515
        self.applyDeprecated(
 
516
            deprecated_in((2, 4)),
 
517
            self.failUnlessExists, '.')
 
518
        self.build_tree(['foo/', 'foo/bar'])
 
519
        self.applyDeprecated(
 
520
            deprecated_in((2, 4)),
 
521
            self.failUnlessExists, 'foo/bar')
 
522
        self.applyDeprecated(
 
523
            deprecated_in((2, 4)),
 
524
            self.failIfExists, 'foo/foo')
 
525
 
 
526
    def test_assertPathExists(self):
 
527
        self.assertPathExists('.')
 
528
        self.build_tree(['foo/', 'foo/bar'])
 
529
        self.assertPathExists('foo/bar')
 
530
        self.assertPathDoesNotExist('foo/foo')
 
531
 
519
532
 
520
533
class TestTestCaseWithMemoryTransport(tests.TestCaseWithMemoryTransport):
521
534
 
555
568
        tree = self.make_branch_and_memory_tree('dir')
556
569
        # Guard against regression into MemoryTransport leaking
557
570
        # files to disk instead of keeping them in memory.
558
 
        self.failIf(osutils.lexists('dir'))
 
571
        self.assertFalse(osutils.lexists('dir'))
559
572
        self.assertIsInstance(tree, memorytree.MemoryTree)
560
573
 
561
574
    def test_make_branch_and_memory_tree_with_format(self):
562
575
        """make_branch_and_memory_tree should accept a format option."""
563
576
        format = bzrdir.BzrDirMetaFormat1()
564
 
        format.repository_format = weaverepo.RepositoryFormat7()
 
577
        format.repository_format = repository.format_registry.get_default()
565
578
        tree = self.make_branch_and_memory_tree('dir', format=format)
566
579
        # Guard against regression into MemoryTransport leaking
567
580
        # files to disk instead of keeping them in memory.
568
 
        self.failIf(osutils.lexists('dir'))
 
581
        self.assertFalse(osutils.lexists('dir'))
569
582
        self.assertIsInstance(tree, memorytree.MemoryTree)
570
583
        self.assertEqual(format.repository_format.__class__,
571
584
            tree.branch.repository._format.__class__)
575
588
        self.assertIsInstance(builder, branchbuilder.BranchBuilder)
576
589
        # Guard against regression into MemoryTransport leaking
577
590
        # files to disk instead of keeping them in memory.
578
 
        self.failIf(osutils.lexists('dir'))
 
591
        self.assertFalse(osutils.lexists('dir'))
579
592
 
580
593
    def test_make_branch_builder_with_format(self):
581
594
        # Use a repo layout that doesn't conform to a 'named' layout, to ensure
582
595
        # that the format objects are used.
583
596
        format = bzrdir.BzrDirMetaFormat1()
584
 
        repo_format = weaverepo.RepositoryFormat7()
 
597
        repo_format = repository.format_registry.get_default()
585
598
        format.repository_format = repo_format
586
599
        builder = self.make_branch_builder('dir', format=format)
587
600
        the_branch = builder.get_branch()
588
601
        # Guard against regression into MemoryTransport leaking
589
602
        # files to disk instead of keeping them in memory.
590
 
        self.failIf(osutils.lexists('dir'))
 
603
        self.assertFalse(osutils.lexists('dir'))
591
604
        self.assertEqual(format.repository_format.__class__,
592
605
                         the_branch.repository._format.__class__)
593
606
        self.assertEqual(repo_format.get_format_string(),
599
612
        the_branch = builder.get_branch()
600
613
        # Guard against regression into MemoryTransport leaking
601
614
        # files to disk instead of keeping them in memory.
602
 
        self.failIf(osutils.lexists('dir'))
 
615
        self.assertFalse(osutils.lexists('dir'))
603
616
        dir_format = bzrdir.format_registry.make_bzrdir('knit')
604
617
        self.assertEqual(dir_format.repository_format.__class__,
605
618
                         the_branch.repository._format.__class__)
638
651
        url2 = self.get_readonly_url('foo/bar')
639
652
        t = transport.get_transport(url)
640
653
        t2 = transport.get_transport(url2)
641
 
        self.failUnless(isinstance(t, ReadonlyTransportDecorator))
642
 
        self.failUnless(isinstance(t2, ReadonlyTransportDecorator))
 
654
        self.assertIsInstance(t, ReadonlyTransportDecorator)
 
655
        self.assertIsInstance(t2, ReadonlyTransportDecorator)
643
656
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
644
657
 
645
658
    def test_get_readonly_url_http(self):
653
666
        # the transport returned may be any HttpTransportBase subclass
654
667
        t = transport.get_transport(url)
655
668
        t2 = transport.get_transport(url2)
656
 
        self.failUnless(isinstance(t, HttpTransportBase))
657
 
        self.failUnless(isinstance(t2, HttpTransportBase))
 
669
        self.assertIsInstance(t, HttpTransportBase)
 
670
        self.assertIsInstance(t2, HttpTransportBase)
658
671
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
659
672
 
660
673
    def test_is_directory(self):
668
681
    def test_make_branch_builder(self):
669
682
        builder = self.make_branch_builder('dir')
670
683
        rev_id = builder.build_commit()
671
 
        self.failUnlessExists('dir')
 
684
        self.assertPathExists('dir')
672
685
        a_dir = bzrdir.BzrDir.open('dir')
673
686
        self.assertRaises(errors.NoWorkingTree, a_dir.open_workingtree)
674
687
        a_branch = a_dir.open_branch()
690
703
        self.assertIsInstance(result_bzrdir.transport,
691
704
                              memory.MemoryTransport)
692
705
        # should not be on disk, should only be in memory
693
 
        self.failIfExists('subdir')
 
706
        self.assertPathDoesNotExist('subdir')
694
707
 
695
708
 
696
709
class TestChrootedTest(tests.ChrootedTestCase):
755
768
        self.check_timing(ShortDelayTestCase('test_short_delay'),
756
769
                          r"^ +[0-9]+ms$")
757
770
 
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
771
    def _time_hello_world_encoding(self):
799
772
        """Profile two sleep calls
800
773
 
1219
1192
            ],
1220
1193
            lines[-3:])
1221
1194
 
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
1195
    def test_verbose_test_count(self):
1246
1196
        """A verbose test run reports the right test count at the start"""
1247
1197
        suite = TestUtil.TestSuite([
1282
1232
        result = self.run_test_runner(runner, test)
1283
1233
        self.assertLength(1, calls)
1284
1234
 
 
1235
    def test_unicode_test_output_on_ascii_stream(self):
 
1236
        """Showing results should always succeed even on an ascii console"""
 
1237
        class FailureWithUnicode(tests.TestCase):
 
1238
            def test_log_unicode(self):
 
1239
                self.log(u"\u2606")
 
1240
                self.fail("Now print that log!")
 
1241
        out = StringIO()
 
1242
        self.overrideAttr(osutils, "get_terminal_encoding",
 
1243
            lambda trace=False: "ascii")
 
1244
        result = self.run_test_runner(tests.TextTestRunner(stream=out),
 
1245
            FailureWithUnicode("test_log_unicode"))
 
1246
        self.assertContainsRe(out.getvalue(),
 
1247
            "Text attachment: log\n"
 
1248
            "-+\n"
 
1249
            "\d+\.\d+  \\\\u2606\n"
 
1250
            "-+\n")
 
1251
 
1285
1252
 
1286
1253
class SampleTestCase(tests.TestCase):
1287
1254
 
1475
1442
        # Note this test won't fail with hooks that the core library doesn't
1476
1443
        # use - but it trigger with a plugin that adds hooks, so its still a
1477
1444
        # useful warning in that case.
1478
 
        self.assertEqual(bzrlib.branch.BranchHooks(),
1479
 
            bzrlib.branch.Branch.hooks)
1480
 
        self.assertEqual(bzrlib.smart.server.SmartServerHooks(),
 
1445
        self.assertEqual(bzrlib.branch.BranchHooks(), bzrlib.branch.Branch.hooks)
 
1446
        self.assertEqual(
 
1447
            bzrlib.smart.server.SmartServerHooks(),
1481
1448
            bzrlib.smart.server.SmartTCPServer.hooks)
1482
 
        self.assertEqual(bzrlib.commands.CommandHooks(),
1483
 
            bzrlib.commands.Command.hooks)
 
1449
        self.assertEqual(
 
1450
            bzrlib.commands.CommandHooks(), bzrlib.commands.Command.hooks)
1484
1451
 
1485
1452
    def test__gather_lsprof_in_benchmarks(self):
1486
1453
        """When _gather_lsprof_in_benchmarks is on, accumulate profile data.
1964
1931
    def test_make_branch_and_tree_with_format(self):
1965
1932
        # we should be able to supply a format to make_branch_and_tree
1966
1933
        self.make_branch_and_tree('a', format=bzrlib.bzrdir.BzrDirMetaFormat1())
1967
 
        self.make_branch_and_tree('b', format=bzrlib.bzrdir.BzrDirFormat6())
1968
1934
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('a')._format,
1969
1935
                              bzrlib.bzrdir.BzrDirMetaFormat1)
1970
 
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('b')._format,
1971
 
                              bzrlib.bzrdir.BzrDirFormat6)
1972
1936
 
1973
1937
    def test_make_branch_and_memory_tree(self):
1974
1938
        # we should be able to get a new branch and a mutable tree from
2353
2317
        # stdout and stderr of the invoked run_bzr
2354
2318
        current_factory = bzrlib.ui.ui_factory
2355
2319
        self.run_bzr(['foo'])
2356
 
        self.failIf(current_factory is self.factory)
 
2320
        self.assertFalse(current_factory is self.factory)
2357
2321
        self.assertNotEqual(sys.stdout, self.factory.stdout)
2358
2322
        self.assertNotEqual(sys.stderr, self.factory.stderr)
2359
2323
        self.assertEqual('foo\n', self.factory.stdout.getvalue())
2541
2505
        self.assertEqual([], command[2:])
2542
2506
 
2543
2507
    def test_set_env(self):
2544
 
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
 
2508
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2545
2509
        # set in the child
2546
2510
        def check_environment():
2547
2511
            self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2553
2517
 
2554
2518
    def test_run_bzr_subprocess_env_del(self):
2555
2519
        """run_bzr_subprocess can remove environment variables too."""
2556
 
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
 
2520
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2557
2521
        def check_environment():
2558
2522
            self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2559
2523
        os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2565
2529
        del os.environ['EXISTANT_ENV_VAR']
2566
2530
 
2567
2531
    def test_env_del_missing(self):
2568
 
        self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
 
2532
        self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2569
2533
        def check_environment():
2570
2534
            self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2571
2535
        self.check_popen_state = check_environment
3193
3157
        tpr.register('bar', 'bBB.aAA.rRR')
3194
3158
        self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
3195
3159
        self.assertThat(self.get_log(),
3196
 
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR", ELLIPSIS))
 
3160
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
 
3161
                           doctest.ELLIPSIS))
3197
3162
 
3198
3163
    def test_get_unknown_prefix(self):
3199
3164
        tpr = self._get_registry()
3234
3199
        class Test(unittest.TestCase):
3235
3200
            def runTest(self):
3236
3201
                pass
3237
 
            addCleanup = None # for when on Python 2.7 with native addCleanup
3238
3202
        result = self.LeakRecordingResult()
3239
3203
        test = Test()
3240
 
        self.assertIs(getattr(test, "addCleanup", None), None)
3241
3204
        result.startTestRun()
3242
3205
        test.run(result)
3243
3206
        result.stopTestRun()
3370
3333
        result = tests.ExtendedTestResult(StringIO(), 0, 1)
3371
3334
        post_mortem_calls = []
3372
3335
        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))
 
3336
        self.overrideEnv('BZR_TEST_PDB', None)
3375
3337
        result._post_mortem(1)
3376
 
        os.environ["BZR_TEST_PDB"] = "on"
 
3338
        self.overrideEnv('BZR_TEST_PDB', 'on')
3377
3339
        result._post_mortem(2)
3378
3340
        self.assertEqual([2], post_mortem_calls)
3379
3341
 
3394
3356
                                                self.verbosity)
3395
3357
        tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3396
3358
        self.assertLength(1, calls)
 
3359
 
 
3360
 
 
3361
class TestEnvironHandling(tests.TestCase):
 
3362
 
 
3363
    def test_overrideEnv_None_called_twice_doesnt_leak(self):
 
3364
        self.assertFalse('MYVAR' in os.environ)
 
3365
        self.overrideEnv('MYVAR', '42')
 
3366
        # We use an embedded test to make sure we fix the _captureVar bug
 
3367
        class Test(tests.TestCase):
 
3368
            def test_me(self):
 
3369
                # The first call save the 42 value
 
3370
                self.overrideEnv('MYVAR', None)
 
3371
                self.assertEquals(None, os.environ.get('MYVAR'))
 
3372
                # Make sure we can call it twice
 
3373
                self.overrideEnv('MYVAR', None)
 
3374
                self.assertEquals(None, os.environ.get('MYVAR'))
 
3375
        output = StringIO()
 
3376
        result = tests.TextTestResult(output, 0, 1)
 
3377
        Test('test_me').run(result)
 
3378
        if not result.wasStrictlySuccessful():
 
3379
            self.fail(output.getvalue())
 
3380
        # We get our value back
 
3381
        self.assertEquals('42', os.environ.get('MYVAR'))
 
3382
 
 
3383
 
 
3384
class TestIsolatedEnv(tests.TestCase):
 
3385
    """Test isolating tests from os.environ.
 
3386
 
 
3387
    Since we use tests that are already isolated from os.environ a bit of care
 
3388
    should be taken when designing the tests to avoid bootstrap side-effects.
 
3389
    The tests start an already clean os.environ which allow doing valid
 
3390
    assertions about which variables are present or not and design tests around
 
3391
    these assertions.
 
3392
    """
 
3393
 
 
3394
    class ScratchMonkey(tests.TestCase):
 
3395
 
 
3396
        def test_me(self):
 
3397
            pass
 
3398
 
 
3399
    def test_basics(self):
 
3400
        # Make sure we know the definition of BZR_HOME: not part of os.environ
 
3401
        # for tests.TestCase.
 
3402
        self.assertTrue('BZR_HOME' in tests.isolated_environ)
 
3403
        self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
 
3404
        # Being part of isolated_environ, BZR_HOME should not appear here
 
3405
        self.assertFalse('BZR_HOME' in os.environ)
 
3406
        # Make sure we know the definition of LINES: part of os.environ for
 
3407
        # tests.TestCase
 
3408
        self.assertTrue('LINES' in tests.isolated_environ)
 
3409
        self.assertEquals('25', tests.isolated_environ['LINES'])
 
3410
        self.assertEquals('25', os.environ['LINES'])
 
3411
 
 
3412
    def test_injecting_unknown_variable(self):
 
3413
        # BZR_HOME is known to be absent from os.environ
 
3414
        test = self.ScratchMonkey('test_me')
 
3415
        tests.override_os_environ(test, {'BZR_HOME': 'foo'})
 
3416
        self.assertEquals('foo', os.environ['BZR_HOME'])
 
3417
        tests.restore_os_environ(test)
 
3418
        self.assertFalse('BZR_HOME' in os.environ)
 
3419
 
 
3420
    def test_injecting_known_variable(self):
 
3421
        test = self.ScratchMonkey('test_me')
 
3422
        # LINES is known to be present in os.environ
 
3423
        tests.override_os_environ(test, {'LINES': '42'})
 
3424
        self.assertEquals('42', os.environ['LINES'])
 
3425
        tests.restore_os_environ(test)
 
3426
        self.assertEquals('25', os.environ['LINES'])
 
3427
 
 
3428
    def test_deleting_variable(self):
 
3429
        test = self.ScratchMonkey('test_me')
 
3430
        # LINES is known to be present in os.environ
 
3431
        tests.override_os_environ(test, {'LINES': None})
 
3432
        self.assertTrue('LINES' not in os.environ)
 
3433
        tests.restore_os_environ(test)
 
3434
        self.assertEquals('25', os.environ['LINES'])
 
3435
 
 
3436
 
 
3437
class TestDocTestSuiteIsolation(tests.TestCase):
 
3438
    """Test that `tests.DocTestSuite` isolates doc tests from os.environ.
 
3439
 
 
3440
    Since tests.TestCase alreay provides an isolation from os.environ, we use
 
3441
    the clean environment as a base for testing. To precisely capture the
 
3442
    isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
 
3443
    compare against.
 
3444
 
 
3445
    We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
 
3446
    not `os.environ` so each test overrides it to suit its needs.
 
3447
 
 
3448
    """
 
3449
 
 
3450
    def get_doctest_suite_for_string(self, klass, string):
 
3451
        class Finder(doctest.DocTestFinder):
 
3452
 
 
3453
            def find(*args, **kwargs):
 
3454
                test = doctest.DocTestParser().get_doctest(
 
3455
                    string, {}, 'foo', 'foo.py', 0)
 
3456
                return [test]
 
3457
 
 
3458
        suite = klass(test_finder=Finder())
 
3459
        return suite
 
3460
 
 
3461
    def run_doctest_suite_for_string(self, klass, string):
 
3462
        suite = self.get_doctest_suite_for_string(klass, string)
 
3463
        output = StringIO()
 
3464
        result = tests.TextTestResult(output, 0, 1)
 
3465
        suite.run(result)
 
3466
        return result, output
 
3467
 
 
3468
    def assertDocTestStringSucceds(self, klass, string):
 
3469
        result, output = self.run_doctest_suite_for_string(klass, string)
 
3470
        if not result.wasStrictlySuccessful():
 
3471
            self.fail(output.getvalue())
 
3472
 
 
3473
    def assertDocTestStringFails(self, klass, string):
 
3474
        result, output = self.run_doctest_suite_for_string(klass, string)
 
3475
        if result.wasStrictlySuccessful():
 
3476
            self.fail(output.getvalue())
 
3477
 
 
3478
    def test_injected_variable(self):
 
3479
        self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
 
3480
        test = """
 
3481
            >>> import os
 
3482
            >>> os.environ['LINES']
 
3483
            '42'
 
3484
            """
 
3485
        # doctest.DocTestSuite fails as it sees '25'
 
3486
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
 
3487
        # tests.DocTestSuite sees '42'
 
3488
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
 
3489
 
 
3490
    def test_deleted_variable(self):
 
3491
        self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
 
3492
        test = """
 
3493
            >>> import os
 
3494
            >>> os.environ.get('LINES')
 
3495
            """
 
3496
        # doctest.DocTestSuite fails as it sees '25'
 
3497
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
 
3498
        # tests.DocTestSuite sees None
 
3499
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)