~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_selftest.py

  • Committer: Vincent Ladeuil
  • Date: 2010-10-08 10:50:51 UTC
  • mfrom: (5050.17.31 2.2.2-dev)
  • mto: This revision was merged to the branch mainline in revision 5474.
  • Revision ID: v.ladeuil+lp@free.fr-20101008105051-xd4knkrohzclffic
Merge 2.2 into trunk including fixes for bug #651706 and bug #646133

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,
58
57
    weaverepo,
59
58
    )
60
59
from bzrlib.symbol_versioning import (
66
65
    features,
67
66
    test_lsprof,
68
67
    test_server,
 
68
    test_sftp_transport,
69
69
    TestUtil,
70
70
    )
71
71
from bzrlib.trace import note, mutter
72
72
from bzrlib.transport import memory
 
73
from bzrlib.version import _get_bzr_source_tree
73
74
 
74
75
 
75
76
def _test_ids(test_suite):
77
78
    return [t.id() for t in tests.iter_suite_tests(test_suite)]
78
79
 
79
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
 
80
93
class MetaTestLog(tests.TestCase):
81
94
 
82
95
    def test_logging(self):
88
101
            "text", "plain", {"charset": "utf8"})))
89
102
        self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
90
103
        self.assertThat(self.get_log(),
91
 
            DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
 
104
            DocTestMatches(u"...a test message\n", ELLIPSIS))
92
105
 
93
106
 
94
107
class TestUnicodeFilename(tests.TestCase):
1106
1119
    def test_result_decorator(self):
1107
1120
        # decorate results
1108
1121
        calls = []
1109
 
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1122
        class LoggingDecorator(tests.ForwardingResult):
1110
1123
            def startTest(self, test):
1111
 
                ExtendedToOriginalDecorator.startTest(self, test)
 
1124
                tests.ForwardingResult.startTest(self, test)
1112
1125
                calls.append('start')
1113
1126
        test = unittest.FunctionTestCase(lambda:None)
1114
1127
        stream = StringIO()
1253
1266
    def test_startTestRun(self):
1254
1267
        """run should call result.startTestRun()"""
1255
1268
        calls = []
1256
 
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1269
        class LoggingDecorator(tests.ForwardingResult):
1257
1270
            def startTestRun(self):
1258
 
                ExtendedToOriginalDecorator.startTestRun(self)
 
1271
                tests.ForwardingResult.startTestRun(self)
1259
1272
                calls.append('startTestRun')
1260
1273
        test = unittest.FunctionTestCase(lambda:None)
1261
1274
        stream = StringIO()
1267
1280
    def test_stopTestRun(self):
1268
1281
        """run should call result.stopTestRun()"""
1269
1282
        calls = []
1270
 
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1283
        class LoggingDecorator(tests.ForwardingResult):
1271
1284
            def stopTestRun(self):
1272
 
                ExtendedToOriginalDecorator.stopTestRun(self)
 
1285
                tests.ForwardingResult.stopTestRun(self)
1273
1286
                calls.append('stopTestRun')
1274
1287
        test = unittest.FunctionTestCase(lambda:None)
1275
1288
        stream = StringIO()
1278
1291
        result = self.run_test_runner(runner, test)
1279
1292
        self.assertLength(1, calls)
1280
1293
 
1281
 
    def test_unicode_test_output_on_ascii_stream(self):
1282
 
        """Showing results should always succeed even on an ascii console"""
1283
 
        class FailureWithUnicode(tests.TestCase):
1284
 
            def test_log_unicode(self):
1285
 
                self.log(u"\u2606")
1286
 
                self.fail("Now print that log!")
1287
 
        out = StringIO()
1288
 
        self.overrideAttr(osutils, "get_terminal_encoding",
1289
 
            lambda trace=False: "ascii")
1290
 
        result = self.run_test_runner(tests.TextTestRunner(stream=out),
1291
 
            FailureWithUnicode("test_log_unicode"))
1292
 
        self.assertContainsRe(out.getvalue(),
1293
 
            "Text attachment: log\n"
1294
 
            "-+\n"
1295
 
            "\d+\.\d+  \\\\u2606\n"
1296
 
            "-+\n")
1297
 
 
1298
1294
 
1299
1295
class SampleTestCase(tests.TestCase):
1300
1296
 
2070
2066
            def __call__(test, result):
