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
64
63
from bzrlib import (
68
commands as _mod_commands,
77
plugin as _mod_plugin,
84
77
transport as _mod_transport,
81
import bzrlib.commands
82
import bzrlib.timestamp
84
import bzrlib.inventory
85
import bzrlib.iterablefile
88
88
import bzrlib.lsprof
89
89
except ImportError:
90
90
# lsprof not available
92
from bzrlib.smart import client, request
92
from bzrlib.merge import merge_inner
95
from bzrlib.smart import client, request, server
97
from bzrlib import symbol_versioning
98
from bzrlib.symbol_versioning import (
93
106
from bzrlib.transport import (
110
from bzrlib.trace import mutter, note
97
111
from bzrlib.tests import (
123
139
TestSuite = TestUtil.TestSuite
124
140
TestLoader = TestUtil.TestLoader
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.
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
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
# This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
146
# as a base class instead of TestCaseInTempDir. Tests inheriting from
147
# TestCase should not use disk resources, BZR_LOG is one.
148
'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
149
'BZR_PLUGIN_PATH': None,
150
'BZR_DISABLE_PLUGINS': None,
151
'BZR_PLUGINS_AT': None,
152
'BZR_CONCURRENCY': None,
153
# Make sure that any text ui tests are consistent regardless of
154
# the environment the test case is run in; you may want tests that
155
# test other combinations. 'dumb' is a reasonable guess for tests
156
# going to a pipe or a StringIO.
162
'SSH_AUTH_SOCK': None,
172
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
173
# least. If you do (care), please update this comment
177
'BZR_REMOTE_PATH': None,
178
# Generally speaking, we don't want apport reporting on crashes in
179
# the test envirnoment unless we're specifically testing apport,
180
# so that it doesn't leak into the real system environment. We
181
# use an env var so it propagates to subprocesses.
182
'APPORT_DISABLE': '1',
186
def override_os_environ(test, env=None):
187
"""Modify os.environ keeping a copy.
189
:param test: A test instance
191
:param env: A dict containing variable definitions to be installed
194
env = isolated_environ
195
test._original_os_environ = dict([(var, value)
196
for var, value in os.environ.iteritems()])
197
for var, value in env.iteritems():
198
osutils.set_or_unset_env(var, value)
199
if var not in test._original_os_environ:
200
# The var is new, add it with a value of None, so
201
# restore_os_environ will delete it
202
test._original_os_environ[var] = None
205
def restore_os_environ(test):
206
"""Restore os.environ to its original state.
208
:param test: A test instance previously passed to override_os_environ.
210
for var, value in test._original_os_environ.iteritems():
211
# Restore the original value (or delete it if the value has been set to
212
# None in override_os_environ).
213
osutils.set_or_unset_env(var, value)
216
142
class ExtendedTestResult(testtools.TextTestResult):
217
143
"""Accepts, reports and accumulates the results of running tests.
356
280
what = re.sub(r'^bzrlib\.tests\.', '', what)
359
# GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
360
# multiple times in a row, because the handler is added for
361
# each test but the container list is shared between cases.
362
# See lp:498869 lp:625574 and lp:637725 for background.
363
def _record_traceback_from_test(self, exc_info):
364
"""Store the traceback from passed exc_info tuple till"""
365
self._traceback_from_test = exc_info[2]
367
283
def startTest(self, test):
368
284
super(ExtendedTestResult, self).startTest(test)
369
285
if self.count == 0:
372
288
self.report_test_start(test)
373
289
test.number = self.count
374
290
self._recordTestStartTime()
375
# Make testtools cases give us the real traceback on failure
376
addOnException = getattr(test, "addOnException", None)
377
if addOnException is not None:
378
addOnException(self._record_traceback_from_test)
379
# Only check for thread leaks on bzrlib derived test cases
380
if isinstance(test, TestCase):
381
test.addCleanup(self._check_leaked_threads, test)
383
def stopTest(self, test):
384
super(ExtendedTestResult, self).stopTest(test)
385
# Manually break cycles, means touching various private things but hey
386
getDetails = getattr(test, "getDetails", None)
387
if getDetails is not None:
389
type_equality_funcs = getattr(test, "_type_equality_funcs", None)
390
if type_equality_funcs is not None:
391
type_equality_funcs.clear()
392
self._traceback_from_test = None
291
# Only check for thread leaks if the test case supports cleanups
292
addCleanup = getattr(test, "addCleanup", None)
293
if addCleanup is not None:
294
addCleanup(self._check_leaked_threads, test)
394
296
def startTests(self):
395
297
self.report_tests_starting()
460
362
self.known_failure_count += 1
461
363
self.report_known_failure(test, err)
463
def addUnexpectedSuccess(self, test, details=None):
464
"""Tell result the test unexpectedly passed, counting as a failure
466
When the minimum version of testtools required becomes 0.9.8 this
467
can be updated to use the new handling there.
469
super(ExtendedTestResult, self).addFailure(test, details=details)
470
self.failure_count += 1
471
self.report_unexpected_success(test,
472
"".join(details["reason"].iter_text()))
476
365
def addNotSupported(self, test, feature):
477
366
"""The test will not be run because of a missing feature.
701
582
% (self._testTimeString(test),
702
583
self._error_summary(err)))
704
def report_unexpected_success(self, test, reason):
705
self.stream.write(' FAIL %s\n%s: %s\n'
706
% (self._testTimeString(test),
707
"Unexpected success. Should have failed",
710
585
def report_success(self, test):
711
586
self.stream.write(' OK %s\n' % self._testTimeString(test))
712
587
for bench_called, stats in getattr(test, '_benchcalls', []):
918
790
return NullProgressView()
921
def isolated_doctest_setUp(test):
922
override_os_environ(test)
925
def isolated_doctest_tearDown(test):
926
restore_os_environ(test)
929
def IsolatedDocTestSuite(*args, **kwargs):
930
"""Overrides doctest.DocTestSuite to handle isolation.
932
The method is really a factory and users are expected to use it as such.
935
kwargs['setUp'] = isolated_doctest_setUp
936
kwargs['tearDown'] = isolated_doctest_tearDown
937
return doctest.DocTestSuite(*args, **kwargs)
940
793
class TestCase(testtools.TestCase):
941
794
"""Base class for bzr unit tests.
983
840
self._track_transports()
984
841
self._track_locks()
985
842
self._clear_debug_flags()
986
# Isolate global verbosity level, to make sure it's reproducible
987
# between tests. We should get rid of this altogether: bug 656694. --
989
self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
990
# Isolate config option expansion until its default value for bzrlib is
991
# settled on or a the FIXME associated with _get_expand_default_value
992
# is addressed -- vila 20110219
993
self.overrideAttr(config, '_expand_default_value', None)
994
self._log_files = set()
995
# Each key in the ``_counters`` dict holds a value for a different
996
# counter. When the test ends, addDetail() should be used to output the
997
# counter values. This happens in install_counter_hook().
999
if 'config_stats' in selftest_debug_flags:
1000
self._install_config_stats_hooks()
1002
844
def debug(self):
1003
845
# debug a frame up.
1005
847
pdb.Pdb().set_trace(sys._getframe().f_back)
1007
def discardDetail(self, name):
1008
"""Extend the addDetail, getDetails api so we can remove a detail.
1010
eg. bzr always adds the 'log' detail at startup, but we don't want to
1011
include it for skipped, xfail, etc tests.
1013
It is safe to call this for a detail that doesn't exist, in case this
1014
gets called multiple times.
1016
# We cheat. details is stored in __details which means we shouldn't
1017
# touch it. but getDetails() returns the dict directly, so we can
1019
details = self.getDetails()
1023
def install_counter_hook(self, hooks, name, counter_name=None):
1024
"""Install a counting hook.
1026
Any hook can be counted as long as it doesn't need to return a value.
1028
:param hooks: Where the hook should be installed.
1030
:param name: The hook name that will be counted.
1032
:param counter_name: The counter identifier in ``_counters``, defaults
1035
_counters = self._counters # Avoid closing over self
1036
if counter_name is None:
1038
if _counters.has_key(counter_name):
1039
raise AssertionError('%s is already used as a counter name'
1041
_counters[counter_name] = 0
1042
self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1043
lambda: ['%d' % (_counters[counter_name],)]))
1044
def increment_counter(*args, **kwargs):
1045
_counters[counter_name] += 1
1046
label = 'count %s calls' % (counter_name,)
1047
hooks.install_named_hook(name, increment_counter, label)
1048
self.addCleanup(hooks.uninstall_named_hook, name, label)
1050
def _install_config_stats_hooks(self):
1051
"""Install config hooks to count hook calls.
1054
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1055
self.install_counter_hook(config.ConfigHooks, hook_name,
1056
'config.%s' % (hook_name,))
1058
# The OldConfigHooks are private and need special handling to protect
1059
# against recursive tests (tests that run other tests), so we just do
1060
# manually what registering them into _builtin_known_hooks will provide
1062
self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1063
for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1064
self.install_counter_hook(config.OldConfigHooks, hook_name,
1065
'old_config.%s' % (hook_name,))
1067
849
def _clear_debug_flags(self):
1068
850
"""Prevent externally set debug flags affecting tests.
1080
862
def _clear_hooks(self):
1081
863
# prevent hooks affecting tests
1082
known_hooks = hooks.known_hooks
1083
864
self._preserved_hooks = {}
1084
for key, (parent, name) in known_hooks.iter_parent_objects():
1085
current_hooks = getattr(parent, name)
865
for key, factory in hooks.known_hooks.items():
866
parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
867
current_hooks = hooks.known_hooks_key_to_object(key)
1086
868
self._preserved_hooks[parent] = (name, current_hooks)
1087
self._preserved_lazy_hooks = hooks._lazy_hooks
1088
hooks._lazy_hooks = {}
1089
869
self.addCleanup(self._restoreHooks)
1090
for key, (parent, name) in known_hooks.iter_parent_objects():
1091
factory = known_hooks.get(key)
870
for key, factory in hooks.known_hooks.items():
871
parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
1092
872
setattr(parent, name, factory())
1093
873
# this hook should always be installed
1094
874
request._install_hook()
1123
903
# break some locks on purpose and should be taken into account by
1124
904
# considering that breaking a lock is just a dirty way of releasing it.
1125
905
if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1127
'Different number of acquired and '
1128
'released or broken locks.\n'
1132
(acquired_locks, released_locks, broken_locks))
906
message = ('Different number of acquired and '
907
'released or broken locks. (%s, %s + %s)' %
908
(acquired_locks, released_locks, broken_locks))
1133
909
if not self._lock_check_thorough:
1134
910
# Rather than fail, just warn
1135
911
print "Broken test %s: %s" % (self, message)
1355
1131
'st_mtime did not match')
1356
1132
self.assertEqual(expected.st_ctime, actual.st_ctime,
1357
1133
'st_ctime did not match')
1358
if sys.platform == 'win32':
1134
if sys.platform != 'win32':
1359
1135
# On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
1360
1136
# is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
1361
# odd. We just force it to always be 0 to avoid any problems.
1362
self.assertEqual(0, expected.st_dev)
1363
self.assertEqual(0, actual.st_dev)
1364
self.assertEqual(0, expected.st_ino)
1365
self.assertEqual(0, actual.st_ino)
1137
# odd. Regardless we shouldn't actually try to assert anything
1138
# about their values
1367
1139
self.assertEqual(expected.st_dev, actual.st_dev,
1368
1140
'st_dev did not match')
1369
1141
self.assertEqual(expected.st_ino, actual.st_ino,
1378
1150
length, len(obj_with_len), obj_with_len))
1380
1152
def assertLogsError(self, exception_class, func, *args, **kwargs):
1381
"""Assert that `func(*args, **kwargs)` quietly logs a specific error.
1153
"""Assert that func(*args, **kwargs) quietly logs a specific exception.
1155
from bzrlib import trace
1384
1157
orig_log_exception_quietly = trace.log_exception_quietly
1387
1160
orig_log_exception_quietly()
1388
captured.append(sys.exc_info()[1])
1161
captured.append(sys.exc_info())
1389
1162
trace.log_exception_quietly = capture
1390
1163
func(*args, **kwargs)
1392
1165
trace.log_exception_quietly = orig_log_exception_quietly
1393
1166
self.assertLength(1, captured)
1167
err = captured[0][1]
1395
1168
self.assertIsInstance(err, exception_class)
1549
1318
self.assertEqual(expected_docstring, obj.__doc__)
1551
@symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1552
1320
def failUnlessExists(self, path):
1553
return self.assertPathExists(path)
1555
def assertPathExists(self, path):
1556
1321
"""Fail unless path or paths, which may be abs or relative, exist."""
1557
1322
if not isinstance(path, basestring):
1559
self.assertPathExists(p)
1324
self.failUnlessExists(p)
1561
self.assertTrue(osutils.lexists(path),
1562
path + " does not exist")
1326
self.failUnless(osutils.lexists(path),path+" does not exist")
1564
@symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1565
1328
def failIfExists(self, path):
1566
return self.assertPathDoesNotExist(path)
1568
def assertPathDoesNotExist(self, path):
1569
1329
"""Fail if path or paths, which may be abs or relative, exist."""
1570
1330
if not isinstance(path, basestring):
1572
self.assertPathDoesNotExist(p)
1332
self.failIfExists(p)
1574
self.assertFalse(osutils.lexists(path),
1334
self.failIf(osutils.lexists(path),path+" exists")
1577
1336
def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1578
1337
"""A helper for callDeprecated and applyDeprecated.
1694
1452
The file is removed as the test is torn down.
1696
pseudo_log_file = StringIO()
1697
def _get_log_contents_for_weird_testtools_api():
1698
return [pseudo_log_file.getvalue().decode(
1699
"utf-8", "replace").encode("utf-8")]
1700
self.addDetail("log", content.Content(content.ContentType("text",
1701
"plain", {"charset": "utf8"}),
1702
_get_log_contents_for_weird_testtools_api))
1703
self._log_file = pseudo_log_file
1704
self._log_memento = trace.push_log_file(self._log_file)
1454
self._log_file = StringIO()
1455
self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1705
1456
self.addCleanup(self._finishLogFile)
1707
1458
def _finishLogFile(self):
1708
1459
"""Finished with the log file.
1710
Close the file and delete it.
1461
Close the file and delete it, unless setKeepLogfile was called.
1712
if trace._trace_file:
1463
if bzrlib.trace._trace_file:
1713
1464
# flush the log file, to get all content
1714
trace._trace_file.flush()
1715
trace.pop_log_file(self._log_memento)
1465
bzrlib.trace._trace_file.flush()
1466
bzrlib.trace.pop_log_file(self._log_memento)
1467
# Cache the log result and delete the file on disk
1468
self._get_log(False)
1717
1470
def thisFailsStrictLockCheck(self):
1718
1471
"""It is known that this test would fail with -Dstrict_locks.
1746
1499
setattr(obj, attr_name, new)
1749
def overrideEnv(self, name, new):
1750
"""Set an environment variable, and reset it after the test.
1752
:param name: The environment variable name.
1754
:param new: The value to set the variable to. If None, the
1755
variable is deleted from the environment.
1757
:returns: The actual variable value.
1759
value = osutils.set_or_unset_env(name, new)
1760
self.addCleanup(osutils.set_or_unset_env, name, value)
1763
1502
def _cleanEnvironment(self):
1764
for name, value in isolated_environ.iteritems():
1765
self.overrideEnv(name, value)
1504
'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1505
'HOME': os.getcwd(),
1506
# bzr now uses the Win32 API and doesn't rely on APPDATA, but the
1507
# tests do check our impls match APPDATA
1508
'BZR_EDITOR': None, # test_msgeditor manipulates this variable
1512
'BZREMAIL': None, # may still be present in the environment
1513
'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
1514
'BZR_PROGRESS_BAR': None,
1516
'BZR_PLUGIN_PATH': None,
1517
'BZR_DISABLE_PLUGINS': None,
1518
'BZR_PLUGINS_AT': None,
1519
'BZR_CONCURRENCY': None,
1520
# Make sure that any text ui tests are consistent regardless of
1521
# the environment the test case is run in; you may want tests that
1522
# test other combinations. 'dumb' is a reasonable guess for tests
1523
# going to a pipe or a StringIO.
1527
'BZR_COLUMNS': '80',
1529
'SSH_AUTH_SOCK': None,
1533
'https_proxy': None,
1534
'HTTPS_PROXY': None,
1539
# Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
1540
# least. If you do (care), please update this comment
1544
'BZR_REMOTE_PATH': None,
1545
# Generally speaking, we don't want apport reporting on crashes in
1546
# the test envirnoment unless we're specifically testing apport,
1547
# so that it doesn't leak into the real system environment. We
1548
# use an env var so it propagates to subprocesses.
1549
'APPORT_DISABLE': '1',
1552
self.addCleanup(self._restoreEnvironment)
1553
for name, value in new_env.iteritems():
1554
self._captureVar(name, value)
1556
def _captureVar(self, name, newvalue):
1557
"""Set an environment variable, and reset it when finished."""
1558
self._old_env[name] = osutils.set_or_unset_env(name, newvalue)
1560
def _restoreEnvironment(self):
1561
for name, value in self._old_env.iteritems():
1562
osutils.set_or_unset_env(name, value)
1767
1564
def _restoreHooks(self):
1768
1565
for klass, (name, hooks) in self._preserved_hooks.items():
1769
1566
setattr(klass, name, hooks)
1770
self._preserved_hooks.clear()
1771
bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1772
self._preserved_lazy_hooks.clear()
1774
1568
def knownFailure(self, reason):
1775
1569
"""This test has failed for some known reason."""
1776
1570
raise KnownFailure(reason)
1778
def _suppress_log(self):
1779
"""Remove the log info from details."""
1780
self.discardDetail('log')
1782
1572
def _do_skip(self, result, reason):
1783
self._suppress_log()
1784
1573
addSkip = getattr(result, 'addSkip', None)
1785
1574
if not callable(addSkip):
1786
1575
result.addSuccess(result)
1811
1598
self._do_skip(result, reason)
1814
def _report_skip(self, result, err):
1815
"""Override the default _report_skip.
1817
We want to strip the 'log' detail. If we waint until _do_skip, it has
1818
already been formatted into the 'reason' string, and we can't pull it
1821
self._suppress_log()
1822
super(TestCase, self)._report_skip(self, result, err)
1825
def _report_expected_failure(self, result, err):
1828
See _report_skip for motivation.
1830
self._suppress_log()
1831
super(TestCase, self)._report_expected_failure(self, result, err)
1834
1601
def _do_unsupported_or_skip(self, result, e):
1835
1602
reason = e.args[0]
1836
self._suppress_log()
1837
1603
addNotSupported = getattr(result, 'addNotSupported', None)
1838
1604
if addNotSupported is not None:
1839
1605
result.addNotSupported(self, reason)
1865
1631
self._benchtime += time.time() - start
1867
1633
def log(self, *args):
1636
def _get_log(self, keep_log_file=False):
1637
"""Internal helper to get the log from bzrlib.trace for this test.
1639
Please use self.getDetails, or self.get_log to access this in test case
1642
:param keep_log_file: When True, if the log is still a file on disk
1643
leave it as a file on disk. When False, if the log is still a file
1644
on disk, the log file is deleted and the log preserved as
1646
:return: A string containing the log.
1648
if self._log_contents is not None:
1650
self._log_contents.decode('utf8')
1651
except UnicodeDecodeError:
1652
unicodestr = self._log_contents.decode('utf8', 'replace')
1653
self._log_contents = unicodestr.encode('utf8')
1654
return self._log_contents
1655
if self._log_file is not None:
1656
log_contents = self._log_file.getvalue()
1658
log_contents.decode('utf8')
1659
except UnicodeDecodeError:
1660
unicodestr = log_contents.decode('utf8', 'replace')
1661
log_contents = unicodestr.encode('utf8')
1662
if not keep_log_file:
1663
self._log_file = None
1664
# Permit multiple calls to get_log until we clean it up in
1666
self._log_contents = log_contents
1669
return "No log file content."
1870
1671
def get_log(self):
1871
1672
"""Get a unicode string containing the log from bzrlib.trace.
2147
def _add_subprocess_log(self, log_file_path):
2148
if len(self._log_files) == 0:
2149
# Register an addCleanup func. We do this on the first call to
2150
# _add_subprocess_log rather than in TestCase.setUp so that this
2151
# addCleanup is registered after any cleanups for tempdirs that
2152
# subclasses might create, which will probably remove the log file
2154
self.addCleanup(self._subprocess_log_cleanup)
2155
# self._log_files is a set, so if a log file is reused we won't grab it
2157
self._log_files.add(log_file_path)
2159
def _subprocess_log_cleanup(self):
2160
for count, log_file_path in enumerate(self._log_files):
2161
# We use buffer_now=True to avoid holding the file open beyond
2162
# the life of this function, which might interfere with e.g.
2163
# cleaning tempdirs on Windows.
2164
# XXX: Testtools 0.9.5 doesn't have the content_from_file helper
2165
#detail_content = content.content_from_file(
2166
# log_file_path, buffer_now=True)
2167
with open(log_file_path, 'rb') as log_file:
2168
log_file_bytes = log_file.read()
2169
detail_content = content.Content(content.ContentType("text",
2170
"plain", {"charset": "utf8"}), lambda: [log_file_bytes])
2171
self.addDetail("start_bzr_subprocess-log-%d" % (count,),
2174
1941
def _popen(self, *args, **kwargs):
2175
1942
"""Place a call to Popen.
2213
1980
if retcode is not None and retcode != process.returncode:
2214
1981
if process_args is None:
2215
1982
process_args = "(unknown args)"
2216
trace.mutter('Output of bzr %s:\n%s', process_args, out)
2217
trace.mutter('Error for bzr %s:\n%s', process_args, err)
1983
mutter('Output of bzr %s:\n%s', process_args, out)
1984
mutter('Error for bzr %s:\n%s', process_args, err)
2218
1985
self.fail('Command bzr %s failed with retcode %s != %s'
2219
1986
% (process_args, retcode, process.returncode))
2220
1987
return [out, err]
2222
def check_tree_shape(self, tree, shape):
2223
"""Compare a tree to a list of expected names.
1989
def check_inventory_shape(self, inv, shape):
1990
"""Compare an inventory to a list of expected names.
2225
1992
Fail if they are not precisely equal.
2228
1995
shape = list(shape) # copy
2229
for path, ie in tree.iter_entries_by_dir():
1996
for path, ie in inv.entries():
2230
1997
name = path.replace('\\', '/')
2231
1998
if ie.kind == 'directory':
2232
1999
name = name + '/'
2234
pass # ignore root entry
2236
2001
shape.remove(name)
2238
2003
extras.append(name)
2328
2093
class TestCaseWithMemoryTransport(TestCase):
2329
2094
"""Common test class for tests that do not need disk resources.
2331
Tests that need disk resources should derive from TestCaseInTempDir
2332
orTestCaseWithTransport.
2096
Tests that need disk resources should derive from TestCaseWithTransport.
2334
2098
TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
2336
For TestCaseWithMemoryTransport the ``test_home_dir`` is set to the name of
2100
For TestCaseWithMemoryTransport the test_home_dir is set to the name of
2337
2101
a directory which does not exist. This serves to help ensure test isolation
2338
is preserved. ``test_dir`` is set to the TEST_ROOT, as is cwd, because they
2339
must exist. However, TestCaseWithMemoryTransport does not offer local file
2340
defaults for the transport in tests, nor does it obey the command line
2102
is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
2103
must exist. However, TestCaseWithMemoryTransport does not offer local
2104
file defaults for the transport in tests, nor does it obey the command line
2341
2105
override, so tests that accidentally write to the common directory should
2344
:cvar TEST_ROOT: Directory containing all temporary directories, plus a
2345
``.bzr`` directory that stops us ascending higher into the filesystem.
2108
:cvar TEST_ROOT: Directory containing all temporary directories, plus
2109
a .bzr directory that stops us ascending higher into the filesystem.
2348
2112
TEST_ROOT = None
3532
class ProfileResult(testtools.ExtendedToOriginalDecorator):
3290
class ForwardingResult(unittest.TestResult):
3292
def __init__(self, target):
3293
unittest.TestResult.__init__(self)
3294
self.result = target
3296
def startTest(self, test):
3297
self.result.startTest(test)
3299
def stopTest(self, test):
3300
self.result.stopTest(test)
3302
def startTestRun(self):
3303
self.result.startTestRun()
3305
def stopTestRun(self):
3306
self.result.stopTestRun()
3308
def addSkip(self, test, reason):
3309
self.result.addSkip(test, reason)
3311
def addSuccess(self, test):
3312
self.result.addSuccess(test)
3314
def addError(self, test, err):
3315
self.result.addError(test, err)
3317
def addFailure(self, test, err):
3318
self.result.addFailure(test, err)
3319
ForwardingResult = testtools.ExtendedToOriginalDecorator
3322
class ProfileResult(ForwardingResult):
3533
3323
"""Generate profiling data for all activity between start and success.
3535
3325
The profile data is appended to the test's _benchcalls attribute and can
3873
3659
'bzrlib.tests.test_commit_merge',
3874
3660
'bzrlib.tests.test_config',
3875
3661
'bzrlib.tests.test_conflicts',
3876
'bzrlib.tests.test_controldir',
3877
3662
'bzrlib.tests.test_counted_lock',
3878
3663
'bzrlib.tests.test_crash',
3879
3664
'bzrlib.tests.test_decorators',
3880
3665
'bzrlib.tests.test_delta',
3881
3666
'bzrlib.tests.test_debug',
3667
'bzrlib.tests.test_deprecated_graph',
3882
3668
'bzrlib.tests.test_diff',
3883
3669
'bzrlib.tests.test_directory_service',
3884
3670
'bzrlib.tests.test_dirstate',
4139
3917
# Some tests mentioned in the list are not in the test suite. The
4140
3918
# list may be out of date, report to the tester.
4141
3919
for id in not_found:
4142
trace.warning('"%s" not found in the test suite', id)
3920
bzrlib.trace.warning('"%s" not found in the test suite', id)
4143
3921
for id in duplicates:
4144
trace.warning('"%s" is used as an id by several tests', id)
3922
bzrlib.trace.warning('"%s" is used as an id by several tests', id)
4149
def multiply_scenarios(*scenarios):
4150
"""Multiply two or more iterables of scenarios.
4152
It is safe to pass scenario generators or iterators.
4154
:returns: A list of compound scenarios: the cross-product of all
4155
scenarios, with the names concatenated and the parameters
4158
return reduce(_multiply_two_scenarios, map(list, scenarios))
4161
def _multiply_two_scenarios(scenarios_left, scenarios_right):
3927
def multiply_scenarios(scenarios_left, scenarios_right):
4162
3928
"""Multiply two sets of scenarios.
4164
3930
:returns: the cartesian product of the two sets of scenarios, that is
4677
4439
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
4442
# Kept for compatibility, use bzrlib.tests.features.subunit instead
4443
SubUnitFeature = _CompatabilityThunkFeature(
4444
deprecated_in((2,1,0)),
4445
'bzrlib.tests.features', 'SubUnitFeature', 'subunit')
4680
4446
# Only define SubUnitBzrRunner if subunit is available.
4682
4448
from subunit import TestProtocolClient
4683
4449
from subunit.test_results import AutoTimingTestResultDecorator
4684
class SubUnitBzrProtocolClient(TestProtocolClient):
4686
def addSuccess(self, test, details=None):
4687
# The subunit client always includes the details in the subunit
4688
# stream, but we don't want to include it in ours.
4689
if details is not None and 'log' in details:
4691
return super(SubUnitBzrProtocolClient, self).addSuccess(
4694
4450
class SubUnitBzrRunner(TextTestRunner):
4695
4451
def run(self, test):
4696
4452
result = AutoTimingTestResultDecorator(
4697
SubUnitBzrProtocolClient(self.stream))
4453
TestProtocolClient(self.stream))
4698
4454
test.run(result)
4700
4456
except ImportError: