~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Jelmer Vernooij
  • Date: 2011-11-25 17:54:52 UTC
  • mfrom: (6303 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6321.
  • Revision ID: jelmer@samba.org-20111125175452-v0uwwxqcp97tzuzv
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
100
100
    )
101
101
from bzrlib.ui import NullProgressView
102
102
from bzrlib.ui.text import TextUIFactory
 
103
from bzrlib.tests.features import _CompatabilityThunkFeature
103
104
 
104
105
# Mark this python module as being part of the implementation
105
106
# of unittest: this gives us better tracebacks where the last
212
213
        osutils.set_or_unset_env(var, value)
213
214
 
214
215
 
 
216
def _clear__type_equality_funcs(test):
 
217
    """Cleanup bound methods stored on TestCase instances
 
218
 
 
219
    Clear the dict breaking a few (mostly) harmless cycles in the affected
 
220
    unittests released with Python 2.6 and initial Python 2.7 versions.
 
221
 
 
222
    For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
 
223
    shipped in Oneiric, an object with no clear method was used, hence the
 
224
    extra complications, see bug 809048 for details.
 
225
    """
 
226
    type_equality_funcs = getattr(test, "_type_equality_funcs", None)
 
227
    if type_equality_funcs is not None:
 
228
        tef_clear = getattr(type_equality_funcs, "clear", None)
 
229
        if tef_clear is None:
 
230
            tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
 
231
            if tef_instance_dict is not None:
 
232
                tef_clear = tef_instance_dict.clear
 
233
        if tef_clear is not None:
 
234
            tef_clear()
 
235
 
 
236
 
215
237
class ExtendedTestResult(testtools.TextTestResult):
216
238
    """Accepts, reports and accumulates the results of running tests.
217
239
 
385
407
        getDetails = getattr(test, "getDetails", None)
386
408
        if getDetails is not None:
387
409
            getDetails().clear()
388
 
        # Clear _type_equality_funcs to try to stop TestCase instances
389
 
        # from wasting memory. 'clear' is not available in all Python
390
 
        # versions (bug 809048)
391
 
        type_equality_funcs = getattr(test, "_type_equality_funcs", None)
392
 
        if type_equality_funcs is not None:
393
 
            tef_clear = getattr(type_equality_funcs, "clear", None)
394
 
            if tef_clear is None:
395
 
                tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
396
 
                if tef_instance_dict is not None:
397
 
                    tef_clear = tef_instance_dict.clear
398
 
            if tef_clear is not None:
399
 
                tef_clear()
 
410
        _clear__type_equality_funcs(test)
400
411
        self._traceback_from_test = None
401
412
 
402
413
    def startTests(self):
503
514
        self.not_applicable_count += 1
504
515
        self.report_not_applicable(test, reason)
505
516
 
 
517
    def _count_stored_tests(self):
 
518
        """Count of tests instances kept alive due to not succeeding"""
 
519
        return self.error_count + self.failure_count + self.known_failure_count
 
520
 
506
521
    def _post_mortem(self, tb=None):
507
522
        """Start a PDB post mortem session."""
508
523
        if os.environ.get('BZR_TEST_PDB', None):
983
998
        for feature in getattr(self, '_test_needs_features', []):
984
999
            self.requireFeature(feature)
985
1000
        self._cleanEnvironment()
986
 
        self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
987
 
                          config.CommandLineSection())
 
1001
        if bzrlib.global_state is not None:
 
1002
            self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
 
1003
                              config.CommandLineStore())
988
1004
        self._silenceUI()
989
1005
        self._startLogFile()
990
1006
        self._benchcalls = []
1703
1719
        return result
1704
1720
 
1705
1721
    def _startLogFile(self):
1706
 
        """Send bzr and test log messages to a temporary file.
1707
 
 
1708
 
        The file is removed as the test is torn down.
1709
 
        """
 
1722
        """Setup a in-memory target for bzr and testcase log messages"""
1710
1723
        pseudo_log_file = StringIO()
1711
1724
        def _get_log_contents_for_weird_testtools_api():
1712
1725
            return [pseudo_log_file.getvalue().decode(
1719
1732
        self.addCleanup(self._finishLogFile)
1720
1733
 
1721
1734
    def _finishLogFile(self):
1722
 
        """Finished with the log file.
1723
 
 
1724
 
        Close the file and delete it.
1725
 
        """
 
1735
        """Flush and dereference the in-memory log for this testcase"""
1726
1736
        if trace._trace_file:
1727
1737
            # flush the log file, to get all content
1728
1738
            trace._trace_file.flush()
1729
1739
        trace.pop_log_file(self._log_memento)
 
1740
        # The logging module now tracks references for cleanup so discard ours
 
1741
        del self._log_memento
1730
1742
 
1731
1743
    def thisFailsStrictLockCheck(self):
1732
1744
        """It is known that this test would fail with -Dstrict_locks.
