~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,
 
68
    i18n,
64
69
    debug,
65
70
    errors,
66
71
    hooks,
93
98
    deprecated_in,
94
99
    )
95
100
from bzrlib.tests import (
 
101
    fixtures,
96
102
    test_server,
97
103
    TestUtil,
98
104
    treeshape,
99
105
    )
100
106
from bzrlib.ui import NullProgressView
101
107
from bzrlib.ui.text import TextUIFactory
 
108
from bzrlib.tests.features import _CompatabilityThunkFeature
102
109
 
103
110
# Mark this python module as being part of the implementation
104
111
# of unittest: this gives us better tracebacks where the last
131
138
isolated_environ = {
132
139
    'BZR_HOME': None,
133
140
    'HOME': None,
 
141
    'XDG_CONFIG_HOME': None,
134
142
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
135
143
    # tests do check our impls match APPDATA
136
144
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
211
219
        osutils.set_or_unset_env(var, value)
212
220
 
213
221
 
 
222
def _clear__type_equality_funcs(test):
 
223
    """Cleanup bound methods stored on TestCase instances
 
224
 
 
225
    Clear the dict breaking a few (mostly) harmless cycles in the affected
 
226
    unittests released with Python 2.6 and initial Python 2.7 versions.
 
227
 
 
228
    For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
 
229
    shipped in Oneiric, an object with no clear method was used, hence the
 
230
    extra complications, see bug 809048 for details.
 
231
    """
 
232
    type_equality_funcs = getattr(test, "_type_equality_funcs", None)
 
233
    if type_equality_funcs is not None:
 
234
        tef_clear = getattr(type_equality_funcs, "clear", None)
 
235
        if tef_clear is None:
 
236
            tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
 
237
            if tef_instance_dict is not None:
 
238
                tef_clear = tef_instance_dict.clear
 
239
        if tef_clear is not None:
 
240
            tef_clear()
 
241
 
 
242
 
214
243
class ExtendedTestResult(testtools.TextTestResult):
215
244
    """Accepts, reports and accumulates the results of running tests.
216
245
 
220
249
    different types of display.
221
250
 
222
251
    When a test finishes, in whatever way, it calls one of the addSuccess,
223
 
    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
224
253
    specific case for the special test results supported by our extended
225
254
    tests.
226
255
 
331
360
            return float(''.join(details['benchtime'].iter_bytes()))
332
361
        return getattr(testCase, "_benchtime", None)
333
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
 
334
372
    def _elapsedTestTimeString(self):
335
373
        """Return a time string for the overall time the current test has taken."""
336
374
        return self._formatTime(self._delta_to_float(
337
 
            self._now() - self._start_datetime))
 
375
            self._now() - self._start_datetime, 3))
338
376
 
339
377
    def _testTimeString(self, testCase):
340
378
        benchmark_time = self._extractBenchmarkTime(testCase)
384
422
        getDetails = getattr(test, "getDetails", None)
385
423
        if getDetails is not None:
386
424
            getDetails().clear()
387
 
        # Clear _type_equality_funcs to try to stop TestCase instances
388
 
        # from wasting memory. 'clear' is not available in all Python
389
 
        # versions (bug 809048)
390
 
        type_equality_funcs = getattr(test, "_type_equality_funcs", None)
391
 
        if type_equality_funcs is not None:
392
 
            tef_clear = getattr(type_equality_funcs, "clear", None)
393
 
            if tef_clear is None:
394
 
                tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
395
 
                if tef_instance_dict is not None:
396
 
                    tef_clear = tef_instance_dict.clear
397
 
            if tef_clear is not None:
398
 
                tef_clear()
 
425
        _clear__type_equality_funcs(test)
399
426
        self._traceback_from_test = None
400
427
 
401
428
    def startTests(self):
502
529
        self.not_applicable_count += 1
503
530
        self.report_not_applicable(test, reason)
504
531
 
 
532
    def _count_stored_tests(self):
 
533
        """Count of tests instances kept alive due to not succeeding"""
 
534
        return self.error_count + self.failure_count + self.known_failure_count
 
535
 
505
536
    def _post_mortem(self, tb=None):
506
537
        """Start a PDB post mortem session."""
507
538
        if os.environ.get('BZR_TEST_PDB', None):
979
1010
 
980
1011
    def setUp(self):
981
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
 
982
1022
        for feature in getattr(self, '_test_needs_features', []):
983
1023
            self.requireFeature(feature)
984
1024
        self._cleanEnvironment()
 
1025
 
 
1026
        if bzrlib.global_state is not None:
 
1027
            self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
 
1028
                              config.CommandLineStore())
 
1029
 
985
1030
        self._silenceUI()
986
1031
        self._startLogFile()
987
1032
        self._benchcalls = []
994
1039
        # between tests.  We should get rid of this altogether: bug 656694. --
995
1040
        # mbp 20101008
996
1041
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
997
 
        # Isolate config option expansion until its default value for bzrlib is
998
 
        # settled on or a the FIXME associated with _get_expand_default_value
999
 
        # is addressed -- vila 20110219
1000
 
        self.overrideAttr(config, '_expand_default_value', None)
1001
1042
        self._log_files = set()
1002
1043
        # Each key in the ``_counters`` dict holds a value for a different
1003
1044
        # counter. When the test ends, addDetail() should be used to output the
1005
1046
        self._counters = {}
1006
1047
        if 'config_stats' in selftest_debug_flags:
1007
1048
            self._install_config_stats_hooks()
 
1049
        # Do not use i18n for tests (unless the test reverses this)
 
1050
        i18n.disable_i18n()
1008
1051
 
1009
1052
    def debug(self):
1010
1053
        # debug a frame up.
1011
1054
        import pdb
1012
 
        pdb.Pdb().set_trace(sys._getframe().f_back)
 
1055
        # The sys preserved stdin/stdout should allow blackbox tests debugging
 
1056
        pdb.Pdb(stdin=sys.__stdin__, stdout=sys.__stdout__
 
1057
                ).set_trace(sys._getframe().f_back)
1013
1058
 
1014
1059
    def discardDetail(self, name):
1015
1060
        """Extend the addDetail, getDetails api so we can remove a detail.
1292
1337
        # hook into bzr dir opening. This leaves a small window of error for
1293
1338
        # transport tests, but they are well known, and we can improve on this
1294
1339
        # step.
1295
 
        bzrdir.BzrDir.hooks.install_named_hook("pre_open",
 
1340
        controldir.ControlDir.hooks.install_named_hook("pre_open",
1296
1341
            self._preopen_isolate_transport, "Check bzr directories are safe.")
1297
1342
 
1298
1343
    def _ndiff_strings(self, a, b):
1324
1369
            % (message,
1325
1370
               pprint.pformat(a), pprint.pformat(b)))
1326
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
1327
1374
    assertEquals = assertEqual
1328
1375
 
1329
1376
    def assertEqualDiff(self, a, b, message=None):
1332
1379
        This is intended for use with multi-line strings where it can
1333
1380
        be hard to find the differences by eye.
1334
1381
        """
1335
 
        # TODO: perhaps override assertEquals to call this for strings?
 
1382
        # TODO: perhaps override assertEqual to call this for strings?
1336
1383
        if a == b:
1337
1384
            return
1338
1385
        if message is None:
1696
1743
        return result
1697
1744
 
1698
1745
    def _startLogFile(self):
1699
 
        """Send bzr and test log messages to a temporary file.
1700
 
 
1701
 
        The file is removed as the test is torn down.
1702
 
        """
 
1746
        """Setup a in-memory target for bzr and testcase log messages"""
1703
1747
        pseudo_log_file = StringIO()
1704
1748
        def _get_log_contents_for_weird_testtools_api():
1705
1749
            return [pseudo_log_file.getvalue().decode(
1712
1756
        self.addCleanup(self._finishLogFile)
1713
1757
 
1714
1758
    def _finishLogFile(self):
1715
 
        """Finished with the log file.
1716
 
 
1717
 
        Close the file and delete it.
1718
 
        """
 
1759
        """Flush and dereference the in-memory log for this testcase"""
1719
1760
        if trace._trace_file:
1720
1761
            # flush the log file, to get all content
1721
1762
            trace._trace_file.flush()
1722
1763
        trace.pop_log_file(self._log_memento)
 
1764
        # The logging module now tracks references for cleanup so discard ours
 
1765
        del self._log_memento
1723
1766
 
1724
1767
    def thisFailsStrictLockCheck(self):
1725
1768
        """It is known that this test would fail with -Dstrict_locks.
1749
1792
 
1750
1793
        :returns: The actual attr value.
1751
1794
        """
1752
 
        value = getattr(obj, attr_name)
1753
1795
        # The actual value is captured by the call below
1754
 
        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)
1755
1804
        if new is not _unitialized_attr:
1756
1805
            setattr(obj, attr_name, new)
1757
1806
        return value
1960
2009
 
1961
2010
        self.log('run bzr: %r', args)
1962
2011
        # FIXME: don't call into logging here
1963
 
        handler = logging.StreamHandler(stderr)
1964
 
        handler.setLevel(logging.INFO)
 
2012
        handler = trace.EncodedStreamHandler(stderr, errors="replace",
 
2013
            level=logging.INFO)
1965
2014
        logger = logging.getLogger('')
1966
2015
        logger.addHandler(handler)
1967
2016
        old_ui_factory = ui.ui_factory
2003
2052
        if err:
2004
2053
            self.log('errors:\n%r', err)
2005
2054
        if retcode is not None:
2006
 
            self.assertEquals(retcode, result,
 
2055
            self.assertEqual(retcode, result,
2007
2056
                              message='Unexpected return code')
2008
2057
        return result, out, err
2009
2058
 
2155
2204
 
2156
2205
        if env_changes is None:
2157
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
2158
2212
        old_env = {}
2159
2213
 
2160
2214
        def cleanup_environment():
2351
2405
        from bzrlib.smart import request
2352
2406
        request_handlers = request.request_handlers
2353
2407
        orig_method = request_handlers.get(verb)
 
2408
        orig_info = request_handlers.get_info(verb)
2354
2409
        request_handlers.remove(verb)
2355
 
        self.addCleanup(request_handlers.register, verb, orig_method)
 
2410
        self.addCleanup(request_handlers.register, verb, orig_method,
 
2411
            info=orig_info)
2356
2412
 
2357
2413
 
2358
2414
class CapturedCall(object):
2411
2467
        self.transport_readonly_server = None
2412
2468
        self.__vfs_server = None
2413
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
 
2414
2498
    def get_transport(self, relpath=None):
2415
2499
        """Return a writeable transport.
2416
2500
 
2431
2515
 
2432
2516
        :param relpath: a path relative to the base url.
2433
2517
        """
2434
 
        t = _mod_transport.get_transport(self.get_readonly_url(relpath))
 
2518
        t = _mod_transport.get_transport_from_url(
 
2519
            self.get_readonly_url(relpath))
2435
2520
        self.assertTrue(t.is_readonly())
2436
2521
        return t
2437
2522
 
2558
2643
        real branch.
2559
2644
        """
2560
2645
        root = TestCaseWithMemoryTransport.TEST_ROOT
2561
 
        wt = bzrdir.BzrDir.create_standalone_workingtree(root)
 
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,))
2562
2656
        # Hack for speed: remember the raw bytes of the dirstate file so that
