~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_selftest.py

  • Committer: Andrew Bennetts
  • Date: 2010-10-08 04:25:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5472.
  • Revision ID: andrew.bennetts@canonical.com-20101008042510-sg9vdhmnggilzxsk
Fix stray TAB in source.

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
26
26
import unittest
27
27
import warnings
28
28
 
29
 
from testtools import (
30
 
    ExtendedToOriginalDecorator,
31
 
    MultiTestResult,
32
 
    )
 
29
from testtools import MultiTestResult
33
30
from testtools.content import Content
34
31
from testtools.content_type import ContentType
35
32
from testtools.matchers import (
42
39
from bzrlib import (
43
40
    branchbuilder,
44
41
    bzrdir,
 
42
    debug,
45
43
    errors,
46
44
    lockdir,
47
45
    memorytree,
55
53
    )
56
54
from bzrlib.repofmt import (
57
55
    groupcompress_repo,
 
56
    pack_repo,
 
57
    weaverepo,
58
58
    )
59
59
from bzrlib.symbol_versioning import (
60
60
    deprecated_function,
65
65
    features,
66
66
    test_lsprof,
67
67
    test_server,
 
68
    test_sftp_transport,
68
69
    TestUtil,
69
70
    )
70
71
from bzrlib.trace import note, mutter
71
72
from bzrlib.transport import memory
 
73
from bzrlib.version import _get_bzr_source_tree
72
74
 
73
75
 
74
76
def _test_ids(test_suite):
76
78
    return [t.id() for t in tests.iter_suite_tests(test_suite)]
77
79
 
78
80
 
 
81
class SelftestTests(tests.TestCase):
 
82
 
 
83
    def test_import_tests(self):
 
84
        mod = TestUtil._load_module_by_name('bzrlib.tests.test_selftest')
 
85
        self.assertEqual(mod.SelftestTests, SelftestTests)
 
86
 
 
87
    def test_import_test_failure(self):
 
88
        self.assertRaises(ImportError,
 
89
                          TestUtil._load_module_by_name,
 
90
                          'bzrlib.no-name-yet')
 
91
 
 
92
 
79
93
class MetaTestLog(tests.TestCase):
80
94
 
81
95
    def test_logging(self):
87
101
            "text", "plain", {"charset": "utf8"})))
88
102
        self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
89
103
        self.assertThat(self.get_log(),
90
 
            DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
 
104
            DocTestMatches(u"...a test message\n", ELLIPSIS))
91
105
 
92
106
 
93
107
class TestUnicodeFilename(tests.TestCase):
106
120
 
107
121
        filename = u'hell\u00d8'
108
122
        self.build_tree_contents([(filename, 'contents of hello')])
109
 
        self.assertPathExists(filename)
 
123
        self.failUnlessExists(filename)
110
124
 
111
125
 
112
126
class TestClassesAvailable(tests.TestCase):
338
352
        from bzrlib.tests.per_workingtree import make_scenarios
339
353
        server1 = "a"
340
354
        server2 = "b"
