21
21
# little as possible, so this should be used rarely if it's added at all.
22
22
# (Suggestion from j-a-meinel, 2005-11-24)
24
# NOTE: Some classes in here use camelCaseNaming() rather than
25
# underscore_naming(). That's for consistency with unittest; it's not the
26
# general style of bzrlib. Please continue that consistency when adding e.g.
27
# new assertFoo() methods.
30
24
from cStringIO import StringIO
39
from subprocess import Popen, PIPE
55
38
import bzrlib.branch
56
39
import bzrlib.commands
57
import bzrlib.bundle.serializer
40
from bzrlib.errors import (BzrError,
42
UninitializableFormat,
59
44
import bzrlib.inventory
60
45
import bzrlib.iterablefile
65
# lsprof not available
67
from bzrlib.merge import merge_inner
68
46
import bzrlib.merge3
69
47
import bzrlib.osutils
48
import bzrlib.osutils as osutils
70
49
import bzrlib.plugin
71
from bzrlib.revision import common_ancestor
72
50
import bzrlib.store
73
from bzrlib import symbol_versioning
74
51
import bzrlib.trace
75
from bzrlib.transport import get_transport
52
from bzrlib.transport import urlescape
76
53
import bzrlib.transport
77
from bzrlib.transport.local import LocalURLServer
78
from bzrlib.transport.memory import MemoryServer
54
from bzrlib.transport.local import LocalRelpathServer
79
55
from bzrlib.transport.readonly import ReadonlyServer
80
from bzrlib.trace import mutter, note
81
from bzrlib.tests import TestUtil
82
from bzrlib.tests.HttpServer import HttpServer
83
from bzrlib.tests.TestUtil import (
56
from bzrlib.trace import mutter
57
from bzrlib.tests.TestUtil import TestLoader, TestSuite
87
58
from bzrlib.tests.treeshape import build_tree_contents
88
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
59
from bzrlib.workingtree import WorkingTree
90
default_transport = LocalURLServer
61
default_transport = LocalRelpathServer
92
63
MODULES_TO_TEST = []
93
64
MODULES_TO_DOCTEST = [
94
bzrlib.bundle.serializer,
98
69
bzrlib.iterablefile,
106
75
def packages_to_test():
107
76
"""Return a list of packages to test.
113
82
import bzrlib.tests.blackbox
114
83
import bzrlib.tests.branch_implementations
115
import bzrlib.tests.bzrdir_implementations
116
import bzrlib.tests.interrepository_implementations
117
import bzrlib.tests.interversionedfile_implementations
118
import bzrlib.tests.intertree_implementations
119
import bzrlib.tests.repository_implementations
120
import bzrlib.tests.revisionstore_implementations
121
import bzrlib.tests.tree_implementations
122
import bzrlib.tests.workingtree_implementations
125
bzrlib.tests.blackbox,
126
86
bzrlib.tests.branch_implementations,
127
bzrlib.tests.bzrdir_implementations,
128
bzrlib.tests.interrepository_implementations,
129
bzrlib.tests.interversionedfile_implementations,
130
bzrlib.tests.intertree_implementations,
131
bzrlib.tests.repository_implementations,
132
bzrlib.tests.revisionstore_implementations,
133
bzrlib.tests.tree_implementations,
134
bzrlib.tests.workingtree_implementations,
138
class ExtendedTestResult(unittest._TextTestResult):
139
"""Accepts, reports and accumulates the results of running tests.
90
class _MyResult(unittest._TextTestResult):
141
Compared to this unittest version this class adds support for profiling,
142
benchmarking, stopping as soon as a test fails, and skipping tests.
143
There are further-specialized subclasses for different types of display.
93
Shows output in a different format, including displaying runtime for tests.
146
95
stop_early = False
148
def __init__(self, stream, descriptions, verbosity,
152
"""Construct new TestResult.
154
:param bench_history: Optionally, a writable file object to accumulate
157
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
158
if bench_history is not None:
159
from bzrlib.version import _get_bzr_source_tree
160
src_tree = _get_bzr_source_tree()
163
revision_id = src_tree.get_parent_ids()[0]
165
# XXX: if this is a brand new tree, do the same as if there
169
# XXX: If there's no branch, what should we do?
171
bench_history.write("--date %s %s\n" % (time.time(), revision_id))
172
self._bench_history = bench_history
173
self.ui = bzrlib.ui.ui_factory
174
self.num_tests = num_tests
176
self.failure_count = 0
179
self._overall_start_time = time.time()
181
def extractBenchmarkTime(self, testCase):
182
"""Add a benchmark time for the current test case."""
183
self._benchmarkTime = getattr(testCase, "_benchtime", None)
185
def _elapsedTestTimeString(self):
186
"""Return a time string for the overall time the current test has taken."""
187
return self._formatTime(time.time() - self._start_time)
189
def _testTimeString(self):
190
if self._benchmarkTime is not None:
192
self._formatTime(self._benchmarkTime),
193
self._elapsedTestTimeString())
195
return " %s" % self._elapsedTestTimeString()
197
def _formatTime(self, seconds):
198
"""Format seconds as milliseconds with leading spaces."""
199
# some benchmarks can take thousands of seconds to run, so we need 8
201
return "%8dms" % (1000 * seconds)
203
def _shortened_test_description(self, test):
205
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
97
def _elapsedTime(self):
98
return "%5dms" % (1000 * (time.time() - self._start_time))
208
100
def startTest(self, test):
209
101
unittest.TestResult.startTest(self, test)
210
self.report_test_start(test)
211
self._recordTestStartTime()
213
def _recordTestStartTime(self):
214
"""Record that a test has started."""
102
# In a short description, the important words are in
103
# the beginning, but in an id, the important words are
105
SHOW_DESCRIPTIONS = False
107
width = osutils.terminal_width()
108
name_width = width - 15
110
if SHOW_DESCRIPTIONS:
111
what = test.shortDescription()
113
if len(what) > name_width:
114
what = what[:name_width-3] + '...'
117
if what.startswith('bzrlib.tests.'):
119
if len(what) > name_width:
120
what = '...' + what[3-name_width:]
121
what = what.ljust(name_width)
122
self.stream.write(what)
215
124
self._start_time = time.time()
217
126
def addError(self, test, err):
218
127
if isinstance(err[1], TestSkipped):
219
128
return self.addSkipped(test, err)
220
129
unittest.TestResult.addError(self, test, err)
221
# We can only do this if we have one of our TestCases, not if
223
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
224
if setKeepLogfile is not None:
226
self.extractBenchmarkTime(test)
227
self.report_error(test, err)
131
self.stream.writeln("ERROR %s" % self._elapsedTime())
133
self.stream.write('E')
228
135
if self.stop_early:
231
138
def addFailure(self, test, err):
232
139
unittest.TestResult.addFailure(self, test, err)
233
# We can only do this if we have one of our TestCases, not if
235
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
236
if setKeepLogfile is not None:
238
self.extractBenchmarkTime(test)
239
self.report_failure(test, err)
141
self.stream.writeln(" FAIL %s" % self._elapsedTime())
143
self.stream.write('F')
240
145
if self.stop_early:
243
148
def addSuccess(self, test):
244
self.extractBenchmarkTime(test)
245
if self._bench_history is not None:
246
if self._benchmarkTime is not None:
247
self._bench_history.write("%s %s\n" % (
248
self._formatTime(self._benchmarkTime),
250
self.report_success(test)
150
self.stream.writeln(' OK %s' % self._elapsedTime())
152
self.stream.write('~')
251
154
unittest.TestResult.addSuccess(self, test)
253
156
def addSkipped(self, test, skip_excinfo):
254
self.extractBenchmarkTime(test)
255
self.report_skip(test, skip_excinfo)
158
print >>self.stream, ' SKIP %s' % self._elapsedTime()
159
print >>self.stream, ' %s' % skip_excinfo[1]
161
self.stream.write('S')
256
163
# seems best to treat this as success from point-of-view of unittest
257
164
# -- it actually does nothing so it barely matters :)
260
except KeyboardInterrupt:
263
self.addError(test, test.__exc_info())
265
unittest.TestResult.addSuccess(self, test)
165
unittest.TestResult.addSuccess(self, test)
267
167
def printErrorList(self, flavour, errors):
268
168
for test, err in errors:
278
178
self.stream.writeln(self.separator2)
279
179
self.stream.writeln("%s" % err)
284
def report_cleaning_up(self):
287
def report_success(self, test):
291
class TextTestResult(ExtendedTestResult):
292
"""Displays progress and results of tests in text form"""
294
def __init__(self, *args, **kw):
295
ExtendedTestResult.__init__(self, *args, **kw)
296
self.pb = self.ui.nested_progress_bar()
297
self.pb.show_pct = False
298
self.pb.show_spinner = False
299
self.pb.show_eta = False,
300
self.pb.show_count = False
301
self.pb.show_bar = False
303
def report_starting(self):
304
self.pb.update('[test 0/%d] starting...' % (self.num_tests))
306
def _progress_prefix_text(self):
307
a = '[%d' % self.count
308
if self.num_tests is not None:
309
a +='/%d' % self.num_tests
310
a += ' in %ds' % (time.time() - self._overall_start_time)
312
a += ', %d errors' % self.error_count
313
if self.failure_count:
314
a += ', %d failed' % self.failure_count
316
a += ', %d skipped' % self.skip_count
320
def report_test_start(self, test):
323
self._progress_prefix_text()
325
+ self._shortened_test_description(test))
327
def report_error(self, test, err):
328
self.error_count += 1
329
self.pb.note('ERROR: %s\n %s\n',
330
self._shortened_test_description(test),
334
def report_failure(self, test, err):
335
self.failure_count += 1
336
self.pb.note('FAIL: %s\n %s\n',
337
self._shortened_test_description(test),
341
def report_skip(self, test, skip_excinfo):
344
# at the moment these are mostly not things we can fix
345
# and so they just produce stipple; use the verbose reporter
348
# show test and reason for skip
349
self.pb.note('SKIP: %s\n %s\n',
350
self._shortened_test_description(test),
353
# since the class name was left behind in the still-visible
355
self.pb.note('SKIP: %s', skip_excinfo[1])
357
def report_cleaning_up(self):
358
self.pb.update('cleaning up...')
364
class VerboseTestResult(ExtendedTestResult):
365
"""Produce long output, with one line per test run plus times"""
367
def _ellipsize_to_right(self, a_string, final_width):
368
"""Truncate and pad a string, keeping the right hand side"""
369
if len(a_string) > final_width:
370
result = '...' + a_string[3-final_width:]
373
return result.ljust(final_width)
375
def report_starting(self):
376
self.stream.write('running %d tests...\n' % self.num_tests)
378
def report_test_start(self, test):
380
name = self._shortened_test_description(test)
381
# width needs space for 6 char status, plus 1 for slash, plus 2 10-char
382
# numbers, plus a trailing blank
383
self.stream.write(self._ellipsize_to_right(name,
384
osutils.terminal_width()-30))
387
def report_error(self, test, err):
388
self.error_count += 1
389
self.stream.writeln('ERROR %s\n %s'
390
% (self._testTimeString(), err[1]))
392
def report_failure(self, test, err):
393
self.failure_count += 1
394
self.stream.writeln(' FAIL %s\n %s'
395
% (self._testTimeString(), err[1]))
397
def report_success(self, test):
398
self.stream.writeln(' OK %s' % self._testTimeString())
399
for bench_called, stats in getattr(test, '_benchcalls', []):
400
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
401
stats.pprint(file=self.stream)
404
def report_skip(self, test, skip_excinfo):
405
print >>self.stream, ' SKIP %s' % self._testTimeString()
406
print >>self.stream, ' %s' % skip_excinfo[1]
409
class TextTestRunner(object):
182
class TextTestRunner(unittest.TextTestRunner):
410
183
stop_on_failure = False
418
self.stream = unittest._WritelnDecorator(stream)
419
self.descriptions = descriptions
420
self.verbosity = verbosity
421
self.keep_output = keep_output
422
self._bench_history = bench_history
425
"Run the given test case or test suite."
426
startTime = time.time()
427
if self.verbosity == 1:
428
result_class = TextTestResult
429
elif self.verbosity >= 2:
430
result_class = VerboseTestResult
431
result = result_class(self.stream,
434
bench_history=self._bench_history,
435
num_tests=test.countTestCases(),
185
def _makeResult(self):
186
result = _MyResult(self.stream, self.descriptions, self.verbosity)
437
187
result.stop_early = self.stop_on_failure
438
result.report_starting()
440
stopTime = time.time()
441
timeTaken = stopTime - startTime
443
self.stream.writeln(result.separator2)
444
run = result.testsRun
445
self.stream.writeln("Ran %d test%s in %.3fs" %
446
(run, run != 1 and "s" or "", timeTaken))
447
self.stream.writeln()
448
if not result.wasSuccessful():
449
self.stream.write("FAILED (")
450
failed, errored = map(len, (result.failures, result.errors))
452
self.stream.write("failures=%d" % failed)
454
if failed: self.stream.write(", ")
455
self.stream.write("errors=%d" % errored)
456
self.stream.writeln(")")
458
self.stream.writeln("OK")
459
result.report_cleaning_up()
460
# This is still a little bogus,
461
# but only a little. Folk not using our testrunner will
462
# have to delete their temp directories themselves.
463
test_root = TestCaseWithMemoryTransport.TEST_ROOT
464
if result.wasSuccessful() or not self.keep_output:
465
if test_root is not None:
466
# If LANG=C we probably have created some bogus paths
467
# which rmtree(unicode) will fail to delete
468
# so make sure we are using rmtree(str) to delete everything
469
# except on win32, where rmtree(str) will fail
470
# since it doesn't have the property of byte-stream paths
471
# (they are either ascii or mbcs)
472
if sys.platform == 'win32':
473
# make sure we are using the unicode win32 api
474
test_root = unicode(test_root)
476
test_root = test_root.encode(
477
sys.getfilesystemencoding())
478
osutils.rmtree(test_root)
480
note("Failed tests working directories are in '%s'\n", test_root)
481
TestCaseWithMemoryTransport.TEST_ROOT = None
609
268
# TODO: perhaps override assertEquals to call this for strings?
613
message = "texts not equal:\n"
614
raise AssertionError(message +
271
raise AssertionError("texts not equal:\n" +
615
272
self._ndiff_strings(a, b))
617
def assertEqualMode(self, mode, mode_test):
618
self.assertEqual(mode, mode_test,
619
'mode mismatch %o != %o' % (mode, mode_test))
621
274
def assertStartsWith(self, s, prefix):
622
275
if not s.startswith(prefix):
623
276
raise AssertionError('string %r does not start with %r' % (s, prefix))
625
278
def assertEndsWith(self, s, suffix):
626
"""Asserts that s ends with suffix."""
627
if not s.endswith(suffix):
279
if not s.endswith(prefix):
628
280
raise AssertionError('string %r does not end with %r' % (s, suffix))
630
282
def assertContainsRe(self, haystack, needle_re):
631
283
"""Assert that a contains something matching a regular expression."""
632
284
if not re.search(needle_re, haystack):
633
raise AssertionError('pattern "%r" not found in "%r"'
634
% (needle_re, haystack))
636
def assertNotContainsRe(self, haystack, needle_re):
637
"""Assert that a does not match a regular expression"""
638
if re.search(needle_re, haystack):
639
raise AssertionError('pattern "%s" found in "%s"'
640
% (needle_re, haystack))
642
def assertSubset(self, sublist, superlist):
285
raise AssertionError('pattern "%s" not found in "%s"'
286
% (needle_re, haystack))
288
def AssertSubset(self, sublist, superlist):
643
289
"""Assert that every entry in sublist is present in superlist."""
645
291
for entry in sublist:
649
295
raise AssertionError("value(s) %r not present in container %r" %
650
296
(missing, superlist))
652
def assertListRaises(self, excClass, func, *args, **kwargs):
653
"""Fail unless excClass is raised when the iterator from func is used.
655
Many functions can return generators this makes sure
656
to wrap them in a list() call to make sure the whole generator
657
is run, and that the proper exception is raised.
660
list(func(*args, **kwargs))
664
if getattr(excClass,'__name__', None) is not None:
665
excName = excClass.__name__
667
excName = str(excClass)
668
raise self.failureException, "%s not raised" % excName
670
def assertIs(self, left, right, message=None):
298
def assertIs(self, left, right):
671
299
if not (left is right):
672
if message is not None:
673
raise AssertionError(message)
675
raise AssertionError("%r is not %r." % (left, right))
677
def assertIsNot(self, left, right, message=None):
679
if message is not None:
680
raise AssertionError(message)
682
raise AssertionError("%r is %r." % (left, right))
300
raise AssertionError("%r is not %r." % (left, right))
684
302
def assertTransportMode(self, transport, path, mode):
685
303
"""Fail if a path does not have mode mode.
687
If modes are not supported on this transport, the assertion is ignored.
305
If modes are not supported on this platform, the test is skipped.
689
if not transport._can_roundtrip_unix_modebits():
307
if sys.platform == 'win32':
691
309
path_stat = transport.stat(path)
692
310
actual_mode = stat.S_IMODE(path_stat.st_mode)
693
311
self.assertEqual(mode, actual_mode,
694
312
'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
696
def assertIsInstance(self, obj, kls):
697
"""Fail if obj is not an instance of kls"""
698
if not isinstance(obj, kls):
699
self.fail("%r is an instance of %s rather than %s" % (
700
obj, obj.__class__, kls))
702
def _capture_warnings(self, a_callable, *args, **kwargs):
703
"""A helper for callDeprecated and applyDeprecated.
705
:param a_callable: A callable to call.
706
:param args: The positional arguments for the callable
707
:param kwargs: The keyword arguments for the callable
708
:return: A tuple (warnings, result). result is the result of calling
709
a_callable(*args, **kwargs).
712
def capture_warnings(msg, cls=None, stacklevel=None):
713
# we've hooked into a deprecation specific callpath,
714
# only deprecations should getting sent via it.
715
self.assertEqual(cls, DeprecationWarning)
716
local_warnings.append(msg)
717
original_warning_method = symbol_versioning.warn
718
symbol_versioning.set_warning_method(capture_warnings)
720
result = a_callable(*args, **kwargs)
722
symbol_versioning.set_warning_method(original_warning_method)
723
return (local_warnings, result)
725
def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
726
"""Call a deprecated callable without warning the user.
728
:param deprecation_format: The deprecation format that the callable
729
should have been deprecated with. This is the same type as the
730
parameter to deprecated_method/deprecated_function. If the
731
callable is not deprecated with this format, an assertion error
733
:param a_callable: A callable to call. This may be a bound method or
734
a regular function. It will be called with *args and **kwargs.
735
:param args: The positional arguments for the callable
736
:param kwargs: The keyword arguments for the callable
737
:return: The result of a_callable(*args, **kwargs)
739
call_warnings, result = self._capture_warnings(a_callable,
741
expected_first_warning = symbol_versioning.deprecation_string(
742
a_callable, deprecation_format)
743
if len(call_warnings) == 0:
744
self.fail("No assertion generated by call to %s" %
746
self.assertEqual(expected_first_warning, call_warnings[0])
749
def callDeprecated(self, expected, callable, *args, **kwargs):
750
"""Assert that a callable is deprecated in a particular way.
752
This is a very precise test for unusual requirements. The
753
applyDeprecated helper function is probably more suited for most tests
754
as it allows you to simply specify the deprecation format being used
755
and will ensure that that is issued for the function being called.
757
:param expected: a list of the deprecation warnings expected, in order
758
:param callable: The callable to call
759
:param args: The positional arguments for the callable
760
:param kwargs: The keyword arguments for the callable
762
call_warnings, result = self._capture_warnings(callable,
764
self.assertEqual(expected, call_warnings)
767
314
def _startLogFile(self):
768
315
"""Send bzr and test log messages to a temporary file.
770
317
The file is removed as the test is torn down.
772
319
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
773
self._log_file = os.fdopen(fileno, 'w+')
320
encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
321
self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
774
322
self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
775
323
self._log_file_name = name
776
324
self.addCleanup(self._finishLogFile)
807
349
def _cleanEnvironment(self):
809
'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
810
351
'HOME': os.getcwd(),
811
352
'APPDATA': os.getcwd(),
813
'BZREMAIL': None, # may still be present in the environment
815
'BZR_PROGRESS_BAR': None,
825
# Nobody cares about these ones AFAIK. So far at
826
# least. If you do (care), please update this comment
831
356
self.__old_env = {}
832
357
self.addCleanup(self._restoreEnvironment)
833
358
for name, value in new_env.iteritems():
834
359
self._captureVar(name, value)
836
362
def _captureVar(self, name, newvalue):
837
"""Set an environment variable, and reset it when finished."""
838
self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
363
"""Set an environment variable, preparing it to be reset when finished."""
364
self.__old_env[name] = os.environ.get(name, None)
366
if name in os.environ:
369
os.environ[name] = newvalue
372
def _restoreVar(name, value):
374
if name in os.environ:
377
os.environ[name] = value
840
379
def _restoreEnvironment(self):
841
380
for name, value in self.__old_env.iteritems():
842
osutils.set_or_unset_env(name, value)
844
def _restoreHooks(self):
845
bzrlib.branch.Branch.hooks = self._preserved_hooks
381
self._restoreVar(name, value)
847
383
def tearDown(self):
848
384
self._runCleanups()
849
385
unittest.TestCase.tearDown(self)
851
def time(self, callable, *args, **kwargs):
852
"""Run callable and accrue the time it takes to the benchmark time.
854
If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
855
this will cause lsprofile statistics to be gathered and stored in
858
if self._benchtime is None:
862
if not self._gather_lsprof_in_benchmarks:
863
return callable(*args, **kwargs)
865
# record this benchmark
866
ret, stats = bzrlib.lsprof.profile(callable, *args, **kwargs)
868
self._benchcalls.append(((callable, args, kwargs), stats))
871
self._benchtime += time.time() - start
873
387
def _runCleanups(self):
874
388
"""Run registered cleanup functions.
927
426
errors, and with logging set to something approximating the
928
427
default, so that error reporting can be checked.
930
:param argv: arguments to invoke bzr
931
:param retcode: expected return code, or None for don't-care.
932
:param encoding: encoding for sys.stdout and sys.stderr
933
:param stdin: A string to be used as stdin for the command.
934
:param working_dir: Change to this directory before running
429
argv -- arguments to invoke bzr
430
retcode -- expected return code, or None for don't-care.
937
encoding = bzrlib.user_encoding
938
if stdin is not None:
939
stdin = StringIO(stdin)
940
stdout = StringIOWrapper()
941
stderr = StringIOWrapper()
942
stdout.encoding = encoding
943
stderr.encoding = encoding
945
self.log('run bzr: %r', argv)
434
self.log('run bzr: %s', ' '.join(argv))
946
435
# FIXME: don't call into logging here
947
436
handler = logging.StreamHandler(stderr)
437
handler.setFormatter(bzrlib.trace.QuietFormatter())
948
438
handler.setLevel(logging.INFO)
949
439
logger = logging.getLogger('')
950
440
logger.addHandler(handler)
951
old_ui_factory = bzrlib.ui.ui_factory
952
bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
955
bzrlib.ui.ui_factory.stdin = stdin
958
if working_dir is not None:
959
cwd = osutils.getcwd()
960
os.chdir(working_dir)
963
saved_debug_flags = frozenset(debug.debug_flags)
964
debug.debug_flags.clear()
966
result = self.apply_redirected(stdin, stdout, stderr,
967
bzrlib.commands.run_bzr_catch_errors,
970
debug.debug_flags.update(saved_debug_flags)
442
result = self.apply_redirected(None, stdout, stderr,
443
bzrlib.commands.run_bzr_catch_errors,
972
446
logger.removeHandler(handler)
973
bzrlib.ui.ui_factory = old_ui_factory
977
447
out = stdout.getvalue()
978
448
err = stderr.getvalue()
980
self.log('output:\n%r', out)
450
self.log('output:\n%s', out)
982
self.log('errors:\n%r', err)
452
self.log('errors:\n%s', err)
983
453
if retcode is not None:
984
self.assertEquals(retcode, result)
454
self.assertEquals(result, retcode)
987
457
def run_bzr(self, *args, **kwargs):
994
464
This sends the stdout/stderr results into the test's log,
995
465
where it may be useful for debugging. See also run_captured.
997
:param stdin: A string to be used as stdin for the command.
999
467
retcode = kwargs.pop('retcode', 0)
1000
encoding = kwargs.pop('encoding', None)
1001
stdin = kwargs.pop('stdin', None)
1002
working_dir = kwargs.pop('working_dir', None)
1003
return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
1004
stdin=stdin, working_dir=working_dir)
1006
def run_bzr_decode(self, *args, **kwargs):
1007
if 'encoding' in kwargs:
1008
encoding = kwargs['encoding']
1010
encoding = bzrlib.user_encoding
1011
return self.run_bzr(*args, **kwargs)[0].decode(encoding)
1013
def run_bzr_error(self, error_regexes, *args, **kwargs):
1014
"""Run bzr, and check that stderr contains the supplied regexes
1016
:param error_regexes: Sequence of regular expressions which
1017
must each be found in the error output. The relative ordering
1019
:param args: command-line arguments for bzr
1020
:param kwargs: Keyword arguments which are interpreted by run_bzr
1021
This function changes the default value of retcode to be 3,
1022
since in most cases this is run when you expect bzr to fail.
1023
:return: (out, err) The actual output of running the command (in case you
1024
want to do more inspection)
1027
# Make sure that commit is failing because there is nothing to do
1028
self.run_bzr_error(['no changes to commit'],
1029
'commit', '-m', 'my commit comment')
1030
# Make sure --strict is handling an unknown file, rather than
1031
# giving us the 'nothing to do' error
1032
self.build_tree(['unknown'])
1033
self.run_bzr_error(['Commit refused because there are unknown files'],
1034
'commit', '--strict', '-m', 'my commit comment')
1036
kwargs.setdefault('retcode', 3)
1037
out, err = self.run_bzr(*args, **kwargs)
1038
for regex in error_regexes:
1039
self.assertContainsRe(err, regex)
1042
def run_bzr_subprocess(self, *args, **kwargs):
1043
"""Run bzr in a subprocess for testing.
1045
This starts a new Python interpreter and runs bzr in there.
1046
This should only be used for tests that have a justifiable need for
1047
this isolation: e.g. they are testing startup time, or signal
1048
handling, or early startup code, etc. Subprocess code can't be
1049
profiled or debugged so easily.
1051
:param retcode: The status code that is expected. Defaults to 0. If
1052
None is supplied, the status code is not checked.
1053
:param env_changes: A dictionary which lists changes to environment
1054
variables. A value of None will unset the env variable.
1055
The values must be strings. The change will only occur in the
1056
child, so you don't need to fix the environment after running.
1057
:param universal_newlines: Convert CRLF => LF
1058
:param allow_plugins: By default the subprocess is run with
1059
--no-plugins to ensure test reproducibility. Also, it is possible
1060
for system-wide plugins to create unexpected output on stderr,
1061
which can cause unnecessary test failures.
1063
env_changes = kwargs.get('env_changes', {})
1064
working_dir = kwargs.get('working_dir', None)
1065
allow_plugins = kwargs.get('allow_plugins', False)
1066
process = self.start_bzr_subprocess(args, env_changes=env_changes,
1067
working_dir=working_dir,
1068
allow_plugins=allow_plugins)
1069
# We distinguish between retcode=None and retcode not passed.
1070
supplied_retcode = kwargs.get('retcode', 0)
1071
return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
1072
universal_newlines=kwargs.get('universal_newlines', False),
1075
def start_bzr_subprocess(self, process_args, env_changes=None,
1076
skip_if_plan_to_signal=False,
1078
allow_plugins=False):
1079
"""Start bzr in a subprocess for testing.
1081
This starts a new Python interpreter and runs bzr in there.
1082
This should only be used for tests that have a justifiable need for
1083
this isolation: e.g. they are testing startup time, or signal
1084
handling, or early startup code, etc. Subprocess code can't be
1085
profiled or debugged so easily.
1087
:param process_args: a list of arguments to pass to the bzr executable,
1088
for example `['--version']`.
1089
:param env_changes: A dictionary which lists changes to environment
1090
variables. A value of None will unset the env variable.
1091
The values must be strings. The change will only occur in the
1092
child, so you don't need to fix the environment after running.
1093
:param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
1095
:param allow_plugins: If False (default) pass --no-plugins to bzr.
1097
:returns: Popen object for the started process.
1099
if skip_if_plan_to_signal:
1100
if not getattr(os, 'kill', None):
1101
raise TestSkipped("os.kill not available.")
1103
if env_changes is None:
1107
def cleanup_environment():
1108
for env_var, value in env_changes.iteritems():
1109
old_env[env_var] = osutils.set_or_unset_env(env_var, value)
1111
def restore_environment():
1112
for env_var, value in old_env.iteritems():
1113
osutils.set_or_unset_env(env_var, value)
1115
bzr_path = self.get_bzr_path()
1118
if working_dir is not None:
1119
cwd = osutils.getcwd()
1120
os.chdir(working_dir)
1123
# win32 subprocess doesn't support preexec_fn
1124
# so we will avoid using it on all platforms, just to
1125
# make sure the code path is used, and we don't break on win32
1126
cleanup_environment()
1127
command = [sys.executable, bzr_path]
1128
if not allow_plugins:
1129
command.append('--no-plugins')
1130
command.extend(process_args)
1131
process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
1133
restore_environment()
1139
def _popen(self, *args, **kwargs):
1140
"""Place a call to Popen.
1142
Allows tests to override this method to intercept the calls made to
1143
Popen for introspection.
1145
return Popen(*args, **kwargs)
1147
def get_bzr_path(self):
1148
"""Return the path of the 'bzr' executable for this test suite."""
1149
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
1150
if not os.path.isfile(bzr_path):
1151
# We are probably installed. Assume sys.argv is the right file
1152
bzr_path = sys.argv[0]
1155
def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
1156
universal_newlines=False, process_args=None):
1157
"""Finish the execution of process.
1159
:param process: the Popen object returned from start_bzr_subprocess.
1160
:param retcode: The status code that is expected. Defaults to 0. If
1161
None is supplied, the status code is not checked.
1162
:param send_signal: an optional signal to send to the process.
1163
:param universal_newlines: Convert CRLF => LF
1164
:returns: (stdout, stderr)
1166
if send_signal is not None:
1167
os.kill(process.pid, send_signal)
1168
out, err = process.communicate()
1170
if universal_newlines:
1171
out = out.replace('\r\n', '\n')
1172
err = err.replace('\r\n', '\n')
1174
if retcode is not None and retcode != process.returncode:
1175
if process_args is None:
1176
process_args = "(unknown args)"
1177
mutter('Output of bzr %s:\n%s', process_args, out)
1178
mutter('Error for bzr %s:\n%s', process_args, err)
1179
self.fail('Command bzr %s failed with retcode %s != %s'
1180
% (process_args, retcode, process.returncode))
468
return self.run_bzr_captured(args, retcode)
1183
470
def check_inventory_shape(self, inv, shape):
1184
471
"""Compare an inventory to a list of expected names.
1232
519
sys.stderr = real_stderr
1233
520
sys.stdin = real_stdin
1235
@symbol_versioning.deprecated_method(symbol_versioning.zero_eleven)
1236
def merge(self, branch_from, wt_to):
1237
"""A helper for tests to do a ui-less merge.
1239
This should move to the main library when someone has time to integrate
1242
# minimal ui-less merge.
1243
wt_to.branch.fetch(branch_from)
1244
base_rev = common_ancestor(branch_from.last_revision(),
1245
wt_to.branch.last_revision(),
1246
wt_to.branch.repository)
1247
merge_inner(wt_to.branch, branch_from.basis_tree(),
1248
wt_to.branch.repository.revision_tree(base_rev),
1250
wt_to.add_parent_tree_id(branch_from.last_revision())
1253
523
BzrTestBase = TestCase
1256
class TestCaseWithMemoryTransport(TestCase):
1257
"""Common test class for tests that do not need disk resources.
1259
Tests that need disk resources should derive from TestCaseWithTransport.
1261
TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
1263
For TestCaseWithMemoryTransport the test_home_dir is set to the name of
1264
a directory which does not exist. This serves to help ensure test isolation
1265
is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
1266
must exist. However, TestCaseWithMemoryTransport does not offer local
1267
file defaults for the transport in tests, nor does it obey the command line
1268
override, so tests that accidentally write to the common directory should
526
class TestCaseInTempDir(TestCase):
527
"""Derived class that runs a test within a temporary directory.
529
This is useful for tests that need to create a branch, etc.
531
The directory is created in a slightly complex way: for each
532
Python invocation, a new temporary top-level directory is created.
533
All test cases create their own directory within that. If the
534
tests complete successfully, the directory is removed.
536
InTempDir is an old alias for FunctionalTestCase.
1272
539
TEST_ROOT = None
1273
540
_TEST_NAME = 'test'
1276
def __init__(self, methodName='runTest'):
1277
# allow test parameterisation after test construction and before test
1278
# execution. Variables that the parameteriser sets need to be
1279
# ones that are not set by setUp, or setUp will trash them.
1280
super(TestCaseWithMemoryTransport, self).__init__(methodName)
1281
self.transport_server = default_transport
1282
self.transport_readonly_server = None
1284
def get_transport(self):
1285
"""Return a writeable transport for the test scratch space"""
1286
t = get_transport(self.get_url())
1287
self.assertFalse(t.is_readonly())
1290
def get_readonly_transport(self):
1291
"""Return a readonly transport for the test scratch space
1293
This can be used to test that operations which should only need
1294
readonly access in fact do not try to write.
1296
t = get_transport(self.get_readonly_url())
1297
self.assertTrue(t.is_readonly())
1300
def create_transport_readonly_server(self):
1301
"""Create a transport server from class defined at init.
1303
This is mostly a hook for daughter classes.
1305
return self.transport_readonly_server()
1307
def get_readonly_server(self):
1308
"""Get the server instance for the readonly transport
1310
This is useful for some tests with specific servers to do diagnostics.
1312
if self.__readonly_server is None:
1313
if self.transport_readonly_server is None:
1314
# readonly decorator requested
1315
# bring up the server
1317
self.__readonly_server = ReadonlyServer()
1318
self.__readonly_server.setUp(self.__server)
1320
self.__readonly_server = self.create_transport_readonly_server()
1321
self.__readonly_server.setUp()
1322
self.addCleanup(self.__readonly_server.tearDown)
1323
return self.__readonly_server
1325
def get_readonly_url(self, relpath=None):
1326
"""Get a URL for the readonly transport.
1328
This will either be backed by '.' or a decorator to the transport
1329
used by self.get_url()
1330
relpath provides for clients to get a path relative to the base url.
1331
These should only be downwards relative, not upwards.
1333
base = self.get_readonly_server().get_url()
1334
if relpath is not None:
1335
if not base.endswith('/'):
1337
base = base + relpath
1340
def get_server(self):
1341
"""Get the read/write server instance.
1343
This is useful for some tests with specific servers that need
1346
For TestCaseWithMemoryTransport this is always a MemoryServer, and there
1347
is no means to override it.
1349
if self.__server is None:
1350
self.__server = MemoryServer()
1351
self.__server.setUp()
1352
self.addCleanup(self.__server.tearDown)
1353
return self.__server
1355
def get_url(self, relpath=None):
1356
"""Get a URL (or maybe a path) for the readwrite transport.
1358
This will either be backed by '.' or to an equivalent non-file based
1360
relpath provides for clients to get a path relative to the base url.
1361
These should only be downwards relative, not upwards.
1363
base = self.get_server().get_url()
1364
if relpath is not None and relpath != '.':
1365
if not base.endswith('/'):
1367
# XXX: Really base should be a url; we did after all call
1368
# get_url()! But sometimes it's just a path (from
1369
# LocalAbspathServer), and it'd be wrong to append urlescaped data
1370
# to a non-escaped local path.
1371
if base.startswith('./') or base.startswith('/'):
1374
base += urlutils.escape(relpath)
541
OVERRIDE_PYTHON = 'python'
543
def check_file_contents(self, filename, expect):
544
self.log("check contents of file %s" % filename)
545
contents = file(filename, 'r').read()
546
if contents != expect:
547
self.log("expected: %r" % expect)
548
self.log("actually: %r" % contents)
549
self.fail("contents of %s not as expected" % filename)
1377
551
def _make_test_root(self):
1378
if TestCaseWithMemoryTransport.TEST_ROOT is not None:
552
if TestCaseInTempDir.TEST_ROOT is not None:
1391
565
# successfully created
1392
TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
566
TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
1394
568
# make a fake bzr directory there to prevent any tests propagating
1395
569
# up onto the source directory's real branch
1396
bzrdir.BzrDir.create_standalone_workingtree(
1397
TestCaseWithMemoryTransport.TEST_ROOT)
1399
def makeAndChdirToTestDir(self):
1400
"""Create a temporary directories for this one test.
1402
This must set self.test_home_dir and self.test_dir and chdir to
1405
For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1407
os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1408
self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1409
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1411
def make_branch(self, relpath, format=None):
1412
"""Create a branch on the transport at relpath."""
1413
repo = self.make_repository(relpath, format=format)
1414
return repo.bzrdir.create_branch()
1416
def make_bzrdir(self, relpath, format=None):
1418
# might be a relative or absolute path
1419
maybe_a_url = self.get_url(relpath)
1420
segments = maybe_a_url.rsplit('/', 1)
1421
t = get_transport(maybe_a_url)
1422
if len(segments) > 1 and segments[-1] not in ('', '.'):
1425
except errors.FileExists:
1429
if isinstance(format, basestring):
1430
format = bzrdir.format_registry.make_bzrdir(format)
1431
return format.initialize_on_transport(t)
1432
except errors.UninitializableFormat:
1433
raise TestSkipped("Format %s is not initializable." % format)
1435
def make_repository(self, relpath, shared=False, format=None):
1436
"""Create a repository on our default transport at relpath."""
1437
made_control = self.make_bzrdir(relpath, format=format)
1438
return made_control.create_repository(shared=shared)
1440
def make_branch_and_memory_tree(self, relpath, format=None):
1441
"""Create a branch on the default transport and a MemoryTree for it."""
1442
b = self.make_branch(relpath, format=format)
1443
return memorytree.MemoryTree.create_on_branch(b)
1445
def overrideEnvironmentForTesting(self):
1446
os.environ['HOME'] = self.test_home_dir
1447
os.environ['APPDATA'] = self.test_home_dir
570
os.mkdir(osutils.pathjoin(TestCaseInTempDir.TEST_ROOT, '.bzr'))
1449
572
def setUp(self):
1450
super(TestCaseWithMemoryTransport, self).setUp()
573
super(TestCaseInTempDir, self).setUp()
1451
574
self._make_test_root()
1452
575
_currentdir = os.getcwdu()
576
short_id = self.id().replace('bzrlib.tests.', '') \
577
.replace('__main__.', '')
578
self.test_dir = osutils.pathjoin(self.TEST_ROOT, short_id)
579
os.mkdir(self.test_dir)
580
os.chdir(self.test_dir)
581
os.environ['HOME'] = self.test_dir
582
os.environ['APPDATA'] = self.test_dir
1453
583
def _leaveDirectory():
1454
584
os.chdir(_currentdir)
1455
585
self.addCleanup(_leaveDirectory)
1456
self.makeAndChdirToTestDir()
1457
self.overrideEnvironmentForTesting()
1458
self.__readonly_server = None
1459
self.__server = None
1462
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1463
"""Derived class that runs a test within a temporary directory.
1465
This is useful for tests that need to create a branch, etc.
1467
The directory is created in a slightly complex way: for each
1468
Python invocation, a new temporary top-level directory is created.
1469
All test cases create their own directory within that. If the
1470
tests complete successfully, the directory is removed.
1472
InTempDir is an old alias for FunctionalTestCase.
1475
OVERRIDE_PYTHON = 'python'
1477
def check_file_contents(self, filename, expect):
1478
self.log("check contents of file %s" % filename)
1479
contents = file(filename, 'r').read()
1480
if contents != expect:
1481
self.log("expected: %r" % expect)
1482
self.log("actually: %r" % contents)
1483
self.fail("contents of %s not as expected" % filename)
1485
def makeAndChdirToTestDir(self):
1486
"""See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
1488
For TestCaseInTempDir we create a temporary directory based on the test
1489
name and then create two subdirs - test and home under it.
1491
# shorten the name, to avoid test failures due to path length
1492
short_id = self.id().replace('bzrlib.tests.', '') \
1493
.replace('__main__.', '')[-100:]
1494
# it's possible the same test class is run several times for
1495
# parameterized tests, so make sure the names don't collide.
1499
candidate_dir = '%s/%s.%d' % (self.TEST_ROOT, short_id, i)
1501
candidate_dir = '%s/%s' % (self.TEST_ROOT, short_id)
1502
if os.path.exists(candidate_dir):
1506
os.mkdir(candidate_dir)
1507
self.test_home_dir = candidate_dir + '/home'
1508
os.mkdir(self.test_home_dir)
1509
self.test_dir = candidate_dir + '/work'
1510
os.mkdir(self.test_dir)
1511
os.chdir(self.test_dir)
1514
def build_tree(self, shape, line_endings='binary', transport=None):
587
def build_tree(self, shape, line_endings='native', transport=None):
1515
588
"""Build a test tree according to a pattern.
1517
590
shape is a sequence of file specifications. If the final
1518
591
character is '/', a directory is created.
1520
This assumes that all the elements in the tree being built are new.
1522
593
This doesn't add anything to a branch.
1523
594
:param line_endings: Either 'binary' or 'native'
1524
595
in binary mode, exact contents are written
1529
600
VFS's. If the transport is readonly or None,
1530
601
"." is opened automatically.
1532
# It's OK to just create them using forward slashes on windows.
603
# XXX: It's OK to just create them using forward slashes on windows?
1533
604
if transport is None or transport.is_readonly():
1534
transport = get_transport(".")
605
transport = bzrlib.transport.get_transport(".")
1535
606
for name in shape:
1536
607
self.assert_(isinstance(name, basestring))
1537
608
if name[-1] == '/':
1538
transport.mkdir(urlutils.escape(name[:-1]))
609
transport.mkdir(urlescape(name[:-1]))
1540
611
if line_endings == 'binary':
1542
613
elif line_endings == 'native':
1543
614
end = os.linesep
1545
raise errors.BzrError(
1546
'Invalid line ending request %r' % line_endings)
1547
content = "contents of %s%s" % (name.encode('utf-8'), end)
1548
transport.put_bytes_non_atomic(urlutils.escape(name), content)
616
raise BzrError('Invalid line ending request %r' % (line_endings,))
617
content = "contents of %s%s" % (name, end)
618
transport.put(urlescape(name), StringIO(content))
1550
620
def build_tree_contents(self, shape):
1551
621
build_tree_contents(shape)
1553
def assertFileEqual(self, content, path):
1554
"""Fail if path does not contain 'content'."""
1555
self.failUnlessExists(path)
1556
# TODO: jam 20060427 Shouldn't this be 'rb'?
1557
self.assertEqualDiff(content, open(path, 'r').read())
1559
623
def failUnlessExists(self, path):
1560
624
"""Fail unless path, which may be abs or relative, exists."""
1561
self.failUnless(osutils.lexists(path),path+" does not exist")
625
self.failUnless(osutils.lexists(path))
1563
627
def failIfExists(self, path):
1564
628
"""Fail if path, which may be abs or relative, exists."""
1565
self.failIf(osutils.lexists(path),path+" exists")
629
self.failIf(osutils.lexists(path))
631
def assertFileEqual(self, content, path):
632
"""Fail if path does not contain 'content'."""
633
self.failUnless(osutils.lexists(path))
634
self.assertEqualDiff(content, open(path, 'r').read())
1568
637
class TestCaseWithTransport(TestCaseInTempDir):
1579
648
readwrite one must both define get_url() as resolving to os.getcwd().
1582
def create_transport_server(self):
1583
"""Create a transport server from class defined at init.
1585
This is mostly a hook for daughter classes.
651
def __init__(self, methodName='testMethod'):
652
super(TestCaseWithTransport, self).__init__(methodName)
653
self.__readonly_server = None
655
self.transport_server = default_transport
656
self.transport_readonly_server = None
658
def get_readonly_url(self, relpath=None):
659
"""Get a URL for the readonly transport.
661
This will either be backed by '.' or a decorator to the transport
662
used by self.get_url()
663
relpath provides for clients to get a path relative to the base url.
664
These should only be downwards relative, not upwards.
1587
return self.transport_server()
1589
def get_server(self):
1590
"""See TestCaseWithMemoryTransport.
1592
This is useful for some tests with specific servers that need
666
if self.__readonly_server is None:
667
if self.transport_readonly_server is None:
668
# readonly decorator requested
669
# bring up the server
671
self.__readonly_server = ReadonlyServer()
672
self.__readonly_server.setUp(self.__server)
674
self.__readonly_server = self.transport_readonly_server()
675
self.__readonly_server.setUp()
676
self.addCleanup(self.__readonly_server.tearDown)
677
base = self.__readonly_server.get_url()
678
if relpath is not None:
679
if not base.endswith('/'):
681
base = base + relpath
684
def get_url(self, relpath=None):
685
"""Get a URL for the readwrite transport.
687
This will either be backed by '.' or to an equivalent non-file based
689
relpath provides for clients to get a path relative to the base url.
690
These should only be downwards relative, not upwards.
1595
692
if self.__server is None:
1596
self.__server = self.create_transport_server()
693
self.__server = self.transport_server()
1597
694
self.__server.setUp()
1598
695
self.addCleanup(self.__server.tearDown)
1599
return self.__server
1601
def make_branch_and_tree(self, relpath, format=None):
696
base = self.__server.get_url()
697
if relpath is not None and relpath != '.':
698
if not base.endswith('/'):
700
base = base + relpath
703
def make_branch(self, relpath):
704
"""Create a branch on the transport at relpath."""
706
url = self.get_url(relpath)
707
segments = relpath.split('/')
708
if segments and segments[-1] not in ('', '.'):
709
parent = self.get_url('/'.join(segments[:-1]))
710
t = bzrlib.transport.get_transport(parent)
712
t.mkdir(segments[-1])
715
return bzrlib.branch.Branch.create(url)
716
except UninitializableFormat:
717
raise TestSkipped("Format %s is not initializable.")
719
def make_branch_and_tree(self, relpath):
1602
720
"""Create a branch on the transport and a tree locally.
1604
If the transport is not a LocalTransport, the Tree can't be created on
1605
the transport. In that case the working tree is created in the local
1606
directory, and the returned tree's branch and repository will also be
1609
This will fail if the original default transport for this test
1610
case wasn't backed by the working directory, as the branch won't
1611
be on disk for us to open it.
1613
:param format: The BzrDirFormat.
1614
:returns: the WorkingTree.
1616
# TODO: always use the local disk path for the working tree,
1617
# this obviously requires a format that supports branch references
1618
# so check for that by checking bzrdir.BzrDirFormat.get_default_format()
1620
b = self.make_branch(relpath, format=format)
1622
return b.bzrdir.create_workingtree()
1623
except errors.NotLocalUrl:
1624
# We can only make working trees locally at the moment. If the
1625
# transport can't support them, then reopen the branch on a local
1626
# transport, and create the working tree there.
1628
# Possibly we should instead keep
1629
# the non-disk-backed branch and create a local checkout?
1630
bd = bzrdir.BzrDir.open(relpath)
1631
return bd.create_workingtree()
1633
def assertIsDirectory(self, relpath, transport):
1634
"""Assert that relpath within transport is a directory.
1636
This may not be possible on all transports; in that case it propagates
1637
a TransportNotPossible.
1640
mode = transport.stat(relpath).st_mode
1641
except errors.NoSuchFile:
1642
self.fail("path %s is not a directory; no such file"
1644
if not stat.S_ISDIR(mode):
1645
self.fail("path %s is not a directory; has mode %#o"
1648
def assertTreesEqual(self, left, right):
1649
"""Check that left and right have the same content and properties."""
1650
# we use a tree delta to check for equality of the content, and we
1651
# manually check for equality of other things such as the parents list.
1652
self.assertEqual(left.get_parent_ids(), right.get_parent_ids())
1653
differences = left.changes_from(right)
1654
self.assertFalse(differences.has_changed(),
1655
"Trees %r and %r are different: %r" % (left, right, differences))
1658
super(TestCaseWithTransport, self).setUp()
1659
self.__server = None
724
b = self.make_branch(relpath)
725
return WorkingTree.create(b, relpath)
1662
728
class ChrootedTestCase(TestCaseWithTransport):
1689
def sort_suite_by_re(suite, pattern):
1692
filter_re = re.compile(pattern)
1693
for test in iter_suite_tests(suite):
1694
if filter_re.search(test.id()):
1698
return TestUtil.TestSuite(first + second)
1701
755
def run_suite(suite, name='test', verbose=False, pattern=".*",
1702
756
stop_on_failure=False, keep_output=False,
1703
transport=None, lsprof_timed=None, bench_history=None,
1704
matching_tests_first=None):
1705
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
758
TestCaseInTempDir._TEST_NAME = name
1710
763
runner = TextTestRunner(stream=sys.stdout,
1712
verbosity=verbosity,
1713
keep_output=keep_output,
1714
bench_history=bench_history)
1715
766
runner.stop_on_failure=stop_on_failure
1716
767
if pattern != '.*':
1717
if matching_tests_first:
1718
suite = sort_suite_by_re(suite, pattern)
1720
suite = filter_suite_by_re(suite, pattern)
768
suite = filter_suite_by_re(suite, pattern)
1721
769
result = runner.run(suite)
770
# This is still a little bogus,
771
# but only a little. Folk not using our testrunner will
772
# have to delete their temp directories themselves.
773
if result.wasSuccessful() or not keep_output:
774
if TestCaseInTempDir.TEST_ROOT is not None:
775
shutil.rmtree(TestCaseInTempDir.TEST_ROOT)
777
print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
1722
778
return result.wasSuccessful()
1725
781
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
1726
782
keep_output=False,
1728
test_suite_factory=None,
1731
matching_tests_first=None):
1732
784
"""Run the whole test suite under the enhanced runner"""
1733
# XXX: Very ugly way to do this...
1734
# Disable warning about old formats because we don't want it to disturb
1735
# any blackbox tests.
1736
from bzrlib import repository
1737
repository._deprecation_warning_done = True
1739
785
global default_transport
1740
786
if transport is None:
1741
787
transport = default_transport
1742
788
old_transport = default_transport
1743
789
default_transport = transport
1745
if test_suite_factory is None:
1746
suite = test_suite()
1748
suite = test_suite_factory()
1749
792
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
1750
793
stop_on_failure=stop_on_failure, keep_output=keep_output,
1751
transport=transport,
1752
lsprof_timed=lsprof_timed,
1753
bench_history=bench_history,
1754
matching_tests_first=matching_tests_first)
1756
796
default_transport = old_transport
1759
800
def test_suite():
1760
"""Build and return TestSuite for the whole of bzrlib.
1762
This function can be replaced if you need to change the default test
1763
suite on a global basis, but it is not encouraged.
801
"""Build and return TestSuite for the whole program."""
802
from doctest import DocTestSuite
804
global MODULES_TO_DOCTEST
1766
807
'bzrlib.tests.test_ancestry',
1767
808
'bzrlib.tests.test_annotate',
1768
809
'bzrlib.tests.test_api',
1769
'bzrlib.tests.test_atomicfile',
1770
810
'bzrlib.tests.test_bad_files',
811
'bzrlib.tests.test_basis_inventory',
1771
812
'bzrlib.tests.test_branch',
1772
'bzrlib.tests.test_bundle',
1773
'bzrlib.tests.test_bzrdir',
1774
'bzrlib.tests.test_cache_utf8',
1775
'bzrlib.tests.test_commands',
813
'bzrlib.tests.test_command',
1776
814
'bzrlib.tests.test_commit',
1777
815
'bzrlib.tests.test_commit_merge',
1778
816
'bzrlib.tests.test_config',
1779
817
'bzrlib.tests.test_conflicts',
818
'bzrlib.tests.test_diff',
1780
819
'bzrlib.tests.test_decorators',
1781
'bzrlib.tests.test_delta',
1782
'bzrlib.tests.test_diff',
1783
'bzrlib.tests.test_dirstate',
1784
'bzrlib.tests.test_doc_generate',
1785
'bzrlib.tests.test_errors',
1786
'bzrlib.tests.test_escaped_store',
1787
820
'bzrlib.tests.test_fetch',
1788
'bzrlib.tests.test_ftp_transport',
1789
'bzrlib.tests.test_generate_docs',
1790
'bzrlib.tests.test_generate_ids',
1791
'bzrlib.tests.test_globbing',
821
'bzrlib.tests.test_fileid_involved',
1792
822
'bzrlib.tests.test_gpg',
1793
823
'bzrlib.tests.test_graph',
1794
824
'bzrlib.tests.test_hashcache',
1795
825
'bzrlib.tests.test_http',
1796
'bzrlib.tests.test_http_response',
1797
826
'bzrlib.tests.test_identitymap',
1798
'bzrlib.tests.test_ignores',
1799
827
'bzrlib.tests.test_inv',
1800
'bzrlib.tests.test_knit',
1801
'bzrlib.tests.test_lazy_import',
1802
'bzrlib.tests.test_lazy_regex',
1803
'bzrlib.tests.test_lockdir',
1804
828
'bzrlib.tests.test_lockable_files',
1805
829
'bzrlib.tests.test_log',
1806
'bzrlib.tests.test_memorytree',
1807
830
'bzrlib.tests.test_merge',
1808
831
'bzrlib.tests.test_merge3',
1809
832
'bzrlib.tests.test_merge_core',
1812
835
'bzrlib.tests.test_nonascii',
1813
836
'bzrlib.tests.test_options',
1814
837
'bzrlib.tests.test_osutils',
1815
'bzrlib.tests.test_osutils_encodings',
1816
'bzrlib.tests.test_patch',
1817
'bzrlib.tests.test_patches',
838
'bzrlib.tests.test_parent',
1818
839
'bzrlib.tests.test_permissions',
1819
840
'bzrlib.tests.test_plugins',
1820
'bzrlib.tests.test_progress',
1821
'bzrlib.tests.test_reconcile',
1822
'bzrlib.tests.test_registry',
1823
'bzrlib.tests.test_repository',
1824
'bzrlib.tests.test_revert',
1825
841
'bzrlib.tests.test_revision',
1826
842
'bzrlib.tests.test_revisionnamespaces',
1827
'bzrlib.tests.test_revisiontree',
843
'bzrlib.tests.test_revprops',
844
'bzrlib.tests.test_reweave',
1828
845
'bzrlib.tests.test_rio',
1829
846
'bzrlib.tests.test_sampler',
1830
847
'bzrlib.tests.test_selftest',
1831
848
'bzrlib.tests.test_setup',
1832
849
'bzrlib.tests.test_sftp_transport',
1833
850
'bzrlib.tests.test_smart_add',
1834
'bzrlib.tests.test_smart_transport',
1835
851
'bzrlib.tests.test_source',
1836
'bzrlib.tests.test_status',
1837
852
'bzrlib.tests.test_store',
1838
853
'bzrlib.tests.test_symbol_versioning',
1839
854
'bzrlib.tests.test_testament',
1840
'bzrlib.tests.test_textfile',
1841
'bzrlib.tests.test_textmerge',
1842
855
'bzrlib.tests.test_trace',
1843
856
'bzrlib.tests.test_transactions',
1844
'bzrlib.tests.test_transform',
1845
857
'bzrlib.tests.test_transport',
1846
'bzrlib.tests.test_tree',
1847
'bzrlib.tests.test_treebuilder',
1848
858
'bzrlib.tests.test_tsort',
1849
'bzrlib.tests.test_tuned_gzip',
1850
859
'bzrlib.tests.test_ui',
860
'bzrlib.tests.test_uncommit',
1851
861
'bzrlib.tests.test_upgrade',
1852
'bzrlib.tests.test_urlutils',
1853
'bzrlib.tests.test_versionedfile',
1854
'bzrlib.tests.test_version',
1855
'bzrlib.tests.test_version_info',
1856
862
'bzrlib.tests.test_weave',
1857
863
'bzrlib.tests.test_whitebox',
1858
864
'bzrlib.tests.test_workingtree',
1859
'bzrlib.tests.test_wsgi',
1860
865
'bzrlib.tests.test_xml',
1862
867
test_transport_implementations = [
1863
'bzrlib.tests.test_transport_implementations',
1864
'bzrlib.tests.test_read_bundle',
1866
suite = TestUtil.TestSuite()
1867
loader = TestUtil.TestLoader()
1868
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
868
'bzrlib.tests.test_transport_implementations']
870
TestCase.BZRPATH = osutils.pathjoin(
871
osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
872
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
873
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
876
# python2.4's TestLoader.loadTestsFromNames gives very poor
877
# errors if it fails to load a named module - no indication of what's
878
# actually wrong, just "no such module". We should probably override that
879
# class, but for the moment just load them ourselves. (mbp 20051202)
880
loader = TestLoader()
1869
881
from bzrlib.transport import TransportTestProviderAdapter
1870
882
adapter = TransportTestProviderAdapter()
1871
883
adapt_modules(test_transport_implementations, adapter, loader, suite)
884
for mod_name in testmod_names:
885
mod = _load_module_by_name(mod_name)
886
suite.addTest(loader.loadTestsFromModule(mod))
1872
887
for package in packages_to_test():
1873
888
suite.addTest(package.test_suite())
1874
889
for m in MODULES_TO_TEST:
1875
890
suite.addTest(loader.loadTestsFromModule(m))
1876
for m in MODULES_TO_DOCTEST:
1878
suite.addTest(doctest.DocTestSuite(m))
1879
except ValueError, e:
1880
print '**failed to get doctest for: %s\n%s' %(m,e)
891
for m in (MODULES_TO_DOCTEST):
892
suite.addTest(DocTestSuite(m))
1882
893
for name, plugin in bzrlib.plugin.all_plugins().items():
1883
894
if getattr(plugin, 'test_suite', None) is not None:
1884
default_encoding = sys.getdefaultencoding()
1886
plugin_suite = plugin.test_suite()
1887
except ImportError, e:
1888
bzrlib.trace.warning(
1889
'Unable to test plugin "%s": %s', name, e)
1891
suite.addTest(plugin_suite)
1892
if default_encoding != sys.getdefaultencoding():
1893
bzrlib.trace.warning(
1894
'Plugin "%s" tried to reset default encoding to: %s', name,
1895
sys.getdefaultencoding())
1897
sys.setdefaultencoding(default_encoding)
895
suite.addTest(plugin.test_suite())
1901
899
def adapt_modules(mods_list, adapter, loader, suite):
1902
900
"""Adapt the modules in mods_list using adapter and add to suite."""
1903
for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1904
suite.addTests(adapter.adapt(test))
1907
def clean_selftest_output(root=None, quiet=False):
1908
"""Remove all selftest output directories from root directory.
1910
:param root: root directory for clean
1911
(if ommitted or None then clean current directory).
1912
:param quiet: suppress report about deleting directories
1917
re_dir = re.compile(r'''test\d\d\d\d\.tmp''')
1920
for i in os.listdir(root):
1921
if os.path.isdir(i) and re_dir.match(i):
1923
print 'delete directory:', i
901
for mod_name in mods_list:
902
mod = _load_module_by_name(mod_name)
903
for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
904
suite.addTests(adapter.adapt(test))
907
def _load_module_by_name(mod_name):
908
parts = mod_name.split('.')
909
module = __import__(mod_name)
911
# for historical reasons python returns the top-level module even though
912
# it loads the submodule; we need to walk down to get the one we want.
914
module = getattr(module, parts.pop(0))