2563
2657
        # we don't need to re-open the wt to check it hasn't changed.
2564
2658
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2571
2665
        propagating. This method ensures than a test did not leaked.
2572
2666
        """
2573
2667
        root = TestCaseWithMemoryTransport.TEST_ROOT
2574
 
        t = _mod_transport.get_transport(root)
 
2668
        t = _mod_transport.get_transport_from_path(root)
2575
2669
        self.permit_url(t.base)
2576
2670
        if (t.get_bytes('.bzr/checkout/dirstate') != 
2577
2671
                TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE):
2612
2706
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
2613
2707
        self.permit_dir(self.test_dir)
2614
2708
 
2615
 
    def make_branch(self, relpath, format=None):
 
2709
    def make_branch(self, relpath, format=None, name=None):
2616
2710
        """Create a branch on the transport at relpath."""
2617
2711
        repo = self.make_repository(relpath, format=format)
2618
 
        return repo.bzrdir.create_branch()
 
2712
        return repo.bzrdir.create_branch(append_revisions_only=False,
 
2713
                                         name=name)
 
2714
 
 
2715
    def get_default_format(self):
 
2716
        return 'default'
 
2717
 
 
2718
    def resolve_format(self, format):
 
2719
        """Resolve an object to a ControlDir format object.
 
