107
130
bzrlib.tests.bzrdir_implementations,
108
131
bzrlib.tests.interrepository_implementations,
109
132
bzrlib.tests.interversionedfile_implementations,
133
bzrlib.tests.intertree_implementations,
110
134
bzrlib.tests.repository_implementations,
111
135
bzrlib.tests.revisionstore_implementations,
136
bzrlib.tests.tree_implementations,
112
137
bzrlib.tests.workingtree_implementations,
116
class _MyResult(unittest._TextTestResult):
117
"""Custom TestResult.
141
class ExtendedTestResult(unittest._TextTestResult):
142
"""Accepts, reports and accumulates the results of running tests.
119
Shows output in a different format, including displaying runtime for tests.
144
Compared to this unittest version this class adds support for profiling,
145
benchmarking, stopping as soon as a test fails, and skipping tests.
146
There are further-specialized subclasses for different types of display.
121
149
stop_early = False
123
def __init__(self, stream, descriptions, verbosity, pb=None):
151
def __init__(self, stream, descriptions, verbosity,
155
"""Construct new TestResult.
157
:param bench_history: Optionally, a writable file object to accumulate
124
160
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
161
if bench_history is not None:
162
from bzrlib.version import _get_bzr_source_tree
163
src_tree = _get_bzr_source_tree()
166
revision_id = src_tree.get_parent_ids()[0]
168
# XXX: if this is a brand new tree, do the same as if there
172
# XXX: If there's no branch, what should we do?
174
bench_history.write("--date %s %s\n" % (time.time(), revision_id))
175
self._bench_history = bench_history
176
self.ui = bzrlib.ui.ui_factory
177
self.num_tests = num_tests
179
self.failure_count = 0
182
self._overall_start_time = time.time()
127
184
def extractBenchmarkTime(self, testCase):
128
185
"""Add a benchmark time for the current test case."""
138
195
self._formatTime(self._benchmarkTime),
139
196
self._elapsedTestTimeString())
141
return " %s" % self._elapsedTestTimeString()
198
return " %s" % self._elapsedTestTimeString()
143
200
def _formatTime(self, seconds):
144
201
"""Format seconds as milliseconds with leading spaces."""
145
return "%5dms" % (1000 * seconds)
202
# some benchmarks can take thousands of seconds to run, so we need 8
204
return "%8dms" % (1000 * seconds)
147
def _ellipsise_unimportant_words(self, a_string, final_width,
149
"""Add ellipses (sp?) for overly long strings.
151
:param keep_start: If true preserve the start of a_string rather
155
if len(a_string) > final_width:
156
result = a_string[:final_width-3] + '...'
160
if len(a_string) > final_width:
161
result = '...' + a_string[3-final_width:]
164
return result.ljust(final_width)
206
def _shortened_test_description(self, test):
208
what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
166
211
def startTest(self, test):
167
212
unittest.TestResult.startTest(self, test)
168
# In a short description, the important words are in
169
# the beginning, but in an id, the important words are
171
SHOW_DESCRIPTIONS = False
173
if not self.showAll and self.dots and self.pb is not None:
176
final_width = osutils.terminal_width()
177
final_width = final_width - 15 - 8
179
if SHOW_DESCRIPTIONS:
180
what = test.shortDescription()
182
what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
185
if what.startswith('bzrlib.tests.'):
187
what = self._ellipsise_unimportant_words(what, final_width)
189
self.stream.write(what)
190
elif self.dots and self.pb is not None:
191
self.pb.update(what, self.testsRun - 1, None)
213
self.report_test_start(test)
214
test.number = self.count
193
215
self._recordTestStartTime()
195
217
def _recordTestStartTime(self):
200
222
if isinstance(err[1], TestSkipped):
201
223
return self.addSkipped(test, err)
202
224
unittest.TestResult.addError(self, test, err)
225
# We can only do this if we have one of our TestCases, not if
227
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
228
if setKeepLogfile is not None:
203
230
self.extractBenchmarkTime(test)
205
self.stream.writeln("ERROR %s" % self._testTimeString())
206
elif self.dots and self.pb is None:
207
self.stream.write('E')
209
self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
231
self.report_error(test, err)
211
232
if self.stop_early:
214
235
def addFailure(self, test, err):
215
236
unittest.TestResult.addFailure(self, test, err)
237
# We can only do this if we have one of our TestCases, not if
239
setKeepLogfile = getattr(test, 'setKeepLogfile', None)
240
if setKeepLogfile is not None:
216
242
self.extractBenchmarkTime(test)
218
self.stream.writeln(" FAIL %s" % self._testTimeString())
219
elif self.dots and self.pb is None:
220
self.stream.write('F')
222
self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
243
self.report_failure(test, err)
224
244
if self.stop_early:
227
247
def addSuccess(self, test):
228
248
self.extractBenchmarkTime(test)
230
self.stream.writeln(' OK %s' % self._testTimeString())
231
for bench_called, stats in test._benchcalls:
232
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
233
stats.pprint(file=self.stream)
234
elif self.dots and self.pb is None:
235
self.stream.write('~')
237
self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
249
if self._bench_history is not None:
250
if self._benchmarkTime is not None:
251
self._bench_history.write("%s %s\n" % (
252
self._formatTime(self._benchmarkTime),
254
self.report_success(test)
239
255
unittest.TestResult.addSuccess(self, test)
241
257
def addSkipped(self, test, skip_excinfo):
242
258
self.extractBenchmarkTime(test)
244
print >>self.stream, ' SKIP %s' % self._testTimeString()
245
print >>self.stream, ' %s' % skip_excinfo[1]
246
elif self.dots and self.pb is None:
247
self.stream.write('S')
249
self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
259
self.report_skip(test, skip_excinfo)
251
260
# seems best to treat this as success from point-of-view of unittest
252
261
# -- it actually does nothing so it barely matters :)
253
unittest.TestResult.addSuccess(self, test)
264
except KeyboardInterrupt:
267
self.addError(test, test.__exc_info())
269
unittest.TestResult.addSuccess(self, test)
255
271
def printErrorList(self, flavour, errors):
256
272
for test, err in errors:
266
282
self.stream.writeln(self.separator2)
267
283
self.stream.writeln("%s" % err)
288
def report_cleaning_up(self):
291
def report_success(self, test):
295
class TextTestResult(ExtendedTestResult):
296
"""Displays progress and results of tests in text form"""
298
def __init__(self, *args, **kw):
299
ExtendedTestResult.__init__(self, *args, **kw)
300
self.pb = self.ui.nested_progress_bar()
301
self.pb.show_pct = False
302
self.pb.show_spinner = False
303
self.pb.show_eta = False,
304
self.pb.show_count = False
305
self.pb.show_bar = False
307
def report_starting(self):
308
self.pb.update('[test 0/%d] starting...' % (self.num_tests))
310
def _progress_prefix_text(self):
311
a = '[%d' % self.count
312
if self.num_tests is not None:
313
a +='/%d' % self.num_tests
314
a += ' in %ds' % (time.time() - self._overall_start_time)
316
a += ', %d errors' % self.error_count
317
if self.failure_count:
318
a += ', %d failed' % self.failure_count
320
a += ', %d skipped' % self.skip_count
324
def report_test_start(self, test):
327
self._progress_prefix_text()
329
+ self._shortened_test_description(test))
331
def _test_description(self, test):
333
return '#%d %s' % (self.count,
334
self._shortened_test_description(test))
336
return self._shortened_test_description(test)
338
def report_error(self, test, err):
339
self.error_count += 1
340
self.pb.note('ERROR: %s\n %s\n',
341
self._test_description(test),
345
def report_failure(self, test, err):
346
self.failure_count += 1
347
self.pb.note('FAIL: %s\n %s\n',
348
self._test_description(test),
352
def report_skip(self, test, skip_excinfo):
355
# at the moment these are mostly not things we can fix
356
# and so they just produce stipple; use the verbose reporter
359
# show test and reason for skip
360
self.pb.note('SKIP: %s\n %s\n',
361
self._shortened_test_description(test),
364
# since the class name was left behind in the still-visible
366
self.pb.note('SKIP: %s', skip_excinfo[1])
368
def report_cleaning_up(self):
369
self.pb.update('cleaning up...')
375
class VerboseTestResult(ExtendedTestResult):
376
"""Produce long output, with one line per test run plus times"""
378
def _ellipsize_to_right(self, a_string, final_width):
379
"""Truncate and pad a string, keeping the right hand side"""
380
if len(a_string) > final_width:
381
result = '...' + a_string[3-final_width:]
384
return result.ljust(final_width)
386
def report_starting(self):
387
self.stream.write('running %d tests...\n' % self.num_tests)
389
def report_test_start(self, test):
391
name = self._shortened_test_description(test)
392
# width needs space for 6 char status, plus 1 for slash, plus 2 10-char
393
# numbers, plus a trailing blank
394
# when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
396
self.stream.write('%5d ' % self.count)
397
self.stream.write(self._ellipsize_to_right(name,
398
osutils.terminal_width()-36))
400
self.stream.write(self._ellipsize_to_right(name,
401
osutils.terminal_width()-30))
404
def _error_summary(self, err):
408
return '%s%s' % (indent, err[1])
410
def report_error(self, test, err):
411
self.error_count += 1
412
self.stream.writeln('ERROR %s\n%s'
413
% (self._testTimeString(),
414
self._error_summary(err)))
416
def report_failure(self, test, err):
417
self.failure_count += 1
418
self.stream.writeln(' FAIL %s\n%s'
419
% (self._testTimeString(),
420
self._error_summary(err)))
422
def report_success(self, test):
423
self.stream.writeln(' OK %s' % self._testTimeString())
424
for bench_called, stats in getattr(test, '_benchcalls', []):
426
self.stream.write(' ' * 6)
427
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
428
stats.pprint(file=self.stream)
431
def report_skip(self, test, skip_excinfo):
433
self.stream.writeln(' SKIP %s\n%s'
434
% (self._testTimeString(),
435
self._error_summary(skip_excinfo)))
270
438
class TextTestRunner(object):
271
439
stop_on_failure = False
316
485
self.stream.writeln(")")
318
487
self.stream.writeln("OK")
319
if self.pb is not None:
320
self.pb.update('Cleaning up', 0, 1)
488
if result.skip_count > 0:
489
skipped = result.skip_count
490
self.stream.writeln('%d test%s skipped' %
491
(skipped, skipped != 1 and "s" or ""))
492
result.report_cleaning_up()
321
493
# This is still a little bogus,
322
494
# but only a little. Folk not using our testrunner will
323
495
# have to delete their temp directories themselves.
324
test_root = TestCaseInTempDir.TEST_ROOT
496
test_root = TestCaseWithMemoryTransport.TEST_ROOT
325
497
if result.wasSuccessful() or not self.keep_output:
326
498
if test_root is not None:
499
# If LANG=C we probably have created some bogus paths
500
# which rmtree(unicode) will fail to delete
501
# so make sure we are using rmtree(str) to delete everything
502
# except on win32, where rmtree(str) will fail
503
# since it doesn't have the property of byte-stream paths
504
# (they are either ascii or mbcs)
505
if sys.platform == 'win32':
506
# make sure we are using the unicode win32 api
507
test_root = unicode(test_root)
509
test_root = test_root.encode(
510
sys.getfilesystemencoding())
327
512
osutils.rmtree(test_root)
514
if sys.platform == 'win32' and e.errno == errno.EACCES:
515
print >>sys.stderr, ('Permission denied: '
516
'unable to remove testing dir '
517
'%s' % os.path.basename(test_root))
329
if self.pb is not None:
330
self.pb.note("Failed tests working directories are in '%s'\n",
334
"Failed tests working directories are in '%s'\n" %
336
TestCaseInTempDir.TEST_ROOT = None
337
if self.pb is not None:
521
note("Failed tests working directories are in '%s'\n", test_root)
522
TestCaseWithMemoryTransport.TEST_ROOT = None
478
751
self.fail("%r is an instance of %s rather than %s" % (
479
752
obj, obj.__class__, kls))
754
def _capture_warnings(self, a_callable, *args, **kwargs):
755
"""A helper for callDeprecated and applyDeprecated.
757
:param a_callable: A callable to call.
758
:param args: The positional arguments for the callable
759
:param kwargs: The keyword arguments for the callable
760
:return: A tuple (warnings, result). result is the result of calling
761
a_callable(*args, **kwargs).
764
def capture_warnings(msg, cls=None, stacklevel=None):
765
# we've hooked into a deprecation specific callpath,
766
# only deprecations should getting sent via it.
767
self.assertEqual(cls, DeprecationWarning)
768
local_warnings.append(msg)
769
original_warning_method = symbol_versioning.warn
770
symbol_versioning.set_warning_method(capture_warnings)
772
result = a_callable(*args, **kwargs)
774
symbol_versioning.set_warning_method(original_warning_method)
775
return (local_warnings, result)
777
def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
778
"""Call a deprecated callable without warning the user.
780
:param deprecation_format: The deprecation format that the callable
781
should have been deprecated with. This is the same type as the
782
parameter to deprecated_method/deprecated_function. If the
783
callable is not deprecated with this format, an assertion error
785
:param a_callable: A callable to call. This may be a bound method or
786
a regular function. It will be called with *args and **kwargs.
787
:param args: The positional arguments for the callable
788
:param kwargs: The keyword arguments for the callable
789
:return: The result of a_callable(*args, **kwargs)
791
call_warnings, result = self._capture_warnings(a_callable,
793
expected_first_warning = symbol_versioning.deprecation_string(
794
a_callable, deprecation_format)
795
if len(call_warnings) == 0:
796
self.fail("No deprecation warning generated by call to %s" %
798
self.assertEqual(expected_first_warning, call_warnings[0])
801
def callDeprecated(self, expected, callable, *args, **kwargs):
802
"""Assert that a callable is deprecated in a particular way.
804
This is a very precise test for unusual requirements. The
805
applyDeprecated helper function is probably more suited for most tests
806
as it allows you to simply specify the deprecation format being used
807
and will ensure that that is issued for the function being called.
809
:param expected: a list of the deprecation warnings expected, in order
810
:param callable: The callable to call
811
:param args: The positional arguments for the callable
812
:param kwargs: The keyword arguments for the callable
814
call_warnings, result = self._capture_warnings(callable,
816
self.assertEqual(expected, call_warnings)
481
819
def _startLogFile(self):
482
820
"""Send bzr and test log messages to a temporary file.
484
822
The file is removed as the test is torn down.
486
824
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
487
encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
488
self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
825
self._log_file = os.fdopen(fileno, 'w+')
489
826
self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
490
827
self._log_file_name = name
491
828
self.addCleanup(self._finishLogFile)
586
935
def log(self, *args):
590
"""Return as a string the log for this test"""
591
if self._log_file_name:
592
return open(self._log_file_name).read()
938
def _get_log(self, keep_log_file=False):
939
"""Return as a string the log for this test. If the file is still
940
on disk and keep_log_file=False, delete the log file and store the
941
content in self._log_contents."""
942
# flush the log file, to get all content
944
bzrlib.trace._trace_file.flush()
945
if self._log_contents:
594
946
return self._log_contents
595
# TODO: Delete the log after it's been read in
947
if self._log_file_name is not None:
948
logfile = open(self._log_file_name)
950
log_contents = logfile.read()
953
if not keep_log_file:
954
self._log_contents = log_contents
956
os.remove(self._log_file_name)
958
if sys.platform == 'win32' and e.errno == errno.EACCES:
959
print >>sys.stderr, ('Unable to delete log file '
960
' %r' % self._log_file_name)
965
return "DELETED log file to reduce memory footprint"
597
967
def capture(self, cmd, retcode=0):
598
968
"""Shortcut that splits cmd into words, runs, and returns stdout"""
599
969
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
601
def run_bzr_captured(self, argv, retcode=0, stdin=None):
971
def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
602
973
"""Invoke bzr and return (stdout, stderr).
604
975
Useful for code that wants to check the contents of the
663
1054
where it may be useful for debugging. See also run_captured.
665
1056
:param stdin: A string to be used as stdin for the command.
1057
:param retcode: The status code the command should return
1058
:param working_dir: The directory to run the command in
667
1060
retcode = kwargs.pop('retcode', 0)
1061
encoding = kwargs.pop('encoding', None)
668
1062
stdin = kwargs.pop('stdin', None)
669
return self.run_bzr_captured(args, retcode, stdin)
1063
working_dir = kwargs.pop('working_dir', None)
1064
return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
1065
stdin=stdin, working_dir=working_dir)
1067
def run_bzr_decode(self, *args, **kwargs):
1068
if 'encoding' in kwargs:
1069
encoding = kwargs['encoding']
1071
encoding = bzrlib.user_encoding
1072
return self.run_bzr(*args, **kwargs)[0].decode(encoding)
1074
def run_bzr_error(self, error_regexes, *args, **kwargs):
1075
"""Run bzr, and check that stderr contains the supplied regexes
1077
:param error_regexes: Sequence of regular expressions which
1078
must each be found in the error output. The relative ordering
1080
:param args: command-line arguments for bzr
1081
:param kwargs: Keyword arguments which are interpreted by run_bzr
1082
This function changes the default value of retcode to be 3,
1083
since in most cases this is run when you expect bzr to fail.
1084
:return: (out, err) The actual output of running the command (in case you
1085
want to do more inspection)
1088
# Make sure that commit is failing because there is nothing to do
1089
self.run_bzr_error(['no changes to commit'],
1090
'commit', '-m', 'my commit comment')
1091
# Make sure --strict is handling an unknown file, rather than
1092
# giving us the 'nothing to do' error
1093
self.build_tree(['unknown'])
1094
self.run_bzr_error(['Commit refused because there are unknown files'],
1095
'commit', '--strict', '-m', 'my commit comment')
1097
kwargs.setdefault('retcode', 3)
1098
out, err = self.run_bzr(*args, **kwargs)
1099
for regex in error_regexes:
1100
self.assertContainsRe(err, regex)
1103
def run_bzr_subprocess(self, *args, **kwargs):
1104
"""Run bzr in a subprocess for testing.
1106
This starts a new Python interpreter and runs bzr in there.
1107
This should only be used for tests that have a justifiable need for
1108
this isolation: e.g. they are testing startup time, or signal
1109
handling, or early startup code, etc. Subprocess code can't be
1110
profiled or debugged so easily.
1112
:param retcode: The status code that is expected. Defaults to 0. If
1113
None is supplied, the status code is not checked.
1114
:param env_changes: A dictionary which lists changes to environment
1115
variables. A value of None will unset the env variable.
1116
The values must be strings. The change will only occur in the
1117
child, so you don't need to fix the environment after running.
1118
:param universal_newlines: Convert CRLF => LF
1119
:param allow_plugins: By default the subprocess is run with
1120
--no-plugins to ensure test reproducibility. Also, it is possible
1121
for system-wide plugins to create unexpected output on stderr,
1122
which can cause unnecessary test failures.
1124
env_changes = kwargs.get('env_changes', {})
1125
working_dir = kwargs.get('working_dir', None)
1126
allow_plugins = kwargs.get('allow_plugins', False)
1127
process = self.start_bzr_subprocess(args, env_changes=env_changes,
1128
working_dir=working_dir,
1129
allow_plugins=allow_plugins)
1130
# We distinguish between retcode=None and retcode not passed.
1131
supplied_retcode = kwargs.get('retcode', 0)
1132
return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
1133
universal_newlines=kwargs.get('universal_newlines', False),
1136
def start_bzr_subprocess(self, process_args, env_changes=None,
1137
skip_if_plan_to_signal=False,
1139
allow_plugins=False):
1140
"""Start bzr in a subprocess for testing.
1142
This starts a new Python interpreter and runs bzr in there.
1143
This should only be used for tests that have a justifiable need for
1144
this isolation: e.g. they are testing startup time, or signal
1145
handling, or early startup code, etc. Subprocess code can't be
1146
profiled or debugged so easily.
1148
:param process_args: a list of arguments to pass to the bzr executable,
1149
for example `['--version']`.
1150
:param env_changes: A dictionary which lists changes to environment
1151
variables. A value of None will unset the env variable.
1152
The values must be strings. The change will only occur in the
1153
child, so you don't need to fix the environment after running.
1154
:param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
1156
:param allow_plugins: If False (default) pass --no-plugins to bzr.
1158
:returns: Popen object for the started process.
1160
if skip_if_plan_to_signal:
1161
if not getattr(os, 'kill', None):
1162
raise TestSkipped("os.kill not available.")
1164
if env_changes is None:
1168
def cleanup_environment():
1169
for env_var, value in env_changes.iteritems():
1170
old_env[env_var] = osutils.set_or_unset_env(env_var, value)
1172
def restore_environment():
1173
for env_var, value in old_env.iteritems():
1174
osutils.set_or_unset_env(env_var, value)
1176
bzr_path = self.get_bzr_path()
1179
if working_dir is not None:
1180
cwd = osutils.getcwd()
1181
os.chdir(working_dir)
1184
# win32 subprocess doesn't support preexec_fn
1185
# so we will avoid using it on all platforms, just to
1186
# make sure the code path is used, and we don't break on win32
1187
cleanup_environment()
1188
command = [sys.executable, bzr_path]
1189
if not allow_plugins:
1190
command.append('--no-plugins')
1191
command.extend(process_args)
1192
process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
1194
restore_environment()
1200
def _popen(self, *args, **kwargs):
1201
"""Place a call to Popen.
1203
Allows tests to override this method to intercept the calls made to
1204
Popen for introspection.
1206
return Popen(*args, **kwargs)
1208
def get_bzr_path(self):
1209
"""Return the path of the 'bzr' executable for this test suite."""
1210
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
1211
if not os.path.isfile(bzr_path):
1212
# We are probably installed. Assume sys.argv is the right file
1213
bzr_path = sys.argv[0]
1216
def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
1217
universal_newlines=False, process_args=None):
1218
"""Finish the execution of process.
1220
:param process: the Popen object returned from start_bzr_subprocess.
1221
:param retcode: The status code that is expected. Defaults to 0. If
1222
None is supplied, the status code is not checked.
1223
:param send_signal: an optional signal to send to the process.
1224
:param universal_newlines: Convert CRLF => LF
1225
:returns: (stdout, stderr)
1227
if send_signal is not None:
1228
os.kill(process.pid, send_signal)
1229
out, err = process.communicate()
1231
if universal_newlines:
1232
out = out.replace('\r\n', '\n')
1233
err = err.replace('\r\n', '\n')
1235
if retcode is not None and retcode != process.returncode:
1236
if process_args is None:
1237
process_args = "(unknown args)"
1238
mutter('Output of bzr %s:\n%s', process_args, out)
1239
mutter('Error for bzr %s:\n%s', process_args, err)
1240
self.fail('Command bzr %s failed with retcode %s != %s'
1241
% (process_args, retcode, process.returncode))
671
1244
def check_inventory_shape(self, inv, shape):
672
1245
"""Compare an inventory to a list of expected names.
731
1305
base_rev = common_ancestor(branch_from.last_revision(),
732
1306
wt_to.branch.last_revision(),
733
1307
wt_to.branch.repository)
734
merge_inner(wt_to.branch, branch_from.basis_tree(),
1308
merge_inner(wt_to.branch, branch_from.basis_tree(),
735
1309
wt_to.branch.repository.revision_tree(base_rev),
736
1310
this_tree=wt_to)
737
wt_to.add_pending_merge(branch_from.last_revision())
1311
wt_to.add_parent_tree_id(branch_from.last_revision())
740
1314
BzrTestBase = TestCase
1317
class TestCaseWithMemoryTransport(TestCase):
1318
"""Common test class for tests that do not need disk resources.
1320
Tests that need disk resources should derive from TestCaseWithTransport.
1322
TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
1324
For TestCaseWithMemoryTransport the test_home_dir is set to the name of
1325
a directory which does not exist. This serves to help ensure test isolation
1326
is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
1327
must exist. However, TestCaseWithMemoryTransport does not offer local
1328
file defaults for the transport in tests, nor does it obey the command line
1329
override, so tests that accidentally write to the common directory should
1337
def __init__(self, methodName='runTest'):
1338
# allow test parameterisation after test construction and before test
1339
# execution. Variables that the parameteriser sets need to be
1340
# ones that are not set by setUp, or setUp will trash them.
1341
super(TestCaseWithMemoryTransport, self).__init__(methodName)
1342
self.transport_server = default_transport
1343
self.transport_readonly_server = None
1345
def get_transport(self):
1346
"""Return a writeable transport for the test scratch space"""
1347
t = get_transport(self.get_url())
1348
self.assertFalse(t.is_readonly())
1351
def get_readonly_transport(self):
1352
"""Return a readonly transport for the test scratch space
1354
This can be used to test that operations which should only need
1355
readonly access in fact do not try to write.
1357
t = get_transport(self.get_readonly_url())
1358
self.assertTrue(t.is_readonly())
1361
def create_transport_readonly_server(self):
1362
"""Create a transport server from class defined at init.
1364
This is mostly a hook for daughter classes.
1366
return self.transport_readonly_server()
1368
def get_readonly_server(self):
1369
"""Get the server instance for the readonly transport
1371
This is useful for some tests with specific servers to do diagnostics.
1373
if self.__readonly_server is None:
1374
if self.transport_readonly_server is None:
1375
# readonly decorator requested
1376
# bring up the server
1378
self.__readonly_server = ReadonlyServer()
1379
self.__readonly_server.setUp(self.__server)
1381
self.__readonly_server = self.create_transport_readonly_server()
1382
self.__readonly_server.setUp()
1383
self.addCleanup(self.__readonly_server.tearDown)
1384
return self.__readonly_server
1386
def get_readonly_url(self, relpath=None):
1387
"""Get a URL for the readonly transport.
1389
This will either be backed by '.' or a decorator to the transport
1390
used by self.get_url()
1391
relpath provides for clients to get a path relative to the base url.
1392
These should only be downwards relative, not upwards.
1394
base = self.get_readonly_server().get_url()
1395
if relpath is not None:
1396
if not base.endswith('/'):
1398
base = base + relpath
1401
def get_server(self):
1402
"""Get the read/write server instance.
1404
This is useful for some tests with specific servers that need
1407
For TestCaseWithMemoryTransport this is always a MemoryServer, and there
1408
is no means to override it.
1410
if self.__server is None:
1411
self.__server = MemoryServer()
1412
self.__server.setUp()
1413
self.addCleanup(self.__server.tearDown)
1414
return self.__server
1416
def get_url(self, relpath=None):
1417
"""Get a URL (or maybe a path) for the readwrite transport.
1419
This will either be backed by '.' or to an equivalent non-file based
1421
relpath provides for clients to get a path relative to the base url.
1422
These should only be downwards relative, not upwards.
1424
base = self.get_server().get_url()
1425
if relpath is not None and relpath != '.':
1426
if not base.endswith('/'):
1428
# XXX: Really base should be a url; we did after all call
1429
# get_url()! But sometimes it's just a path (from
1430
# LocalAbspathServer), and it'd be wrong to append urlescaped data
1431
# to a non-escaped local path.
1432
if base.startswith('./') or base.startswith('/'):
1435
base += urlutils.escape(relpath)
1438
def _make_test_root(self):
1439
if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1443
root = u'test%04d.tmp' % i
1447
if e.errno == errno.EEXIST:
1452
# successfully created
1453
TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
1455
# make a fake bzr directory there to prevent any tests propagating
1456
# up onto the source directory's real branch
1457
bzrdir.BzrDir.create_standalone_workingtree(
1458
TestCaseWithMemoryTransport.TEST_ROOT)
1460
def makeAndChdirToTestDir(self):
1461
"""Create a temporary directories for this one test.
1463
This must set self.test_home_dir and self.test_dir and chdir to
1466
For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1468
os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1469
self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1470
self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1472
def make_branch(self, relpath, format=None):
1473
"""Create a branch on the transport at relpath."""
1474
repo = self.make_repository(relpath, format=format)
1475
return repo.bzrdir.create_branch()
1477
def make_bzrdir(self, relpath, format=None):
1479
# might be a relative or absolute path
1480
maybe_a_url = self.get_url(relpath)
1481
segments = maybe_a_url.rsplit('/', 1)
1482
t = get_transport(maybe_a_url)
1483
if len(segments) > 1 and segments[-1] not in ('', '.'):
1486
except errors.FileExists:
1490
if isinstance(format, basestring):
1491
format = bzrdir.format_registry.make_bzrdir(format)
1492
return format.initialize_on_transport(t)
1493
except errors.UninitializableFormat:
1494
raise TestSkipped("Format %s is not initializable." % format)
1496
def make_repository(self, relpath, shared=False, format=None):
1497
"""Create a repository on our default transport at relpath."""
1498
made_control = self.make_bzrdir(relpath, format=format)
1499
return made_control.create_repository(shared=shared)
1501
def make_branch_and_memory_tree(self, relpath, format=None):
1502
"""Create a branch on the default transport and a MemoryTree for it."""
1503
b = self.make_branch(relpath, format=format)
1504
return memorytree.MemoryTree.create_on_branch(b)
1506
def overrideEnvironmentForTesting(self):
1507
os.environ['HOME'] = self.test_home_dir
1508
os.environ['BZR_HOME'] = self.test_home_dir
1511
super(TestCaseWithMemoryTransport, self).setUp()
1512
self._make_test_root()
1513
_currentdir = os.getcwdu()
1514
def _leaveDirectory():
1515
os.chdir(_currentdir)
1516
self.addCleanup(_leaveDirectory)
1517
self.makeAndChdirToTestDir()
1518
self.overrideEnvironmentForTesting()
1519
self.__readonly_server = None
1520
self.__server = None
743
class TestCaseInTempDir(TestCase):
1523
class TestCaseInTempDir(TestCaseWithMemoryTransport):
744
1524
"""Derived class that runs a test within a temporary directory.
746
1526
This is useful for tests that need to create a branch, etc.
831
1607
VFS's. If the transport is readonly or None,
832
1608
"." is opened automatically.
834
# XXX: It's OK to just create them using forward slashes on windows?
1610
# It's OK to just create them using forward slashes on windows.
835
1611
if transport is None or transport.is_readonly():
836
1612
transport = get_transport(".")
837
1613
for name in shape:
838
1614
self.assert_(isinstance(name, basestring))
839
1615
if name[-1] == '/':
840
transport.mkdir(urlescape(name[:-1]))
1616
transport.mkdir(urlutils.escape(name[:-1]))
842
1618
if line_endings == 'binary':
844
1620
elif line_endings == 'native':
845
1621
end = os.linesep
847
raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
848
content = "contents of %s%s" % (name, end)
849
transport.put(urlescape(name), StringIO(content))
1623
raise errors.BzrError(
1624
'Invalid line ending request %r' % line_endings)
1625
content = "contents of %s%s" % (name.encode('utf-8'), end)
1626
transport.put_bytes_non_atomic(urlutils.escape(name), content)
851
1628
def build_tree_contents(self, shape):
852
1629
build_tree_contents(shape)
1631
def assertFileEqual(self, content, path):
1632
"""Fail if path does not contain 'content'."""
1633
self.failUnlessExists(path)
1634
# TODO: jam 20060427 Shouldn't this be 'rb'?
1635
self.assertEqualDiff(content, open(path, 'r').read())
854
1637
def failUnlessExists(self, path):
855
1638
"""Fail unless path, which may be abs or relative, exists."""
856
self.failUnless(osutils.lexists(path))
1639
self.failUnless(osutils.lexists(path),path+" does not exist")
858
1641
def failIfExists(self, path):
859
1642
"""Fail if path, which may be abs or relative, exists."""
860
self.failIf(osutils.lexists(path))
862
def assertFileEqual(self, content, path):
863
"""Fail if path does not contain 'content'."""
864
self.failUnless(osutils.lexists(path))
865
self.assertEqualDiff(content, open(path, 'r').read())
1643
self.failIf(osutils.lexists(path),path+" exists")
868
1646
class TestCaseWithTransport(TestCaseInTempDir):
879
1657
readwrite one must both define get_url() as resolving to os.getcwd().
882
def __init__(self, methodName='testMethod'):
883
super(TestCaseWithTransport, self).__init__(methodName)
884
self.__readonly_server = None
886
self.transport_server = default_transport
887
self.transport_readonly_server = None
889
def get_readonly_url(self, relpath=None):
890
"""Get a URL for the readonly transport.
892
This will either be backed by '.' or a decorator to the transport
893
used by self.get_url()
894
relpath provides for clients to get a path relative to the base url.
895
These should only be downwards relative, not upwards.
897
base = self.get_readonly_server().get_url()
898
if relpath is not None:
899
if not base.endswith('/'):
901
base = base + relpath
904
def get_readonly_server(self):
905
"""Get the server instance for the readonly transport
907
This is useful for some tests with specific servers to do diagnostics.
909
if self.__readonly_server is None:
910
if self.transport_readonly_server is None:
911
# readonly decorator requested
912
# bring up the server
914
self.__readonly_server = ReadonlyServer()
915
self.__readonly_server.setUp(self.__server)
917
self.__readonly_server = self.transport_readonly_server()
918
self.__readonly_server.setUp()
919
self.addCleanup(self.__readonly_server.tearDown)
920
return self.__readonly_server
1660
def create_transport_server(self):
1661
"""Create a transport server from class defined at init.
1663
This is mostly a hook for daughter classes.
1665
return self.transport_server()
922
1667
def get_server(self):
923
"""Get the read/write server instance.
1668
"""See TestCaseWithMemoryTransport.
925
1670
This is useful for some tests with specific servers that need
928
1673
if self.__server is None:
929
self.__server = self.transport_server()
1674
self.__server = self.create_transport_server()
930
1675
self.__server.setUp()
931
1676
self.addCleanup(self.__server.tearDown)
932
1677
return self.__server
934
def get_url(self, relpath=None):
935
"""Get a URL for the readwrite transport.
937
This will either be backed by '.' or to an equivalent non-file based
939
relpath provides for clients to get a path relative to the base url.
940
These should only be downwards relative, not upwards.
942
base = self.get_server().get_url()
943
if relpath is not None and relpath != '.':
944
if not base.endswith('/'):
946
base = base + relpath
949
def get_transport(self):
950
"""Return a writeable transport for the test scratch space"""
951
t = get_transport(self.get_url())
952
self.assertFalse(t.is_readonly())
955
def get_readonly_transport(self):
956
"""Return a readonly transport for the test scratch space
958
This can be used to test that operations which should only need
959
readonly access in fact do not try to write.
961
t = get_transport(self.get_readonly_url())
962
self.assertTrue(t.is_readonly())
965
def make_branch(self, relpath, format=None):
966
"""Create a branch on the transport at relpath."""
967
repo = self.make_repository(relpath, format=format)
968
return repo.bzrdir.create_branch()
970
def make_bzrdir(self, relpath, format=None):
972
url = self.get_url(relpath)
973
segments = relpath.split('/')
974
if segments and segments[-1] not in ('', '.'):
975
parent = self.get_url('/'.join(segments[:-1]))
976
t = get_transport(parent)
978
t.mkdir(segments[-1])
979
except errors.FileExists:
982
format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
983
# FIXME: make this use a single transport someday. RBC 20060418
984
return format.initialize_on_transport(get_transport(relpath))
985
except errors.UninitializableFormat:
986
raise TestSkipped("Format %s is not initializable." % format)
988
def make_repository(self, relpath, shared=False, format=None):
989
"""Create a repository on our default transport at relpath."""
990
made_control = self.make_bzrdir(relpath, format=format)
991
return made_control.create_repository(shared=shared)
993
1679
def make_branch_and_tree(self, relpath, format=None):
994
1680
"""Create a branch on the transport and a tree locally.
1682
If the transport is not a LocalTransport, the Tree can't be created on
1683
the transport. In that case the working tree is created in the local
1684
directory, and the returned tree's branch and repository will also be
1687
This will fail if the original default transport for this test
1688
case wasn't backed by the working directory, as the branch won't
1689
be on disk for us to open it.
1691
:param format: The BzrDirFormat.
1692
:returns: the WorkingTree.
998
1694
# TODO: always use the local disk path for the working tree,
999
1695
# this obviously requires a format that supports branch references
1105
1846
This function can be replaced if you need to change the default test
1106
1847
suite on a global basis, but it is not encouraged.
1108
from doctest import DocTestSuite
1110
global MODULES_TO_DOCTEST
1113
1850
'bzrlib.tests.test_ancestry',
1851
'bzrlib.tests.test_annotate',
1114
1852
'bzrlib.tests.test_api',
1853
'bzrlib.tests.test_atomicfile',
1115
1854
'bzrlib.tests.test_bad_files',
1116
1855
'bzrlib.tests.test_branch',
1856
'bzrlib.tests.test_bundle',
1117
1857
'bzrlib.tests.test_bzrdir',
1118
'bzrlib.tests.test_command',
1858
'bzrlib.tests.test_cache_utf8',
1859
'bzrlib.tests.test_commands',
1119
1860
'bzrlib.tests.test_commit',
1120
1861
'bzrlib.tests.test_commit_merge',
1121
1862
'bzrlib.tests.test_config',
1122
1863
'bzrlib.tests.test_conflicts',
1123
1864
'bzrlib.tests.test_decorators',
1865
'bzrlib.tests.test_delta',
1124
1866
'bzrlib.tests.test_diff',
1867
'bzrlib.tests.test_dirstate',
1125
1868
'bzrlib.tests.test_doc_generate',
1126
1869
'bzrlib.tests.test_errors',
1127
1870
'bzrlib.tests.test_escaped_store',
1871
'bzrlib.tests.test_extract',
1128
1872
'bzrlib.tests.test_fetch',
1873
'bzrlib.tests.test_ftp_transport',
1874
'bzrlib.tests.test_generate_docs',
1875
'bzrlib.tests.test_generate_ids',
1876
'bzrlib.tests.test_globbing',
1129
1877
'bzrlib.tests.test_gpg',
1130
1878
'bzrlib.tests.test_graph',
1131
1879
'bzrlib.tests.test_hashcache',
1132
1880
'bzrlib.tests.test_http',
1881
'bzrlib.tests.test_http_response',
1882
'bzrlib.tests.test_https_ca_bundle',
1133
1883
'bzrlib.tests.test_identitymap',
1884
'bzrlib.tests.test_ignores',
1134
1885
'bzrlib.tests.test_inv',
1135
1886
'bzrlib.tests.test_knit',
1887
'bzrlib.tests.test_lazy_import',
1888
'bzrlib.tests.test_lazy_regex',
1136
1889
'bzrlib.tests.test_lockdir',
1137
1890
'bzrlib.tests.test_lockable_files',
1138
1891
'bzrlib.tests.test_log',
1892
'bzrlib.tests.test_memorytree',
1139
1893
'bzrlib.tests.test_merge',
1140
1894
'bzrlib.tests.test_merge3',
1141
1895
'bzrlib.tests.test_merge_core',
1896
'bzrlib.tests.test_merge_directive',
1142
1897
'bzrlib.tests.test_missing',
1143
1898
'bzrlib.tests.test_msgeditor',
1144
1899
'bzrlib.tests.test_nonascii',
1145
1900
'bzrlib.tests.test_options',
1146
1901
'bzrlib.tests.test_osutils',
1902
'bzrlib.tests.test_osutils_encodings',
1147
1903
'bzrlib.tests.test_patch',
1904
'bzrlib.tests.test_patches',
1148
1905
'bzrlib.tests.test_permissions',
1149
1906
'bzrlib.tests.test_plugins',
1150
1907
'bzrlib.tests.test_progress',
1151
1908
'bzrlib.tests.test_reconcile',
1909
'bzrlib.tests.test_registry',
1152
1910
'bzrlib.tests.test_repository',
1911
'bzrlib.tests.test_revert',
1153
1912
'bzrlib.tests.test_revision',
1154
1913
'bzrlib.tests.test_revisionnamespaces',
1155
'bzrlib.tests.test_revprops',
1914
'bzrlib.tests.test_revisiontree',
1156
1915
'bzrlib.tests.test_rio',
1157
1916
'bzrlib.tests.test_sampler',
1158
1917
'bzrlib.tests.test_selftest',
1159
1918
'bzrlib.tests.test_setup',
1160
1919
'bzrlib.tests.test_sftp_transport',
1161
1920
'bzrlib.tests.test_smart_add',
1921
'bzrlib.tests.test_smart_transport',
1162
1922
'bzrlib.tests.test_source',
1163
1923
'bzrlib.tests.test_status',
1164
1924
'bzrlib.tests.test_store',
1925
'bzrlib.tests.test_subsume',
1165
1926
'bzrlib.tests.test_symbol_versioning',
1927
'bzrlib.tests.test_tag',
1166
1928
'bzrlib.tests.test_testament',
1167
1929
'bzrlib.tests.test_textfile',
1168
1930
'bzrlib.tests.test_textmerge',
1931
'bzrlib.tests.test_timestamp',
1169
1932
'bzrlib.tests.test_trace',
1170
1933
'bzrlib.tests.test_transactions',
1171
1934
'bzrlib.tests.test_transform',
1172
1935
'bzrlib.tests.test_transport',
1936
'bzrlib.tests.test_tree',
1937
'bzrlib.tests.test_treebuilder',
1173
1938
'bzrlib.tests.test_tsort',
1174
1939
'bzrlib.tests.test_tuned_gzip',
1175
1940
'bzrlib.tests.test_ui',
1176
1941
'bzrlib.tests.test_upgrade',
1942
'bzrlib.tests.test_urlutils',
1177
1943
'bzrlib.tests.test_versionedfile',
1944
'bzrlib.tests.test_version',
1945
'bzrlib.tests.test_version_info',
1178
1946
'bzrlib.tests.test_weave',
1179
1947
'bzrlib.tests.test_whitebox',
1180
1948
'bzrlib.tests.test_workingtree',
1949
'bzrlib.tests.test_workingtree_4',
1950
'bzrlib.tests.test_wsgi',
1181
1951
'bzrlib.tests.test_xml',
1183
1953
test_transport_implementations = [
1184
'bzrlib.tests.test_transport_implementations']
1954
'bzrlib.tests.test_transport_implementations',
1955
'bzrlib.tests.test_read_bundle',
1957
suite = TestUtil.TestSuite()
1187
1958
loader = TestUtil.TestLoader()
1959
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1188
1960
from bzrlib.transport import TransportTestProviderAdapter
1189
1961
adapter = TransportTestProviderAdapter()
1190
1962
adapt_modules(test_transport_implementations, adapter, loader, suite)
1191
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1192
1963
for package in packages_to_test():
1193
1964
suite.addTest(package.test_suite())
1194
1965
for m in MODULES_TO_TEST:
1195
1966
suite.addTest(loader.loadTestsFromModule(m))
1196
for m in (MODULES_TO_DOCTEST):
1197
suite.addTest(DocTestSuite(m))
1967
for m in MODULES_TO_DOCTEST:
1969
suite.addTest(doctest.DocTestSuite(m))
1970
except ValueError, e:
1971
print '**failed to get doctest for: %s\n%s' %(m,e)
1198
1973
for name, plugin in bzrlib.plugin.all_plugins().items():
1199
1974
if getattr(plugin, 'test_suite', None) is not None:
1200
suite.addTest(plugin.test_suite())
1975
default_encoding = sys.getdefaultencoding()
1977
plugin_suite = plugin.test_suite()
1978
except ImportError, e:
1979
bzrlib.trace.warning(
1980
'Unable to test plugin "%s": %s', name, e)
1982
suite.addTest(plugin_suite)
1983
if default_encoding != sys.getdefaultencoding():
1984
bzrlib.trace.warning(
1985
'Plugin "%s" tried to reset default encoding to: %s', name,
1986
sys.getdefaultencoding())
1988
sys.setdefaultencoding(default_encoding)