~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_selftest.py

  • Committer: John Arbash Meinel
  • Date: 2010-11-05 20:54:32 UTC
  • mfrom: (5526 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5527.
  • Revision ID: john@arbash-meinel.com-20101105205432-rmyozu8sthyhmri8
Merge bzr.dev to resolve bzr-2.3.txt (aka NEWS)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
 
import doctest
 
20
from doctest import ELLIPSIS
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,
45
46
    errors,
46
47
    lockdir,
47
48
    memorytree,
52
53
    tests,
53
54
    transport,
54
55
    workingtree,
55
 
    workingtree_3,
56
 
    workingtree_4,
57
56
    )
58
57
from bzrlib.repofmt import (
59
58
    groupcompress_repo,
 
59
    pack_repo,
 
60
    weaverepo,
60
61
    )
61
62
from bzrlib.symbol_versioning import (
62
63
    deprecated_function,
67
68
    features,
68
69
    test_lsprof,
69
70
    test_server,
 
71
    test_sftp_transport,
70
72
    TestUtil,
71
73
    )
72
74
from bzrlib.trace import note, mutter
73
75
from bzrlib.transport import memory
 
76
from bzrlib.version import _get_bzr_source_tree
74
77
 
75
78
 
76
79
def _test_ids(test_suite):
89
92
            "text", "plain", {"charset": "utf8"})))
90
93
        self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
91
94
        self.assertThat(self.get_log(),
92
 
            DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
 
95
            DocTestMatches(u"...a test message\n", ELLIPSIS))
93
96
 
94
97
 
95
98
class TestUnicodeFilename(tests.TestCase):
108
111
 
109
112
        filename = u'hell\u00d8'
110
113
        self.build_tree_contents([(filename, 'contents of hello')])
111
 
        self.assertPathExists(filename)
 
114
        self.failUnlessExists(filename)
112
115
 
113
116
 
114
117
class TestClassesAvailable(tests.TestCase):
340
343
        from bzrlib.tests.per_workingtree import make_scenarios
341
344
        server1 = "a"
342
345
        server2 = "b"
343
 
        formats = [workingtree_4.WorkingTreeFormat4(),
344
 
                   workingtree_3.WorkingTreeFormat3(),]
 
346
        formats = [workingtree.WorkingTreeFormat2(),
 
347
                   workingtree.WorkingTreeFormat3(),]
345
348
        scenarios = make_scenarios(server1, server2, formats)