2720
 
 
2721
        The initial format object can either already be
 
2722
        a ControlDirFormat, None (for the default format),
 
2723
        or a string with the name of the control dir format.
 
2724
 
 
2725
        :param format: Object to resolve
 
2726
        :return A ControlDirFormat instance
 
2727
        """
 
2728
        if format is None:
 
2729
            format = self.get_default_format()
 
2730
        if isinstance(format, basestring):
 
2731
            format = controldir.format_registry.make_bzrdir(format)
 
2732
        return format
2619
2733
 
2620
2734
    def make_bzrdir(self, relpath, format=None):
2621
2735
        try:
2625
2739
            t = _mod_transport.get_transport(maybe_a_url)
2626
2740
            if len(segments) > 1 and segments[-1] not in ('', '.'):
2627
2741
                t.ensure_base()
2628
 
            if format is None:
2629
 
                format = 'default'
2630
 
            if isinstance(format, basestring):
2631
 
                format = bzrdir.format_registry.make_bzrdir(format)
 
2742
            format = self.resolve_format(format)
2632
2743
            return format.initialize_on_transport(t)
2633
2744
        except errors.UninitializableFormat:
2634
2745
            raise TestSkipped("Format %s is not initializable." % format)
2635
2746
 
2636
 
    def make_repository(self, relpath, shared=False, format=None):
 
2747
    def make_repository(self, relpath, shared=None, format=None):
2637
2748
        """Create a repository on our default transport at relpath.