2071
2067
                test.run(result)
2072
2068
            def run(test, result):
2073
 
                self.assertIsInstance(result, ExtendedToOriginalDecorator)
 
2069
                self.assertIsInstance(result, tests.ForwardingResult)
2074
2070
                calls.append("called")
2075
2071
            def countTestCases(self):
2076
2072
                return 1
3206
3202
        tpr.register('bar', 'bBB.aAA.rRR')
3207
3203
        self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
3208
3204
        self.assertThat(self.get_log(),
3209
 
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
3210
 
                           doctest.ELLIPSIS))
 
3205
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR", ELLIPSIS))
3211
3206
 
3212
3207
    def test_get_unknown_prefix(self):
3213
3208
        tpr = self._get_registry()
3248
3243
        class Test(unittest.TestCase):
3249
3244
            def runTest(self):
3250
3245
                pass
 
3246
            addCleanup = None # for when on Python 2.7 with native addCleanup
3251
3247
        result = self.LeakRecordingResult()
3252
3248
        test = Test()
 
3249
        self.assertIs(getattr(test, "addCleanup", None), None)
3253
3250
        result.startTestRun()
3254
3251
        test.run(result)
3255
3252
        result.stopTestRun()
3382
3379
        result = tests.ExtendedTestResult(StringIO(), 0, 1)
3383
3380
        post_mortem_calls = []
3384
3381
        self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3385
 
        self.overrideEnv('BZR_TEST_PDB', None)
 
3382
        self.addCleanup(osutils.set_or_unset_env, "BZR_TEST_PDB",
 
3383
            osutils.set_or_unset_env("BZR_TEST_PDB", None))
3386
3384
        result._post_mortem(1)
3387
 
        self.overrideEnv('BZR_TEST_PDB', 'on')
 
3385
        os.environ["BZR_TEST_PDB"] = "on"
3388
3386
        result._post_mortem(2)
3389
3387
        self.assertEqual([2], post_mortem_calls)
3390
3388
 
3405
3403
                                                self.verbosity)
3406
3404
        tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3407
3405
        self.assertLength(1, calls)
3408
 
 
3409
 
 
3410
 
class TestEnvironHandling(tests.TestCase):
3411
 
 
3412
 
    def test_overrideEnv_None_called_twice_doesnt_leak(self):
3413
 
        self.failIf('MYVAR' in os.environ)
3414
 
        self.overrideEnv('MYVAR', '42')
3415
 
        # We use an embedded test to make sure we fix the _captureVar bug
3416
 
        class Test(tests.TestCase):
3417
 
            def test_me(self):
3418
 
                # The first call save the 42 value
3419
 
                self.overrideEnv('MYVAR', None)
3420
 
                self.assertEquals(None, os.environ.get('MYVAR'))
3421
 
                # Make sure we can call it twice
3422
 
                self.overrideEnv('MYVAR', None)
3423
 
                self.assertEquals(None, os.environ.get('MYVAR'))
3424
 
        output = StringIO()
3425
 
        result = tests.TextTestResult(output, 0, 1)
3426
 
        Test('test_me').run(result)
3427
 
        if not result.wasStrictlySuccessful():
3428
 
            self.fail(output.getvalue())
3429
 
        # We get our value back
3430
 
        self.assertEquals('42', os.environ.get('MYVAR'))
3431
 
 
3432
 
 
3433
 
class TestIsolatedEnv(tests.TestCase):
3434
 
    """Test isolating tests from os.environ.
3435
 
 
3436
 
    Since we use tests that are already isolated from os.environ a bit of care
3437
 
    should be taken when designing the tests to avoid bootstrap side-effects.
3438
 
    The tests start an already clean os.environ which allow doing valid
3439
 
    assertions about which variables are present or not and design tests around
3440
 
    these assertions.
3441
 
    """
3442
 
 
3443
 
    class ScratchMonkey(tests.TestCase):
3444
 
 
3445
 
        def test_me(self):
3446
 
            pass
3447
 
 
3448
 
    def test_basics(self):
3449
 
        # Make sure we know the definition of BZR_HOME: not part of os.environ
3450
 
        # for tests.TestCase.
3451
 
        self.assertTrue('BZR_HOME' in tests.isolated_environ)
3452
 
        self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3453
 
        # Being part of isolated_environ, BZR_HOME should not appear here
