~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Patch Queue Manager
  • Date: 2016-02-01 19:13:13 UTC
  • mfrom: (6614.2.2 trunk)
  • Revision ID: pqm@pqm.ubuntu.com-20160201191313-wdfvmfff1djde6oq
(vila) Release 2.7.0 (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2013, 2015, 2016 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
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,
133
138
isolated_environ = {
134
139
    'BZR_HOME': None,
135
140
    'HOME': None,
 
141
    'XDG_CONFIG_HOME': None,
136
142
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
137
143
    # tests do check our impls match APPDATA
138
144
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
243
249
    different types of display.
244
250
 
245
251
    When a test finishes, in whatever way, it calls one of the addSuccess,
246
 
    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
247
253
    specific case for the special test results supported by our extended
248
254
    tests.
249
255
 
354
360
            return float(''.join(details['benchtime'].iter_bytes()))
355
361
        return getattr(testCase, "_benchtime", None)
356
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
 
357
372
    def _elapsedTestTimeString(self):
358
373
        """Return a time string for the overall time the current test has taken."""
359
374
        return self._formatTime(self._delta_to_float(
360
 
            self._now() - self._start_datetime))
 
375
            self._now() - self._start_datetime, 3))
361
376
 
362
377
    def _testTimeString(self, testCase):
363
378
        benchmark_time = self._extractBenchmarkTime(testCase)
995
1010
 
996
1011
    def setUp(self):
997
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
 
998
1022
        for feature in getattr(self, '_test_needs_features', []):
999
1023
            self.requireFeature(feature)
1000
1024
        self._cleanEnvironment()
 
1025
 
1001
1026
        if bzrlib.global_state is not None:
1002
1027
            self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
1003
1028
                              config.CommandLineStore())
 
1029
 
1004
1030
        self._silenceUI()
1005
1031
        self._startLogFile()
1006
1032
        self._benchcalls = []
1013
1039
        # between tests.  We should get rid of this altogether: bug 656694. --
1014
1040
        # mbp 20101008
1015
1041
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
1016
 
        # Isolate config option expansion until its default value for bzrlib is
1017
 
        # settled on or a the FIXME associated with _get_expand_default_value
1018
 
        # is addressed -- vila 20110219
1019
 
        self.overrideAttr(config, '_expand_default_value', None)
1020
1042
        self._log_files = set()
1021
1043
        # Each key in the ``_counters`` dict holds a value for a different
1022
1044
        # counter. When the test ends, addDetail() should be used to output the
1315
1337
        # hook into bzr dir opening. This leaves a small window of error for
1316
1338
        # transport tests, but they are well known, and we can improve on this
1317
1339
        # step.
1318
 
        bzrdir.BzrDir.hooks.install_named_hook("pre_open",
 
1340
        controldir.ControlDir.hooks.install_named_hook("pre_open",
1319
1341
            self._preopen_isolate_transport, "Check bzr directories are safe.")
1320
1342
 
1321
1343
    def _ndiff_strings(self, a, b):
1347
1369
            % (message,
1348
1370
               pprint.pformat(a), pprint.pformat(b)))
1349
1371
 
 
1372
    # FIXME: This is deprecated in unittest2 but plugins may still use it so we
 
1373
    # need a deprecation period for them -- vila 2016-02-01
1350
1374
    assertEquals = assertEqual
1351
1375
 
1352
1376
    def assertEqualDiff(self, a, b, message=None):
1355
1379
        This is intended for use with multi-line strings where it can
1356
1380
        be hard to find the differences by eye.
1357
1381
        """
1358
 
        # TODO: perhaps override assertEquals to call this for strings?
 
1382
        # TODO: perhaps override assertEqual to call this for strings?
1359
1383
        if a == b:
1360
1384
            return
1361
1385
        if message is None:
1768
1792
 
1769
1793
        :returns: The actual attr value.
1770
1794
        """
1771
 
        value = getattr(obj, attr_name)
1772
1795
        # The actual value is captured by the call below
1773
 
        self.addCleanup(setattr, obj, attr_name, value)
 
1796
        value = getattr(obj, attr_name, _unitialized_attr)
 
1797
        if value is _unitialized_attr:
 
1798
            # When the test completes, the attribute should not exist, but if
 
1799
            # we aren't setting a value, we don't need to do anything.
 