2638
2749
 
2639
2750
        Note that relpath must be a relative path, not a full url.
2670
2781
        self.overrideEnv('HOME', test_home_dir)
2671
2782
        self.overrideEnv('BZR_HOME', test_home_dir)
2672
2783
 
2673
 
    def setUp(self):
2674
 
        super(TestCaseWithMemoryTransport, self).setUp()
2675
 
        # Ensure that ConnectedTransport doesn't leak sockets
2676
 
        def get_transport_from_url_with_cleanup(*args, **kwargs):
2677
 
            t = orig_get_transport_from_url(*args, **kwargs)
2678
 
            if isinstance(t, _mod_transport.ConnectedTransport):
2679
 
                self.addCleanup(t.disconnect)
2680
 
            return t
2681
 
 
2682
 
        orig_get_transport_from_url = self.overrideAttr(
2683
 
            _mod_transport, 'get_transport_from_url',
2684
 
            get_transport_from_url_with_cleanup)
2685
 
        self._make_test_root()
2686
 
        self.addCleanup(os.chdir, os.getcwdu())
2687
 
        self.makeAndChdirToTestDir()
2688
 
        self.overrideEnvironmentForTesting()
2689
 
        self.__readonly_server = None
2690
 
        self.__server = None
2691
 
        self.reduceLockdirTimeout()
2692
 
 
2693
2784
    def setup_smart_server_with_call_log(self):
2694
2785
        """Sets up a smart server as the transport server with a call log."""
2695
2786
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2787
        self.hpss_connections = []
2696
2788
        self.hpss_calls = []
2697
2789
        import traceback
2698
2790
        # Skip the current stack down to the caller of
2701
2793
        def capture_hpss_call(params):
2702
2794
            self.hpss_calls.append(
2703
2795
                CapturedCall(params, prefix_length))
 
2796
        def capture_connect(transport):
 
2797
            self.hpss_connections.append(transport)
2704
2798
        client._SmartClient.hooks.install_named_hook(
2705
2799
            'call', capture_hpss_call, None)
 
2800
        _mod_transport.Transport.hooks.install_named_hook(
 
2801
            'post_connect', capture_connect, None)
2706
2802
 
2707
2803
    def reset_smart_call_log(self):
2708
2804
        self.hpss_calls = []
 
2805
        self.hpss_connections = []
2709
2806
 
2710
2807
 
2711
2808
class TestCaseInTempDir(TestCaseWithMemoryTransport):
2781
2878
        # stacking policy to honour; create a bzr dir with an unshared
2782
2879
        # repository (but not a branch - our code would be trying to escape
2783
2880
        # then!) to stop them, and permit it to be read.
2784
 
        # control = bzrdir.BzrDir.create(self.test_base_dir)
 
2881
        # control = controldir.ControlDir.create(self.test_base_dir)
2785
2882
        # control.create_repository()
2786
2883
        self.test_home_dir = self.test_base_dir + '/home'
2787
2884
        os.mkdir(self.test_home_dir)
2822
2919
                "a list or a tuple. Got %r instead" % (shape,))
2823
2920
        # It's OK to just create them using forward slashes on windows.
2824
2921
        if transport is None or transport.is_readonly():
2825
 
            transport = _mod_transport.get_transport(".")
 
2922
            transport = _mod_transport.get_transport_from_path(".")
2826
2923
        for name in shape:
2827
2924
            self.assertIsInstance(name, basestring)
2828
2925
            if name[-1] == '/':
2876
2973
    readwrite one must both define get_url() as resolving to os.getcwd().