341
 
        formats = [workingtree.WorkingTreeFormat4(),
 
355
        formats = [workingtree.WorkingTreeFormat2(),
342
356
                   workingtree.WorkingTreeFormat3(),]
343
357
        scenarios = make_scenarios(server1, server2, formats)
344
358
        self.assertEqual([
345
 
            ('WorkingTreeFormat4',
 
359
            ('WorkingTreeFormat2',
346
360
             {'bzrdir_format': formats[0]._matchingbzrdir,
347
361
              'transport_readonly_server': 'b',
348
362
              'transport_server': 'a',
375
389
            )
376
390
        server1 = "a"
377
391
        server2 = "b"
378
 
        formats = [workingtree.WorkingTreeFormat4(),
 
392
        formats = [workingtree.WorkingTreeFormat2(),
379
393
                   workingtree.WorkingTreeFormat3(),]
380
394
        scenarios = make_scenarios(server1, server2, formats)
381
395
        self.assertEqual(7, len(scenarios))
382
 
        default_wt_format = workingtree.format_registry.get_default()
 
396
        default_wt_format = workingtree.WorkingTreeFormat4._default_format
383
397
        wt4_format = workingtree.WorkingTreeFormat4()
384
398
        wt5_format = workingtree.WorkingTreeFormat5()
385
399
        expected_scenarios = [
386
 
            ('WorkingTreeFormat4',
 
400
            ('WorkingTreeFormat2',
387
401
             {'bzrdir_format': formats[0]._matchingbzrdir,
388
402
              'transport_readonly_server': 'b',
389
403
              'transport_server': 'a',
449
463
        # ones to add.
450
464
        from bzrlib.tests.per_tree import (
451
465
            return_parameter,
 
466
            revision_tree_from_workingtree
452
467
            )
453
468
        from bzrlib.tests.per_intertree import (
454
469
            make_scenarios,
455
470
            )
456
 
        from bzrlib.workingtree import WorkingTreeFormat3, WorkingTreeFormat4
 
471
        from bzrlib.workingtree import WorkingTreeFormat2, WorkingTreeFormat3
457
472
        input_test = TestInterTreeScenarios(
458
473
            "test_scenarios")
459
474
        server1 = "a"
460
475
        server2 = "b"
461
 
        format1 = WorkingTreeFormat4()
 
476
        format1 = WorkingTreeFormat2()
462
477
        format2 = WorkingTreeFormat3()
463
478
        formats = [("1", str, format1, format2, "converter1"),
464
479
            ("2", int, format2, format1, "converter2")]
510
525
        self.assertRaises(AssertionError, self.assertEqualStat,
511
526
            os.lstat("foo"), os.lstat("longname"))
512
527
 
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
 
 
532
528
 
533
529
class TestTestCaseWithMemoryTransport(tests.TestCaseWithMemoryTransport):
534
530
 
568
564
        tree = self.make_branch_and_memory_tree('dir')
569
565
        # Guard against regression into MemoryTransport leaking
570
566
        # files to disk instead of keeping them in memory.
571
 
        self.assertFalse(osutils.lexists('dir'))
 
567
        self.failIf(osutils.lexists('dir'))
572
568
        self.assertIsInstance(tree, memorytree.MemoryTree)
573
569
 
574
570
    def test_make_branch_and_memory_tree_with_format(self):
575
571
        """make_branch_and_memory_tree should accept a format option."""
576
572
        format = bzrdir.BzrDirMetaFormat1()
577
 
        format.repository_format = repository.format_registry.get_default()
 
573
        format.repository_format = weaverepo.RepositoryFormat7()
578
574
        tree = self.make_branch_and_memory_tree('dir', format=format)
579
575
        # Guard against regression into MemoryTransport leaking
580
576
        # files to disk instead of keeping them in memory.
581
 
        self.assertFalse(osutils.lexists('dir'))
 
577
        self.failIf(osutils.lexists('dir'))
582
578
        self.assertIsInstance(tree, memorytree.MemoryTree)
583
579
        self.assertEqual(format.repository_format.__class__,
584
580
            tree.branch.repository._format.__class__)
588
584
        self.assertIsInstance(builder, branchbuilder.BranchBuilder)
589
585
        # Guard against regression into MemoryTransport leaking
590
586
        # files to disk instead of keeping them in memory.
591
 
        self.assertFalse(osutils.lexists('dir'))
 
587
        self.failIf(osutils.lexists('dir'))
592
588
 
593
589
    def test_make_branch_builder_with_format(self):
594
590
        # Use a repo layout that doesn't conform to a 'named' layout, to ensure
595
591
        # that the format objects are used.
596
592
        format = bzrdir.BzrDirMetaFormat1()
597
 
        repo_format = repository.format_registry.get_default()
 
593
        repo_format = weaverepo.RepositoryFormat7()
598
594
        format.repository_format = repo_format
599
595
        builder = self.make_branch_builder('dir', format=format)
600
596
        the_branch = builder.get_branch()
601
597
        # Guard against regression into MemoryTransport leaking
602
598
        # files to disk instead of keeping them in memory.
603
 
        self.assertFalse(osutils.lexists('dir'))
 
599
        self.failIf(osutils.lexists('dir'))
604
600
        self.assertEqual(format.repository_format.__class__,
605
601
                         the_branch.repository._format.__class__)
606
602
        self.assertEqual(repo_format.get_format_string(),
612
608
        the_branch = builder.get_branch()
613
609
        # Guard against regression into MemoryTransport leaking
614
610
        # files to disk instead of keeping them in memory.
615
 
        self.assertFalse(osutils.lexists('dir'))
 
611
        self.failIf(osutils.lexists('dir'))
616
612
        dir_format = bzrdir.format_registry.make_bzrdir('knit')
617
613
        self.assertEqual(dir_format.repository_format.__class__,
618
614
                         the_branch.repository._format.__class__)
651
647
        url2 = self.get_readonly_url('foo/bar')
652
648
        t = transport.get_transport(url)
653
649
        t2 = transport.get_transport(url2)
654
 
        self.assertIsInstance(t, ReadonlyTransportDecorator)
655
 
        self.assertIsInstance(t2, ReadonlyTransportDecorator)
 
650
        self.failUnless(isinstance(t, ReadonlyTransportDecorator))
 
651
        self.failUnless(isinstance(t2, ReadonlyTransportDecorator))
656
652
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
657
653
 
658
654
    def test_get_readonly_url_http(self):
666
662
        # the transport returned may be any HttpTransportBase subclass
667
663
        t = transport.get_transport(url)
668
664
        t2 = transport.get_transport(url2)
669
 
        self.assertIsInstance(t, HttpTransportBase)
670
 
        self.assertIsInstance(t2, HttpTransportBase)
 
665
        self.failUnless(isinstance(t, HttpTransportBase))
 
666
        self.failUnless(isinstance(t2, HttpTransportBase))
671
667
        self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
672
668
 
673
669
    def test_is_directory(self):
681
677
    def test_make_branch_builder(self):
682
678
        builder = self.make_branch_builder('dir')
683
679
        rev_id = builder.build_commit()
684
 
        self.assertPathExists('dir')
 
680
        self.failUnlessExists('dir')
685
681
        a_dir = bzrdir.BzrDir.open('dir')
686
682
        self.assertRaises(errors.NoWorkingTree, a_dir.open_workingtree)
687
683
        a_branch = a_dir.open_branch()
703
699
        self.assertIsInstance(result_bzrdir.transport,
704
700
                              memory.MemoryTransport)
705
701
        # should not be on disk, should only be in memory
706
 
        self.assertPathDoesNotExist('subdir')
 
702
        self.failIfExists('subdir')
707
703
 
708
704
 
709
705
class TestChrootedTest(tests.ChrootedTestCase):
768
764
        self.check_timing(ShortDelayTestCase('test_short_delay'),
769
765
                          r"^ +[0-9]+ms$")
770
766
 
 
767
    def _patch_get_bzr_source_tree(self):
 
768
        # Reading from the actual source tree breaks isolation, but we don't
 
769
        # want to assume that thats *all* that would happen.
 
770
        self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', lambda: None)
 
771
 
 
772
    def test_assigned_benchmark_file_stores_date(self):
 
773
        self._patch_get_bzr_source_tree()
 
774
        output = StringIO()
 
775
        result = bzrlib.tests.TextTestResult(self._log_file,
 
776
                                        descriptions=0,
 
777
                                        verbosity=1,
 
778
                                        bench_history=output
 
779
                                        )
 
780
        output_string = output.getvalue()
 
781
        # if you are wondering about the regexp please read the comment in
 
782
        # test_bench_history (bzrlib.tests.test_selftest.TestRunner)
 
783
        # XXX: what comment?  -- Andrew Bennetts
 
784
        self.assertContainsRe(output_string, "--date [0-9.]+")
 
785
 
 
786
    def test_benchhistory_records_test_times(self):
 
787
        self._patch_get_bzr_source_tree()
 
788
        result_stream = StringIO()
 
789
        result = bzrlib.tests.TextTestResult(
 
790
            self._log_file,
 
791
            descriptions=0,
 
792
            verbosity=1,
 
793
            bench_history=result_stream
 
794
            )
 
795
 
 
796
        # we want profile a call and check that its test duration is recorded
 
797
        # make a new test instance that when run will generate a benchmark
 
798
        example_test_case = TestTestResult("_time_hello_world_encoding")
 
799
        # execute the test, which should succeed and record times
 
800
        example_test_case.run(result)
 
801
        lines = result_stream.getvalue().splitlines()
 
802
        self.assertEqual(2, len(lines))
 
803
        self.assertContainsRe(lines[1],
 
804
            " *[0-9]+ms bzrlib.tests.test_selftest.TestTestResult"
 
805
            "._time_hello_world_encoding")
 
806
 
771
807
    def _time_hello_world_encoding(self):
772
808
        """Profile two sleep calls
773
809
 
1083
1119
    def test_result_decorator(self):
1084
1120
        # decorate results
1085
1121
        calls = []
1086
 
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1122
        class LoggingDecorator(tests.ForwardingResult):
1087
1123
            def startTest(self, test):
1088
 
                ExtendedToOriginalDecorator.startTest(self, test)
 
1124
                tests.ForwardingResult.startTest(self, test)
1089
1125
                calls.append('start')
1090
1126
        test = unittest.FunctionTestCase(lambda:None)
1091
1127
        stream = StringIO()
1192
1228
            ],
1193
1229
            lines[-3:])
1194
1230
 
 
1231
    def _patch_get_bzr_source_tree(self):
 
1232
        # Reading from the actual source tree breaks isolation, but we don't
 
1233
        # want to assume that thats *all* that would happen.
 
1234
        self._get_source_tree_calls = []
 
1235
        def new_get():
 
1236
            self._get_source_tree_calls.append("called")
 
1237
            return None
 
1238
        self.overrideAttr(bzrlib.version, '_get_bzr_source_tree',  new_get)
 
1239
 
 
1240
    def test_bench_history(self):
 
1241
        # tests that the running the benchmark passes bench_history into
 
1242
        # the test result object. We can tell that happens if
 
1243
        # _get_bzr_source_tree is called.
 
1244
        self._patch_get_bzr_source_tree()
 
1245
        test = TestRunner('dummy_test')
 
1246
        output = StringIO()
 
1247
        runner = tests.TextTestRunner(stream=self._log_file,
 
1248
                                      bench_history=output)
 
1249
        result = self.run_test_runner(runner, test)
 
1250
        output_string = output.getvalue()
 
1251
        self.assertContainsRe(output_string, "--date [0-9.]+")
 
1252
        self.assertLength(1, self._get_source_tree_calls)
 
1253
 
1195
1254
    def test_verbose_test_count(self):
1196
1255
        """A verbose test run reports the right test count at the start"""
1197
1256
        suite = TestUtil.TestSuite([
1207
1266
    def test_startTestRun(self):
1208
1267
        """run should call result.startTestRun()"""
1209
1268
        calls = []
1210
 
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1269
        class LoggingDecorator(tests.ForwardingResult):
1211
1270
            def startTestRun(self):
1212
 
                ExtendedToOriginalDecorator.startTestRun(self)
 
1271
                tests.ForwardingResult.startTestRun(self)
1213
1272
                calls.append('startTestRun')
1214
1273
        test = unittest.FunctionTestCase(lambda:None)
1215
1274
        stream = StringIO()
1221
1280
    def test_stopTestRun(self):
1222
1281
        """run should call result.stopTestRun()"""
1223
1282
        calls = []
1224
 
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1283
        class LoggingDecorator(tests.ForwardingResult):
1225
1284
            def stopTestRun(self):
1226
 
                ExtendedToOriginalDecorator.stopTestRun(self)
 
1285
                tests.ForwardingResult.stopTestRun(self)
1227
1286
                calls.append('stopTestRun')
1228
1287
        test = unittest.FunctionTestCase(lambda:None)
1229
1288
        stream = StringIO()
1232
1291
        result = self.run_test_runner(runner, test)
1233
1292
        self.assertLength(1, calls)
1234
1293
 
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
 
 
1252
1294
 
1253
1295
class SampleTestCase(tests.TestCase):
1254
1296
 
1442
1484
        # Note this test won't fail with hooks that the core library doesn't
1443
1485
        # use - but it trigger with a plugin that adds hooks, so its still a
1444
1486
        # useful warning in that case.
1445
 
        self.assertEqual(bzrlib.branch.BranchHooks(), bzrlib.branch.Branch.hooks)
1446
 
        self.assertEqual(
1447
 
            bzrlib.smart.server.SmartServerHooks(),
 
1487
        self.assertEqual(bzrlib.branch.BranchHooks(),
 
1488
            bzrlib.branch.Branch.hooks)
 
1489
        self.assertEqual(bzrlib.smart.server.SmartServerHooks(),
1448
1490
            bzrlib.smart.server.SmartTCPServer.hooks)
1449
 
        self.assertEqual(
1450
 
            bzrlib.commands.CommandHooks(), bzrlib.commands.Command.hooks)
 
1491
        self.assertEqual(bzrlib.commands.CommandHooks(),
 
1492
            bzrlib.commands.Command.hooks)
1451
1493
 
1452
1494
    def test__gather_lsprof_in_benchmarks(self):
1453
1495
        """When _gather_lsprof_in_benchmarks is on, accumulate profile data.
1931
1973
    def test_make_branch_and_tree_with_format(self):
1932
1974
        # we should be able to supply a format to make_branch_and_tree
1933
1975
        self.make_branch_and_tree('a', format=bzrlib.bzrdir.BzrDirMetaFormat1())
 
1976
        self.make_branch_and_tree('b', format=bzrlib.bzrdir.BzrDirFormat6())
1934
1977
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('a')._format,
1935
1978
                              bzrlib.bzrdir.BzrDirMetaFormat1)
 
1979
        self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('b')._format,
 
1980
                              bzrlib.bzrdir.BzrDirFormat6)
1936
1981
 
1937
1982
    def test_make_branch_and_memory_tree(self):
1938
1983
        # we should be able to get a new branch and a mutable tree from
2021
2066
            def __call__(test, result):
2022
2067
                test.run(result)
2023
2068
            def run(test, result):
2024
 
                self.assertIsInstance(result, ExtendedToOriginalDecorator)
 
2069
                self.assertIsInstance(result, tests.ForwardingResult)
2025
2070
                calls.append("called")
2026
2071
            def countTestCases(self):
2027
2072
                return 1
2317
2362
        # stdout and stderr of the invoked run_bzr
2318
2363
        current_factory = bzrlib.ui.ui_factory
2319
2364
        self.run_bzr(['foo'])
2320
 
        self.assertFalse(current_factory is self.factory)
 
2365
        self.failIf(current_factory is self.factory)
2321
2366
        self.assertNotEqual(sys.stdout, self.factory.stdout)
2322
2367
        self.assertNotEqual(sys.stderr, self.factory.stderr)
2323
2368
        self.assertEqual('foo\n', self.factory.stdout.getvalue())
2505
2550
        self.assertEqual([], command[2:])
2506
2551
 
2507
2552
    def test_set_env(self):
2508
 
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
 
2553
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
2509
2554
        # set in the child
2510
2555
        def check_environment():
2511
2556
            self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2517
2562
 
2518
2563
    def test_run_bzr_subprocess_env_del(self):
2519
2564
        """run_bzr_subprocess can remove environment variables too."""
2520
 
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
 
2565
        self.failIf('EXISTANT_ENV_VAR' in os.environ)
2521
2566
        def check_environment():
2522
2567
            self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2523
2568
        os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2529
2574
        del os.environ['EXISTANT_ENV_VAR']
2530
2575
 
2531
2576
    def test_env_del_missing(self):
2532
 
        self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
 
2577
        self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
2533
2578
        def check_environment():
2534
2579
            self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2535
2580
        self.check_popen_state = check_environment
3157
3202
        tpr.register('bar', 'bBB.aAA.rRR')
3158
3203
        self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
3159
3204
        self.assertThat(self.get_log(),
3160
 
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
3161
 
                           doctest.ELLIPSIS))
 
3205
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR", ELLIPSIS))
3162
3206
 
3163
3207
    def test_get_unknown_prefix(self):
3164
3208
        tpr = self._get_registry()
3199
3243
        class Test(unittest.TestCase):
3200
3244
            def runTest(self):
3201
3245
                pass
 
3246
            addCleanup = None # for when on Python 2.7 with native addCleanup
3202
3247
        result = self.LeakRecordingResult()
3203
3248
        test = Test()
 
3249
        self.assertIs(getattr(test, "addCleanup", None), None)
3204
3250
        result.startTestRun()
3205
3251
        test.run(result)
3206
3252
        result.stopTestRun()
3270
3316
        self.assertContainsString(result.stream.getvalue(), "leaking threads")
3271
3317
 
3272
3318
 
3273
 
class TestPostMortemDebugging(tests.TestCase):
3274
 
    """Check post mortem debugging works when tests fail or error"""
3275
 
 
3276
 
    class TracebackRecordingResult(tests.ExtendedTestResult):
3277
 
        def __init__(self):
3278
 
            tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3279
 
            self.postcode = None
3280
 
        def _post_mortem(self, tb=None):
3281
 
            """Record the code object at the end of the current traceback"""
3282
 
            tb = tb or sys.exc_info()[2]
3283
 
            if tb is not None:
3284
 
                next = tb.tb_next
3285
 
                while next is not None:
3286
 
                    tb = next
3287
 
                    next = next.tb_next
3288
 
                self.postcode = tb.tb_frame.f_code
3289
 
        def report_error(self, test, err):
3290
 
            pass
3291
 
        def report_failure(self, test, err):
3292
 
            pass
3293
 
 
3294
 
    def test_location_unittest_error(self):
3295
 
        """Needs right post mortem traceback with erroring unittest case"""
3296
 
        class Test(unittest.TestCase):
3297
 
            def runTest(self):
3298
 
                raise RuntimeError
3299
 
        result = self.TracebackRecordingResult()
3300
 
        Test().run(result)
3301
 
        self.assertEqual(result.postcode, Test.runTest.func_code)
3302
 
 
3303
 
    def test_location_unittest_failure(self):
3304
 
        """Needs right post mortem traceback with failing unittest case"""
3305
 
        class Test(unittest.TestCase):
3306
 
            def runTest(self):
3307
 
                raise self.failureException
3308
 
        result = self.TracebackRecordingResult()
3309
 
        Test().run(result)
3310
 
        self.assertEqual(result.postcode, Test.runTest.func_code)
3311
 
 
3312
 
    def test_location_bt_error(self):
3313
 
        """Needs right post mortem traceback with erroring bzrlib.tests case"""
3314
 
        class Test(tests.TestCase):
3315
 
            def test_error(self):
3316
 
                raise RuntimeError
3317
 
        result = self.TracebackRecordingResult()
3318
 
        Test("test_error").run(result)
3319
 
        self.assertEqual(result.postcode, Test.test_error.func_code)
3320
 
 
3321
 
    def test_location_bt_failure(self):
3322
 
        """Needs right post mortem traceback with failing bzrlib.tests case"""
3323
 
        class Test(tests.TestCase):
3324
 
            def test_failure(self):
3325
 
                raise self.failureException
3326
 
        result = self.TracebackRecordingResult()
3327
 
        Test("test_failure").run(result)
3328
 
        self.assertEqual(result.postcode, Test.test_failure.func_code)
3329
 
 
3330
 
    def test_env_var_triggers_post_mortem(self):
3331
 
        """Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3332
 
        import pdb
3333
 
        result = tests.ExtendedTestResult(StringIO(), 0, 1)
3334
 
        post_mortem_calls = []
3335
 
        self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3336
 
        self.overrideEnv('BZR_TEST_PDB', None)
3337
 
        result._post_mortem(1)
3338
 
        self.overrideEnv('BZR_TEST_PDB', 'on')
3339
 
        result._post_mortem(2)
3340
 
        self.assertEqual([2], post_mortem_calls)
3341
 
 
3342
 
 
3343
3319
class TestRunSuite(tests.TestCase):
3344
3320
 
3345
3321
    def test_runner_class(self):
3356
3332
                                                self.verbosity)
3357
3333
        tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3358
3334
        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)