~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Patch Queue Manager
  • Date: 2013-05-20 17:46:29 UTC
  • mfrom: (6573.1.1 bzr)
  • Revision ID: pqm@pqm.ubuntu.com-20130520174629-dp7zujtuclvomuzd
(jameinel) Fix CVE 2013-2009. Avoid allowing multiple wildcards in a single
 SSL cert hostname segment. (Andrew Starr-Bochicchio)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Testing framework extensions"""
18
18
 
 
19
from __future__ import absolute_import
 
20
 
19
21
# NOTE: Some classes in here use camelCaseNaming() rather than
20
22
# underscore_naming().  That's for consistency with unittest; it's not the
21
23
# general style of bzrlib.  Please continue that consistency when adding e.g.
36
38
import random
37
39
import re
38
40
import shlex
 
41
import site
39
42
import stat
40
43
import subprocess
41
44
import sys
57
60
import bzrlib
58
61
from bzrlib import (
59
62
    branchbuilder,
60
 
    bzrdir,
 
63
    controldir,
61
64
    chk_map,
62
65
    commands as _mod_commands,
63
66
    config,
94
97
    deprecated_in,
95
98
    )
96
99
from bzrlib.tests import (
 
100
    fixtures,
97
101
    test_server,
98
102
    TestUtil,
99
103
    treeshape,
100
104
    )
101
105
from bzrlib.ui import NullProgressView
102
106
from bzrlib.ui.text import TextUIFactory
 
107
from bzrlib.tests.features import _CompatabilityThunkFeature
103
108
 
104
109
# Mark this python module as being part of the implementation
105
110
# of unittest: this gives us better tracebacks where the last
132
137
isolated_environ = {
133
138
    'BZR_HOME': None,
134
139
    'HOME': None,
 
140
    'XDG_CONFIG_HOME': None,
135
141
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
136
142
    # tests do check our impls match APPDATA
137
143
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
212
218
        osutils.set_or_unset_env(var, value)
213
219
 
214
220
 
 
221
def _clear__type_equality_funcs(test):
 
222
    """Cleanup bound methods stored on TestCase instances
 
223
 
 
224
    Clear the dict breaking a few (mostly) harmless cycles in the affected
 
225
    unittests released with Python 2.6 and initial Python 2.7 versions.
 
226
 
 
227
    For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
 
228
    shipped in Oneiric, an object with no clear method was used, hence the
 
229
    extra complications, see bug 809048 for details.
 
230
    """
 
231
    type_equality_funcs = getattr(test, "_type_equality_funcs", None)
 
232
    if type_equality_funcs is not None:
 
233
        tef_clear = getattr(type_equality_funcs, "clear", None)
 
234
        if tef_clear is None:
 
235
            tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
 
236
            if tef_instance_dict is not None:
 
237
                tef_clear = tef_instance_dict.clear
 
238
        if tef_clear is not None:
 
239
            tef_clear()
 
240
 
 
241
 
215
242
class ExtendedTestResult(testtools.TextTestResult):
216
243
    """Accepts, reports and accumulates the results of running tests.
217
244
 
221
248
    different types of display.
222
249
 
223
250
    When a test finishes, in whatever way, it calls one of the addSuccess,
224
 
    addFailure or addError classes.  These in turn may redirect to a more
 
251
    addFailure or addError methods.  These in turn may redirect to a more
225
252
    specific case for the special test results supported by our extended
226
253
    tests.
227
254
 
385
412
        getDetails = getattr(test, "getDetails", None)
386
413
        if getDetails is not None:
387
414
            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()
 
415
        _clear__type_equality_funcs(test)
400
416
        self._traceback_from_test = None
401
417
 
402
418
    def startTests(self):
503
519
        self.not_applicable_count += 1
504
520
        self.report_not_applicable(test, reason)
505
521
 
 
522
    def _count_stored_tests(self):
 
523
        """Count of tests instances kept alive due to not succeeding"""
 
524
        return self.error_count + self.failure_count + self.known_failure_count
 
525
 
506
526
    def _post_mortem(self, tb=None):
507
527
        """Start a PDB post mortem session."""
508
528
        if os.environ.get('BZR_TEST_PDB', None):
980
1000
 
981
1001
    def setUp(self):