2566
2578
        real branch.
2567
2579
        """
2568
2580
        root = TestCaseWithMemoryTransport.TEST_ROOT
2569
 
        try:
2570
 
            # Make sure we get a readable and accessible home for .bzr.log
2571
 
            # and/or config files, and not fallback to weird defaults (see
2572
 
            # http://pad.lv/825027).
2573
 
            self.assertIs(None, os.environ.get('BZR_HOME', None))
2574
 
            os.environ['BZR_HOME'] = root
2575
 
            wt = bzrdir.BzrDir.create_standalone_workingtree(root)
2576
 
            del os.environ['BZR_HOME']
2577
 
        except Exception, e:
2578
 
            self.fail("Fail to initialize the safety net: %r\nExiting\n" % (e,))
 
2581
        # Make sure we get a readable and accessible home for .bzr.log
 
2582
        # and/or config files, and not fallback to weird defaults (see
 
2583
        # http://pad.lv/825027).
 
2584
        self.assertIs(None, os.environ.get('BZR_HOME', None))
 
2585
        os.environ['BZR_HOME'] = root
 
2586
        wt = bzrdir.BzrDir.create_standalone_workingtree(root)
 
2587
        del os.environ['BZR_HOME']
2579
2588
        # Hack for speed: remember the raw bytes of the dirstate file so that
2580
2589
        # we don't need to re-open the wt to check it hasn't changed.
2581
2590
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2947
2956
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
2948
2957
        # RBC 20060208
2949
2958
        format = self.resolve_format(format=format)
 
2959
        if not format.supports_workingtrees:
 
2960
            b = self.make_branch(relpath+'.branch', format=format)
 
2961
            return b.create_checkout(relpath, lightweight=True)
2950
2962
        b = self.make_branch(relpath, format=format)
2951
2963
        try:
2952
2964
            return b.bzrdir.create_workingtree()
3251
3263
                            result_decorators=result_decorators,
3252
3264
                            )
3253
3265
    runner.stop_on_failure=stop_on_failure
 
3266
    if isinstance(suite, unittest.TestSuite):
 
3267
        # Empty out _tests list of passed suite and populate new TestSuite
 
3268
        suite._tests[:], suite = [], TestSuite(suite)
3254
3269
    # built in decorator factories:
3255
3270
    decorators = [
3256
3271
        random_order(random_seed, runner),
3354
3369
 
3355
3370
class TestDecorator(TestUtil.TestSuite):
3356
3371
    """A decorator for TestCase/TestSuite objects.
3357
 
    
3358
 
    Usually, subclasses should override __iter__(used when flattening test
3359
 
    suites), which we do to filter, reorder, parallelise and so on, run() and
3360
 
    debug().
 
3372
 
 
3373
    Contains rather than flattening suite passed on construction
