~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-11-08 11:35:49 UTC
  • mfrom: (5531.1.3 662509-ignore-empty)
  • Revision ID: pqm@pqm.ubuntu.com-20101108113549-e4mhhq2fe1i0etbf
(vila) Add an option to accept any output from commands in shell-like tests.
 (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-2010 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
55
55
import testtools
56
56
# nb: check this before importing anything else from within it
57
57
_testtools_version = getattr(testtools, '__version__', ())
58
 
if _testtools_version < (0, 9, 5):
59
 
    raise ImportError("need at least testtools 0.9.5: %s is %r"
 
58
if _testtools_version < (0, 9, 2):
 
59
    raise ImportError("need at least testtools 0.9.2: %s is %r"
60
60
        % (testtools.__file__, _testtools_version))
61
61
from testtools import content
62
62
 
63
 
import bzrlib
64
63
from bzrlib import (
65
64
    branchbuilder,
66
65
    bzrdir,
67
66
    chk_map,
68
 
    commands as _mod_commands,
69
67
    config,
70
68
    debug,
71
69
    errors,
72
70
    hooks,
73
71
    lock as _mod_lock,
74
 
    lockdir,
75
72
    memorytree,
76
73
    osutils,
77
 
    plugin as _mod_plugin,
78
74
    pyutils,
79
75
    ui,
80
76
    urlutils,
81
77
    registry,
82
 
    symbol_versioning,
83
 
    trace,
84
78
    transport as _mod_transport,
85
79
    workingtree,
86
80
    )
 
81
import bzrlib.branch
 
82
import bzrlib.commands
 
83
import bzrlib.timestamp
 
84
import bzrlib.export
 
85
import bzrlib.inventory
 
86
import bzrlib.iterablefile
 
87
import bzrlib.lockdir
87
88
try:
88
89
    import bzrlib.lsprof
89
90
except ImportError:
90
91
    # lsprof not available
91
92
    pass
 
93
import bzrlib.merge3
 
94
import bzrlib.plugin
92
95
from bzrlib.smart import client, request
 
96
import bzrlib.store
 
97
from bzrlib import symbol_versioning
 
98
from bzrlib.symbol_versioning import (
 
99
    DEPRECATED_PARAMETER,
 
100
    deprecated_function,
 
101
    deprecated_in,
 
102
    deprecated_method,
 
103
    deprecated_passed,
 
104
    )
 
105
import bzrlib.trace
93
106
from bzrlib.transport import (
94
107
    memory,
95
108
    pathfilter,
96
109
    )
 
110
from bzrlib.trace import mutter, note
97
111
from bzrlib.tests import (
98
112
    test_server,
99
113
    TestUtil,
101
115
    )
102
116
from bzrlib.ui import NullProgressView
103
117
from bzrlib.ui.text import TextUIFactory
 
118
import bzrlib.version_info_formats.format_custom
104
119
 
105
120
# Mark this python module as being part of the implementation
106
121
# of unittest: this gives us better tracebacks where the last
123
138
TestSuite = TestUtil.TestSuite
124
139
TestLoader = TestUtil.TestLoader
125
140
 
126
 
# Tests should run in a clean and clearly defined environment. The goal is to
127
 
# keep them isolated from the running environment as mush as possible. The test
128
 
# framework ensures the variables defined below are set (or deleted if the
129
 
# value is None) before a test is run and reset to their original value after
130
 
# the test is run. Generally if some code depends on an environment variable,
131
 
# the tests should start without this variable in the environment. There are a
132
 
# few exceptions but you shouldn't violate this rule lightly.
133
 
isolated_environ = {
134
 
    'BZR_HOME': None,
135
 
    'HOME': None,
136
 
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
137
 
    # tests do check our impls match APPDATA
138
 
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
139
 
    'VISUAL': None,
140
 
    'EDITOR': None,
141
 
    'BZR_EMAIL': None,
142
 
    'BZREMAIL': None, # may still be present in the environment
143
 
    'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
144
 
    'BZR_PROGRESS_BAR': None,
145
 
    'BZR_LOG': None,
146
 
    'BZR_PLUGIN_PATH': None,
147
 
    'BZR_DISABLE_PLUGINS': None,
148
 
    'BZR_PLUGINS_AT': None,
149
 
    'BZR_CONCURRENCY': None,
150
 
    # Make sure that any text ui tests are consistent regardless of
151
 
    # the environment the test case is run in; you may want tests that
152
 
    # test other combinations.  'dumb' is a reasonable guess for tests
153
 
    # going to a pipe or a StringIO.
154
 
    'TERM': 'dumb',
155
 
    'LINES': '25',
156
 
    'COLUMNS': '80',
157
 
    'BZR_COLUMNS': '80',
158
 
    # Disable SSH Agent
159
 
    'SSH_AUTH_SOCK': None,
160
 
    # Proxies
161
 
    'http_proxy': None,
162
 
    'HTTP_PROXY': None,
163
 
    'https_proxy': None,
164
 
    'HTTPS_PROXY': None,
165
 
    'no_proxy': None,
166
 
    'NO_PROXY': None,
167
 
    'all_proxy': None,
168
 
    'ALL_PROXY': None,
169
 
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
170
 
    # least. If you do (care), please update this comment
171
 
    # -- vila 20080401
172
 
    'ftp_proxy': None,
173
 
    'FTP_PROXY': None,
174
 
    'BZR_REMOTE_PATH': None,
175
 
    # Generally speaking, we don't want apport reporting on crashes in
176
 
    # the test envirnoment unless we're specifically testing apport,
177
 
    # so that it doesn't leak into the real system environment.  We
178
 
    # use an env var so it propagates to subprocesses.
179
 
    'APPORT_DISABLE': '1',
180
 
    }
181
 
 
182
 
 
183
 
def override_os_environ(test, env=None):
184
 
    """Modify os.environ keeping a copy.
185
 
    
186
 
    :param test: A test instance
187
 
 
188
 
    :param env: A dict containing variable definitions to be installed
189
 
    """
190
 
    if env is None:
191
 
        env = isolated_environ
192
 
    test._original_os_environ = dict([(var, value)
193
 
                                      for var, value in os.environ.iteritems()])
194
 
    for var, value in env.iteritems():
195
 
        osutils.set_or_unset_env(var, value)
196
 
        if var not in test._original_os_environ:
197
 
            # The var is new, add it with a value of None, so
198
 
            # restore_os_environ will delete it
199
 
            test._original_os_environ[var] = None
200
 
 
201
 
 
202
 
def restore_os_environ(test):
203
 
    """Restore os.environ to its original state.
204
 
 
205
 
    :param test: A test instance previously passed to override_os_environ.
206
 
    """
207
 
    for var, value in test._original_os_environ.iteritems():
208
 
        # Restore the original value (or delete it if the value has been set to
209
 
        # None in override_os_environ).
210
 
        osutils.set_or_unset_env(var, value)
211
 
 
212
 
 
213
141
class ExtendedTestResult(testtools.TextTestResult):
214
142
    """Accepts, reports and accumulates the results of running tests.
215
143
 
373
301
        addOnException = getattr(test, "addOnException", None)
374
302
        if addOnException is not None:
375
303
            addOnException(self._record_traceback_from_test)
376
 
        # Only check for thread leaks on bzrlib derived test cases
377
 
        if isinstance(test, TestCase):
378
 
            test.addCleanup(self._check_leaked_threads, test)
 
304
        # Only check for thread leaks if the test case supports cleanups
 
305
        addCleanup = getattr(test, "addCleanup", None)
 
306
        if addCleanup is not None:
 
307
            addCleanup(self._check_leaked_threads, test)
379
308
 
380
309
    def startTests(self):
381
310
        self.report_tests_starting()
722
651
            encode = codec[0]
723
652
        else:
724
653
            encode = codec.encode
725
 
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
726
 
        #                so should swap to the plain codecs.StreamWriter
727
 
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
728
 
            "backslashreplace")
 
654
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream)
729
655
        stream.encoding = new_encoding
730
656
        self.stream = stream
731
657
        self.descriptions = descriptions
881
807
        return NullProgressView()
882
808
 
883
809
 
884
 
def isolated_doctest_setUp(test):
885
 
    override_os_environ(test)
886
 
 
887
 
 
888
 
def isolated_doctest_tearDown(test):
889
 
    restore_os_environ(test)
890
 
 
891
 
 
892
 
def IsolatedDocTestSuite(*args, **kwargs):
893
 
    """Overrides doctest.DocTestSuite to handle isolation.
894
 
 
895
 
    The method is really a factory and users are expected to use it as such.
896
 
    """
897
 
    
898
 
    kwargs['setUp'] = isolated_doctest_setUp
899
 
    kwargs['tearDown'] = isolated_doctest_tearDown
900
 
    return doctest.DocTestSuite(*args, **kwargs)
901
 
 
902
 
 
903
810
class TestCase(testtools.TestCase):
904
811
    """Base class for bzr unit tests.
905
812
 
1216
1123
        except UnicodeError, e:
1217
1124
            # If we can't compare without getting a UnicodeError, then
1218
1125
            # obviously they are different
1219
 
            trace.mutter('UnicodeError: %s', e)
 
1126
            mutter('UnicodeError: %s', e)
1220
1127
        if message:
1221
1128
            message += '\n'
1222
1129
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
1282
1189
    def assertLogsError(self, exception_class, func, *args, **kwargs):
1283
1190
        """Assert that func(*args, **kwargs) quietly logs a specific exception.
1284
1191
        """
 
1192
        from bzrlib import trace
1285
1193
        captured = []
1286
1194
        orig_log_exception_quietly = trace.log_exception_quietly
1287
1195
        try:
1336
1244
        if haystack.find(needle) == -1:
1337
1245
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
1338
1246
 
1339
 
    def assertNotContainsString(self, haystack, needle):
1340
 
        if haystack.find(needle) != -1:
1341
 
            self.fail("string %r found in '''%s'''" % (needle, haystack))
1342
 
 
1343
1247
    def assertSubset(self, sublist, superlist):
1344
1248
        """Assert that every entry in sublist is present in superlist."""
1345
1249
        missing = set(sublist) - set(superlist)
1585
1489
        The file is removed as the test is torn down.
1586
1490
        """
1587
1491
        self._log_file = StringIO()
1588
 
        self._log_memento = trace.push_log_file(self._log_file)
 
1492
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1589
1493
        self.addCleanup(self._finishLogFile)
1590
1494
 
1591
1495
    def _finishLogFile(self):
1593
1497
 
1594
1498
        Close the file and delete it, unless setKeepLogfile was called.
1595
1499
        """
1596
 
        if trace._trace_file:
 
1500
        if bzrlib.trace._trace_file:
1597
1501
            # flush the log file, to get all content
1598
 
            trace._trace_file.flush()
1599
 
        trace.pop_log_file(self._log_memento)
 
1502
            bzrlib.trace._trace_file.flush()
 
1503
        bzrlib.trace.pop_log_file(self._log_memento)
1600
1504
        # Cache the log result and delete the file on disk
1601
1505
        self._get_log(False)
1602
1506
 
1632
1536
            setattr(obj, attr_name, new)
1633
1537
        return value
1634
1538
 
1635
 
    def overrideEnv(self, name, new):
1636
 
        """Set an environment variable, and reset it after the test.
1637
 
 
1638
 
        :param name: The environment variable name.
1639
 
 
1640
 
        :param new: The value to set the variable to. If None, the 
1641
 
            variable is deleted from the environment.
1642
 
 
1643
 
        :returns: The actual variable value.
1644
 
        """
1645
 
        value = osutils.set_or_unset_env(name, new)
1646
 
        self.addCleanup(osutils.set_or_unset_env, name, value)
1647
 
        return value
1648
 
 
1649
1539
    def _cleanEnvironment(self):
1650
 
        for name, value in isolated_environ.iteritems():
1651
 
            self.overrideEnv(name, value)
 
1540
        new_env = {
 
1541
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
 
1542
            'HOME': os.getcwd(),
 
1543
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
1544
            # tests do check our impls match APPDATA
 
1545
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
1546
            'VISUAL': None,
 
1547
            'EDITOR': None,
 
1548
            'BZR_EMAIL': None,
 
1549
            'BZREMAIL': None, # may still be present in the environment
 
1550
            'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
 
1551
            'BZR_PROGRESS_BAR': None,
 
1552
            'BZR_LOG': None,
 
1553
            'BZR_PLUGIN_PATH': None,
 
1554
            'BZR_DISABLE_PLUGINS': None,
 
1555
            'BZR_PLUGINS_AT': None,
 
1556
            'BZR_CONCURRENCY': None,
 
1557
            # Make sure that any text ui tests are consistent regardless of
 
1558
            # the environment the test case is run in; you may want tests that
 
1559
            # test other combinations.  'dumb' is a reasonable guess for tests
 
1560
            # going to a pipe or a StringIO.
 
1561
            'TERM': 'dumb',
 
1562
            'LINES': '25',
 
1563
            'COLUMNS': '80',
 
1564
            'BZR_COLUMNS': '80',
 
1565
            # SSH Agent
 
1566
            'SSH_AUTH_SOCK': None,
 
1567
            # Proxies
 
1568
            'http_proxy': None,
 
1569
            'HTTP_PROXY': None,
 
1570
            'https_proxy': None,
 
1571
            'HTTPS_PROXY': None,
 
1572
            'no_proxy': None,
 
1573
            'NO_PROXY': None,
 
1574
            'all_proxy': None,
 
1575
            'ALL_PROXY': None,
 
1576
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
1577
            # least. If you do (care), please update this comment
 
1578
            # -- vila 20080401
 
1579
            'ftp_proxy': None,
 
1580
            'FTP_PROXY': None,
 
1581
            'BZR_REMOTE_PATH': None,
 
1582
            # Generally speaking, we don't want apport reporting on crashes in
 
1583
            # the test envirnoment unless we're specifically testing apport,
 
1584
            # so that it doesn't leak into the real system environment.  We
 
1585
            # use an env var so it propagates to subprocesses.
 
1586
            'APPORT_DISABLE': '1',
 
1587
        }
 
1588
        self._old_env = {}
 
1589
        self.addCleanup(self._restoreEnvironment)
 
1590
        for name, value in new_env.iteritems():
 
1591
            self._captureVar(name, value)
 
1592
 
 
1593
    def _captureVar(self, name, newvalue):
 
1594
        """Set an environment variable, and reset it when finished."""
 
1595
        self._old_env[name] = osutils.set_or_unset_env(name, newvalue)
 
1596
 
 
1597
    def _restoreEnvironment(self):
 
1598
        for name, value in self._old_env.iteritems():
 
1599
            osutils.set_or_unset_env(name, value)
1652
1600
 
1653
1601
    def _restoreHooks(self):
1654
1602
        for klass, (name, hooks) in self._preserved_hooks.items():
1748
1696
            self._benchtime += time.time() - start
1749
1697
 
1750
1698
    def log(self, *args):
1751
 
        trace.mutter(*args)
 
1699
        mutter(*args)
1752
1700
 
1753
1701
    def _get_log(self, keep_log_file=False):
1754
1702
        """Internal helper to get the log from bzrlib.trace for this test.
1839
1787
 
1840
1788
        try:
1841
1789
            try:
1842
 
                result = self.apply_redirected(
1843
 
                    ui.ui_factory.stdin,
 
1790
                result = self.apply_redirected(ui.ui_factory.stdin,
1844
1791
                    stdout, stderr,
1845
 
                    _mod_commands.run_bzr_catch_user_errors,
 
1792
                    bzrlib.commands.run_bzr_catch_user_errors,
1846
1793
                    args)
1847
1794
            except KeyboardInterrupt:
1848
1795
                # Reraise KeyboardInterrupt with contents of redirected stdout
2098
2045
        if retcode is not None and retcode != process.returncode:
2099
2046
            if process_args is None:
2100
2047
                process_args = "(unknown args)"
2101
 
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
2102
 
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
 
2048
            mutter('Output of bzr %s:\n%s', process_args, out)
 
2049
            mutter('Error for bzr %s:\n%s', process_args, err)
2103
2050
            self.fail('Command bzr %s failed with retcode %s != %s'
2104
2051
                      % (process_args, retcode, process.returncode))
2105
2052
        return [out, err]
2162
2109
 
2163
2110
        Tests that expect to provoke LockContention errors should call this.
2164
2111
        """
2165
 
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
2112
        self.overrideAttr(bzrlib.lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
2166
2113
 
2167
2114
    def make_utf8_encoded_stringio(self, encoding_type=None):
2168
2115
        """Return a StringIOWrapper instance, that will encode Unicode
2492
2439
        test_home_dir = self.test_home_dir
2493
2440
        if isinstance(test_home_dir, unicode):
2494
2441
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2495
 
        self.overrideEnv('HOME', test_home_dir)
2496
 
        self.overrideEnv('BZR_HOME', test_home_dir)
 
2442
        os.environ['HOME'] = test_home_dir
 
2443
        os.environ['BZR_HOME'] = test_home_dir
2497
2444
 
2498
2445
    def setUp(self):
2499
2446
        super(TestCaseWithMemoryTransport, self).setUp()
2504
2451
                self.addCleanup(t.disconnect)
2505
2452
            return t
2506
2453
 
2507
 
        orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
 
2454
        orig_get_transport = self.overrideAttr(_mod_transport, '_get_transport',
2508
2455
                                               get_transport_with_cleanup)
2509
2456
        self._make_test_root()
2510
2457
        self.addCleanup(os.chdir, os.getcwdu())
3649
3596
                key, obj, help=help, info=info, override_existing=False)
3650
3597
        except KeyError:
3651
3598
            actual = self.get(key)
3652
 
            trace.note(
3653
 
                'Test prefix alias %s is already used for %s, ignoring %s'
3654
 
                % (key, actual, obj))
 
3599
            note('Test prefix alias %s is already used for %s, ignoring %s'
 
3600
                 % (key, actual, obj))
3655
3601
 
3656
3602
    def resolve_alias(self, id_start):
3657
3603
        """Replace the alias by the prefix in the given string.
3802
3748
        'bzrlib.tests.test_merge3',
3803
3749
        'bzrlib.tests.test_merge_core',
3804
3750
        'bzrlib.tests.test_merge_directive',
3805
 
        'bzrlib.tests.test_mergetools',
3806
3751
        'bzrlib.tests.test_missing',
3807
3752
        'bzrlib.tests.test_msgeditor',
3808
3753
        'bzrlib.tests.test_multiparent',
3858
3803
        'bzrlib.tests.test_testament',
3859
3804
        'bzrlib.tests.test_textfile',
3860
3805
        'bzrlib.tests.test_textmerge',
3861
 
        'bzrlib.tests.test_cethread',
3862
3806
        'bzrlib.tests.test_timestamp',
3863
3807
        'bzrlib.tests.test_trace',
3864
3808
        'bzrlib.tests.test_transactions',
3967
3911
        try:
3968
3912
            # note that this really does mean "report only" -- doctest
3969
3913
            # still runs the rest of the examples
3970
 
            doc_suite = IsolatedDocTestSuite(
3971
 
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
3914
            doc_suite = doctest.DocTestSuite(mod,
 
3915
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
3972
3916
        except ValueError, e:
3973
3917
            print '**failed to get doctest for: %s\n%s' % (mod, e)
3974
3918
            raise
3977
3921
        suite.addTest(doc_suite)
3978
3922
 
3979
3923
    default_encoding = sys.getdefaultencoding()
3980
 
    for name, plugin in _mod_plugin.plugins().items():
 
3924
    for name, plugin in bzrlib.plugin.plugins().items():
3981
3925
        if not interesting_module(plugin.module.__name__):
3982
3926
            continue
3983
3927
        plugin_suite = plugin.test_suite()
3989
3933
        if plugin_suite is not None:
3990
3934
            suite.addTest(plugin_suite)
3991
3935
        if default_encoding != sys.getdefaultencoding():
3992
 
            trace.warning(
 
3936
            bzrlib.trace.warning(
3993
3937
                'Plugin "%s" tried to reset default encoding to: %s', name,
3994
3938
                sys.getdefaultencoding())
3995
3939
            reload(sys)
4010
3954
            # Some tests mentioned in the list are not in the test suite. The
4011
3955
            # list may be out of date, report to the tester.
4012
3956
            for id in not_found:
4013
 
                trace.warning('"%s" not found in the test suite', id)
 
3957
                bzrlib.trace.warning('"%s" not found in the test suite', id)
4014
3958
        for id in duplicates:
4015
 
            trace.warning('"%s" is used as an id by several tests', id)
 
3959
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
4016
3960
 
4017
3961
    return suite
4018
3962
 
4356
4300
        return self.module_name
4357
4301
 
4358
4302
 
 
4303
# This is kept here for compatibility, it is recommended to use
 
4304
# 'bzrlib.tests.feature.paramiko' instead
 
4305
ParamikoFeature = _CompatabilityThunkFeature(
 
4306
    deprecated_in((2,1,0)),
 
4307
    'bzrlib.tests.features', 'ParamikoFeature', 'paramiko')
 
4308
 
 
4309
 
4359
4310
def probe_unicode_in_user_encoding():
4360
4311
    """Try to encode several unicode strings to use in unicode-aware tests.
4361
4312
    Return first successfull match.
4548
4499
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
4549
4500
 
4550
4501
 
 
4502
# Kept for compatibility, use bzrlib.tests.features.subunit instead
 
4503
SubUnitFeature = _CompatabilityThunkFeature(
 
4504
    deprecated_in((2,1,0)),
 
4505
    'bzrlib.tests.features', 'SubUnitFeature', 'subunit')
4551
4506
# Only define SubUnitBzrRunner if subunit is available.
4552
4507
try:
4553
4508
    from subunit import TestProtocolClient