982
1002
        super(TestCase, self).setUp()
 
1003
 
 
1004
        # At this point we're still accessing the config files in $BZR_HOME (as
 
1005
        # set by the user running selftest).
 
1006
        timeout = config.GlobalStack().get('selftest.timeout')
 
1007
        if timeout:
 
1008
            timeout_fixture = fixtures.TimeoutFixture(timeout)
 
1009
            timeout_fixture.setUp()
 
1010
            self.addCleanup(timeout_fixture.cleanUp)
 
1011
 
983
1012
        for feature in getattr(self, '_test_needs_features', []):
984
1013
            self.requireFeature(feature)
985
1014
        self._cleanEnvironment()
 
1015
 
 
1016
        if bzrlib.global_state is not None:
 
1017
            self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
 
1018
                              config.CommandLineStore())
 
1019
 
986
1020
        self._silenceUI()
987
1021
        self._startLogFile()
988
1022
        self._benchcalls = []
995
1029
        # between tests.  We should get rid of this altogether: bug 656694. --
996
1030
        # mbp 20101008
997
1031
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
998
 
        # Isolate config option expansion until its default value for bzrlib is
999
 
        # settled on or a the FIXME associated with _get_expand_default_value
1000
 
        # is addressed -- vila 20110219
1001
 
        self.overrideAttr(config, '_expand_default_value', None)
1002
1032
        self._log_files = set()
1003
1033
        # Each key in the ``_counters`` dict holds a value for a different
1004
1034
        # counter. When the test ends, addDetail() should be used to output the
1297
1327
        # hook into bzr dir opening. This leaves a small window of error for
1298
1328
        # transport tests, but they are well known, and we can improve on this
1299
1329
        # step.