3361
3374
    """
3362
3375
 
3363
 
    def __init__(self, suite):
3364
 
        TestUtil.TestSuite.__init__(self)
3365
 
        self.addTest(suite)
3366
 
 
3367
 
    def countTestCases(self):
3368
 
        cases = 0
3369
 
        for test in self:
3370
 
            cases += test.countTestCases()
3371
 
        return cases
3372
 
 
3373
 
    def debug(self):
3374
 
        for test in self:
3375
 
            test.debug()
3376
 
 
3377
 
    def run(self, result):
3378
 
        # Use iteration on self, not self._tests, to allow subclasses to hook
3379
 
        # into __iter__.
3380
 
        for test in self:
3381
 
            if result.shouldStop:
3382
 
                break
3383
 
            test.run(result)
3384
 
        return result
 
3376
    def __init__(self, suite=None):
 
3377
        super(TestDecorator, self).__init__()
 
3378
        if suite is not None:
 
3379
            self.addTest(suite)
 
3380
 
 
3381
    # Don't need subclass run method with suite emptying
 
3382
    run = unittest.TestSuite.run
3385
3383
 
3386
3384
 
3387
3385
class CountingDecorator(TestDecorator):
3398
3396
    """A decorator which excludes test matching an exclude pattern."""
3399
3397
 
3400
3398
    def __init__(self, suite, exclude_pattern):
3401
 
        TestDecorator.__init__(self, suite)
3402
 
        self.exclude_pattern = exclude_pattern
3403
 
        self.excluded = False
3404
 
 
3405
 
    def __iter__(self):
3406
 
        if self.excluded:
3407
 
            return iter(self._tests)
3408
 
        self.excluded = True
3409
 
        suite = exclude_tests_by_re(self, self.exclude_pattern)
3410
 
        del self._tests[:]
3411
 
        self.addTests(suite)
3412
 
        return iter(self._tests)
 
3399
        super(ExcludeDecorator, self).__init__(
 
3400
            exclude_tests_by_re(suite, exclude_pattern))
3413
3401
 
3414
3402
 
3415
3403
class FilterTestsDecorator(TestDecorator):
3416
3404
    """A decorator which filters tests to those matching a pattern."""
3417
3405
 
3418
3406
    def __init__(self, suite, pattern):
3419
 
        TestDecorator.__init__(self, suite)
3420
 
        self.pattern = pattern
3421
 
        self.filtered = False
3422
 
 
3423
 
    def __iter__(self):
3424
 
        if self.filtered:
3425
 
            return iter(self._tests)
3426
 
        self.filtered = True
3427
 
        suite = filter_suite_by_re(self, self.pattern)
3428
 
        del self._tests[:]
3429
 
        self.addTests(suite)
3430
 
        return iter(self._tests)
 
3407
        super(FilterTestsDecorator, self).__init__(
 
3408
            filter_suite_by_re(suite, pattern))
3431
3409
 
3432
3410
 
3433
3411
class RandomDecorator(TestDecorator):
3434
3412
    """A decorator which randomises the order of its tests."""
3435
3413
 
3436
3414
    def __init__(self, suite, random_seed, stream):
3437
 
        TestDecorator.__init__(self, suite)
3438
 
        self.random_seed = random_seed
3439
 
        self.randomised = False
3440
 
        self.stream = stream
3441
 
 
3442
 
    def __iter__(self):
3443
 
        if self.randomised:
3444
 
            return iter(self._tests)
3445
 
        self.randomised = True
3446
 
        self.stream.write("Randomizing test order using seed %s\n\n" %
3447
 
            (self.actual_seed()))
 
3415
        random_seed = self.actual_seed(random_seed)
 
3416
        stream.write("Randomizing test order using seed %s\n\n" %
 
3417
            (random_seed,))
3448
3418
        # Initialise the random number generator.
3449
 
        random.seed(self.actual_seed())
3450
 
        suite = randomize_suite(self)
3451
 
        del self._tests[:]
3452
 
        self.addTests(suite)
3453
 
        return iter(self._tests)
 
3419
        random.seed(random_seed)
 
3420
        super(RandomDecorator, self).__init__(randomize_suite(suite))
3454
3421
 
3455
 
    def actual_seed(self):
3456
 
        if self.random_seed == "now":
 
3422
    @staticmethod
 
3423
    def actual_seed(seed):
 
3424
        if seed == "now":
3457
3425
            # We convert the seed to a long to make it reuseable across
3458
3426
            # invocations (because the user can reenter it).
3459
 
            self.random_seed = long(time.time())
 
3427
            return long(time.time())
3460
3428
        else:
3461
3429
            # Convert the seed to a long if we can
3462
3430
            try:
3463
 
                self.random_seed = long(self.random_seed)
3464
 
            except:
 
3431
                return long(seed)
 
3432
            except (TypeError, ValueError):
3465
3433
                pass
3466
 
        return self.random_seed
 
3434
        return seed
3467
3435
 
3468
3436
 
3469
3437
class TestFirstDecorator(TestDecorator):
3470
3438
    """A decorator which moves named tests to the front."""
3471
3439
 
3472
3440
    def __init__(self, suite, pattern):
3473
 
        TestDecorator.__init__(self, suite)
3474
 
        self.pattern = pattern
3475
 
        self.filtered = False
3476
 
 
3477
 
    def __iter__(self):
3478
 
        if self.filtered:
3479
 
            return iter(self._tests)
3480
 
        self.filtered = True
3481
 
        suites = split_suite_by_re(self, self.pattern)
3482
 
        del self._tests[:]
3483
 
        self.addTests(suites)
3484
 
        return iter(self._tests)
 
3441
        super(TestFirstDecorator, self).__init__()
 
3442
        self.addTests(split_suite_by_re(suite, pattern))
3485
3443
 
3486
3444
 
3487
3445
def partition_tests(suite, count):
3519
3477
    """
3520
3478
    concurrency = osutils.local_concurrency()
3521
3479
    result = []
3522
 
    from subunit import TestProtocolClient, ProtocolTestCase
 
3480
    from subunit import ProtocolTestCase
3523
3481
    from subunit.test_results import AutoTimingTestResultDecorator
3524
3482
    class TestInOtherProcess(ProtocolTestCase):
3525
3483
        # Should be in subunit, I think. RBC.
3531
3489
            try:
3532
3490
                ProtocolTestCase.run(self, result)
3533
3491
            finally:
3534
 
                os.waitpid(self.pid, 0)
 
3492
                pid, status = os.waitpid(self.pid, 0)
 
3493
            # GZ 2011-10-18: If status is nonzero, should report to the result
 