2877
2974
    """
2878
2975
 
 
2976
    def setUp(self):
 
2977
        super(TestCaseWithTransport, self).setUp()
 
2978
        self.__vfs_server = None
 
2979
 
2879
2980
    def get_vfs_only_server(self):
2880
2981
        """See TestCaseWithMemoryTransport.
2881
2982
 
2913
3014
        # this obviously requires a format that supports branch references
2914
3015
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
2915
3016
        # RBC 20060208
 
3017
        format = self.resolve_format(format=format)
 
3018
        if not format.supports_workingtrees:
 
3019
            b = self.make_branch(relpath+'.branch', format=format)
 
3020
            return b.create_checkout(relpath, lightweight=True)
2916
3021
        b = self.make_branch(relpath, format=format)
2917
3022
        try:
2918
3023
            return b.bzrdir.create_workingtree()
2923
3028
            if self.vfs_transport_factory is test_server.LocalURLServer:
2924
3029
                # the branch is colocated on disk, we cannot create a checkout.
2925
3030
                # hopefully callers will expect this.
2926
 
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
 
3031
                local_controldir = controldir.ControlDir.open(
 
3032
                    self.get_vfs_only_url(relpath))
2927
3033
                wt = local_controldir.create_workingtree()
2928
3034
                if wt.branch._format != b._format:
2929
3035
                    wt._branch = b
2959
3065
        self.assertFalse(differences.has_changed(),
2960
3066
            "Trees %r and %r are different: %r" % (left, right, differences))
2961
3067
 
2962
 
    def setUp(self):
2963
 
        super(TestCaseWithTransport, self).setUp()
2964
 
        self.__vfs_server = None
2965
 
 
2966
3068
    def disable_missing_extensions_warning(self):
2967
3069
        """Some tests expect a precise stderr content.
2968
3070
 
2969
3071
        There is no point in forcing them to duplicate the extension related
2970
3072
        warning.
2971
3073
        """
2972
 
        config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
 
3074
        config.GlobalStack().set('ignore_missing_extensions', True)
2973
3075
 
2974
3076
 
2975
3077
class ChrootedTestCase(TestCaseWithTransport):
3217
3319
                            result_decorators=result_decorators,
3218
3320
                            )
3219
3321
    runner.stop_on_failure=stop_on_failure
 
3322
    if isinstance(suite, unittest.TestSuite):
 
3323
        # Empty out _tests list of passed suite and populate new TestSuite
 
3324
        suite._tests[:], suite = [], TestSuite(suite)
3220
3325
    # built in decorator factories:
3221
3326
    decorators = [
3222
3327
        random_order(random_seed, runner),
3320
3425
 
3321
3426
class TestDecorator(TestUtil.TestSuite):
3322
3427
    """A decorator for TestCase/TestSuite objects.
3323
 
    
3324
 
    Usually, subclasses should override __iter__(used when flattening test
3325
 
    suites), which we do to filter, reorder, parallelise and so on, run() and
3326
 
    debug().
 
3428
 
 
3429
    Contains rather than flattening suite passed on construction
3327
3430
    """
3328
3431
 
3329
 
    def __init__(self, suite):
3330
 
        TestUtil.TestSuite.__init__(self)
3331
 
        self.addTest(suite)
3332
 
 
3333
 
    def countTestCases(self):
3334
 
        cases = 0
3335
 
        for test in self:
3336
 
            cases += test.countTestCases()
3337
 
        return cases
3338
 
 
3339
 
    def debug(self):
3340
 
        for test in self:
3341
 
            test.debug()
3342
 
 
3343
 
    def run(self, result):
3344
 
        # Use iteration on self, not self._tests, to allow subclasses to hook
3345
 
        # into __iter__.
3346
 
        for test in self:
3347
 
            if result.shouldStop:
3348
 
                break
3349
 
            test.run(result)
3350
 
        return result
 
3432
    def __init__(self, suite=None):
 
3433
        super(TestDecorator, self).__init__()
 
3434
        if suite is not None:
 
3435
            self.addTest(suite)
 
3436
 
 
3437
    # Don't need subclass run method with suite emptying
 
3438
    run = unittest.TestSuite.run
3351
3439
 
3352
3440
 
3353
3441
class CountingDecorator(TestDecorator):
3364
3452
    """A decorator which excludes test matching an exclude pattern."""
3365
3453
 
3366
3454
    def __init__(self, suite, exclude_pattern):
3367
 
        TestDecorator.__init__(self, suite)
3368
 
        self.exclude_pattern = exclude_pattern
3369
 
        self.excluded = False
3370
 
 
3371
 
    def __iter__(self):
3372
 
        if self.excluded:
3373
 
            return iter(self._tests)
3374
 
        self.excluded = True
3375
 
        suite = exclude_tests_by_re(self, self.exclude_pattern)
3376
 
        del self._tests[:]
3377
 
        self.addTests(suite)
3378
 
        return iter(self._tests)
 
3455
        super(ExcludeDecorator, self).__init__(
 
3456
            exclude_tests_by_re(suite, exclude_pattern))
3379
3457
 
3380
3458
 
3381
3459
class FilterTestsDecorator(TestDecorator):
3382
3460
    """A decorator which filters tests to those matching a pattern."""
3383
3461
 
3384
3462
    def __init__(self, suite, pattern):
3385
 
        TestDecorator.__init__(self, suite)
3386
 
        self.pattern = pattern
3387
 
        self.filtered = False
3388
 
 
3389
 
    def __iter__(self):
3390
 
        if self.filtered:
3391
 
            return iter(self._tests)
3392
 
        self.filtered = True
3393
 
        suite = filter_suite_by_re(self, self.pattern)
3394
 
        del self._tests[:]
3395
 
        self.addTests(suite)
3396
 
        return iter(self._tests)
 
3463
        super(FilterTestsDecorator, self).__init__(
 
3464
            filter_suite_by_re(suite, pattern))
3397
3465
 
3398
3466
 
3399
3467
class RandomDecorator(TestDecorator):
3400
3468
    """A decorator which randomises the order of its tests."""
3401
3469
 
3402
3470
    def __init__(self, suite, random_seed, stream):
3403
 
        TestDecorator.__init__(self, suite)
3404
 
        self.random_seed = random_seed
3405
 
        self.randomised = False
3406
 
        self.stream = stream
3407
 
 
3408
 
    def __iter__(self):
3409
 
        if self.randomised:
3410
 
            return iter(self._tests)
3411
 
        self.randomised = True
3412
 
        self.stream.write("Randomizing test order using seed %s\n\n" %
3413
 
            (self.actual_seed()))
 
3471
        random_seed = self.actual_seed(random_seed)
 
3472
        stream.write("Randomizing test order using seed %s\n\n" %
 
3473
            (random_seed,))
3414
3474
        # Initialise the random number generator.
3415
 
        random.seed(self.actual_seed())
3416
 
        suite = randomize_suite(self)
3417
 
        del self._tests[:]
3418
 
        self.addTests(suite)
3419
 
        return iter(self._tests)
 
3475
        random.seed(random_seed)
 
3476
        super(RandomDecorator, self).__init__(randomize_suite(suite))
3420
3477
 
3421
 
    def actual_seed(self):
3422
 
        if self.random_seed == "now":
 
3478
    @staticmethod
 
3479
    def actual_seed(seed):
 
3480
        if seed == "now":
3423
3481
            # We convert the seed to a long to make it reuseable across
3424
3482
            # invocations (because the user can reenter it).
3425
 
            self.random_seed = long(time.time())
 
3483
            return long(time.time())
3426
3484
        else:
3427
3485
            # Convert the seed to a long if we can
3428
3486
            try:
3429
 
                self.random_seed = long(self.random_seed)
3430
 
            except:
 
3487
                return long(seed)
 
3488
            except (TypeError, ValueError):
3431
3489
                pass
3432
 
        return self.random_seed
 
3490
        return seed
3433
3491
 
3434
3492
 
3435
3493
class TestFirstDecorator(TestDecorator):
3436
3494
    """A decorator which moves named tests to the front."""
3437
3495
 
3438
3496
    def __init__(self, suite, pattern):
3439
 
        TestDecorator.__init__(self, suite)
3440
 
        self.pattern = pattern
3441
 
        self.filtered = False
3442
 
 
3443
 
    def __iter__(self):
3444
 
        if self.filtered:
3445
 
            return iter(self._tests)
3446
 
        self.filtered = True
3447
 
        suites = split_suite_by_re(self, self.pattern)
3448
 
        del self._tests[:]
3449
 
        self.addTests(suites)
3450
 
        return iter(self._tests)
 
3497
        super(TestFirstDecorator, self).__init__()
 
3498
        self.addTests(split_suite_by_re(suite, pattern))
3451
3499
 
3452
3500
 
3453
3501
def partition_tests(suite, count):
3485
3533
    """
3486
3534
    concurrency = osutils.local_concurrency()
3487
3535
    result = []
3488
 
    from subunit import TestProtocolClient, ProtocolTestCase
 
3536
    from subunit import ProtocolTestCase
3489
3537
    from subunit.test_results import AutoTimingTestResultDecorator
3490
3538
    class TestInOtherProcess(ProtocolTestCase):
3491
3539
        # Should be in subunit, I think. RBC.
3497
3545
            try:
3498
3546
                ProtocolTestCase.run(self, result)
3499
3547
            finally:
3500
 
                os.waitpid(self.pid, 0)
 
3548
                pid, status = os.waitpid(self.pid, 0)
 
3549
            # GZ 2011-10-18: If status is nonzero, should report to the result
 
3550
            #                that something went wrong.
3501
3551
 
3502
3552
    test_blocks = partition_tests(suite, concurrency)
 
3553
    # Clear the tests from the original suite so it doesn't keep them alive
 
3554
    suite._tests[:] = []
3503
3555
    for process_tests in test_blocks:
3504
 
        process_suite = TestUtil.TestSuite()
3505
 
        process_suite.addTests(process_tests)
 
3556
        process_suite = TestUtil.TestSuite(process_tests)
 
3557
        # Also clear each split list so new suite has only reference
 
3558
        process_tests[:] = []
3506
3559
        c2pread, c2pwrite = os.pipe()
3507
3560
        pid = os.fork()
3508
3561
        if pid == 0:
3509
 
            workaround_zealous_crypto_random()
3510
3562
            try:
 
3563
                stream = os.fdopen(c2pwrite, 'wb', 1)
 
3564
                workaround_zealous_crypto_random()
3511
3565
                os.close(c2pread)
3512
3566
                # Leave stderr and stdout open so we can see test noise
3513
3567
                # Close stdin so that the child goes away if it decides to
3514
3568
                # read from stdin (otherwise its a roulette to see what
3515
3569
                # child actually gets keystrokes for pdb etc).
3516
3570
                sys.stdin.close()
3517
 
                sys.stdin = None
3518
 
                stream = os.fdopen(c2pwrite, 'wb', 1)
3519
3571
                subunit_result = AutoTimingTestResultDecorator(
3520
 
                    TestProtocolClient(stream))
 
3572
                    SubUnitBzrProtocolClient(stream))
3521
3573
                process_suite.run(subunit_result)
3522
 
            finally:
3523
 
                os._exit(0)
 
3574
            except:
 
3575
                # Try and report traceback on stream, but exit with error even
 
3576
                # if stream couldn't be created or something else goes wrong.
 
3577
                # The traceback is formatted to a string and written in one go
 
3578
                # to avoid interleaving lines from multiple failing children.
 
3579
                try:
 
3580
                    stream.write(traceback.format_exc())
 
3581
                finally:
 
3582
                    os._exit(1)
 
3583
            os._exit(0)
3524
3584
        else:
3525
3585
            os.close(c2pwrite)
3526
3586
            stream = os.fdopen(c2pread, 'rb', 1)
3632
3692
#                           with proper exclusion rules.
3633
3693
#   -Ethreads               Will display thread ident at creation/join time to
3634
3694
#                           help track thread leaks
3635
 
 
 
3695
#   -Euncollected_cases     Display the identity of any test cases that weren't
 
3696
#                           deallocated after being completed.
3636
3697
#   -Econfig_stats          Will collect statistics using addDetail
3637
3698
selftest_debug_flags = set()
3638
3699
 
3743
3804
 
3744
3805
    :return: (absents, duplicates) absents is a list containing the test found
3745
3806
        in id_list but not in test_suite, duplicates is a list containing the
3746
 
        test found multiple times in test_suite.
 
3807
        tests found multiple times in test_suite.
3747
3808
 
3748
3809
    When using a prefined test id list, it may occurs that some tests do not
3749
3810
    exist anymore or that some tests use the same id. This function warns the
3873
3934
        'bzrlib.doc',
3874
3935
        'bzrlib.tests.blackbox',
3875
3936
        'bzrlib.tests.commands',
3876
 
        'bzrlib.tests.doc_generate',
3877
3937
        'bzrlib.tests.per_branch',
3878
3938
        'bzrlib.tests.per_bzrdir',
3879
3939
        'bzrlib.tests.per_controldir',
3943
4003
        'bzrlib.tests.test_email_message',
3944
4004
        'bzrlib.tests.test_eol_filters',
3945
4005
        'bzrlib.tests.test_errors',
 
4006
        'bzrlib.tests.test_estimate_compressed_size',
3946
4007
        'bzrlib.tests.test_export',
3947
4008
        'bzrlib.tests.test_export_pot',
3948
4009
        'bzrlib.tests.test_extract',
3966
4027
        'bzrlib.tests.test_http',
3967
4028
        'bzrlib.tests.test_http_response',
3968
4029
        'bzrlib.tests.test_https_ca_bundle',
 
4030
        'bzrlib.tests.test_https_urllib',
3969
4031
        'bzrlib.tests.test_i18n',
3970
4032
        'bzrlib.tests.test_identitymap',
3971
4033
        'bzrlib.tests.test_ignores',
4020
4082
        'bzrlib.tests.test_revisiontree',
4021
4083
        'bzrlib.tests.test_rio',
4022
4084
        'bzrlib.tests.test_rules',
 
4085
        'bzrlib.tests.test_url_policy_open',
4023
4086
        'bzrlib.tests.test_sampler',
4024
4087
        'bzrlib.tests.test_scenarios',
4025
4088
        'bzrlib.tests.test_script',
4032
4095
        'bzrlib.tests.test_smart',
4033
4096
        'bzrlib.tests.test_smart_add',
4034
4097
        'bzrlib.tests.test_smart_request',
 
4098
        'bzrlib.tests.test_smart_signals',
4035
4099
        'bzrlib.tests.test_smart_transport',
4036
4100
        'bzrlib.tests.test_smtp_connection',
4037
4101
        'bzrlib.tests.test_source',
4068
4132
        'bzrlib.tests.test_version',
4069
4133
        'bzrlib.tests.test_version_info',
4070
4134
        'bzrlib.tests.test_versionedfile',
 
4135
        'bzrlib.tests.test_vf_search',
4071
4136
        'bzrlib.tests.test_weave',
4072
4137
        'bzrlib.tests.test_whitebox',
4073
4138
        'bzrlib.tests.test_win32utils',
4288
4353
    """Copy test and apply scenario to it.
4289
4354
 
4290
4355
    :param test: A test to adapt.
4291
 
    :param scenario: A tuple describing the scenarion.
 
4356
    :param scenario: A tuple describing the scenario.
4292
4357
        The first element of the tuple is the new test id.
4293
4358
        The second element is a dict containing attributes to set on the
4294
4359
        test.
4434
4499
    from subunit.test_results import AutoTimingTestResultDecorator
4435
4500
    class SubUnitBzrProtocolClient(TestProtocolClient):
4436
4501
 
 
4502
        def stopTest(self, test):
 
4503
            super(SubUnitBzrProtocolClient, self).stopTest(test)
 
4504
            _clear__type_equality_funcs(test)
 
4505
 
4437
4506
        def addSuccess(self, test, details=None):
4438
4507
            # The subunit client always includes the details in the subunit
4439
4508
            # stream, but we don't want to include it in ours.
4452
4521
    pass
4453
4522
 
4454
4523
 
4455
 
@deprecated_function(deprecated_in((2, 5, 0)))
4456
 
def ModuleAvailableFeature(name):
4457
 
    from bzrlib.tests import features
4458
 
    return features.ModuleAvailableFeature(name)
4459
 
    
 
4524
# API compatibility for old plugins; see bug 892622.
 
4525
for name in [
 
4526
    'Feature',
 
4527
    'HTTPServerFeature', 
 
4528
    'ModuleAvailableFeature',
 
4529
    'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
 
4530
    'OsFifoFeature', 'UnicodeFilenameFeature',
 
4531
    'ByteStringNamedFilesystem', 'UTF8Filesystem',
 
4532
    'BreakinFeature', 'CaseInsCasePresFilenameFeature',
 
4533
    'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
 
4534
    'posix_permissions_feature',
 
4535
    ]:
 
4536
    globals()[name] = _CompatabilityThunkFeature(
 
4537
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4538
        'bzrlib.tests', name,
 
4539
        name, 'bzrlib.tests.features')
 
4540
 
 
4541
 
 
4542
for (old_name, new_name) in [
 
4543
    ('UnicodeFilename', 'UnicodeFilenameFeature'),
 
4544
    ]:
 
4545
    globals()[name] = _CompatabilityThunkFeature(
 
4546
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4547
        'bzrlib.tests', old_name,
 
4548
        new_name, 'bzrlib.tests.features')