~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Jelmer Vernooij
  • Date: 2011-10-13 14:12:19 UTC
  • mfrom: (6212 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6214.
  • Revision ID: jelmer@samba.org-20111013141219-ro2enod24w19vkg6
MergeĀ lp:bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
212
212
        osutils.set_or_unset_env(var, value)
213
213
 
214
214
 
 
215
def _clear__type_equality_funcs(test):
 
216
    """Cleanup bound methods stored on TestCase instances
 
217
 
 
218
    Clear the dict breaking a few (mostly) harmless cycles in the affected
 
219
    unittests released with Python 2.6 and initial Python 2.7 versions.
 
220
 
 
221
    For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
 
222
    shipped in Oneiric, an object with no clear method was used, hence the
 
223
    extra complications, see bug 809048 for details.
 
224
    """
 
225
    type_equality_funcs = getattr(test, "_type_equality_funcs", None)
 
226
    if type_equality_funcs is not None:
 
227
        tef_clear = getattr(type_equality_funcs, "clear", None)
 
228
        if tef_clear is None:
 
229
            tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
 
230
            if tef_instance_dict is not None:
 
231
                tef_clear = tef_instance_dict.clear
 
232
        if tef_clear is not None:
 
233
            tef_clear()
 
234
 
 
235
 
215
236
class ExtendedTestResult(testtools.TextTestResult):
216
237
    """Accepts, reports and accumulates the results of running tests.
217
238
 
385
406
        getDetails = getattr(test, "getDetails", None)
386
407
        if getDetails is not None:
387
408
            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()
 
409
        _clear__type_equality_funcs(test)
400
410
        self._traceback_from_test = None
401
411
 
402
412
    def startTests(self):
503
513
        self.not_applicable_count += 1
504
514
        self.report_not_applicable(test, reason)
505
515
 
 
516
    def _count_stored_tests(self):
 
517
        """Count of tests instances kept alive due to not succeeding"""
 
518
        return self.error_count + self.failure_count + self.known_failure_count
 
519
 
506
520
    def _post_mortem(self, tb=None):
507
521
        """Start a PDB post mortem session."""
508
522
        if os.environ.get('BZR_TEST_PDB', None):
983
997
        for feature in getattr(self, '_test_needs_features', []):
984
998
            self.requireFeature(feature)
985
999
        self._cleanEnvironment()
986
 
        self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
987
 
                          config.CommandLineSection())
 
1000
        if bzrlib.global_state is not None:
 
1001
            self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
 
1002
                              config.CommandLineSection())
988
1003
        self._silenceUI()
989
1004
        self._startLogFile()
990
1005
        self._benchcalls = []
3248
3263
                            result_decorators=result_decorators,
3249
3264
                            )
3250
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)
3251
3269
    # built in decorator factories:
3252
3270
    decorators = [
3253
3271
        random_order(random_seed, runner),
3351
3369
 
3352
3370
class TestDecorator(TestUtil.TestSuite):
3353
3371
    """A decorator for TestCase/TestSuite objects.
3354
 
    
3355
 
    Usually, subclasses should override __iter__(used when flattening test
3356
 
    suites), which we do to filter, reorder, parallelise and so on, run() and
3357
 
    debug().
 
3372
 
 
3373
    Contains rather than flattening suite passed on construction
3358
3374
    """
3359
3375
 
3360
 
    def __init__(self, suite):
3361
 
        TestUtil.TestSuite.__init__(self)
3362
 
        self.addTest(suite)
3363
 
 
3364
 
    def countTestCases(self):
3365
 
        cases = 0
3366
 
        for test in self:
3367
 
            cases += test.countTestCases()
3368
 
        return cases
3369
 
 
3370
 
    def debug(self):
3371
 
        for test in self:
3372
 
            test.debug()
3373
 
 
3374
 
    def run(self, result):
3375
 
        # Use iteration on self, not self._tests, to allow subclasses to hook
3376
 
        # into __iter__.
3377
 
        for test in self:
3378
 
            if result.shouldStop:
3379
 
                break
3380
 
            test.run(result)
3381
 
        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
3382
3383
 
3383
3384
 
3384
3385
class CountingDecorator(TestDecorator):
3395
3396
    """A decorator which excludes test matching an exclude pattern."""
3396
3397
 
3397
3398
    def __init__(self, suite, exclude_pattern):
3398
 
        TestDecorator.__init__(self, suite)
3399
 
        self.exclude_pattern = exclude_pattern
3400
 
        self.excluded = False
3401
 
 
3402
 
    def __iter__(self):
3403
 
        if self.excluded:
3404
 
            return iter(self._tests)
3405
 
        self.excluded = True
3406
 
        suite = exclude_tests_by_re(self, self.exclude_pattern)
3407
 
        del self._tests[:]
3408
 
        self.addTests(suite)
3409
 
        return iter(self._tests)
 
3399
        super(ExcludeDecorator, self).__init__(
 
3400
            exclude_tests_by_re(suite, exclude_pattern))
3410
3401
 
3411
3402
 
3412
3403
class FilterTestsDecorator(TestDecorator):
3413
3404
    """A decorator which filters tests to those matching a pattern."""
3414
3405
 
3415
3406
    def __init__(self, suite, pattern):
3416
 
        TestDecorator.__init__(self, suite)
3417
 
        self.pattern = pattern
3418
 
        self.filtered = False
3419
 
 
3420
 
    def __iter__(self):
3421
 
        if self.filtered:
3422
 
            return iter(self._tests)
3423
 
        self.filtered = True
3424
 
        suite = filter_suite_by_re(self, self.pattern)
3425
 
        del self._tests[:]
3426
 
        self.addTests(suite)
3427
 
        return iter(self._tests)
 
3407
        super(FilterTestsDecorator, self).__init__(
 
3408
            filter_suite_by_re(suite, pattern))
3428
3409
 
3429
3410
 
3430
3411
class RandomDecorator(TestDecorator):
3431
3412
    """A decorator which randomises the order of its tests."""
3432
3413
 
3433
3414
    def __init__(self, suite, random_seed, stream):
3434
 
        TestDecorator.__init__(self, suite)
3435
 
        self.random_seed = random_seed
3436
 
        self.randomised = False
3437
 
        self.stream = stream
3438
 
 
3439
 
    def __iter__(self):
3440
 
        if self.randomised:
3441
 
            return iter(self._tests)
3442
 
        self.randomised = True
3443
 
        self.stream.write("Randomizing test order using seed %s\n\n" %
3444
 
            (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,))
3445
3418
        # Initialise the random number generator.
3446
 
        random.seed(self.actual_seed())
3447
 
        suite = randomize_suite(self)
3448
 
        del self._tests[:]
3449
 
        self.addTests(suite)
3450
 
        return iter(self._tests)
 
3419
        random.seed(random_seed)
 
3420
        super(RandomDecorator, self).__init__(randomize_suite(suite))
3451
3421
 
3452
 
    def actual_seed(self):
3453
 
        if self.random_seed == "now":
 
3422
    @staticmethod
 
3423
    def actual_seed(seed):
 
3424
        if seed == "now":
3454
3425
            # We convert the seed to a long to make it reuseable across
3455
3426
            # invocations (because the user can reenter it).
3456
 
            self.random_seed = long(time.time())
 
3427
            return long(time.time())
3457
3428
        else:
3458
3429
            # Convert the seed to a long if we can
3459
3430
            try:
3460
 
                self.random_seed = long(self.random_seed)
3461
 
            except:
 
3431
                return long(seed)
 
3432
            except (TypeError, ValueError):
3462
3433
                pass
3463
 
        return self.random_seed
 
3434
        return seed
3464
3435
 
3465
3436
 
3466
3437
class TestFirstDecorator(TestDecorator):
3467
3438
    """A decorator which moves named tests to the front."""
3468
3439
 
3469
3440
    def __init__(self, suite, pattern):
3470
 
        TestDecorator.__init__(self, suite)
3471
 
        self.pattern = pattern
3472
 
        self.filtered = False
3473
 
 
3474
 
    def __iter__(self):
3475
 
        if self.filtered:
3476
 
            return iter(self._tests)
3477
 
        self.filtered = True
3478
 
        suites = split_suite_by_re(self, self.pattern)
3479
 
        del self._tests[:]
3480
 
        self.addTests(suites)
3481
 
        return iter(self._tests)
 
3441
        super(TestFirstDecorator, self).__init__()
 
3442
        self.addTests(split_suite_by_re(suite, pattern))
3482
3443
 
3483
3444
 
3484
3445
def partition_tests(suite, count):
3516
3477
    """
3517
3478
    concurrency = osutils.local_concurrency()
3518
3479
    result = []
3519
 
    from subunit import TestProtocolClient, ProtocolTestCase
 
3480
    from subunit import ProtocolTestCase
3520
3481
    from subunit.test_results import AutoTimingTestResultDecorator
3521
3482
    class TestInOtherProcess(ProtocolTestCase):
3522
3483
        # Should be in subunit, I think. RBC.
3531
3492
                os.waitpid(self.pid, 0)
3532
3493
 
3533
3494
    test_blocks = partition_tests(suite, concurrency)
 
3495
    # Clear the tests from the original suite so it doesn't keep them alive
 
3496
    suite._tests[:] = []
3534
3497
    for process_tests in test_blocks:
3535
 
        process_suite = TestUtil.TestSuite()
3536
 
        process_suite.addTests(process_tests)
 
3498
        process_suite = TestUtil.TestSuite(process_tests)
 
3499
        # Also clear each split list so new suite has only reference
 
3500
        process_tests[:] = []
3537
3501
        c2pread, c2pwrite = os.pipe()
3538
3502
        pid = os.fork()
3539
3503
        if pid == 0:
3545
3509
                # read from stdin (otherwise its a roulette to see what
3546
3510
                # child actually gets keystrokes for pdb etc).
3547
3511
                sys.stdin.close()
3548
 
                sys.stdin = None
 
3512
                # GZ 2011-06-16: Why set stdin to None? Breaks multi fork.
 
3513
                #sys.stdin = None
3549
3514
                stream = os.fdopen(c2pwrite, 'wb', 1)
3550
3515
                subunit_result = AutoTimingTestResultDecorator(
3551
 
                    TestProtocolClient(stream))
 
3516
                    SubUnitBzrProtocolClient(stream))
