~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

(vila) Revise legal option names to be less drastic. (Vincent Ladeuil)

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.
30
32
import errno
31
33
import itertools
32
34
import logging
 
35
import math
33
36
import os
34
37
import platform
35
38
import pprint
36
39
import random
37
40
import re
38
41
import shlex
 
42
import site
39
43
import stat
40
44
import subprocess
41
45
import sys
57
61
import bzrlib
58
62
from bzrlib import (
59
63
    branchbuilder,
60
 
    bzrdir,
 
64
    controldir,
61
65
    chk_map,
62
66
    commands as _mod_commands,
63
67
    config,
94
98
    deprecated_in,
95
99
    )
96
100
from bzrlib.tests import (
 
101
    fixtures,
97
102
    test_server,
98
103
    TestUtil,
99
104
    treeshape,
100
105
    )
101
106
from bzrlib.ui import NullProgressView
102
107
from bzrlib.ui.text import TextUIFactory
 
108
from bzrlib.tests.features import _CompatabilityThunkFeature
103
109
 
104
110
# Mark this python module as being part of the implementation
105
111
# of unittest: this gives us better tracebacks where the last
132
138
isolated_environ = {
133
139
    'BZR_HOME': None,
134
140
    'HOME': None,
 
141
    'XDG_CONFIG_HOME': None,
135
142
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
136
143
    # tests do check our impls match APPDATA
137
144
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
242
249
    different types of display.
243
250
 
244
251
    When a test finishes, in whatever way, it calls one of the addSuccess,
245
 
    addFailure or addError classes.  These in turn may redirect to a more
 
252
    addFailure or addError methods.  These in turn may redirect to a more
246
253
    specific case for the special test results supported by our extended
247
254
    tests.
248
255
 
353
360
            return float(''.join(details['benchtime'].iter_bytes()))
354
361
        return getattr(testCase, "_benchtime", None)
355
362
 
 
363
    def _delta_to_float(self, a_timedelta, precision):
 
364
        # This calls ceiling to ensure that the most pessimistic view of time
 
365
        # taken is shown (rather than leaving it to the Python %f operator
 
366
        # to decide whether to round/floor/ceiling. This was added when we
 
367
        # had pyp3 test failures that suggest a floor was happening.
 
368
        shift = 10 ** precision
 
369
        return math.ceil((a_timedelta.days * 86400.0 + a_timedelta.seconds +
 
370
            a_timedelta.microseconds / 1000000.0) * shift) / shift
 
371
 
356
372
    def _elapsedTestTimeString(self):
357
373
        """Return a time string for the overall time the current test has taken."""
358
374
        return self._formatTime(self._delta_to_float(
359
 
            self._now() - self._start_datetime))
 
375
            self._now() - self._start_datetime, 3))
360
376
 
361
377
    def _testTimeString(self, testCase):
362
378
        benchmark_time = self._extractBenchmarkTime(testCase)
994
1010
 
995
1011
    def setUp(self):
996
1012
        super(TestCase, self).setUp()
 
1013
 
 
1014
        # At this point we're still accessing the config files in $BZR_HOME (as
 
1015
        # set by the user running selftest).
 
1016
        timeout = config.GlobalStack().get('selftest.timeout')
 
1017
        if timeout:
 
1018
            timeout_fixture = fixtures.TimeoutFixture(timeout)
 
1019
            timeout_fixture.setUp()
 
1020
            self.addCleanup(timeout_fixture.cleanUp)
 
1021
 
997
1022
        for feature in getattr(self, '_test_needs_features', []):
998
1023
            self.requireFeature(feature)
999
1024
        self._cleanEnvironment()
 
1025
 
1000
1026
        if bzrlib.global_state is not None:
1001
1027
            self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1002
 
                              config.CommandLineSection())
 
1028
                              config.CommandLineStore())
 
1029
 
1003
1030
        self._silenceUI()
1004
1031
        self._startLogFile()
1005
1032
        self._benchcalls = []
1012
1039
        # between tests.  We should get rid of this altogether: bug 656694. --
