1
# Copyright (C) 2005 by Canonical Ltd
1
# Copyright (C) 2005, 2006 by Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
# TODO: Perhaps there should be an API to find out if bzr running under the
19
# test suite -- some plugins might want to avoid making intrusive changes if
20
# this is the case. However, we want behaviour under to test to diverge as
21
# little as possible, so this should be used rarely if it's added at all.
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
from cStringIO import StringIO
39
from subprocess import Popen, PIPE
25
from testsweet import run_suite
46
from bzrlib import memorytree
48
import bzrlib.bzrdir as bzrdir
26
49
import bzrlib.commands
50
import bzrlib.bundle.serializer
51
import bzrlib.errors as errors
53
import bzrlib.inventory
54
import bzrlib.iterablefile
59
# lsprof not available
61
from bzrlib.merge import merge_inner
64
import bzrlib.osutils as osutils
66
import bzrlib.progress as progress
67
from bzrlib.revision import common_ancestor
69
from bzrlib import symbol_versioning
28
70
import bzrlib.trace
71
from bzrlib.transport import get_transport
72
import bzrlib.transport
73
from bzrlib.transport.local import LocalRelpathServer
74
from bzrlib.transport.readonly import ReadonlyServer
75
from bzrlib.trace import mutter
76
from bzrlib.tests import TestUtil
77
from bzrlib.tests.TestUtil import (
81
from bzrlib.tests.treeshape import build_tree_contents
82
import bzrlib.urlutils as urlutils
83
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
85
default_transport = LocalRelpathServer
32
87
MODULES_TO_TEST = []
33
MODULES_TO_DOCTEST = []
35
from logging import debug, warning, error
88
MODULES_TO_DOCTEST = [
90
bzrlib.bundle.serializer,
105
def packages_to_test():
106
"""Return a list of packages to test.
108
The packages are not globally imported so that import failures are
109
triggered when running selftest, not when importing the command.
112
import bzrlib.tests.blackbox
113
import bzrlib.tests.branch_implementations
114
import bzrlib.tests.bzrdir_implementations
115
import bzrlib.tests.interrepository_implementations
116
import bzrlib.tests.interversionedfile_implementations
117
import bzrlib.tests.intertree_implementations
118
import bzrlib.tests.repository_implementations
119
import bzrlib.tests.revisionstore_implementations
120
import bzrlib.tests.tree_implementations
121
import bzrlib.tests.workingtree_implementations
124
bzrlib.tests.blackbox,
125
bzrlib.tests.branch_implementations,
126
bzrlib.tests.bzrdir_implementations,
127
bzrlib.tests.interrepository_implementations,
128
bzrlib.tests.interversionedfile_implementations,
129
bzrlib.tests.intertree_implementations,
130
bzrlib.tests.repository_implementations,
131
bzrlib.tests.revisionstore_implementations,
132
bzrlib.tests.tree_implementations,
133
bzrlib.tests.workingtree_implementations,
137
class _MyResult(unittest._TextTestResult):
138
"""Custom TestResult.
140
Shows output in a different format, including displaying runtime for tests.
144
def __init__(self, stream, descriptions, verbosity, pb=None,
146
"""Construct new TestResult.
148
:param bench_history: Optionally, a writable file object to accumulate
151
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
153
if bench_history is not None:
154
from bzrlib.version import _get_bzr_source_tree
155
src_tree = _get_bzr_source_tree()
158
revision_id = src_tree.get_parent_ids()[0]
160
# XXX: if this is a brand new tree, do the same as if there
164
# XXX: If there's no branch, what should we do?
166
bench_history.write("--date %s %s\n" % (time.time(), revision_id))
167
self._bench_history = bench_history
169
def extractBenchmarkTime(self, testCase):
170
"""Add a benchmark time for the current test case."""
171
self._benchmarkTime = getattr(testCase, "_benchtime", None)
173
def _elapsedTestTimeString(self):
174
"""Return a time string for the overall time the current test has taken."""
175
return self._formatTime(time.time() - self._start_time)
177
def _testTimeString(self):
178
if self._benchmarkTime is not None:
180
self._formatTime(self._benchmarkTime),
181
self._elapsedTestTimeString())
183
return " %s" % self._elapsedTestTimeString()
185
def _formatTime(self, seconds):
186
"""Format seconds as milliseconds with leading spaces."""
187
return "%5dms" % (1000 * seconds)
189
def _ellipsise_unimportant_words(self, a_string, final_width,
191
"""Add ellipses (sp?) for overly long strings.
193
:param keep_start: If true preserve the start of a_string rather
197
if len(a_string) > final_width:
198
result = a_string[:final_width-3] + '...'
202
if len(a_string) > final_width:
203
result = '...' + a_string[3-final_width:]
206
return result.ljust(final_width)
208
def startTest(self, test):
209
unittest.TestResult.startTest(self, test)
210
# In a short description, the important words are in
211
# the beginning, but in an id, the important words are
213
SHOW_DESCRIPTIONS = False
215
if not self.showAll and self.dots and self.pb is not None:
218
final_width = osutils.terminal_width()
219
final_width = final_width - 15 - 8
221
if SHOW_DESCRIPTIONS:
222
what = test.shortDescription()
224
what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
227
if what.startswith('bzrlib.tests.'):
229
what = self._ellipsise_unimportant_words(what, final_width)
231
self.stream.write(what)
232
elif self.dots and self.pb is not None:
233
self.pb.update(what, self.testsRun - 1, None)
235
self._recordTestStartTime()
237
def _recordTestStartTime(self):
238
"""Record that a test has started."""
239
self._start_time = time.time()
241
def addError(self, test, err):
242
if isinstance(err[1], TestSkipped):
243
return self.addSkipped(test, err)
244
unittest.TestResult.addError(self, test, err)
245
self.extractBenchmarkTime(test)
247
self.stream.writeln("ERROR %s" % self._testTimeString())
248
elif self.dots and self.pb is None:
249
self.stream.write('E')
251
self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
252
self.pb.note(self._ellipsise_unimportant_words(
253
test.id() + ': ERROR',
254
osutils.terminal_width()))
259
def addFailure(self, test, err):
260
unittest.TestResult.addFailure(self, test, err)
261
self.extractBenchmarkTime(test)
263
self.stream.writeln(" FAIL %s" % self._testTimeString())
264
elif self.dots and self.pb is None:
265
self.stream.write('F')
267
self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
268
self.pb.note(self._ellipsise_unimportant_words(
269
test.id() + ': FAIL',
270
osutils.terminal_width()))
275
def addSuccess(self, test):
276
self.extractBenchmarkTime(test)
277
if self._bench_history is not None:
278
if self._benchmarkTime is not None:
279
self._bench_history.write("%s %s\n" % (
280
self._formatTime(self._benchmarkTime),
283
self.stream.writeln(' OK %s' % self._testTimeString())
284
for bench_called, stats in getattr(test, '_benchcalls', []):
285
self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
286
stats.pprint(file=self.stream)
287
elif self.dots and self.pb is None:
288
self.stream.write('~')
290
self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
292
unittest.TestResult.addSuccess(self, test)
294
def addSkipped(self, test, skip_excinfo):
295
self.extractBenchmarkTime(test)
297
print >>self.stream, ' SKIP %s' % self._testTimeString()
298
print >>self.stream, ' %s' % skip_excinfo[1]
299
elif self.dots and self.pb is None:
300
self.stream.write('S')
302
self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
304
# seems best to treat this as success from point-of-view of unittest
305
# -- it actually does nothing so it barely matters :)
308
except KeyboardInterrupt:
311
self.addError(test, test.__exc_info())
313
unittest.TestResult.addSuccess(self, test)
315
def printErrorList(self, flavour, errors):
316
for test, err in errors:
317
self.stream.writeln(self.separator1)
318
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
319
if getattr(test, '_get_log', None) is not None:
321
print >>self.stream, \
322
('vvvv[log from %s]' % test.id()).ljust(78,'-')
323
print >>self.stream, test._get_log()
324
print >>self.stream, \
325
('^^^^[log from %s]' % test.id()).ljust(78,'-')
326
self.stream.writeln(self.separator2)
327
self.stream.writeln("%s" % err)
330
class TextTestRunner(object):
331
stop_on_failure = False
340
self.stream = unittest._WritelnDecorator(stream)
341
self.descriptions = descriptions
342
self.verbosity = verbosity
343
self.keep_output = keep_output
345
self._bench_history = bench_history
347
def _makeResult(self):
348
result = _MyResult(self.stream,
352
bench_history=self._bench_history)
353
result.stop_early = self.stop_on_failure
357
"Run the given test case or test suite."
358
result = self._makeResult()
359
startTime = time.time()
360
if self.pb is not None:
361
self.pb.update('Running tests', 0, test.countTestCases())
363
stopTime = time.time()
364
timeTaken = stopTime - startTime
366
self.stream.writeln(result.separator2)
367
run = result.testsRun
368
self.stream.writeln("Ran %d test%s in %.3fs" %
369
(run, run != 1 and "s" or "", timeTaken))
370
self.stream.writeln()
371
if not result.wasSuccessful():
372
self.stream.write("FAILED (")
373
failed, errored = map(len, (result.failures, result.errors))
375
self.stream.write("failures=%d" % failed)
377
if failed: self.stream.write(", ")
378
self.stream.write("errors=%d" % errored)
379
self.stream.writeln(")")
381
self.stream.writeln("OK")
382
if self.pb is not None:
383
self.pb.update('Cleaning up', 0, 1)
384
# This is still a little bogus,
385
# but only a little. Folk not using our testrunner will
386
# have to delete their temp directories themselves.
387
test_root = TestCaseInTempDir.TEST_ROOT
388
if result.wasSuccessful() or not self.keep_output:
389
if test_root is not None:
390
# If LANG=C we probably have created some bogus paths
391
# which rmtree(unicode) will fail to delete
392
# so make sure we are using rmtree(str) to delete everything
393
# except on win32, where rmtree(str) will fail
394
# since it doesn't have the property of byte-stream paths
395
# (they are either ascii or mbcs)
396
if sys.platform == 'win32':
397
# make sure we are using the unicode win32 api
398
test_root = unicode(test_root)
400
test_root = test_root.encode(
401
sys.getfilesystemencoding())
402
osutils.rmtree(test_root)
404
if self.pb is not None:
405
self.pb.note("Failed tests working directories are in '%s'\n",
409
"Failed tests working directories are in '%s'\n" %
411
TestCaseInTempDir.TEST_ROOT = None
412
if self.pb is not None:
417
def iter_suite_tests(suite):
418
"""Return all tests in a suite, recursing through nested suites"""
419
for item in suite._tests:
420
if isinstance(item, unittest.TestCase):
422
elif isinstance(item, unittest.TestSuite):
423
for r in iter_suite_tests(item):
426
raise Exception('unknown object %r inside test suite %r'
430
class TestSkipped(Exception):
431
"""Indicates that a test was intentionally skipped, rather than failing."""
37
434
class CommandFailed(Exception):
438
class StringIOWrapper(object):
439
"""A wrapper around cStringIO which just adds an encoding attribute.
441
Internally we can check sys.stdout to see what the output encoding
442
should be. However, cStringIO has no encoding attribute that we can
443
set. So we wrap it instead.
448
def __init__(self, s=None):
450
self.__dict__['_cstring'] = StringIO(s)
452
self.__dict__['_cstring'] = StringIO()
454
def __getattr__(self, name, getattr=getattr):
455
return getattr(self.__dict__['_cstring'], name)
457
def __setattr__(self, name, val):
458
if name == 'encoding':
459
self.__dict__['encoding'] = val
461
return setattr(self._cstring, name, val)
40
464
class TestCase(unittest.TestCase):
41
465
"""Base class for bzr unit tests.
46
470
Error and debug log messages are redirected from their usual
47
471
location into a temporary file, the contents of which can be
48
retrieved by _get_log().
472
retrieved by _get_log(). We use a real OS file, not an in-memory object,
473
so that it can also capture file IO. When the test completes this file
474
is read into memory and removed from disk.
50
476
There are also convenience functions to invoke bzr's command-line
51
routine, and to build and check bzr trees."""
477
routine, and to build and check bzr trees.
479
In addition to the usual method of overriding tearDown(), this class also
480
allows subclasses to register functions into the _cleanups list, which is
481
run in order as the object is torn down. It's less likely this will be
482
accidentally overlooked.
485
_log_file_name = None
487
# record lsprof data when performing benchmark calls.
488
_gather_lsprof_in_benchmarks = False
490
def __init__(self, methodName='testMethod'):
491
super(TestCase, self).__init__(methodName)
56
# this replaces the default testsweet.TestCase; we don't want logging changed
57
495
unittest.TestCase.setUp(self)
496
self._cleanEnvironment()
58
497
bzrlib.trace.disable_default_logging()
59
self._enable_file_logging()
62
def _enable_file_logging(self):
499
self._benchcalls = []
500
self._benchtime = None
502
def _ndiff_strings(self, a, b):
503
"""Return ndiff between two strings containing lines.
505
A trailing newline is added if missing to make the strings
507
if b and b[-1] != '\n':
509
if a and a[-1] != '\n':
511
difflines = difflib.ndiff(a.splitlines(True),
513
linejunk=lambda x: False,
514
charjunk=lambda x: False)
515
return ''.join(difflines)
517
def assertEqualDiff(self, a, b, message=None):
518
"""Assert two texts are equal, if not raise an exception.
520
This is intended for use with multi-line strings where it can
521
be hard to find the differences by eye.
523
# TODO: perhaps override assertEquals to call this for strings?
527
message = "texts not equal:\n"
528
raise AssertionError(message +
529
self._ndiff_strings(a, b))
531
def assertEqualMode(self, mode, mode_test):
532
self.assertEqual(mode, mode_test,
533
'mode mismatch %o != %o' % (mode, mode_test))
535
def assertStartsWith(self, s, prefix):
536
if not s.startswith(prefix):
537
raise AssertionError('string %r does not start with %r' % (s, prefix))
539
def assertEndsWith(self, s, suffix):
540
"""Asserts that s ends with suffix."""
541
if not s.endswith(suffix):
542
raise AssertionError('string %r does not end with %r' % (s, suffix))
544
def assertContainsRe(self, haystack, needle_re):
545
"""Assert that a contains something matching a regular expression."""
546
if not re.search(needle_re, haystack):
547
raise AssertionError('pattern "%s" not found in "%s"'
548
% (needle_re, haystack))
550
def assertNotContainsRe(self, haystack, needle_re):
551
"""Assert that a does not match a regular expression"""
552
if re.search(needle_re, haystack):
553
raise AssertionError('pattern "%s" found in "%s"'
554
% (needle_re, haystack))
556
def assertSubset(self, sublist, superlist):
557
"""Assert that every entry in sublist is present in superlist."""
559
for entry in sublist:
560
if entry not in superlist:
561
missing.append(entry)
563
raise AssertionError("value(s) %r not present in container %r" %
564
(missing, superlist))
566
def assertIs(self, left, right):
567
if not (left is right):
568
raise AssertionError("%r is not %r." % (left, right))
570
def assertTransportMode(self, transport, path, mode):
571
"""Fail if a path does not have mode mode.
573
If modes are not supported on this transport, the assertion is ignored.
575
if not transport._can_roundtrip_unix_modebits():
577
path_stat = transport.stat(path)
578
actual_mode = stat.S_IMODE(path_stat.st_mode)
579
self.assertEqual(mode, actual_mode,
580
'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
582
def assertIsInstance(self, obj, kls):
583
"""Fail if obj is not an instance of kls"""
584
if not isinstance(obj, kls):
585
self.fail("%r is an instance of %s rather than %s" % (
586
obj, obj.__class__, kls))
588
def _capture_warnings(self, a_callable, *args, **kwargs):
589
"""A helper for callDeprecated and applyDeprecated.
591
:param a_callable: A callable to call.
592
:param args: The positional arguments for the callable
593
:param kwargs: The keyword arguments for the callable
594
:return: A tuple (warnings, result). result is the result of calling
595
a_callable(*args, **kwargs).
598
def capture_warnings(msg, cls, stacklevel=None):
599
# we've hooked into a deprecation specific callpath,
600
# only deprecations should getting sent via it.
601
self.assertEqual(cls, DeprecationWarning)
602
local_warnings.append(msg)
603
original_warning_method = symbol_versioning.warn
604
symbol_versioning.set_warning_method(capture_warnings)
606
result = a_callable(*args, **kwargs)
608
symbol_versioning.set_warning_method(original_warning_method)
609
return (local_warnings, result)
611
def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
612
"""Call a deprecated callable without warning the user.
614
:param deprecation_format: The deprecation format that the callable
615
should have been deprecated with. This is the same type as the
616
parameter to deprecated_method/deprecated_function. If the
617
callable is not deprecated with this format, an assertion error
619
:param a_callable: A callable to call. This may be a bound method or
620
a regular function. It will be called with *args and **kwargs.
621
:param args: The positional arguments for the callable
622
:param kwargs: The keyword arguments for the callable
623
:return: The result of a_callable(*args, **kwargs)
625
call_warnings, result = self._capture_warnings(a_callable,
627
expected_first_warning = symbol_versioning.deprecation_string(
628
a_callable, deprecation_format)
629
if len(call_warnings) == 0:
630
self.fail("No assertion generated by call to %s" %
632
self.assertEqual(expected_first_warning, call_warnings[0])
635
def callDeprecated(self, expected, callable, *args, **kwargs):
636
"""Assert that a callable is deprecated in a particular way.
638
This is a very precise test for unusual requirements. The
639
applyDeprecated helper function is probably more suited for most tests
640
as it allows you to simply specify the deprecation format being used
641
and will ensure that that is issued for the function being called.
643
:param expected: a list of the deprecation warnings expected, in order
644
:param callable: The callable to call
645
:param args: The positional arguments for the callable
646
:param kwargs: The keyword arguments for the callable
648
call_warnings, result = self._capture_warnings(callable,
650
self.assertEqual(expected, call_warnings)
653
def _startLogFile(self):
654
"""Send bzr and test log messages to a temporary file.
656
The file is removed as the test is torn down.
63
658
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
65
659
self._log_file = os.fdopen(fileno, 'w+')
67
hdlr = logging.StreamHandler(self._log_file)
68
hdlr.setLevel(logging.DEBUG)
69
hdlr.setFormatter(logging.Formatter('%(levelname)8s %(message)s'))
70
logging.getLogger('').addHandler(hdlr)
71
logging.getLogger('').setLevel(logging.DEBUG)
73
debug('opened log file %s', name)
660
self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
75
661
self._log_file_name = name
79
logging.getLogger('').removeHandler(self._log_hdlr)
80
bzrlib.trace.enable_default_logging()
81
logging.debug('%s teardown', self.id())
662
self.addCleanup(self._finishLogFile)
664
def _finishLogFile(self):
665
"""Finished with the log file.
667
Read contents into memory, close, and delete.
669
if self._log_file is None:
671
bzrlib.trace.disable_test_log(self._log_nonce)
672
self._log_file.seek(0)
673
self._log_contents = self._log_file.read()
82
674
self._log_file.close()
675
os.remove(self._log_file_name)
676
self._log_file = self._log_file_name = None
678
def addCleanup(self, callable):
679
"""Arrange to run a callable when this case is torn down.
681
Callables are run in the reverse of the order they are registered,
682
ie last-in first-out.
684
if callable in self._cleanups:
685
raise ValueError("cleanup function %r already registered on %s"
687
self._cleanups.append(callable)
689
def _cleanEnvironment(self):
692
'APPDATA': os.getcwd(),
694
'BZREMAIL': None, # may still be present in the environment
696
'BZR_PROGRESS_BAR': None,
699
self.addCleanup(self._restoreEnvironment)
700
for name, value in new_env.iteritems():
701
self._captureVar(name, value)
703
def _captureVar(self, name, newvalue):
704
"""Set an environment variable, and reset it when finished."""
705
self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
707
def _restoreEnvironment(self):
708
for name, value in self.__old_env.iteritems():
709
osutils.set_or_unset_env(name, value)
83
713
unittest.TestCase.tearDown(self)
715
def time(self, callable, *args, **kwargs):
716
"""Run callable and accrue the time it takes to the benchmark time.
718
If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
719
this will cause lsprofile statistics to be gathered and stored in
722
if self._benchtime is None:
726
if not self._gather_lsprof_in_benchmarks:
727
return callable(*args, **kwargs)
729
# record this benchmark
730
ret, stats = bzrlib.lsprof.profile(callable, *args, **kwargs)
732
self._benchcalls.append(((callable, args, kwargs), stats))
735
self._benchtime += time.time() - start
737
def _runCleanups(self):
738
"""Run registered cleanup functions.
740
This should only be called from TestCase.tearDown.
742
# TODO: Perhaps this should keep running cleanups even if
744
for cleanup_fn in reversed(self._cleanups):
86
747
def log(self, *args):
89
750
def _get_log(self):
90
751
"""Return as a string the log for this test"""
91
return open(self._log_file_name).read()
752
if self._log_file_name:
753
return open(self._log_file_name).read()
755
return self._log_contents
756
# TODO: Delete the log after it's been read in
758
def capture(self, cmd, retcode=0):
759
"""Shortcut that splits cmd into words, runs, and returns stdout"""
760
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
762
def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None):
763
"""Invoke bzr and return (stdout, stderr).
765
Useful for code that wants to check the contents of the
766
output, the way error messages are presented, etc.
768
This should be the main method for tests that want to exercise the
769
overall behavior of the bzr application (rather than a unit test
770
or a functional test of the library.)
772
Much of the old code runs bzr by forking a new copy of Python, but
773
that is slower, harder to debug, and generally not necessary.
775
This runs bzr through the interface that catches and reports
776
errors, and with logging set to something approximating the
777
default, so that error reporting can be checked.
779
:param argv: arguments to invoke bzr
780
:param retcode: expected return code, or None for don't-care.
781
:param encoding: encoding for sys.stdout and sys.stderr
782
:param stdin: A string to be used as stdin for the command.
785
encoding = bzrlib.user_encoding
786
if stdin is not None:
787
stdin = StringIO(stdin)
788
stdout = StringIOWrapper()
789
stderr = StringIOWrapper()
790
stdout.encoding = encoding
791
stderr.encoding = encoding
793
self.log('run bzr: %r', argv)
794
# FIXME: don't call into logging here
795
handler = logging.StreamHandler(stderr)
796
handler.setLevel(logging.INFO)
797
logger = logging.getLogger('')
798
logger.addHandler(handler)
799
old_ui_factory = bzrlib.ui.ui_factory
800
bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
803
bzrlib.ui.ui_factory.stdin = stdin
805
result = self.apply_redirected(stdin, stdout, stderr,
806
bzrlib.commands.run_bzr_catch_errors,
809
logger.removeHandler(handler)
810
bzrlib.ui.ui_factory = old_ui_factory
812
out = stdout.getvalue()
813
err = stderr.getvalue()
815
self.log('output:\n%r', out)
817
self.log('errors:\n%r', err)
818
if retcode is not None:
819
self.assertEquals(retcode, result)
93
822
def run_bzr(self, *args, **kwargs):
94
823
"""Invoke bzr, as if it were run from the command line.
97
826
overall behavior of the bzr application (rather than a unit test
98
827
or a functional test of the library.)
100
Much of the old code runs bzr by forking a new copy of Python, but
101
that is slower, harder to debug, and generally not necessary.
103
retcode = kwargs.get('retcode', 0)
104
result = self.apply_redirected(None, None, None,
105
bzrlib.commands.run_bzr, args)
106
self.assertEquals(result, retcode)
829
This sends the stdout/stderr results into the test's log,
830
where it may be useful for debugging. See also run_captured.
832
:param stdin: A string to be used as stdin for the command.
834
retcode = kwargs.pop('retcode', 0)
835
encoding = kwargs.pop('encoding', None)
836
stdin = kwargs.pop('stdin', None)
837
return self.run_bzr_captured(args, retcode=retcode, encoding=encoding, stdin=stdin)
839
def run_bzr_decode(self, *args, **kwargs):
840
if 'encoding' in kwargs:
841
encoding = kwargs['encoding']
843
encoding = bzrlib.user_encoding
844
return self.run_bzr(*args, **kwargs)[0].decode(encoding)
846
def run_bzr_error(self, error_regexes, *args, **kwargs):
847
"""Run bzr, and check that stderr contains the supplied regexes
849
:param error_regexes: Sequence of regular expressions which
850
must each be found in the error output. The relative ordering
852
:param args: command-line arguments for bzr
853
:param kwargs: Keyword arguments which are interpreted by run_bzr
854
This function changes the default value of retcode to be 3,
855
since in most cases this is run when you expect bzr to fail.
856
:return: (out, err) The actual output of running the command (in case you
857
want to do more inspection)
860
# Make sure that commit is failing because there is nothing to do
861
self.run_bzr_error(['no changes to commit'],
862
'commit', '-m', 'my commit comment')
863
# Make sure --strict is handling an unknown file, rather than
864
# giving us the 'nothing to do' error
865
self.build_tree(['unknown'])
866
self.run_bzr_error(['Commit refused because there are unknown files'],
867
'commit', '--strict', '-m', 'my commit comment')
869
kwargs.setdefault('retcode', 3)
870
out, err = self.run_bzr(*args, **kwargs)
871
for regex in error_regexes:
872
self.assertContainsRe(err, regex)
875
def run_bzr_subprocess(self, *args, **kwargs):
876
"""Run bzr in a subprocess for testing.
878
This starts a new Python interpreter and runs bzr in there.
879
This should only be used for tests that have a justifiable need for
880
this isolation: e.g. they are testing startup time, or signal
881
handling, or early startup code, etc. Subprocess code can't be
882
profiled or debugged so easily.
884
:param retcode: The status code that is expected. Defaults to 0. If
885
None is supplied, the status code is not checked.
886
:param env_changes: A dictionary which lists changes to environment
887
variables. A value of None will unset the env variable.
888
The values must be strings. The change will only occur in the
889
child, so you don't need to fix the environment after running.
890
:param universal_newlines: Convert CRLF => LF
892
env_changes = kwargs.get('env_changes', {})
893
process = self.start_bzr_subprocess(args, env_changes=env_changes)
894
# We distinguish between retcode=None and retcode not passed.
895
supplied_retcode = kwargs.get('retcode', 0)
896
return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
897
universal_newlines=kwargs.get('universal_newlines', False),
900
def start_bzr_subprocess(self, process_args, env_changes=None,
901
skip_if_plan_to_signal=False):
902
"""Start bzr in a subprocess for testing.
904
This starts a new Python interpreter and runs bzr in there.
905
This should only be used for tests that have a justifiable need for
906
this isolation: e.g. they are testing startup time, or signal
907
handling, or early startup code, etc. Subprocess code can't be
908
profiled or debugged so easily.
910
:param process_args: a list of arguments to pass to the bzr executable,
911
for example `['--version']`.
912
:param env_changes: A dictionary which lists changes to environment
913
variables. A value of None will unset the env variable.
914
The values must be strings. The change will only occur in the
915
child, so you don't need to fix the environment after running.
916
:param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
919
:returns: Popen object for the started process.
921
if skip_if_plan_to_signal:
922
if not getattr(os, 'kill', None):
923
raise TestSkipped("os.kill not available.")
925
if env_changes is None:
929
def cleanup_environment():
930
for env_var, value in env_changes.iteritems():
931
old_env[env_var] = osutils.set_or_unset_env(env_var, value)
933
def restore_environment():
934
for env_var, value in old_env.iteritems():
935
osutils.set_or_unset_env(env_var, value)
937
bzr_path = self.get_bzr_path()
940
# win32 subprocess doesn't support preexec_fn
941
# so we will avoid using it on all platforms, just to
942
# make sure the code path is used, and we don't break on win32
943
cleanup_environment()
944
process = Popen([sys.executable, bzr_path] + list(process_args),
945
stdin=PIPE, stdout=PIPE, stderr=PIPE)
947
restore_environment()
950
def get_bzr_path(self):
951
"""Return the path of the 'bzr' executable for this test suite."""
952
bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
953
if not os.path.isfile(bzr_path):
954
# We are probably installed. Assume sys.argv is the right file
955
bzr_path = sys.argv[0]
958
def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
959
universal_newlines=False, process_args=None):
960
"""Finish the execution of process.
962
:param process: the Popen object returned from start_bzr_subprocess.
963
:param retcode: The status code that is expected. Defaults to 0. If
964
None is supplied, the status code is not checked.
965
:param send_signal: an optional signal to send to the process.
966
:param universal_newlines: Convert CRLF => LF
967
:returns: (stdout, stderr)
969
if send_signal is not None:
970
os.kill(process.pid, send_signal)
971
out, err = process.communicate()
973
if universal_newlines:
974
out = out.replace('\r\n', '\n')
975
err = err.replace('\r\n', '\n')
977
if retcode is not None and retcode != process.returncode:
978
if process_args is None:
979
process_args = "(unknown args)"
980
mutter('Output of bzr %s:\n%s', process_args, out)
981
mutter('Error for bzr %s:\n%s', process_args, err)
982
self.fail('Command bzr %s failed with retcode %s != %s'
983
% (process_args, retcode, process.returncode))
109
986
def check_inventory_shape(self, inv, shape):
111
Compare an inventory to a list of expected names.
987
"""Compare an inventory to a list of expected names.
113
989
Fail if they are not precisely equal.
181
1079
if contents != expect:
182
1080
self.log("expected: %r" % expect)
183
1081
self.log("actually: %r" % contents)
184
self.fail("contents of %s not as expected")
1082
self.fail("contents of %s not as expected" % filename)
186
1084
def _make_test_root(self):
191
1085
if TestCaseInTempDir.TEST_ROOT is not None:
193
TestCaseInTempDir.TEST_ROOT = os.path.abspath(
194
tempfile.mkdtemp(suffix='.tmp',
195
prefix=self._TEST_NAME + '-',
1089
root = u'test%04d.tmp' % i
1093
if e.errno == errno.EEXIST:
1098
# successfully created
1099
TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
198
1101
# make a fake bzr directory there to prevent any tests propagating
199
1102
# up onto the source directory's real branch
200
os.mkdir(os.path.join(TestCaseInTempDir.TEST_ROOT, '.bzr'))
1103
bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
202
1105
def setUp(self):
203
1106
super(TestCaseInTempDir, self).setUp()
205
1107
self._make_test_root()
206
self._currentdir = os.getcwdu()
207
short_id = self.id().replace('bzrlib.selftest.', '')
208
self.test_dir = os.path.join(self.TEST_ROOT, short_id)
209
os.mkdir(self.test_dir)
210
os.chdir(self.test_dir)
1108
_currentdir = os.getcwdu()
1109
# shorten the name, to avoid test failures due to path length
1110
short_id = self.id().replace('bzrlib.tests.', '') \
1111
.replace('__main__.', '')[-100:]
1112
# it's possible the same test class is run several times for
1113
# parameterized tests, so make sure the names don't collide.
1117
candidate_dir = '%s/%s.%d' % (self.TEST_ROOT, short_id, i)
1119
candidate_dir = '%s/%s' % (self.TEST_ROOT, short_id)
1120
if os.path.exists(candidate_dir):
1124
os.mkdir(candidate_dir)
1125
self.test_home_dir = candidate_dir + '/home'
1126
os.mkdir(self.test_home_dir)
1127
self.test_dir = candidate_dir + '/work'
1128
os.mkdir(self.test_dir)
1129
os.chdir(self.test_dir)
1131
os.environ['HOME'] = self.test_home_dir
1132
os.environ['APPDATA'] = self.test_home_dir
1133
def _leaveDirectory():
1134
os.chdir(_currentdir)
1135
self.addCleanup(_leaveDirectory)
214
os.chdir(self._currentdir)
215
super(TestCaseInTempDir, self).tearDown()
217
def _formcmd(self, cmd):
218
if isinstance(cmd, basestring):
221
cmd[0] = self.BZRPATH
222
if self.OVERRIDE_PYTHON:
223
cmd.insert(0, self.OVERRIDE_PYTHON)
224
self.log('$ %r' % cmd)
227
def runcmd(self, cmd, retcode=0):
228
"""Run one command and check the return code.
230
Returns a tuple of (stdout,stderr) strings.
232
If a single string is based, it is split into words.
233
For commands that are not simple space-separated words, please
234
pass a list instead."""
235
cmd = self._formcmd(cmd)
236
self.log('$ ' + ' '.join(cmd))
237
actual_retcode = subprocess.call(cmd, stdout=self._log_file,
238
stderr=self._log_file)
239
if retcode != actual_retcode:
240
raise CommandFailed("test failed: %r returned %d, expected %d"
241
% (cmd, actual_retcode, retcode))
243
def backtick(self, cmd, retcode=0):
244
"""Run a command and return its output"""
245
cmd = self._formcmd(cmd)
246
child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=self._log_file)
247
outd, errd = child.communicate()
249
actual_retcode = child.wait()
251
outd = outd.replace('\r', '')
253
if retcode != actual_retcode:
254
raise CommandFailed("test failed: %r returned %d, expected %d"
255
% (cmd, actual_retcode, retcode))
261
def build_tree(self, shape):
1137
def build_tree(self, shape, line_endings='native', transport=None):
262
1138
"""Build a test tree according to a pattern.
264
1140
shape is a sequence of file specifications. If the final
265
1141
character is '/', a directory is created.
1143
This assumes that all the elements in the tree being built are new.
267
1145
This doesn't add anything to a branch.
1146
:param line_endings: Either 'binary' or 'native'
1147
in binary mode, exact contents are written
1148
in native mode, the line endings match the
1149
default platform endings.
1151
:param transport: A transport to write to, for building trees on
1152
VFS's. If the transport is readonly or None,
1153
"." is opened automatically.
269
# XXX: It's OK to just create them using forward slashes on windows?
1155
# It's OK to just create them using forward slashes on windows.
1156
if transport is None or transport.is_readonly():
1157
transport = get_transport(".")
271
1158
for name in shape:
272
assert isinstance(name, basestring)
1159
self.assert_(isinstance(name, basestring))
273
1160
if name[-1] == '/':
277
print >>f, "contents of", name
282
class MetaTestLog(TestCase):
283
def test_logging(self):
284
"""Test logs are captured when a test fails."""
285
logging.info('an info message')
286
warning('something looks dodgy...')
287
logging.debug('hello, test is running')
291
def selftest(verbose=False, pattern=".*"):
1161
transport.mkdir(urlutils.escape(name[:-1]))
1163
if line_endings == 'binary':
1165
elif line_endings == 'native':
1168
raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
1169
content = "contents of %s%s" % (name.encode('utf-8'), end)
1170
# Technically 'put()' is the right command. However, put
1171
# uses an AtomicFile, which requires an extra rename into place
1172
# As long as the files didn't exist in the past, append() will
1173
# do the same thing as put()
1174
# On jam's machine, make_kernel_like_tree is:
1175
# put: 4.5-7.5s (averaging 6s)
1177
# put_non_atomic: 2.9-4.5s
1178
transport.put_bytes_non_atomic(urlutils.escape(name), content)
1180
def build_tree_contents(self, shape):
1181
build_tree_contents(shape)
1183
def failUnlessExists(self, path):
1184
"""Fail unless path, which may be abs or relative, exists."""
1185
self.failUnless(osutils.lexists(path))
1187
def failIfExists(self, path):
1188
"""Fail if path, which may be abs or relative, exists."""
1189
self.failIf(osutils.lexists(path))
1191
def assertFileEqual(self, content, path):
1192
"""Fail if path does not contain 'content'."""
1193
self.failUnless(osutils.lexists(path))
1194
# TODO: jam 20060427 Shouldn't this be 'rb'?
1195
self.assertEqualDiff(content, open(path, 'r').read())
1198
class TestCaseWithTransport(TestCaseInTempDir):
1199
"""A test case that provides get_url and get_readonly_url facilities.
1201
These back onto two transport servers, one for readonly access and one for
1204
If no explicit class is provided for readonly access, a
1205
ReadonlyTransportDecorator is used instead which allows the use of non disk
1206
based read write transports.
1208
If an explicit class is provided for readonly access, that server and the
1209
readwrite one must both define get_url() as resolving to os.getcwd().
1212
def __init__(self, methodName='testMethod'):
1213
super(TestCaseWithTransport, self).__init__(methodName)
1214
self.__readonly_server = None
1215
self.__server = None
1216
self.transport_server = default_transport
1217
self.transport_readonly_server = None
1219
def get_readonly_url(self, relpath=None):
1220
"""Get a URL for the readonly transport.
1222
This will either be backed by '.' or a decorator to the transport
1223
used by self.get_url()
1224
relpath provides for clients to get a path relative to the base url.
1225
These should only be downwards relative, not upwards.
1227
base = self.get_readonly_server().get_url()
1228
if relpath is not None:
1229
if not base.endswith('/'):
1231
base = base + relpath
1234
def get_readonly_server(self):
1235
"""Get the server instance for the readonly transport
1237
This is useful for some tests with specific servers to do diagnostics.
1239
if self.__readonly_server is None:
1240
if self.transport_readonly_server is None:
1241
# readonly decorator requested
1242
# bring up the server
1244
self.__readonly_server = ReadonlyServer()
1245
self.__readonly_server.setUp(self.__server)
1247
self.__readonly_server = self.transport_readonly_server()
1248
self.__readonly_server.setUp()
1249
self.addCleanup(self.__readonly_server.tearDown)
1250
return self.__readonly_server
1252
def get_server(self):
1253
"""Get the read/write server instance.
1255
This is useful for some tests with specific servers that need
1258
if self.__server is None:
1259
self.__server = self.transport_server()
1260
self.__server.setUp()
1261
self.addCleanup(self.__server.tearDown)
1262
return self.__server
1264
def get_url(self, relpath=None):
1265
"""Get a URL (or maybe a path) for the readwrite transport.
1267
This will either be backed by '.' or to an equivalent non-file based
1269
relpath provides for clients to get a path relative to the base url.
1270
These should only be downwards relative, not upwards.
1272
base = self.get_server().get_url()
1273
if relpath is not None and relpath != '.':
1274
if not base.endswith('/'):
1276
# XXX: Really base should be a url; we did after all call
1277
# get_url()! But sometimes it's just a path (from
1278
# LocalAbspathServer), and it'd be wrong to append urlescaped data
1279
# to a non-escaped local path.
1280
if base.startswith('./') or base.startswith('/'):
1283
base += urlutils.escape(relpath)
1286
def get_transport(self):
1287
"""Return a writeable transport for the test scratch space"""
1288
t = get_transport(self.get_url())
1289
self.assertFalse(t.is_readonly())
1292
def get_readonly_transport(self):
1293
"""Return a readonly transport for the test scratch space
1295
This can be used to test that operations which should only need
1296
readonly access in fact do not try to write.
1298
t = get_transport(self.get_readonly_url())
1299
self.assertTrue(t.is_readonly())
1302
def make_branch(self, relpath, format=None):
1303
"""Create a branch on the transport at relpath."""
1304
repo = self.make_repository(relpath, format=format)
1305
return repo.bzrdir.create_branch()
1307
def make_bzrdir(self, relpath, format=None):
1309
# might be a relative or absolute path
1310
maybe_a_url = self.get_url(relpath)
1311
segments = maybe_a_url.rsplit('/', 1)
1312
t = get_transport(maybe_a_url)
1313
if len(segments) > 1 and segments[-1] not in ('', '.'):
1316
except errors.FileExists:
1319
format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
1320
return format.initialize_on_transport(t)
1321
except errors.UninitializableFormat:
1322
raise TestSkipped("Format %s is not initializable." % format)
1324
def make_repository(self, relpath, shared=False, format=None):
1325
"""Create a repository on our default transport at relpath."""
1326
made_control = self.make_bzrdir(relpath, format=format)
1327
return made_control.create_repository(shared=shared)
1329
def make_branch_and_memory_tree(self, relpath):
1330
"""Create a branch on the default transport and a MemoryTree for it."""
1331
b = self.make_branch(relpath)
1332
return memorytree.MemoryTree.create_on_branch(b)
1334
def make_branch_and_tree(self, relpath, format=None):
1335
"""Create a branch on the transport and a tree locally.
1337
If the transport is not a LocalTransport, the Tree can't be created on
1338
the transport. In that case the working tree is created in the local
1339
directory, and the returned tree's branch and repository will also be
1342
This will fail if the original default transport for this test
1343
case wasn't backed by the working directory, as the branch won't
1344
be on disk for us to open it.
1346
:param format: The BzrDirFormat.
1347
:returns: the WorkingTree.
1349
# TODO: always use the local disk path for the working tree,
1350
# this obviously requires a format that supports branch references
1351
# so check for that by checking bzrdir.BzrDirFormat.get_default_format()
1353
b = self.make_branch(relpath, format=format)
1355
return b.bzrdir.create_workingtree()
1356
except errors.NotLocalUrl:
1357
# We can only make working trees locally at the moment. If the
1358
# transport can't support them, then reopen the branch on a local
1359
# transport, and create the working tree there.
1361
# Possibly we should instead keep
1362
# the non-disk-backed branch and create a local checkout?
1363
bd = bzrdir.BzrDir.open(relpath)
1364
return bd.create_workingtree()
1366
def assertIsDirectory(self, relpath, transport):
1367
"""Assert that relpath within transport is a directory.
1369
This may not be possible on all transports; in that case it propagates
1370
a TransportNotPossible.
1373
mode = transport.stat(relpath).st_mode
1374
except errors.NoSuchFile:
1375
self.fail("path %s is not a directory; no such file"
1377
if not stat.S_ISDIR(mode):
1378
self.fail("path %s is not a directory; has mode %#o"
1382
class ChrootedTestCase(TestCaseWithTransport):
1383
"""A support class that provides readonly urls outside the local namespace.
1385
This is done by checking if self.transport_server is a MemoryServer. if it
1386
is then we are chrooted already, if it is not then an HttpServer is used
1389
TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
1390
be used without needed to redo it when a different
1391
subclass is in use ?
1395
super(ChrootedTestCase, self).setUp()
1396
if not self.transport_server == bzrlib.transport.memory.MemoryServer:
1397
self.transport_readonly_server = bzrlib.transport.http.HttpServer
1400
def filter_suite_by_re(suite, pattern):
1401
result = TestUtil.TestSuite()
1402
filter_re = re.compile(pattern)
1403
for test in iter_suite_tests(suite):
1404
if filter_re.search(test.id()):
1405
result.addTest(test)
1409
def run_suite(suite, name='test', verbose=False, pattern=".*",
1410
stop_on_failure=False, keep_output=False,
1411
transport=None, lsprof_timed=None, bench_history=None):
1412
TestCaseInTempDir._TEST_NAME = name
1413
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1419
pb = progress.ProgressBar()
1420
runner = TextTestRunner(stream=sys.stdout,
1422
verbosity=verbosity,
1423
keep_output=keep_output,
1425
bench_history=bench_history)
1426
runner.stop_on_failure=stop_on_failure
1428
suite = filter_suite_by_re(suite, pattern)
1429
result = runner.run(suite)
1430
return result.wasSuccessful()
1433
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
1436
test_suite_factory=None,
1438
bench_history=None):
292
1439
"""Run the whole test suite under the enhanced runner"""
293
return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
1440
# XXX: Very ugly way to do this...
1441
# Disable warning about old formats because we don't want it to disturb
1442
# any blackbox tests.
1443
from bzrlib import repository
1444
repository._deprecation_warning_done = True
1446
global default_transport
1447
if transport is None:
1448
transport = default_transport
1449
old_transport = default_transport
1450
default_transport = transport
1452
if test_suite_factory is None:
1453
suite = test_suite()
1455
suite = test_suite_factory()
1456
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
1457
stop_on_failure=stop_on_failure, keep_output=keep_output,
1458
transport=transport,
1459
lsprof_timed=lsprof_timed,
1460
bench_history=bench_history)
1462
default_transport = old_transport
296
1465
def test_suite():
297
"""Build and return TestSuite for the whole program."""
298
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
299
import bzrlib, bzrlib.store, bzrlib.inventory, bzrlib.branch
300
import bzrlib.osutils, bzrlib.commands, bzrlib.merge3, bzrlib.plugin
301
from doctest import DocTestSuite
307
global MODULES_TO_TEST, MODULES_TO_DOCTEST
310
['bzrlib.selftest.MetaTestLog',
311
'bzrlib.selftest.testinv',
312
'bzrlib.selftest.versioning',
313
'bzrlib.selftest.testmerge3',
314
'bzrlib.selftest.testhashcache',
315
'bzrlib.selftest.teststatus',
316
'bzrlib.selftest.testlog',
317
'bzrlib.selftest.testrevisionnamespaces',
318
'bzrlib.selftest.testbranch',
319
'bzrlib.selftest.testrevision',
320
'bzrlib.selftest.test_merge_core',
321
'bzrlib.selftest.test_smart_add',
322
'bzrlib.selftest.testdiff',
323
'bzrlib.selftest.test_parent',
324
'bzrlib.selftest.test_xml',
325
'bzrlib.selftest.testfetch',
326
'bzrlib.selftest.whitebox',
327
'bzrlib.selftest.teststore',
328
'bzrlib.selftest.blackbox',
1466
"""Build and return TestSuite for the whole of bzrlib.
1468
This function can be replaced if you need to change the default test
1469
suite on a global basis, but it is not encouraged.
1472
'bzrlib.tests.test_ancestry',
1473
'bzrlib.tests.test_api',
1474
'bzrlib.tests.test_atomicfile',
1475
'bzrlib.tests.test_bad_files',
1476
'bzrlib.tests.test_branch',
1477
'bzrlib.tests.test_bundle',
1478
'bzrlib.tests.test_bzrdir',
1479
'bzrlib.tests.test_cache_utf8',
1480
'bzrlib.tests.test_command',
1481
'bzrlib.tests.test_commit',
1482
'bzrlib.tests.test_commit_merge',
1483
'bzrlib.tests.test_config',
1484
'bzrlib.tests.test_conflicts',
1485
'bzrlib.tests.test_decorators',
1486
'bzrlib.tests.test_diff',
1487
'bzrlib.tests.test_doc_generate',
1488
'bzrlib.tests.test_errors',
1489
'bzrlib.tests.test_escaped_store',
1490
'bzrlib.tests.test_fetch',
1491
'bzrlib.tests.test_ftp_transport',
1492
'bzrlib.tests.test_gpg',
1493
'bzrlib.tests.test_graph',
1494
'bzrlib.tests.test_hashcache',
1495
'bzrlib.tests.test_http',
1496
'bzrlib.tests.test_http_response',
1497
'bzrlib.tests.test_identitymap',
1498
'bzrlib.tests.test_ignores',
1499
'bzrlib.tests.test_inv',
1500
'bzrlib.tests.test_knit',
1501
'bzrlib.tests.test_lazy_import',
1502
'bzrlib.tests.test_lockdir',
1503
'bzrlib.tests.test_lockable_files',
1504
'bzrlib.tests.test_log',
1505
'bzrlib.tests.test_memorytree',
1506
'bzrlib.tests.test_merge',
1507
'bzrlib.tests.test_merge3',
1508
'bzrlib.tests.test_merge_core',
1509
'bzrlib.tests.test_missing',
1510
'bzrlib.tests.test_msgeditor',
1511
'bzrlib.tests.test_nonascii',
1512
'bzrlib.tests.test_options',
1513
'bzrlib.tests.test_osutils',
1514
'bzrlib.tests.test_patch',
1515
'bzrlib.tests.test_patches',
1516
'bzrlib.tests.test_permissions',
1517
'bzrlib.tests.test_plugins',
1518
'bzrlib.tests.test_progress',
1519
'bzrlib.tests.test_reconcile',
1520
'bzrlib.tests.test_repository',
1521
'bzrlib.tests.test_revert',
1522
'bzrlib.tests.test_revision',
1523
'bzrlib.tests.test_revisionnamespaces',
1524
'bzrlib.tests.test_revisiontree',
1525
'bzrlib.tests.test_rio',
1526
'bzrlib.tests.test_sampler',
1527
'bzrlib.tests.test_selftest',
1528
'bzrlib.tests.test_setup',
1529
'bzrlib.tests.test_sftp_transport',
1530
'bzrlib.tests.test_smart_add',
1531
'bzrlib.tests.test_smart_transport',
1532
'bzrlib.tests.test_source',
1533
'bzrlib.tests.test_status',
1534
'bzrlib.tests.test_store',
1535
'bzrlib.tests.test_symbol_versioning',
1536
'bzrlib.tests.test_testament',
1537
'bzrlib.tests.test_textfile',
1538
'bzrlib.tests.test_textmerge',
1539
'bzrlib.tests.test_trace',
1540
'bzrlib.tests.test_transactions',
1541
'bzrlib.tests.test_transform',
1542
'bzrlib.tests.test_transport',
1543
'bzrlib.tests.test_tree',
1544
'bzrlib.tests.test_treebuilder',
1545
'bzrlib.tests.test_tsort',
1546
'bzrlib.tests.test_tuned_gzip',
1547
'bzrlib.tests.test_ui',
1548
'bzrlib.tests.test_upgrade',
1549
'bzrlib.tests.test_urlutils',
1550
'bzrlib.tests.test_versionedfile',
1551
'bzrlib.tests.test_version',
1552
'bzrlib.tests.test_weave',
1553
'bzrlib.tests.test_whitebox',
1554
'bzrlib.tests.test_workingtree',
1555
'bzrlib.tests.test_xml',
331
for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,
332
bzrlib.osutils, bzrlib.commands, bzrlib.merge3):
333
if m not in MODULES_TO_DOCTEST:
334
MODULES_TO_DOCTEST.append(m)
336
TestCase.BZRPATH = os.path.join(os.path.realpath(os.path.dirname(bzrlib.__path__[0])), 'bzr')
337
print '%-30s %s' % ('bzr binary', TestCase.BZRPATH)
340
suite.addTest(TestLoader().loadTestsFromNames(testmod_names))
1557
test_transport_implementations = [
1558
'bzrlib.tests.test_transport_implementations',
1559
'bzrlib.tests.test_read_bundle',
1561
suite = TestUtil.TestSuite()
1562
loader = TestUtil.TestLoader()
1563
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1564
from bzrlib.transport import TransportTestProviderAdapter
1565
adapter = TransportTestProviderAdapter()
1566
adapt_modules(test_transport_implementations, adapter, loader, suite)
1567
for package in packages_to_test():
1568
suite.addTest(package.test_suite())
341
1569
for m in MODULES_TO_TEST:
342
suite.addTest(TestLoader().loadTestsFromModule(m))
343
for m in (MODULES_TO_DOCTEST):
344
suite.addTest(DocTestSuite(m))
345
for p in bzrlib.plugin.all_plugins:
346
if hasattr(p, 'test_suite'):
347
suite.addTest(p.test_suite())
1570
suite.addTest(loader.loadTestsFromModule(m))
1571
for m in MODULES_TO_DOCTEST:
1572
suite.addTest(doctest.DocTestSuite(m))
1573
for name, plugin in bzrlib.plugin.all_plugins().items():
1574
if getattr(plugin, 'test_suite', None) is not None:
1575
suite.addTest(plugin.test_suite())
1579
def adapt_modules(mods_list, adapter, loader, suite):
1580
"""Adapt the modules in mods_list using adapter and add to suite."""
1581
for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1582
suite.addTests(adapter.adapt(test))