3552
3517
                process_suite.run(subunit_result)
3553
3518
            finally:
 
3519
                # GZ 2011-06-16: Is always exiting with silent success
 
3520
                #                really the right thing? Hurts debugging.
3554
3521
                os._exit(0)
3555
3522
        else:
3556
3523
            os.close(c2pwrite)
3663
3630
#                           with proper exclusion rules.
3664
3631
#   -Ethreads               Will display thread ident at creation/join time to
3665
3632
#                           help track thread leaks
3666
 
 
 
3633
#   -Euncollected_cases     Display the identity of any test cases that weren't
 
3634
#                           deallocated after being completed.
3667
3635
#   -Econfig_stats          Will collect statistics using addDetail
3668
3636
selftest_debug_flags = set()
3669
3637
 
4467
4435
    from subunit.test_results import AutoTimingTestResultDecorator
4468
4436
    class SubUnitBzrProtocolClient(TestProtocolClient):
4469
4437
 
 
4438
        def stopTest(self, test):
 
4439
            super(SubUnitBzrProtocolClient, self).stopTest(test)
 
4440
            _clear__type_equality_funcs(test)
 
4441
 
4470
4442
        def addSuccess(self, test, details=None):
4471
4443
            # The subunit client always includes the details in the subunit
4472
4444
            # stream, but we don't want to include it in ours.