1013
1040
        # mbp 20101008
1014
1041
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
1015
 
        # Isolate config option expansion until its default value for bzrlib is
1016
 
        # settled on or a the FIXME associated with _get_expand_default_value
1017
 
        # is addressed -- vila 20110219
1018
 
        self.overrideAttr(config, '_expand_default_value', None)
1019
1042
        self._log_files = set()
1020
1043
        # Each key in the ``_counters`` dict holds a value for a different
1021
1044
        # counter. When the test ends, addDetail() should be used to output the
1314
1337
        # hook into bzr dir opening. This leaves a small window of error for
1315
1338
        # transport tests, but they are well known, and we can improve on this
1316
1339
        # step.
1317
 
        bzrdir.BzrDir.hooks.install_named_hook("pre_open",
 
1340
        controldir.ControlDir.hooks.install_named_hook("pre_open",
1318
1341
            self._preopen_isolate_transport, "Check bzr directories are safe.")
1319
1342
 
1320
1343
    def _ndiff_strings(self, a, b):
1767
1790
 
1768
1791
        :returns: The actual attr value.
1769
1792
        """
1770
 
        value = getattr(obj, attr_name)
1771
1793
        # The actual value is captured by the call below
1772
 
        self.addCleanup(setattr, obj, attr_name, value)
 
1794
        value = getattr(obj, attr_name, _unitialized_attr)
 
1795
        if value is _unitialized_attr:
 
1796
            # When the test completes, the attribute should not exist, but if
 
1797
            # we aren't setting a value, we don't need to do anything.
 
1798
            if new is not _unitialized_attr:
 
1799
                self.addCleanup(delattr, obj, attr_name)
 
1800
        else:
 
1801
            self.addCleanup(setattr, obj, attr_name, value)
1773
1802
        if new is not _unitialized_attr:
1774
1803
            setattr(obj, attr_name, new)
1775
1804
        return value
1978
2007
 
1979
2008
        self.log('run bzr: %r', args)
1980
2009
        # FIXME: don't call into logging here
1981
 
        handler = logging.StreamHandler(stderr)
1982
 
        handler.setLevel(logging.INFO)
 
2010
        handler = trace.EncodedStreamHandler(stderr, errors="replace",
 
2011
            level=logging.INFO)
1983
2012
        logger = logging.getLogger('')
1984
2013
        logger.addHandler(handler)
1985
2014
        old_ui_factory = ui.ui_factory
2173
2202
 
2174
2203
        if env_changes is None:
2175
2204
            env_changes = {}
 
2205
        # Because $HOME is set to a tempdir for the context of a test, modules
 
2206
        # installed in the user dir will not be found unless $PYTHONUSERBASE
 
2207
        # gets set to the computed directory of this parent process.
 
2208
        if site.USER_BASE is not None:
 
2209
            env_changes["PYTHONUSERBASE"] = site.USER_BASE
2176
2210
        old_env = {}
2177
2211
 
2178
2212
        def cleanup_environment():
2369
2403
        from bzrlib.smart import request
2370
2404
        request_handlers = request.request_handlers
2371
2405
        orig_method = request_handlers.get(verb)
 
2406
        orig_info = request_handlers.get_info(verb)
2372
2407
        request_handlers.remove(verb)
2373
 
        self.addCleanup(request_handlers.register, verb, orig_method)
 
2408
        self.addCleanup(request_handlers.register, verb, orig_method,
 
2409
            info=orig_info)
2374
2410
 
2375
2411
 
2376
2412
class CapturedCall(object):
2429
2465
        self.transport_readonly_server = None
2430
2466
        self.__vfs_server = None
2431
2467
 
 
2468
    def setUp(self):
 
2469
        super(TestCaseWithMemoryTransport, self).setUp()
 
2470
 
 
2471
        def _add_disconnect_cleanup(transport):
 
2472
            """Schedule disconnection of given transport at test cleanup
 
2473
 
 
2474
            This needs to happen for all connected transports or leaks occur.
 
2475
 
 
2476
            Note reconnections may mean we call disconnect multiple times per
 
2477
            transport which is suboptimal but seems harmless.
 
2478
            """
 
2479
            self.addCleanup(transport.disconnect)
 
2480
 
 
2481
        _mod_transport.Transport.hooks.install_named_hook('post_connect',
 
2482
            _add_disconnect_cleanup, None)
 
2483
 
 
2484
        self._make_test_root()
 
2485
        self.addCleanup(os.chdir, os.getcwdu())
 
2486
        self.makeAndChdirToTestDir()
 
2487
        self.overrideEnvironmentForTesting()
 
2488
        self.__readonly_server = None
 
2489
        self.__server = None
 
2490
        self.reduceLockdirTimeout()
 
2491
        # Each test may use its own config files even if the local config files
 
2492
        # don't actually exist. They'll rightly fail if they try to create them
 
2493
        # though.
 
2494
        self.overrideAttr(config, '_shared_stores', {})
 
2495
 
2432
2496
    def get_transport(self, relpath=None):
2433
2497
        """Return a writeable transport.
2434
2498
 
2577
2641
        real branch.
2578
2642
        """
2579
2643
        root = TestCaseWithMemoryTransport.TEST_ROOT
2580
 
        # Make sure we get a readable and accessible home for .bzr.log
2581
 
        # and/or config files, and not fallback to weird defaults (see
2582
 
        # http://pad.lv/825027).
2583
 
        self.assertIs(None, os.environ.get('BZR_HOME', None))
2584
 
        os.environ['BZR_HOME'] = root
2585
 
        wt = bzrdir.BzrDir.create_standalone_workingtree(root)
2586
 
        del os.environ['BZR_HOME']
 
2644
        try:
 
2645
            # Make sure we get a readable and accessible home for .bzr.log
 
2646
            # and/or config files, and not fallback to weird defaults (see
 
2647
            # http://pad.lv/825027).
 
2648
            self.assertIs(None, os.environ.get('BZR_HOME', None))
 
2649
            os.environ['BZR_HOME'] = root
 
2650
            wt = controldir.ControlDir.create_standalone_workingtree(root)
 
2651
            del os.environ['BZR_HOME']
 
2652
        except Exception, e:
 
2653
            self.fail("Fail to initialize the safety net: %r\n" % (e,))
2587
2654
        # Hack for speed: remember the raw bytes of the dirstate file so that
2588
2655
        # we don't need to re-open the wt to check it hasn't changed.
2589
2656
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2637
2704
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2638
2705
        self.permit_dir(self.test_dir)
2639
2706
 
2640
 
    def make_branch(self, relpath, format=None):
 
2707
    def make_branch(self, relpath, format=None, name=None):
2641
2708
        """Create a branch on the transport at relpath."""
2642
2709
        repo = self.make_repository(relpath, format=format)
2643
 
        return repo.bzrdir.create_branch(append_revisions_only=False)
 
2710
        return repo.bzrdir.create_branch(append_revisions_only=False,
 
2711
                                         name=name)
2644
2712
 
2645
2713
    def get_default_format(self):
2646
2714
        return 'default'
2658
2726
        if format is None:
2659
2727
            format = self.get_default_format()
2660
2728
        if isinstance(format, basestring):
2661
 
            format = bzrdir.format_registry.make_bzrdir(format)
 
2729
            format = controldir.format_registry.make_bzrdir(format)
2662
2730
        return format
2663
2731
 
2664
2732
    def make_bzrdir(self, relpath, format=None):
2711
2779
        self.overrideEnv('HOME', test_home_dir)
2712
2780
        self.overrideEnv('BZR_HOME', test_home_dir)
2713
2781
 
2714
 
    def setUp(self):
2715
 
        super(TestCaseWithMemoryTransport, self).setUp()
2716
 
        # Ensure that ConnectedTransport doesn't leak sockets
2717
 
        def get_transport_from_url_with_cleanup(*args, **kwargs):
2718
 
            t = orig_get_transport_from_url(*args, **kwargs)
2719
 
            if isinstance(t, _mod_transport.ConnectedTransport):
2720
 
                self.addCleanup(t.disconnect)
2721
 
            return t
2722
 
 
2723
 
        orig_get_transport_from_url = self.overrideAttr(
2724
 
            _mod_transport, 'get_transport_from_url',
2725
 
            get_transport_from_url_with_cleanup)
2726
 
        self._make_test_root()
2727
 
        self.addCleanup(os.chdir, os.getcwdu())
2728
 
        self.makeAndChdirToTestDir()
2729
 
        self.overrideEnvironmentForTesting()
2730
 
        self.__readonly_server = None
2731
 
        self.__server = None
2732
 
        self.reduceLockdirTimeout()
2733
 
 
2734
2782
    def setup_smart_server_with_call_log(self):
2735
2783
        """Sets up a smart server as the transport server with a call log."""
2736
2784
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2785
        self.hpss_connections = []
2737
2786
        self.hpss_calls = []
2738
2787
        import traceback
2739
2788
        # Skip the current stack down to the caller of
2742
2791
        def capture_hpss_call(params):
2743
2792
            self.hpss_calls.append(
2744
2793
                CapturedCall(params, prefix_length))
 
2794
        def capture_connect(transport):
 
2795
            self.hpss_connections.append(transport)
2745
2796
        client._SmartClient.hooks.install_named_hook(
2746
2797
            'call', capture_hpss_call, None)
 
2798
        _mod_transport.Transport.hooks.install_named_hook(
 
2799
            'post_connect', capture_connect, None)
2747
2800
 
2748
2801
    def reset_smart_call_log(self):
2749
2802
        self.hpss_calls = []
 
2803
        self.hpss_connections = []
2750
2804
 
2751
2805
 
2752
2806
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2822
2876
        # stacking policy to honour; create a bzr dir with an unshared
2823
2877
        # repository (but not a branch - our code would be trying to escape
2824
2878
        # then!) to stop them, and permit it to be read.
2825
 
        # control = bzrdir.BzrDir.create(self.test_base_dir)
 
2879
        # control = controldir.ControlDir.create(self.test_base_dir)
2826
2880
        # control.create_repository()
2827
2881
        self.test_home_dir = self.test_base_dir + '/home'
2828
2882
        os.mkdir(self.test_home_dir)
2917
2971
    readwrite one must both define get_url() as resolving to os.getcwd().
2918
2972
    """
2919
2973
 
 
2974
    def setUp(self):
 
2975
        super(TestCaseWithTransport, self).setUp()
 
2976
        self.__vfs_server = None
 
2977
 
2920
2978
    def get_vfs_only_server(self):
2921
2979
        """See TestCaseWithMemoryTransport.
2922
2980
 
2968
3026
            if self.vfs_transport_factory is test_server.LocalURLServer:
2969
3027
                # the branch is colocated on disk, we cannot create a checkout.
2970
3028
                # hopefully callers will expect this.
2971
 
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
 
3029
                local_controldir = controldir.ControlDir.open(
 
3030
                    self.get_vfs_only_url(relpath))
2972
3031
                wt = local_controldir.create_workingtree()
2973
3032
                if wt.branch._format != b._format:
2974
3033
                    wt._branch = b
3004
3063
        self.assertFalse(differences.has_changed(),
3005
3064
            "Trees %r and %r are different: %r" % (left, right, differences))
3006
3065
 
3007
 
    def setUp(self):
3008
 
        super(TestCaseWithTransport, self).setUp()
3009
 
        self.__vfs_server = None
3010
 
 
3011
3066
    def disable_missing_extensions_warning(self):
3012
3067
        """Some tests expect a precise stderr content.
3013
3068
 
3014
3069
        There is no point in forcing them to duplicate the extension related
3015
3070
        warning.
3016
3071
        """
3017
 
        config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
 
3072
        config.GlobalStack().set('ignore_missing_extensions', True)
3018
3073
 
3019
3074
 
3020
3075
class ChrootedTestCase(TestCaseWithTransport):
3747
3802
 
3748
3803
    :return: (absents, duplicates) absents is a list containing the test found
3749
3804
        in id_list but not in test_suite, duplicates is a list containing the
3750
 
        test found multiple times in test_suite.
 
3805
        tests found multiple times in test_suite.
3751
3806
 
3752
3807
    When using a prefined test id list, it may occurs that some tests do not
3753
3808
    exist anymore or that some tests use the same id. This function warns the
3877
3932
        'bzrlib.doc',
3878
3933
        'bzrlib.tests.blackbox',
3879
3934
        'bzrlib.tests.commands',
3880
 
        'bzrlib.tests.doc_generate',
3881
3935
        'bzrlib.tests.per_branch',
3882
3936
        'bzrlib.tests.per_bzrdir',
3883
3937
        'bzrlib.tests.per_controldir',
3971
4025
        'bzrlib.tests.test_http',
3972
4026
        'bzrlib.tests.test_http_response',
3973
4027
        'bzrlib.tests.test_https_ca_bundle',
 
4028
        'bzrlib.tests.test_https_urllib',
3974
4029
        'bzrlib.tests.test_i18n',
3975
4030
        'bzrlib.tests.test_identitymap',
3976
4031
        'bzrlib.tests.test_ignores',
4025
4080
        'bzrlib.tests.test_revisiontree',
4026
4081
        'bzrlib.tests.test_rio',
4027
4082
        'bzrlib.tests.test_rules',
 
4083
        'bzrlib.tests.test_url_policy_open',
4028
4084
        'bzrlib.tests.test_sampler',
4029
4085
        'bzrlib.tests.test_scenarios',
4030
4086
        'bzrlib.tests.test_script',
4074
4130
        'bzrlib.tests.test_version',
4075
4131
        'bzrlib.tests.test_version_info',
4076
4132
        'bzrlib.tests.test_versionedfile',
 
4133
        'bzrlib.tests.test_vf_search',
4077
4134
        'bzrlib.tests.test_weave',
4078
4135
        'bzrlib.tests.test_whitebox',
4079
4136
        'bzrlib.tests.test_win32utils',
4294
4351
    """Copy test and apply scenario to it.
4295
4352
 
4296
4353
    :param test: A test to adapt.
4297
 
    :param scenario: A tuple describing the scenarion.
 
4354
    :param scenario: A tuple describing the scenario.
4298
4355
        The first element of the tuple is the new test id.
4299
4356
        The second element is a dict containing attributes to set on the
4300
4357
        test.
4462
4519
    pass
4463
4520
 
4464
4521
 
4465
 
@deprecated_function(deprecated_in((2, 5, 0)))
4466
 
def ModuleAvailableFeature(name):
4467
 
    from bzrlib.tests import features
4468
 
    return features.ModuleAvailableFeature(name)
4469
 
    
 
4522
# API compatibility for old plugins; see bug 892622.
 
4523
for name in [
 
4524
    'Feature',
 
4525
    'HTTPServerFeature', 
 
4526
    'ModuleAvailableFeature',
 
4527
    'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
 
4528
    'OsFifoFeature', 'UnicodeFilenameFeature',
 
4529
    'ByteStringNamedFilesystem', 'UTF8Filesystem',
 
4530
    'BreakinFeature', 'CaseInsCasePresFilenameFeature',
 
4531
    'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
 
4532
    'posix_permissions_feature',
 
4533
    ]:
 
4534
    globals()[name] = _CompatabilityThunkFeature(
 
4535
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4536
        'bzrlib.tests', name,
 
4537
        name, 'bzrlib.tests.features')
 
4538
 
 
4539
 
 
4540
for (old_name, new_name) in [
 
4541
    ('UnicodeFilename', 'UnicodeFilenameFeature'),
 
4542
    ]:
 
4543
    globals()[name] = _CompatabilityThunkFeature(
 
4544
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4545
        'bzrlib.tests', old_name,
 
4546
        new_name, 'bzrlib.tests.features')