1300
 
        bzrdir.BzrDir.hooks.install_named_hook("pre_open",
 
1330
        controldir.ControlDir.hooks.install_named_hook("pre_open",
1301
1331
            self._preopen_isolate_transport, "Check bzr directories are safe.")
1302
1332
 
1303
1333
    def _ndiff_strings(self, a, b):
1701
1731
        return result
1702
1732
 
1703
1733
    def _startLogFile(self):
1704
 
        """Send bzr and test log messages to a temporary file.
1705
 
 
1706
 
        The file is removed as the test is torn down.
1707
 
        """
 
1734
        """Setup a in-memory target for bzr and testcase log messages"""
1708
1735
        pseudo_log_file = StringIO()
1709
1736
        def _get_log_contents_for_weird_testtools_api():
1710
1737
            return [pseudo_log_file.getvalue().decode(
1717
1744
        self.addCleanup(self._finishLogFile)
1718
1745
 
1719
1746
    def _finishLogFile(self):
1720
 
        """Finished with the log file.
1721
 
 
1722
 
        Close the file and delete it.
1723
 
        """
 
1747
        """Flush and dereference the in-memory log for this testcase"""
1724
1748
        if trace._trace_file:
1725
1749
            # flush the log file, to get all content
1726
1750
            trace._trace_file.flush()
1727
1751
        trace.pop_log_file(self._log_memento)
 
1752
        # The logging module now tracks references for cleanup so discard ours
 
1753
        del self._log_memento
1728
1754
 
1729
1755
    def thisFailsStrictLockCheck(self):
1730
1756
        """It is known that this test would fail with -Dstrict_locks.
1965
1991
 
1966
1992
        self.log('run bzr: %r', args)
1967
1993
        # FIXME: don't call into logging here
1968
 
        handler = logging.StreamHandler(stderr)
1969
 
        handler.setLevel(logging.INFO)
 
1994
        handler = trace.EncodedStreamHandler(stderr, errors="replace",
 
1995
            level=logging.INFO)
1970
1996
        logger = logging.getLogger('')
1971
1997
        logger.addHandler(handler)
1972
1998
        old_ui_factory = ui.ui_factory
2160
2186
 
2161
2187
        if env_changes is None:
2162
2188
            env_changes = {}
 
2189
        # Because $HOME is set to a tempdir for the context of a test, modules
 
2190
        # installed in the user dir will not be found unless $PYTHONUSERBASE
 
2191
        # gets set to the computed directory of this parent process.
 
2192
        if site.USER_BASE is not None:
 
2193
            env_changes["PYTHONUSERBASE"] = site.USER_BASE
2163
2194
        old_env = {}
2164
2195
 
2165
2196
        def cleanup_environment():
2356
2387
        from bzrlib.smart import request
2357
2388
        request_handlers = request.request_handlers
2358
2389
        orig_method = request_handlers.get(verb)
 
2390
        orig_info = request_handlers.get_info(verb)
2359
2391
        request_handlers.remove(verb)
2360
 
        self.addCleanup(request_handlers.register, verb, orig_method)
 
2392
        self.addCleanup(request_handlers.register, verb, orig_method,
 
2393
            info=orig_info)
2361
2394
 
2362
2395
 
2363
2396
class CapturedCall(object):
2416
2449
        self.transport_readonly_server = None
2417
2450
        self.__vfs_server = None
2418
2451
 
 
2452
    def setUp(self):
 
2453
        super(TestCaseWithMemoryTransport, self).setUp()
 
2454
 
 
2455
        def _add_disconnect_cleanup(transport):
 
2456
            """Schedule disconnection of given transport at test cleanup
 
2457
 
 
2458
            This needs to happen for all connected transports or leaks occur.
 
2459
 
 
2460
            Note reconnections may mean we call disconnect multiple times per
 
2461
            transport which is suboptimal but seems harmless.
 
2462
            """
 
2463
            self.addCleanup(transport.disconnect)
 
2464
 
 
2465
        _mod_transport.Transport.hooks.install_named_hook('post_connect',
 
2466
            _add_disconnect_cleanup, None)
 
2467
 
 
2468
        self._make_test_root()
 
2469
        self.addCleanup(os.chdir, os.getcwdu())
 
2470
        self.makeAndChdirToTestDir()
 
2471
        self.overrideEnvironmentForTesting()
 
2472
        self.__readonly_server = None
 
2473
        self.__server = None
 
2474
        self.reduceLockdirTimeout()
 
2475
        # Each test may use its own config files even if the local config files
 
2476
        # don't actually exist. They'll rightly fail if they try to create them
 
2477
        # though.
 
2478
        self.overrideAttr(config, '_shared_stores', {})
 
2479
 
2419
2480
    def get_transport(self, relpath=None):
2420
2481
        """Return a writeable transport.
2421
2482
 
2570
2631
            # http://pad.lv/825027).
2571
2632
            self.assertIs(None, os.environ.get('BZR_HOME', None))
2572
2633
            os.environ['BZR_HOME'] = root
2573
 
            wt = bzrdir.BzrDir.create_standalone_workingtree(root)
 
2634
            wt = controldir.ControlDir.create_standalone_workingtree(root)
2574
2635
            del os.environ['BZR_HOME']
2575
2636
        except Exception, e:
2576
 
            self.fail("Fail to initialize the safety net: %r\nExiting\n" % (e,))
 
2637
            self.fail("Fail to initialize the safety net: %r\n" % (e,))
2577
2638
        # Hack for speed: remember the raw bytes of the dirstate file so that
2578
2639
        # we don't need to re-open the wt to check it hasn't changed.
2579
2640
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2627
2688
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2628
2689
        self.permit_dir(self.test_dir)
2629
2690
 
2630
 
    def make_branch(self, relpath, format=None):
 
2691
    def make_branch(self, relpath, format=None, name=None):
2631
2692
        """Create a branch on the transport at relpath."""
2632
2693
        repo = self.make_repository(relpath, format=format)
2633
 
        return repo.bzrdir.create_branch(append_revisions_only=False)
2634
 
 
2635
 
    def resolve_format(self, format):
2636
 
        """Resolve an object to a ControlDir format object.
2637
 
 
2638
 
        The initial format object can either already be
2639
 
        a ControlDirFormat, None (for the default format),
2640
 
        or a string with the name of the control dir format.
2641
 
 
2642
 
        :param format: Object to resolve
2643
 
        :return A ControlDirFormat instance
2644
 
        """
2645
 
        if format is None:
2646
 
            format = 'default'
2647
 
        if isinstance(format, basestring):
2648
 
            format = bzrdir.format_registry.make_bzrdir(format)
2649
 
        return format
2650
 
 
2651
 
    def resolve_format(self, format):
2652
 
        """Resolve an object to a ControlDir format object.
2653
 
 
2654
 
        The initial format object can either already be
2655
 
        a ControlDirFormat, None (for the default format),
2656
 
        or a string with the name of the control dir format.
2657
 
 
2658
 
        :param format: Object to resolve
2659
 
        :return A ControlDirFormat instance
2660
 
        """
2661
 
        if format is None:
2662
 
            format = 'default'
2663
 
        if isinstance(format, basestring):
2664
 
            format = bzrdir.format_registry.make_bzrdir(format)
 
2694
        return repo.bzrdir.create_branch(append_revisions_only=False,
 
2695
                                         name=name)
 
2696
 
 
2697
    def get_default_format(self):
 
2698
        return 'default'
 
2699
 
 
2700
    def resolve_format(self, format):
 
2701
        """Resolve an object to a ControlDir format object.
 
2702
 
 
2703
        The initial format object can either already be
 
2704
        a ControlDirFormat, None (for the default format),
 
2705
        or a string with the name of the control dir format.
 
2706
 
 
2707
        :param format: Object to resolve
 
2708
        :return A ControlDirFormat instance
 
2709
        """
 
2710
        if format is None:
 
2711
            format = self.get_default_format()
 
2712
        if isinstance(format, basestring):
 
2713
            format = controldir.format_registry.make_bzrdir(format)
2665
2714
        return format
2666
2715
 
2667
2716
    def make_bzrdir(self, relpath, format=None):
2714
2763
        self.overrideEnv('HOME', test_home_dir)
2715
2764
        self.overrideEnv('BZR_HOME', test_home_dir)
2716
2765
 
2717
 
    def setUp(self):
2718
 
        super(TestCaseWithMemoryTransport, self).setUp()
2719
 
        # Ensure that ConnectedTransport doesn't leak sockets
2720
 
        def get_transport_from_url_with_cleanup(*args, **kwargs):
2721
 
            t = orig_get_transport_from_url(*args, **kwargs)
2722
 
            if isinstance(t, _mod_transport.ConnectedTransport):
2723
 
                self.addCleanup(t.disconnect)
2724
 
            return t
2725
 
 
2726
 
        orig_get_transport_from_url = self.overrideAttr(
2727
 
            _mod_transport, 'get_transport_from_url',
2728
 
            get_transport_from_url_with_cleanup)
2729
 
        self._make_test_root()
2730
 
        self.addCleanup(os.chdir, os.getcwdu())
2731
 
        self.makeAndChdirToTestDir()
2732
 
        self.overrideEnvironmentForTesting()
2733
 
        self.__readonly_server = None
2734
 
        self.__server = None
2735
 
        self.reduceLockdirTimeout()
2736
 
 
2737
2766
    def setup_smart_server_with_call_log(self):
2738
2767
        """Sets up a smart server as the transport server with a call log."""
2739
2768
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2769
        self.hpss_connections = []
2740
2770
        self.hpss_calls = []
2741
2771
        import traceback
2742
2772
        # Skip the current stack down to the caller of
2745
2775
        def capture_hpss_call(params):
2746
2776
            self.hpss_calls.append(
2747
2777
                CapturedCall(params, prefix_length))
 
2778
        def capture_connect(transport):
 
2779
            self.hpss_connections.append(transport)
2748
2780
        client._SmartClient.hooks.install_named_hook(
2749
2781
            'call', capture_hpss_call, None)
 
2782
        _mod_transport.Transport.hooks.install_named_hook(
 
2783
            'post_connect', capture_connect, None)
2750
2784
 
2751
2785
    def reset_smart_call_log(self):
2752
2786
        self.hpss_calls = []
 
2787
        self.hpss_connections = []
2753
2788
 
2754
2789
 
2755
2790
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2825
2860
        # stacking policy to honour; create a bzr dir with an unshared
2826
2861
        # repository (but not a branch - our code would be trying to escape
2827
2862
        # then!) to stop them, and permit it to be read.
2828
 
        # control = bzrdir.BzrDir.create(self.test_base_dir)
 
2863
        # control = controldir.ControlDir.create(self.test_base_dir)
2829
2864
        # control.create_repository()
2830
2865
        self.test_home_dir = self.test_base_dir + '/home'
2831
2866
        os.mkdir(self.test_home_dir)
2920
2955
    readwrite one must both define get_url() as resolving to os.getcwd().
2921
2956
    """
2922
2957
 
 
2958
    def setUp(self):
 
2959
        super(TestCaseWithTransport, self).setUp()
 
2960
        self.__vfs_server = None
 
2961
 
2923
2962
    def get_vfs_only_server(self):
2924
2963
        """See TestCaseWithMemoryTransport.
2925
2964
 
2957
2996
        # this obviously requires a format that supports branch references
2958
2997
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
2959
2998
        # RBC 20060208
 
2999
        format = self.resolve_format(format=format)
 
3000
        if not format.supports_workingtrees:
 
3001
            b = self.make_branch(relpath+'.branch', format=format)
 
3002
            return b.create_checkout(relpath, lightweight=True)
2960
3003
        b = self.make_branch(relpath, format=format)
2961
3004
        try:
2962
3005
            return b.bzrdir.create_workingtree()
2967
3010
            if self.vfs_transport_factory is test_server.LocalURLServer:
2968
3011
                # the branch is colocated on disk, we cannot create a checkout.
2969
3012
                # hopefully callers will expect this.
2970
 
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
 
3013
                local_controldir = controldir.ControlDir.open(
 
3014
                    self.get_vfs_only_url(relpath))
2971
3015
                wt = local_controldir.create_workingtree()
2972
3016
                if wt.branch._format != b._format:
2973
3017
                    wt._branch = b
3003
3047
        self.assertFalse(differences.has_changed(),
3004
3048
            "Trees %r and %r are different: %r" % (left, right, differences))
3005
3049
 
3006
 
    def setUp(self):
3007
 
        super(TestCaseWithTransport, self).setUp()
3008
 
        self.__vfs_server = None
3009
 
 
3010
3050
    def disable_missing_extensions_warning(self):
3011
3051
        """Some tests expect a precise stderr content.
3012
3052
 
3013
3053
        There is no point in forcing them to duplicate the extension related
3014
3054
        warning.
3015
3055
        """
3016
 
        config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
 
3056
        config.GlobalStack().set('ignore_missing_extensions', True)
3017
3057
 
3018
3058
 
3019
3059
class ChrootedTestCase(TestCaseWithTransport):
3261
3301
                            result_decorators=result_decorators,
3262
3302
                            )
3263
3303
    runner.stop_on_failure=stop_on_failure
 
3304
    if isinstance(suite, unittest.TestSuite):
 
3305
        # Empty out _tests list of passed suite and populate new TestSuite
 
3306
        suite._tests[:], suite = [], TestSuite(suite)
3264
3307
    # built in decorator factories:
3265
3308
    decorators = [
3266
3309
        random_order(random_seed, runner),
3364
3407
 
3365
3408
class TestDecorator(TestUtil.TestSuite):
3366
3409
    """A decorator for TestCase/TestSuite objects.
3367
 
    
3368
 
    Usually, subclasses should override __iter__(used when flattening test
3369
 
    suites), which we do to filter, reorder, parallelise and so on, run() and
3370
 
    debug().
 
3410
 
 
3411
    Contains rather than flattening suite passed on construction
3371
3412
    """
3372
3413
 
3373
 
    def __init__(self, suite):
3374
 
        TestUtil.TestSuite.__init__(self)
3375
 
        self.addTest(suite)
3376
 
 
3377
 
    def countTestCases(self):
3378
 
        cases = 0
3379
 
        for test in self:
3380
 
            cases += test.countTestCases()
3381
 
        return cases
3382
 
 
3383
 
    def debug(self):
3384
 
        for test in self:
3385
 
            test.debug()
3386
 
 
3387
 
    def run(self, result):
3388
 
        # Use iteration on self, not self._tests, to allow subclasses to hook
3389
 
        # into __iter__.
3390
 
        for test in self:
3391
 
            if result.shouldStop:
3392
 
                break
3393
 
            test.run(result)
3394
 
        return result
 
3414
    def __init__(self, suite=None):
 
3415
        super(TestDecorator, self).__init__()
 
3416
        if suite is not None:
 
3417
            self.addTest(suite)
 
3418
 
 
3419
    # Don't need subclass run method with suite emptying
 
3420
    run = unittest.TestSuite.run
3395
3421
 
3396
3422
 
3397
3423
class CountingDecorator(TestDecorator):
3408
3434
    """A decorator which excludes test matching an exclude pattern."""
3409
3435
 
3410
3436
    def __init__(self, suite, exclude_pattern):
3411
 
        TestDecorator.__init__(self, suite)
3412
 
        self.exclude_pattern = exclude_pattern
3413
 
        self.excluded = False
3414
 
 
3415
 
    def __iter__(self):
3416
 
        if self.excluded:
3417
 
            return iter(self._tests)
3418
 
        self.excluded = True
3419
 
        suite = exclude_tests_by_re(self, self.exclude_pattern)
3420
 
        del self._tests[:]
3421
 
        self.addTests(suite)
3422
 
        return iter(self._tests)
 
3437
        super(ExcludeDecorator, self).__init__(
 
3438
            exclude_tests_by_re(suite, exclude_pattern))
3423
3439
 
3424
3440
 
3425
3441
class FilterTestsDecorator(TestDecorator):
3426
3442
    """A decorator which filters tests to those matching a pattern."""
3427
3443
 
3428
3444
    def __init__(self, suite, pattern):
3429
 
        TestDecorator.__init__(self, suite)
3430
 
        self.pattern = pattern
3431
 
        self.filtered = False
3432
 
 
3433
 
    def __iter__(self):
3434
 
        if self.filtered:
3435
 
            return iter(self._tests)
3436
 
        self.filtered = True
3437
 
        suite = filter_suite_by_re(self, self.pattern)
3438
 
        del self._tests[:]
3439
 
        self.addTests(suite)
3440
 
        return iter(self._tests)
 
3445
        super(FilterTestsDecorator, self).__init__(
 
3446
            filter_suite_by_re(suite, pattern))
3441
3447
 
3442
3448
 
3443
3449
class RandomDecorator(TestDecorator):
3444
3450
    """A decorator which randomises the order of its tests."""
3445
3451
 
3446
3452
    def __init__(self, suite, random_seed, stream):
3447
 
        TestDecorator.__init__(self, suite)
3448
 
        self.random_seed = random_seed
3449
 
        self.randomised = False
3450
 
        self.stream = stream
3451
 
 
3452
 
    def __iter__(self):
3453
 
        if self.randomised:
3454
 
            return iter(self._tests)
3455
 
        self.randomised = True
3456
 
        self.stream.write("Randomizing test order using seed %s\n\n" %
3457
 
            (self.actual_seed()))
 
3453
        random_seed = self.actual_seed(random_seed)
 
3454
        stream.write("Randomizing test order using seed %s\n\n" %
 
3455
            (random_seed,))
3458
3456
        # Initialise the random number generator.
3459
 
        random.seed(self.actual_seed())
3460
 
        suite = randomize_suite(self)
3461
 
        del self._tests[:]
3462
 
        self.addTests(suite)
3463
 
        return iter(self._tests)
 
3457
        random.seed(random_seed)
 
3458
        super(RandomDecorator, self).__init__(randomize_suite(suite))
3464
3459
 
3465
 
    def actual_seed(self):
3466
 
        if self.random_seed == "now":
 
3460
    @staticmethod
 
3461
    def actual_seed(seed):
 
3462
        if seed == "now":
3467
3463
            # We convert the seed to a long to make it reuseable across
3468
3464
            # invocations (because the user can reenter it).
3469
 
            self.random_seed = long(time.time())
 
3465
            return long(time.time())
3470
3466
        else:
3471
3467
            # Convert the seed to a long if we can
3472
3468
            try:
3473
 
                self.random_seed = long(self.random_seed)
3474
 
            except:
 
3469
                return long(seed)
 
3470
            except (TypeError, ValueError):
3475
3471
                pass
3476
 
        return self.random_seed
 
3472
        return seed
3477
3473
 
3478
3474
 
3479
3475
class TestFirstDecorator(TestDecorator):
3480
3476
    """A decorator which moves named tests to the front."""
3481
3477
 
3482
3478
    def __init__(self, suite, pattern):
3483
 
        TestDecorator.__init__(self, suite)
3484
 
        self.pattern = pattern
3485
 
        self.filtered = False
3486
 
 
3487
 
    def __iter__(self):
3488
 
        if self.filtered:
3489
 
            return iter(self._tests)
3490
 
        self.filtered = True
3491
 
        suites = split_suite_by_re(self, self.pattern)
3492
 
        del self._tests[:]
3493
 
        self.addTests(suites)
3494
 
        return iter(self._tests)
 
3479
        super(TestFirstDecorator, self).__init__()
 
3480
        self.addTests(split_suite_by_re(suite, pattern))
3495
3481
 
3496
3482
 
3497
3483
def partition_tests(suite, count):
3529
3515
    """
3530
3516
    concurrency = osutils.local_concurrency()
3531
3517
    result = []
3532
 
    from subunit import TestProtocolClient, ProtocolTestCase
 
3518
    from subunit import ProtocolTestCase
3533
3519
    from subunit.test_results import AutoTimingTestResultDecorator
3534
3520
    class TestInOtherProcess(ProtocolTestCase):
3535
3521
        # Should be in subunit, I think. RBC.
3541
3527
            try:
3542
3528
                ProtocolTestCase.run(self, result)
3543
3529
            finally:
3544
 
                os.waitpid(self.pid, 0)
 
3530
                pid, status = os.waitpid(self.pid, 0)
 
3531
            # GZ 2011-10-18: If status is nonzero, should report to the result
 
3532
            #                that something went wrong.
3545
3533
 
3546
3534
    test_blocks = partition_tests(suite, concurrency)
 
3535
    # Clear the tests from the original suite so it doesn't keep them alive
 
3536
    suite._tests[:] = []
3547
3537
    for process_tests in test_blocks:
3548
 
        process_suite = TestUtil.TestSuite()
3549
 
        process_suite.addTests(process_tests)
 
3538
        process_suite = TestUtil.TestSuite(process_tests)
 
3539
        # Also clear each split list so new suite has only reference
 
3540
        process_tests[:] = []
3550
3541
        c2pread, c2pwrite = os.pipe()
3551
3542
        pid = os.fork()
3552
3543
        if pid == 0:
3553
 
            workaround_zealous_crypto_random()
3554
3544
            try:
 
3545
                stream = os.fdopen(c2pwrite, 'wb', 1)
 
3546
                workaround_zealous_crypto_random()
3555
3547
                os.close(c2pread)
3556
3548
                # Leave stderr and stdout open so we can see test noise
3557
3549
                # Close stdin so that the child goes away if it decides to
3558
3550
                # read from stdin (otherwise its a roulette to see what
3559
3551
                # child actually gets keystrokes for pdb etc).
3560
3552
                sys.stdin.close()
3561
 
                sys.stdin = None
3562
 
                stream = os.fdopen(c2pwrite, 'wb', 1)
3563
3553
                subunit_result = AutoTimingTestResultDecorator(
3564
 
                    TestProtocolClient(stream))
 
3554
                    SubUnitBzrProtocolClient(stream))
3565
3555
                process_suite.run(subunit_result)
3566
 
            finally:
3567
 
                os._exit(0)
 
3556
            except:
 
3557
                # Try and report traceback on stream, but exit with error even
 
3558
                # if stream couldn't be created or something else goes wrong.
 
3559
                # The traceback is formatted to a string and written in one go
 
3560
                # to avoid interleaving lines from multiple failing children.
 
3561
                try:
 
3562
                    stream.write(traceback.format_exc())
 
3563
                finally:
 
3564
                    os._exit(1)
 
3565
            os._exit(0)
3568
3566
        else:
3569
3567
            os.close(c2pwrite)
3570
3568
            stream = os.fdopen(c2pread, 'rb', 1)
3676
3674
#                           with proper exclusion rules.
3677
3675
#   -Ethreads               Will display thread ident at creation/join time to
3678
3676
#                           help track thread leaks
3679
 
 
 
3677
#   -Euncollected_cases     Display the identity of any test cases that weren't
 
3678
#                           deallocated after being completed.
3680
3679
#   -Econfig_stats          Will collect statistics using addDetail
3681
3680
selftest_debug_flags = set()
3682
3681
 
3917
3916
        'bzrlib.doc',
3918
3917
        'bzrlib.tests.blackbox',
3919
3918
        'bzrlib.tests.commands',
3920
 
        'bzrlib.tests.doc_generate',
3921
3919
        'bzrlib.tests.per_branch',
3922
3920
        'bzrlib.tests.per_bzrdir',
3923
3921
        'bzrlib.tests.per_controldir',
4011
4009
        'bzrlib.tests.test_http',
4012
4010
        'bzrlib.tests.test_http_response',
4013
4011
        'bzrlib.tests.test_https_ca_bundle',
 
4012
        'bzrlib.tests.test_https_urllib',
4014
4013
        'bzrlib.tests.test_i18n',
4015
4014
        'bzrlib.tests.test_identitymap',
4016
4015
        'bzrlib.tests.test_ignores',
4065
4064
        'bzrlib.tests.test_revisiontree',
4066
4065
        'bzrlib.tests.test_rio',
4067
4066
        'bzrlib.tests.test_rules',
 
4067
        'bzrlib.tests.test_url_policy_open',
4068
4068
        'bzrlib.tests.test_sampler',
4069
4069
        'bzrlib.tests.test_scenarios',
4070
4070
        'bzrlib.tests.test_script',
4077
4077
        'bzrlib.tests.test_smart',
4078
4078
        'bzrlib.tests.test_smart_add',
4079
4079
        'bzrlib.tests.test_smart_request',
 
4080
        'bzrlib.tests.test_smart_signals',
4080
4081
        'bzrlib.tests.test_smart_transport',
4081
4082
        'bzrlib.tests.test_smtp_connection',
4082
4083
        'bzrlib.tests.test_source',
4113
4114
        'bzrlib.tests.test_version',
4114
4115
        'bzrlib.tests.test_version_info',
4115
4116
        'bzrlib.tests.test_versionedfile',
 
4117
        'bzrlib.tests.test_vf_search',
4116
4118
        'bzrlib.tests.test_weave',
4117
4119
        'bzrlib.tests.test_whitebox',
4118
4120
        'bzrlib.tests.test_win32utils',
4479
4481
    from subunit.test_results import AutoTimingTestResultDecorator
4480
4482
    class SubUnitBzrProtocolClient(TestProtocolClient):
4481
4483
 
 
4484
        def stopTest(self, test):
 
4485
            super(SubUnitBzrProtocolClient, self).stopTest(test)
 
4486
            _clear__type_equality_funcs(test)
 
4487
 
4482
4488
        def addSuccess(self, test, details=None):
4483
4489
            # The subunit client always includes the details in the subunit
4484
4490
            # stream, but we don't want to include it in ours.
4497
4503
    pass
4498
4504
 
4499
4505
 
4500
 
@deprecated_function(deprecated_in((2, 5, 0)))
4501
 
def ModuleAvailableFeature(name):
4502
 
    from bzrlib.tests import features
4503
 
    return features.ModuleAvailableFeature(name)
4504
 
    
 
4506
# API compatibility for old plugins; see bug 892622.
 
4507
for name in [
 
4508
    'Feature',
 
4509
    'HTTPServerFeature', 
 
4510
    'ModuleAvailableFeature',
 
4511
    'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
 
4512
    'OsFifoFeature', 'UnicodeFilenameFeature',
 
4513
    'ByteStringNamedFilesystem', 'UTF8Filesystem',
 
4514
    'BreakinFeature', 'CaseInsCasePresFilenameFeature',
 
4515
    'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
 
4516
    'posix_permissions_feature',
 
4517
    ]:
 
4518
    globals()[name] = _CompatabilityThunkFeature(
 
4519
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4520
        'bzrlib.tests', name,
 
4521
        name, 'bzrlib.tests.features')
 
4522
 
 
4523
 
 
4524
for (old_name, new_name) in [
 
4525
    ('UnicodeFilename', 'UnicodeFilenameFeature'),
 
4526
    ]:
 
4527
    globals()[name] = _CompatabilityThunkFeature(
 
4528
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4529
        'bzrlib.tests', old_name,
 
4530
        new_name, 'bzrlib.tests.features')