346
349
        self.assertEqual([
347
 
            ('WorkingTreeFormat4',
 
350
            ('WorkingTreeFormat2',
348
351
             {'bzrdir_format': formats[0]._matchingbzrdir,
349
352
              'transport_readonly_server': 'b',
350
353
              'transport_server': 'a',
377
380
            )
378
381
        server1 = "a"
379
382
        server2 = "b"
380
 
        formats = [workingtree_4.WorkingTreeFormat4(),
381
 
                   workingtree_3.WorkingTreeFormat3(),]
 
383
        formats = [workingtree.WorkingTreeFormat2(),
 
384
                   workingtree.WorkingTreeFormat3(),]
382
385
        scenarios = make_scenarios(server1, server2, formats)
383
386
        self.assertEqual(7, len(scenarios))
384
 
        default_wt_format = workingtree.format_registry.get_default()
385
 
        wt4_format = workingtree_4.WorkingTreeFormat4()
386
 
        wt5_format = workingtree_4.WorkingTreeFormat5()
 
387
        default_wt_format = workingtree.WorkingTreeFormat4._default_format
 
388
        wt4_format = workingtree.WorkingTreeFormat4()
 
389
        wt5_format = workingtree.WorkingTreeFormat5()
387
390
        expected_scenarios = [
388
 
            ('WorkingTreeFormat4',
 
391
            ('WorkingTreeFormat2',
389
392
             {'bzrdir_format': formats[0]._matchingbzrdir,
390
393
              'transport_readonly_server': 'b',
391
394
              'transport_server': 'a',
451
454
        # ones to add.
452
455
        from bzrlib.tests.per_tree import (
453
456
            return_parameter,
 
457
            revision_tree_from_workingtree
454
458
            )
455
459
        from bzrlib.tests.per_intertree import (
456
460
            make_scenarios,
457
461
            )
458
 
        from bzrlib.workingtree_3 import WorkingTreeFormat3
459
 
        from bzrlib.workingtree_4 import WorkingTreeFormat4
 
462
        from bzrlib.workingtree import WorkingTreeFormat2, WorkingTreeFormat3
460
463
        input_test = TestInterTreeScenarios(
461
464
            "test_scenarios")
462
465
        server1 = "a"
463
466
        server2 = "b"
464
 
        format1 = WorkingTreeFormat4()
 
467
        format1 = WorkingTreeFormat2()
465
468
        format2 = WorkingTreeFormat3()
466
469
        formats = [("1", str, format1, format2, "converter1"),
467
470
            ("2", int, format2, format1, "converter2")]
513
516
        self.assertRaises(AssertionError, self.assertEqualStat,
514
517
            os.lstat("foo"), os.lstat("longname"))
515
518
 
516
 
    def test_failUnlessExists(self):
517
 
        """Deprecated failUnlessExists and failIfExists"""
518
 
        self.applyDeprecated(
519
 
            deprecated_in((2, 4)),
520
 
            self.failUnlessExists, '.')
521
 
        self.build_tree(['foo/', 'foo/bar'])
522
 
        self.applyDeprecated(
523
 
            deprecated_in((2, 4)),
524
 
            self.failUnlessExists, 'foo/bar')
525
 
        self.applyDeprecated(
526
 
            deprecated_in((2, 4)),
527
 
            self.failIfExists, 'foo/foo')
528
 
 
529
 
    def test_assertPathExists(self):
530
 
        self.assertPathExists('.')
531
 
        self.build_tree(['foo/', 'foo/bar'])
532
 
        self.assertPathExists('foo/bar')
533
 
        self.assertPathDoesNotExist('foo/foo')
534
 
 
535
519
 
536
520
class TestTestCaseWithMemoryTransport(tests.TestCaseWithMemoryTransport):
537
521
 
571
555
        tree = self.make_branch_and_memory_tree('dir')
572
556
        # Guard against regression into MemoryTransport leaking
573
557
        # files to disk instead of keeping them in memory.
574
 
        self.assertFalse(osutils.lexists('dir'))
 
558
        self.failIf(osutils.lexists('dir'))
575
559
        self.assertIsInstance(tree, memorytree.MemoryTree)
576
560
 
577
561
    def test_make_branch_and_memory_tree_with_format(self):
578
562
        """make_branch_and_memory_tree should accept a format option."""
579
563
        format = bzrdir.BzrDirMetaFormat1()
580
 
        format.repository_format = repository.format_registry.get_default()
 
564
        format.repository_format = weaverepo.RepositoryFormat7()
581
565
        tree = self.make_branch_and_memory_tree('dir', format=format)
582
566
        # Guard against regression into MemoryTransport leaking
583
567
        # files to disk instead of keeping them in memory.
584
 
        self.assertFalse(osutils.lexists('dir'))
 
568
        self.failIf(osutils.lexists('dir'))
585
569
        self.assertIsInstance(tree, memorytree.MemoryTree)
586
570
        self.assertEqual(format.repository_format.__class__,
587
571
            tree.branch.repository._format.__class__)
591
575
        self.assertIsInstance(builder, branchbuilder.BranchBuilder)
592
576
        # Guard against regression into MemoryTransport leaking
593
577
        # files to disk instead of keeping them in memory.
594
 
        self.assertFalse(osutils.lexists('dir'))
 
578
        self.failIf(osutils.lexists('dir'))
595
579
 
596
580
    def test_make_branch_builder_with_format(self):
597
581
        # Use a repo layout that doesn't conform to a 'named' layout, to ensure
598
582
        # that the format objects are used.
599
583
        format = bzrdir.BzrDirMetaFormat1()
600
 
        repo_format = repository.format_registry.get_default()
 
584
        repo_format = weaverepo.RepositoryFormat7()
601
585
        format.repository_format = repo_format
602
586
        builder = self.make_branch_builder('dir', format=format)
603
587
        the_branch = builder.get_branch()
604
588
        # Guard against regression into MemoryTransport leaking
605
589
        # files to disk instead of keeping them in memory.
606
 
        self.assertFalse(osutils.lexists('dir'))
 
590
        self.failIf(osutils.lexists('dir'))
607
591
        self.assertEqual(format.repository_format.__class__,
608
592
                         the_branch.repository._format.__class__)
609
593
        self.assertEqual(repo_format.get_format_string(),
615
599
        the_branch = builder.get_branch()
616
600
        # Guard against regression into MemoryTransport leaking
617
601
        # files to disk instead of keeping them in memory.
618
 
        self.assertFalse(osutils.lexists('dir'))
 
602
        self.failIf(osutils.lexists('dir'))
619
603
        dir_format = bzrdir.format_registry.make_bzrdir('knit')
620
604
        self.assertEqual(dir_format.repository_format.__class__,
621
605
                         the_branch.repository._format.__class__)
654
638
        url2 = self.get_readonly_url('foo/bar')
655
639
        t = transport.get_transport(url)
656
640
        t2 = transport.get_transport(url2)
657
 
        self.assertIsInstance(t, ReadonlyTransportDecorator)
658
 
        self.assertIsInstance(t2, ReadonlyTransportDecorator)
 
641
        self.failUnless(isinstance(t, ReadonlyTransportDecorator))
 
642
        self.failUnless(isinstance(t2, ReadonlyTransportDecorator))
659
643
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
660
644
 
661
645
    def test_get_readonly_url_http(self):
669
653
        # the transport returned may be any HttpTransportBase subclass
670
654
        t = transport.get_transport(url)
671
655
        t2 = transport.get_transport(url2)
672
 
        self.assertIsInstance(t, HttpTransportBase)
673
 
        self.assertIsInstance(t2, HttpTransportBase)
 
656
        self.failUnless(isinstance(t, HttpTransportBase))
 
657
        self.failUnless(isinstance(t2, HttpTransportBase))
674
658
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
675
659
 
676
660
    def test_is_directory(self):
684
668
    def test_make_branch_builder(self):
685
669
        builder = self.make_branch_builder('dir')
686
670
        rev_id = builder.build_commit()
687
 
        self.assertPathExists('dir')
 
671
        self.failUnlessExists('dir')
688
672
        a_dir = bzrdir.BzrDir.open('dir')
689
673
        self.assertRaises(errors.NoWorkingTree, a_dir.open_workingtree)
690
674
        a_branch = a_dir.open_branch()
706
690
        self.assertIsInstance(result_bzrdir.transport,
707
691
                              memory.MemoryTransport)
708
692
        # should not be on disk, should only be in memory
709
 
        self.assertPathDoesNotExist('subdir')
 
693
        self.failIfExists('subdir')
710
694
 
711
695
 
712
696
class TestChrootedTest(tests.ChrootedTestCase):
771
755
        self.check_timing(ShortDelayTestCase('test_short_delay'),
772
756
                          r"^ +[0-9]+ms$")
773
757
 
 
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
 
774
798
    def _time_hello_world_encoding(self):
775
799
        """Profile two sleep calls
776
800
 
1195
1219
            ],
1196
1220
            lines[-3:])
1197
1221
 
 
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
 
1198
1245
    def test_verbose_test_count(self):
1199
1246
        """A verbose test run reports the right test count at the start"""
1200
1247
        suite = TestUtil.TestSuite([
1235
1282
        result = self.run_test_runner(runner, test)
1236
1283
        self.assertLength(1, calls)
1237
1284
 
1238
 
    def test_unicode_test_output_on_ascii_stream(self):
1239
 
        """Showing results should always succeed even on an ascii console"""
1240
 
        class FailureWithUnicode(tests.TestCase):
1241
 
            def test_log_unicode(self):
1242
 
                self.log(u"\u2606")
1243
 
                self.fail("Now print that log!")
1244
 
        out = StringIO()
1245
 
        self.overrideAttr(osutils, "get_terminal_encoding",
1246
 
            lambda trace=False: "ascii")
1247
 
        result = self.run_test_runner(tests.TextTestRunner(stream=out),
1248
 
            FailureWithUnicode("test_log_unicode"))
1249
 
        self.assertContainsRe(out.getvalue(),
1250
 
            "Text attachment: log\n"
1251
 
            "-+\n"
1252
 
            "\d+\.\d+  \\\\u2606\n"
1253
 
            "-+\n")
1254
 
 
1255
1285
 
1256
1286
class SampleTestCase(tests.TestCase):
1257
1287
 
1445
1475
        # Note this test won't fail with hooks that the core library doesn't
1446
1476
        # use - but it trigger with a plugin that adds hooks, so its still a
1447
1477
        # useful warning in that case.
1448
 
        self.assertEqual(bzrlib.branch.BranchHooks(), bzrlib.branch.Branch.hooks)
1449
 
        self.assertEqual(
1450
 
            bzrlib.smart.server.SmartServerHooks(),
 
1478
        self.assertEqual(bzrlib.branch.BranchHooks(),
 
1479
            bzrlib.branch.Branch.hooks)
 
1480
        self.assertEqual(bzrlib.smart.server.SmartServerHooks(),
1451
1481
            bzrlib.smart.server.SmartTCPServer.hooks)
1452
 
        self.assertEqual(
1453
 
            bzrlib.commands.CommandHooks(), bzrlib.commands.Command.hooks)
 
1482
        self.assertEqual(bzrlib.commands.CommandHooks(),
 
1483
            bzrlib.commands.Command.hooks)
1454
1484
 
1455
1485
    def test__gather_lsprof_in_benchmarks(self):
1456
1486
        """When _gather_lsprof_in_benchmarks is on, accumulate profile data.
1934
1964
    def test_make_branch_and_tree_with_format(self):
1935
1965
        # we should be able to supply a format to make_branch_and_tree
1936
1966
        self.make_branch_and_tree('a', format=bzrlib.bzrdir.BzrDirMetaFormat1())
 
1967
        self.make_branch_and_tree('b', format=bzrlib.bzrdir.BzrDirFormat6())
1937
1968
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('a')._format,
1938
1969
                              bzrlib.bzrdir.BzrDirMetaFormat1)
 
1970
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('b')._format,
 
1971
                              bzrlib.bzrdir.BzrDirFormat6)
1939
1972
 
1940
1973
    def test_make_branch_and_memory_tree(self):
1941
1974
        # we should be able to get a new branch and a mutable tree from
2320
2353
        # stdout and stderr of the invoked run_bzr
2321
2354
        current_factory = bzrlib.ui.ui_factory
2322
2355
        self.run_bzr(['foo'])
2323
 
        self.assertFalse(current_factory is self.factory)
 
2356
        self.failIf(current_factory is self.factory)
2324
2357
        self.assertNotEqual(sys.stdout, self.factory.stdout)
2325
2358
        self.assertNotEqual(sys.stderr, self.factory.stderr)
2326
2359
        self.assertEqual('foo\n', self.factory.stdout.getvalue())
2508
2541
        self.assertEqual([], command[2:])
2509
2542
 
2510
2543
    def test_set_env(self):
2511
 
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
 
2544
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
2512
2545
        # set in the child
2513
2546
        def check_environment():
2514
2547
            self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2520
2553
 
2521
2554
    def test_run_bzr_subprocess_env_del(self):
2522
2555
        """run_bzr_subprocess can remove environment variables too."""
2523
 
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
 
2556
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
2524
2557
        def check_environment():
2525
2558
            self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2526
2559
        os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2532
2565
        del os.environ['EXISTANT_ENV_VAR']
2533
2566
 
2534
2567
    def test_env_del_missing(self):
2535
 
        self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
 
2568
        self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
2536
2569
        def check_environment():
2537
2570
            self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2538
2571
        self.check_popen_state = check_environment
2813
2846
        self.assertEqual(remaining_names, _test_ids(split_suite[1]))
2814
2847
 
2815
2848
 
2816
 
class TestCheckTreeShape(tests.TestCaseWithTransport):
 
2849
class TestCheckInventoryShape(tests.TestCaseWithTransport):
2817
2850
 
2818
 
    def test_check_tree_shape(self):
 
2851
    def test_check_inventory_shape(self):
2819
2852
        files = ['a', 'b/', 'b/c']
2820
2853
        tree = self.make_branch_and_tree('.')
2821
2854
        self.build_tree(files)
2822
2855
        tree.add(files)
2823
2856
        tree.lock_read()
2824
2857
        try:
2825
 
            self.check_tree_shape(tree, files)
 
2858
            self.check_inventory_shape(tree.inventory, files)
2826
2859
        finally:
2827
2860
            tree.unlock()
2828
2861
 
3160
3193
        tpr.register('bar', 'bBB.aAA.rRR')
3161
3194
        self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
3162
3195
        self.assertThat(self.get_log(),
3163
 
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
3164
 
                           doctest.ELLIPSIS))
 
3196
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR", ELLIPSIS))
3165
3197
 
3166
3198
    def test_get_unknown_prefix(self):
3167
3199
        tpr = self._get_registry()
3202
3234
        class Test(unittest.TestCase):
3203
3235
            def runTest(self):
3204
3236
                pass
 
3237
            addCleanup = None # for when on Python 2.7 with native addCleanup
3205
3238
        result = self.LeakRecordingResult()
3206
3239
        test = Test()
 
3240
        self.assertIs(getattr(test, "addCleanup", None), None)
3207
3241
        result.startTestRun()
3208
3242
        test.run(result)
3209
3243
        result.stopTestRun()
3336
3370
        result = tests.ExtendedTestResult(StringIO(), 0, 1)
3337
3371
        post_mortem_calls = []
3338
3372
        self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3339
 
        self.overrideEnv('BZR_TEST_PDB', None)
 
3373
        self.addCleanup(osutils.set_or_unset_env, "BZR_TEST_PDB",
 
3374
            osutils.set_or_unset_env("BZR_TEST_PDB", None))
3340
3375
        result._post_mortem(1)
3341
 
        self.overrideEnv('BZR_TEST_PDB', 'on')
 
3376
        os.environ["BZR_TEST_PDB"] = "on"
3342
3377
        result._post_mortem(2)
3343
3378
        self.assertEqual([2], post_mortem_calls)
3344
3379
 
3359
3394
                                                self.verbosity)
3360
3395
        tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3361
3396
        self.assertLength(1, calls)
3362
 
 
3363
 
 
3364
 
class TestEnvironHandling(tests.TestCase):
3365
 
 
3366
 
    def test_overrideEnv_None_called_twice_doesnt_leak(self):
3367
 
        self.assertFalse('MYVAR' in os.environ)
3368
 
        self.overrideEnv('MYVAR', '42')
3369
 
        # We use an embedded test to make sure we fix the _captureVar bug
3370
 
        class Test(tests.TestCase):
3371
 
            def test_me(self):
3372
 
                # The first call save the 42 value
3373
 
                self.overrideEnv('MYVAR', None)
3374
 
                self.assertEquals(None, os.environ.get('MYVAR'))
3375
 
                # Make sure we can call it twice
3376
 
                self.overrideEnv('MYVAR', None)
3377
 
                self.assertEquals(None, os.environ.get('MYVAR'))
3378
 
        output = StringIO()
3379
 
        result = tests.TextTestResult(output, 0, 1)
3380
 
        Test('test_me').run(result)
3381
 
        if not result.wasStrictlySuccessful():
3382
 
            self.fail(output.getvalue())
3383
 
        # We get our value back
3384
 
        self.assertEquals('42', os.environ.get('MYVAR'))
3385
 
 
3386
 
 
3387
 
class TestIsolatedEnv(tests.TestCase):
3388
 
    """Test isolating tests from os.environ.
3389
 
 
3390
 
    Since we use tests that are already isolated from os.environ a bit of care
3391
 
    should be taken when designing the tests to avoid bootstrap side-effects.
3392
 
    The tests start an already clean os.environ which allow doing valid
3393
 
    assertions about which variables are present or not and design tests around
3394
 
    these assertions.
3395
 
    """
3396
 
 
3397
 
    class ScratchMonkey(tests.TestCase):
3398
 
 
3399
 
        def test_me(self):
3400
 
            pass
3401
 
 
3402
 
    def test_basics(self):
3403
 
        # Make sure we know the definition of BZR_HOME: not part of os.environ
3404
 
        # for tests.TestCase.
3405
 
        self.assertTrue('BZR_HOME' in tests.isolated_environ)
3406
 
        self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3407
 
        # Being part of isolated_environ, BZR_HOME should not appear here
3408
 
        self.assertFalse('BZR_HOME' in os.environ)
3409
 
        # Make sure we know the definition of LINES: part of os.environ for
3410
 
        # tests.TestCase
3411
 
        self.assertTrue('LINES' in tests.isolated_environ)
3412
 
        self.assertEquals('25', tests.isolated_environ['LINES'])
3413
 
        self.assertEquals('25', os.environ['LINES'])
3414
 
 
3415
 
    def test_injecting_unknown_variable(self):
3416
 
        # BZR_HOME is known to be absent from os.environ
3417
 
        test = self.ScratchMonkey('test_me')
3418
 
        tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3419
 
        self.assertEquals('foo', os.environ['BZR_HOME'])
3420
 
        tests.restore_os_environ(test)
3421
 
        self.assertFalse('BZR_HOME' in os.environ)
3422
 
 
3423
 
    def test_injecting_known_variable(self):
3424
 
        test = self.ScratchMonkey('test_me')
3425
 
        # LINES is known to be present in os.environ
3426
 
        tests.override_os_environ(test, {'LINES': '42'})
3427
 
        self.assertEquals('42', os.environ['LINES'])
3428
 
        tests.restore_os_environ(test)
3429
 
        self.assertEquals('25', os.environ['LINES'])
3430
 
 
3431
 
    def test_deleting_variable(self):
3432
 
        test = self.ScratchMonkey('test_me')
3433
 
        # LINES is known to be present in os.environ
3434
 
        tests.override_os_environ(test, {'LINES': None})
3435
 
        self.assertTrue('LINES' not in os.environ)
3436
 
        tests.restore_os_environ(test)
3437
 
        self.assertEquals('25', os.environ['LINES'])
3438
 
 
3439
 
 
3440
 
class TestDocTestSuiteIsolation(tests.TestCase):
3441
 
    """Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3442
 
 
3443
 
    Since tests.TestCase alreay provides an isolation from os.environ, we use
3444
 
    the clean environment as a base for testing. To precisely capture the
3445
 
    isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3446
 
    compare against.
3447
 
 
3448
 
    We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3449
 
    not `os.environ` so each test overrides it to suit its needs.
3450
 
 
3451
 
    """
3452
 
 
3453
 
    def get_doctest_suite_for_string(self, klass, string):
3454
 
        class Finder(doctest.DocTestFinder):
3455
 
 
3456
 
            def find(*args, **kwargs):
3457
 
                test = doctest.DocTestParser().get_doctest(
3458
 
                    string, {}, 'foo', 'foo.py', 0)
3459
 
                return [test]
3460
 
 
3461
 
        suite = klass(test_finder=Finder())
3462
 
        return suite
3463
 
 
3464
 
    def run_doctest_suite_for_string(self, klass, string):
3465
 
        suite = self.get_doctest_suite_for_string(klass, string)
3466
 
        output = StringIO()
3467
 
        result = tests.TextTestResult(output, 0, 1)
3468
 
        suite.run(result)
3469
 
        return result, output
3470
 
 
3471
 
    def assertDocTestStringSucceds(self, klass, string):
3472
 
        result, output = self.run_doctest_suite_for_string(klass, string)
3473
 
        if not result.wasStrictlySuccessful():
3474
 
            self.fail(output.getvalue())
3475
 
 
3476
 
    def assertDocTestStringFails(self, klass, string):
3477
 
        result, output = self.run_doctest_suite_for_string(klass, string)
3478
 
        if result.wasStrictlySuccessful():
3479
 
            self.fail(output.getvalue())
3480
 
 
3481
 
    def test_injected_variable(self):
3482
 
        self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3483
 
        test = """
3484
 
            >>> import os
3485
 
            >>> os.environ['LINES']
3486
 
            '42'
3487
 
            """
3488
 
        # doctest.DocTestSuite fails as it sees '25'
3489
 
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
3490
 
        # tests.DocTestSuite sees '42'
3491
 
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3492
 
 
3493
 
    def test_deleted_variable(self):
3494
 
        self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3495
 
        test = """
3496
 
            >>> import os
3497
 
            >>> os.environ.get('LINES')
3498
 
            """
3499
 
        # doctest.DocTestSuite fails as it sees '25'
3500
 
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
3501
 
        # tests.DocTestSuite sees None
3502
 
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)