1800
            if new is not _unitialized_attr:
 
1801
                self.addCleanup(delattr, obj, attr_name)
 
1802
        else:
 
1803
            self.addCleanup(setattr, obj, attr_name, value)
1774
1804
        if new is not _unitialized_attr:
1775
1805
            setattr(obj, attr_name, new)
1776
1806
        return value
1979
2009
 
1980
2010
        self.log('run bzr: %r', args)
1981
2011
        # FIXME: don't call into logging here
1982
 
        handler = logging.StreamHandler(stderr)
1983
 
        handler.setLevel(logging.INFO)
 
2012
        handler = trace.EncodedStreamHandler(stderr, errors="replace",
 
2013
            level=logging.INFO)
1984
2014
        logger = logging.getLogger('')
1985
2015
        logger.addHandler(handler)
1986
2016
        old_ui_factory = ui.ui_factory
2022
2052
        if err:
2023
2053
            self.log('errors:\n%r', err)
2024
2054
        if retcode is not None:
2025
 
            self.assertEquals(retcode, result,
 
2055
            self.assertEqual(retcode, result,
2026
2056
                              message='Unexpected return code')
2027
2057
        return result, out, err
2028
2058
 
2174
2204
 
2175
2205
        if env_changes is None:
2176
2206
            env_changes = {}
 
2207
        # Because $HOME is set to a tempdir for the context of a test, modules
 
2208
        # installed in the user dir will not be found unless $PYTHONUSERBASE
 
2209
        # gets set to the computed directory of this parent process.
 
2210
        if site.USER_BASE is not None:
 
2211
            env_changes["PYTHONUSERBASE"] = site.USER_BASE
2177
2212
        old_env = {}
2178
2213
 
2179
2214
        def cleanup_environment():
2370
2405
        from bzrlib.smart import request
2371
2406
        request_handlers = request.request_handlers
2372
2407
        orig_method = request_handlers.get(verb)
 
2408
        orig_info = request_handlers.get_info(verb)
2373
2409
        request_handlers.remove(verb)
2374
 
        self.addCleanup(request_handlers.register, verb, orig_method)
 
2410
        self.addCleanup(request_handlers.register, verb, orig_method,
 
2411
            info=orig_info)
2375
2412
 
2376
2413
 
2377
2414
class CapturedCall(object):
2430
2467
        self.transport_readonly_server = None
2431
2468
        self.__vfs_server = None
2432
2469
 
 
2470
    def setUp(self):
 
2471
        super(TestCaseWithMemoryTransport, self).setUp()
 
2472
 
 
2473
        def _add_disconnect_cleanup(transport):
 
2474
            """Schedule disconnection of given transport at test cleanup
 
2475
 
 
2476
            This needs to happen for all connected transports or leaks occur.
 
2477
 
 
2478
            Note reconnections may mean we call disconnect multiple times per
 
2479
            transport which is suboptimal but seems harmless.
 
2480
            """
 
2481
            self.addCleanup(transport.disconnect)
 
2482
 
 
2483
        _mod_transport.Transport.hooks.install_named_hook('post_connect',
 
2484
            _add_disconnect_cleanup, None)
 
2485
 
 
2486
        self._make_test_root()
 
2487
        self.addCleanup(os.chdir, os.getcwdu())
 
2488
        self.makeAndChdirToTestDir()
 
2489
        self.overrideEnvironmentForTesting()
 
2490
        self.__readonly_server = None
 
2491
        self.__server = None
 
2492
        self.reduceLockdirTimeout()
 
2493
        # Each test may use its own config files even if the local config files
 
2494
        # don't actually exist. They'll rightly fail if they try to create them
 
2495
        # though.
 
2496
        self.overrideAttr(config, '_shared_stores', {})
 
2497
 
2433
2498
    def get_transport(self, relpath=None):
2434
2499
        """Return a writeable transport.
2435
2500
 
2578
2643
        real branch.
2579
2644
        """
2580
2645
        root = TestCaseWithMemoryTransport.TEST_ROOT
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']
 
2646
        try:
 
2647
            # Make sure we get a readable and accessible home for .bzr.log
 
2648
            # and/or config files, and not fallback to weird defaults (see
 
2649
            # http://pad.lv/825027).
 
2650
            self.assertIs(None, os.environ.get('BZR_HOME', None))
 
2651
            os.environ['BZR_HOME'] = root
 
2652
            wt = controldir.ControlDir.create_standalone_workingtree(root)
 
2653
            del os.environ['BZR_HOME']
 
2654
        except Exception, e:
 
2655
            self.fail("Fail to initialize the safety net: %r\n" % (e,))
2588
2656
        # Hack for speed: remember the raw bytes of the dirstate file so that
2589
2657
        # we don't need to re-open the wt to check it hasn't changed.
2590
2658
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2638
2706
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2639
2707
        self.permit_dir(self.test_dir)
2640
2708
 
2641
 
    def make_branch(self, relpath, format=None):
 
2709
    def make_branch(self, relpath, format=None, name=None):
2642
2710
        """Create a branch on the transport at relpath."""
2643
2711
        repo = self.make_repository(relpath, format=format)
2644
 
        return repo.bzrdir.create_branch(append_revisions_only=False)
 
2712
        return repo.bzrdir.create_branch(append_revisions_only=False,
 
2713
                                         name=name)
2645
2714
 
2646
2715
    def get_default_format(self):
2647
2716
        return 'default'
2659
2728
        if format is None:
2660
2729
            format = self.get_default_format()
2661
2730
        if isinstance(format, basestring):
2662
 
            format = bzrdir.format_registry.make_bzrdir(format)
 
2731
            format = controldir.format_registry.make_bzrdir(format)
2663
2732
        return format
2664
2733
 
2665
2734
    def make_bzrdir(self, relpath, format=None):
2712
2781
        self.overrideEnv('HOME', test_home_dir)
2713
2782
        self.overrideEnv('BZR_HOME', test_home_dir)
2714
2783
 
2715
 
    def setUp(self):
2716
 
        super(TestCaseWithMemoryTransport, self).setUp()
2717
 
        # Ensure that ConnectedTransport doesn't leak sockets
2718
 
        def get_transport_from_url_with_cleanup(*args, **kwargs):
2719
 
            t = orig_get_transport_from_url(*args, **kwargs)
2720
 
            if isinstance(t, _mod_transport.ConnectedTransport):
2721
 
                self.addCleanup(t.disconnect)
2722
 
            return t
2723
 
 
2724
 
        orig_get_transport_from_url = self.overrideAttr(
2725
 
            _mod_transport, 'get_transport_from_url',
2726
 
            get_transport_from_url_with_cleanup)
2727
 
        self._make_test_root()
2728
 
        self.addCleanup(os.chdir, os.getcwdu())
2729
 
        self.makeAndChdirToTestDir()
2730
 
        self.overrideEnvironmentForTesting()
2731
 
        self.__readonly_server = None
2732
 
        self.__server = None
2733
 
        self.reduceLockdirTimeout()
2734
 
 
2735
2784
    def setup_smart_server_with_call_log(self):
2736
2785
        """Sets up a smart server as the transport server with a call log."""
2737
2786
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2787
        self.hpss_connections = []
2738
2788
        self.hpss_calls = []
2739
2789
        import traceback
2740
2790
        # Skip the current stack down to the caller of
2743
2793
        def capture_hpss_call(params):
2744
2794
            self.hpss_calls.append(
2745
2795
                CapturedCall(params, prefix_length))
 
2796
        def capture_connect(transport):
 
2797
            self.hpss_connections.append(transport)
2746
2798
        client._SmartClient.hooks.install_named_hook(
2747
2799
            'call', capture_hpss_call, None)
 
2800
        _mod_transport.Transport.hooks.install_named_hook(
 
2801
            'post_connect', capture_connect, None)
2748
2802
 
2749
2803
    def reset_smart_call_log(self):
2750
2804
        self.hpss_calls = []
 
2805
        self.hpss_connections = []
2751
2806
 
2752
2807
 
2753
2808
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2823
2878
        # stacking policy to honour; create a bzr dir with an unshared
2824
2879
        # repository (but not a branch - our code would be trying to escape
2825
2880
        # then!) to stop them, and permit it to be read.
2826
 
        # control = bzrdir.BzrDir.create(self.test_base_dir)
 
2881
        # control = controldir.ControlDir.create(self.test_base_dir)
2827
2882
        # control.create_repository()
2828
2883
        self.test_home_dir = self.test_base_dir + '/home'
2829
2884
        os.mkdir(self.test_home_dir)
2918
2973
    readwrite one must both define get_url() as resolving to os.getcwd().
2919
2974
    """
2920
2975
 
 
2976
    def setUp(self):
 
2977
        super(TestCaseWithTransport, self).setUp()
 
2978
        self.__vfs_server = None
 
2979
 
2921
2980
    def get_vfs_only_server(self):
2922
2981
        """See TestCaseWithMemoryTransport.
2923
2982
 
2969
3028
            if self.vfs_transport_factory is test_server.LocalURLServer:
2970
3029
                # the branch is colocated on disk, we cannot create a checkout.
2971
3030
                # hopefully callers will expect this.
2972
 
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
 
3031
                local_controldir = controldir.ControlDir.open(
 
3032
                    self.get_vfs_only_url(relpath))
2973
3033
                wt = local_controldir.create_workingtree()
2974
3034
                if wt.branch._format != b._format:
2975
3035
                    wt._branch = b
3005
3065
        self.assertFalse(differences.has_changed(),
3006
3066
            "Trees %r and %r are different: %r" % (left, right, differences))
3007
3067
 
3008
 
    def setUp(self):
3009
 
        super(TestCaseWithTransport, self).setUp()
3010
 
        self.__vfs_server = None
3011
 
 
3012
3068
    def disable_missing_extensions_warning(self):
3013
3069
        """Some tests expect a precise stderr content.
3014
3070
 
3015
3071
        There is no point in forcing them to duplicate the extension related
3016
3072
        warning.
3017
3073
        """
3018
 
        config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
 
3074
        config.GlobalStack().set('ignore_missing_extensions', True)
3019
3075
 
3020
3076
 
3021
3077
class ChrootedTestCase(TestCaseWithTransport):
3748
3804
 
3749
3805
    :return: (absents, duplicates) absents is a list containing the test found
3750
3806
        in id_list but not in test_suite, duplicates is a list containing the
3751
 
        test found multiple times in test_suite.
 
3807
        tests found multiple times in test_suite.
3752
3808
 
3753
3809
    When using a prefined test id list, it may occurs that some tests do not
3754
3810
    exist anymore or that some tests use the same id. This function warns the
3878
3934
        'bzrlib.doc',
3879
3935
        'bzrlib.tests.blackbox',
3880
3936
        'bzrlib.tests.commands',
3881
 
        'bzrlib.tests.doc_generate',
3882
3937
        'bzrlib.tests.per_branch',
3883
3938
        'bzrlib.tests.per_bzrdir',
3884
3939
        'bzrlib.tests.per_controldir',
3972
4027
        'bzrlib.tests.test_http',
3973
4028
        'bzrlib.tests.test_http_response',
3974
4029
        'bzrlib.tests.test_https_ca_bundle',
 
4030
        'bzrlib.tests.test_https_urllib',
3975
4031
        'bzrlib.tests.test_i18n',
3976
4032
        'bzrlib.tests.test_identitymap',
3977
4033
        'bzrlib.tests.test_ignores',
4026
4082
        'bzrlib.tests.test_revisiontree',
4027
4083
        'bzrlib.tests.test_rio',
4028
4084
        'bzrlib.tests.test_rules',
 
4085
        'bzrlib.tests.test_url_policy_open',
4029
4086
        'bzrlib.tests.test_sampler',
4030
4087
        'bzrlib.tests.test_scenarios',
4031
4088
        'bzrlib.tests.test_script',
4075
4132
        'bzrlib.tests.test_version',
4076
4133
        'bzrlib.tests.test_version_info',
4077
4134
        'bzrlib.tests.test_versionedfile',
 
4135
        'bzrlib.tests.test_vf_search',
4078
4136
        'bzrlib.tests.test_weave',
4079
4137
        'bzrlib.tests.test_whitebox',
4080
4138
        'bzrlib.tests.test_win32utils',
4295
4353
    """Copy test and apply scenario to it.
4296
4354
 
4297
4355
    :param test: A test to adapt.
4298
 
    :param scenario: A tuple describing the scenarion.
 
4356
    :param scenario: A tuple describing the scenario.
4299
4357
        The first element of the tuple is the new test id.
4300
4358
        The second element is a dict containing attributes to set on the
4301
4359
        test.