3454
 
        self.assertFalse('BZR_HOME' in os.environ)
3455
 
        # Make sure we know the definition of LINES: part of os.environ for
3456
 
        # tests.TestCase
3457
 
        self.assertTrue('LINES' in tests.isolated_environ)
3458
 
        self.assertEquals('25', tests.isolated_environ['LINES'])
3459
 
        self.assertEquals('25', os.environ['LINES'])
3460
 
 
3461
 
    def test_injecting_unknown_variable(self):
3462
 
        # BZR_HOME is known to be absent from os.environ
3463
 
        test = self.ScratchMonkey('test_me')
3464
 
        tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3465
 
        self.assertEquals('foo', os.environ['BZR_HOME'])
3466
 
        tests.restore_os_environ(test)
3467
 
        self.assertFalse('BZR_HOME' in os.environ)
3468
 
 
3469
 
    def test_injecting_known_variable(self):
3470
 
        test = self.ScratchMonkey('test_me')
3471
 
        # LINES is known to be present in os.environ
3472
 
        tests.override_os_environ(test, {'LINES': '42'})
3473
 
        self.assertEquals('42', os.environ['LINES'])
3474
 
        tests.restore_os_environ(test)
3475
 
        self.assertEquals('25', os.environ['LINES'])
3476
 
 
3477
 
    def test_deleting_variable(self):
3478
 
        test = self.ScratchMonkey('test_me')
3479
 
        # LINES is known to be present in os.environ
3480
 
        tests.override_os_environ(test, {'LINES': None})
3481
 
        self.assertTrue('LINES' not in os.environ)
3482
 
        tests.restore_os_environ(test)
3483
 
        self.assertEquals('25', os.environ['LINES'])
3484
 
 
3485
 
 
3486
 
class TestDocTestSuiteIsolation(tests.TestCase):
3487
 
    """Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3488
 
 
3489
 
    Since tests.TestCase alreay provides an isolation from os.environ, we use
3490
 
    the clean environment as a base for testing. To precisely capture the
3491
 
    isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3492
 
    compare against.
3493
 
 
3494
 
    We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3495
 
    not `os.environ` so each test overrides it to suit its needs.
3496
 
 
3497
 
    """
3498
 
 
3499
 
    def get_doctest_suite_for_string(self, klass, string):
3500
 
        class Finder(doctest.DocTestFinder):
3501
 
 
3502
 
            def find(*args, **kwargs):
3503
 
                test = doctest.DocTestParser().get_doctest(
3504
 
                    string, {}, 'foo', 'foo.py', 0)
3505
 
                return [test]
3506
 
 
3507
 
        suite = klass(test_finder=Finder())
3508
 
        return suite
3509
 
 
3510
 
    def run_doctest_suite_for_string(self, klass, string):
3511
 
        suite = self.get_doctest_suite_for_string(klass, string)
3512
 
        output = StringIO()
3513
 
        result = tests.TextTestResult(output, 0, 1)
3514
 
        suite.run(result)
3515
 
        return result, output
3516
 
 
3517
 
    def assertDocTestStringSucceds(self, klass, string):
3518
 
        result, output = self.run_doctest_suite_for_string(klass, string)
3519
 
        if not result.wasStrictlySuccessful():
3520
 
            self.fail(output.getvalue())
3521
 
 
3522
 
    def assertDocTestStringFails(self, klass, string):
3523
 
        result, output = self.run_doctest_suite_for_string(klass, string)
3524
 
        if result.wasStrictlySuccessful():
3525
 
            self.fail(output.getvalue())
3526
 
 
3527
 
    def test_injected_variable(self):
3528
 
        self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3529
 
        test = """
3530
 
            >>> import os
3531
 
            >>> os.environ['LINES']
3532
 
            '42'
3533
 
            """
3534
 
        # doctest.DocTestSuite fails as it sees '25'
3535
 
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
3536
 
        # tests.DocTestSuite sees '42'
3537
 
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3538
 
 
3539
 
    def test_deleted_variable(self):
3540
 
        self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3541
 
        test = """
3542
 
            >>> import os
3543
 
            >>> os.environ.get('LINES')
3544
 
            """
3545
 
        # doctest.DocTestSuite fails as it sees '25'
3546
 
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
3547
 
        # tests.DocTestSuite sees None
3548
 
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)