3494
            #                that something went wrong.
3535
3495
 
3536
3496
    test_blocks = partition_tests(suite, concurrency)
 
3497
    # Clear the tests from the original suite so it doesn't keep them alive
 
3498
    suite._tests[:] = []
3537
3499
    for process_tests in test_blocks:
3538
 
        process_suite = TestUtil.TestSuite()
3539
 
        process_suite.addTests(process_tests)
 
3500
        process_suite = TestUtil.TestSuite(process_tests)
 
3501
        # Also clear each split list so new suite has only reference
 
3502
        process_tests[:] = []
3540
3503
        c2pread, c2pwrite = os.pipe()
3541
3504
        pid = os.fork()
3542
3505
        if pid == 0:
3543
 
            workaround_zealous_crypto_random()
3544
3506
            try:
 
3507
                stream = os.fdopen(c2pwrite, 'wb', 1)
 
3508
                workaround_zealous_crypto_random()
3545
3509
                os.close(c2pread)
3546
3510
                # Leave stderr and stdout open so we can see test noise
3547
3511
                # Close stdin so that the child goes away if it decides to
3548
3512
                # read from stdin (otherwise its a roulette to see what
3549
3513
                # child actually gets keystrokes for pdb etc).
3550
3514
                sys.stdin.close()
3551
 
                sys.stdin = None
3552
 
                stream = os.fdopen(c2pwrite, 'wb', 1)
3553
3515
                subunit_result = AutoTimingTestResultDecorator(
3554
 
                    TestProtocolClient(stream))
 
3516
                    SubUnitBzrProtocolClient(stream))
3555
3517
                process_suite.run(subunit_result)
3556
 
            finally:
3557
 
                os._exit(0)
 
3518
            except:
 
3519
                # Try and report traceback on stream, but exit with error even
 
3520
                # if stream couldn't be created or something else goes wrong.
 
3521
                # The traceback is formatted to a string and written in one go
 
3522
                # to avoid interleaving lines from multiple failing children.
 
3523
                try:
 
3524
                    stream.write(traceback.format_exc())
 
3525
                finally:
 
3526
                    os._exit(1)
 
3527
            os._exit(0)
3558
3528
        else:
3559
3529
            os.close(c2pwrite)
3560
3530
            stream = os.fdopen(c2pread, 'rb', 1)
3666
3636
#                           with proper exclusion rules.
3667
3637
#   -Ethreads               Will display thread ident at creation/join time to
3668
3638
#                           help track thread leaks
3669
 
 
 
3639
#   -Euncollected_cases     Display the identity of any test cases that weren't
 
3640
#                           deallocated after being completed.
3670
3641
#   -Econfig_stats          Will collect statistics using addDetail
3671
3642
selftest_debug_flags = set()
3672
3643
 
4470
4441
    from subunit.test_results import AutoTimingTestResultDecorator
4471
4442
    class SubUnitBzrProtocolClient(TestProtocolClient):
4472
4443
 
 
4444
        def stopTest(self, test):
 
4445
            super(SubUnitBzrProtocolClient, self).stopTest(test)
 
4446
            _clear__type_equality_funcs(test)
 
4447
 
4473
4448
        def addSuccess(self, test, details=None):
4474
4449
            # The subunit client always includes the details in the subunit
4475
4450
            # stream, but we don't want to include it in ours.
4488
4463
    pass
4489
4464
 
4490
4465
 
4491
 
@deprecated_function(deprecated_in((2, 5, 0)))
4492
 
def ModuleAvailableFeature(name):
4493
 
    from bzrlib.tests import features
4494
 
    return features.ModuleAvailableFeature(name)
4495
 
    
 
4466
# API compatibility for old plugins; see bug 892622.
 
4467
for name in [
 
4468
    'Feature',
 
4469
    'HTTPServerFeature', 
 
4470
    'ModuleAvailableFeature',
 
4471
    'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
 
4472
    'OsFifoFeature', 'UnicodeFilenameFeature',
 
4473
    'ByteStringNamedFilesystem', 'UTF8Filesystem',
 
4474
    'BreakinFeature', 'CaseInsCasePresFilenameFeature',
 
4475
    'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
 
4476
    'posix_permissions_feature',
 
4477
    ]:
 
4478
    globals()[name] = _CompatabilityThunkFeature(
 
4479
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4480
        'bzrlib.tests', name,
 
4481
        name, 'bzrlib.tests.features')
 
4482
 
 
4483
 
 
4484
for (old_name, new_name) in [
 
4485
    ('UnicodeFilename', 'UnicodeFilenameFeature'),
 
4486
    ]:
 
4487
    globals()[name] = _CompatabilityThunkFeature(
 
4488
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4489
        'bzrlib.tests', old_name,
 
4490
        new_name, 'bzrlib.tests.features')