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
25
from testsweet import run_suite
44
import bzrlib.bzrdir as bzrdir
26
45
import bzrlib.commands
46
import bzrlib.errors as errors
47
import bzrlib.inventory
48
import bzrlib.iterablefile
50
from bzrlib.merge import merge_inner
53
import bzrlib.osutils as osutils
55
from bzrlib.revision import common_ancestor
28
57
import bzrlib.trace
58
from bzrlib.transport import urlescape, get_transport
59
import bzrlib.transport
60
from bzrlib.transport.local import LocalRelpathServer
61
from bzrlib.transport.readonly import ReadonlyServer
62
from bzrlib.trace import mutter
63
from bzrlib.tests.TestUtil import TestLoader, TestSuite
64
from bzrlib.tests.treeshape import build_tree_contents
65
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
67
default_transport = LocalRelpathServer
32
69
MODULES_TO_TEST = []
33
MODULES_TO_DOCTEST = []
35
from logging import debug, warning, error
70
MODULES_TO_DOCTEST = [
82
def packages_to_test():
83
"""Return a list of packages to test.
85
The packages are not globally imported so that import failures are
86
triggered when running selftest, not when importing the command.
89
import bzrlib.tests.blackbox
90
import bzrlib.tests.branch_implementations
91
import bzrlib.tests.bzrdir_implementations
92
import bzrlib.tests.interrepository_implementations
93
import bzrlib.tests.interversionedfile_implementations
94
import bzrlib.tests.repository_implementations
95
import bzrlib.tests.revisionstore_implementations
96
import bzrlib.tests.workingtree_implementations
99
bzrlib.tests.blackbox,
100
bzrlib.tests.branch_implementations,
101
bzrlib.tests.bzrdir_implementations,
102
bzrlib.tests.interrepository_implementations,
103
bzrlib.tests.interversionedfile_implementations,
104
bzrlib.tests.repository_implementations,
105
bzrlib.tests.revisionstore_implementations,
106
bzrlib.tests.workingtree_implementations,
110
class _MyResult(unittest._TextTestResult):
111
"""Custom TestResult.
113
Shows output in a different format, including displaying runtime for tests.
117
def _elapsedTime(self):
118
return "%5dms" % (1000 * (time.time() - self._start_time))
120
def startTest(self, test):
121
unittest.TestResult.startTest(self, test)
122
# In a short description, the important words are in
123
# the beginning, but in an id, the important words are
125
SHOW_DESCRIPTIONS = False
127
width = osutils.terminal_width()
128
name_width = width - 15
130
if SHOW_DESCRIPTIONS:
131
what = test.shortDescription()
133
if len(what) > name_width:
134
what = what[:name_width-3] + '...'
137
if what.startswith('bzrlib.tests.'):
139
if len(what) > name_width:
140
what = '...' + what[3-name_width:]
141
what = what.ljust(name_width)
142
self.stream.write(what)
144
self._start_time = time.time()
146
def addError(self, test, err):
147
if isinstance(err[1], TestSkipped):
148
return self.addSkipped(test, err)
149
unittest.TestResult.addError(self, test, err)
151
self.stream.writeln("ERROR %s" % self._elapsedTime())
153
self.stream.write('E')
158
def addFailure(self, test, err):
159
unittest.TestResult.addFailure(self, test, err)
161
self.stream.writeln(" FAIL %s" % self._elapsedTime())
163
self.stream.write('F')
168
def addSuccess(self, test):
170
self.stream.writeln(' OK %s' % self._elapsedTime())
172
self.stream.write('~')
174
unittest.TestResult.addSuccess(self, test)
176
def addSkipped(self, test, skip_excinfo):
178
print >>self.stream, ' SKIP %s' % self._elapsedTime()
179
print >>self.stream, ' %s' % skip_excinfo[1]
181
self.stream.write('S')
183
# seems best to treat this as success from point-of-view of unittest
184
# -- it actually does nothing so it barely matters :)
185
unittest.TestResult.addSuccess(self, test)
187
def printErrorList(self, flavour, errors):
188
for test, err in errors:
189
self.stream.writeln(self.separator1)
190
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
191
if getattr(test, '_get_log', None) is not None:
193
print >>self.stream, \
194
('vvvv[log from %s]' % test.id()).ljust(78,'-')
195
print >>self.stream, test._get_log()
196
print >>self.stream, \
197
('^^^^[log from %s]' % test.id()).ljust(78,'-')
198
self.stream.writeln(self.separator2)
199
self.stream.writeln("%s" % err)
202
class TextTestRunner(unittest.TextTestRunner):
203
stop_on_failure = False
205
def _makeResult(self):
206
result = _MyResult(self.stream, self.descriptions, self.verbosity)
207
result.stop_early = self.stop_on_failure
211
def iter_suite_tests(suite):
212
"""Return all tests in a suite, recursing through nested suites"""
213
for item in suite._tests:
214
if isinstance(item, unittest.TestCase):
216
elif isinstance(item, unittest.TestSuite):
217
for r in iter_suite_tests(item):
220
raise Exception('unknown object %r inside test suite %r'
224
class TestSkipped(Exception):
225
"""Indicates that a test was intentionally skipped, rather than failing."""
37
229
class CommandFailed(Exception):
46
238
Error and debug log messages are redirected from their usual
47
239
location into a temporary file, the contents of which can be
48
retrieved by _get_log().
240
retrieved by _get_log(). We use a real OS file, not an in-memory object,
241
so that it can also capture file IO. When the test completes this file
242
is read into memory and removed from disk.
50
244
There are also convenience functions to invoke bzr's command-line
51
routine, and to build and check bzr trees."""
245
routine, and to build and check bzr trees.
247
In addition to the usual method of overriding tearDown(), this class also
248
allows subclasses to register functions into the _cleanups list, which is
249
run in order as the object is torn down. It's less likely this will be
250
accidentally overlooked.
254
_log_file_name = None
257
def __init__(self, methodName='testMethod'):
258
super(TestCase, self).__init__(methodName)
56
# this replaces the default testsweet.TestCase; we don't want logging changed
57
262
unittest.TestCase.setUp(self)
263
self._cleanEnvironment()
58
264
bzrlib.trace.disable_default_logging()
59
self._enable_file_logging()
62
def _enable_file_logging(self):
267
def _ndiff_strings(self, a, b):
268
"""Return ndiff between two strings containing lines.
270
A trailing newline is added if missing to make the strings
272
if b and b[-1] != '\n':
274
if a and a[-1] != '\n':
276
difflines = difflib.ndiff(a.splitlines(True),
278
linejunk=lambda x: False,
279
charjunk=lambda x: False)
280
return ''.join(difflines)
282
def assertEqualDiff(self, a, b, message=None):
283
"""Assert two texts are equal, if not raise an exception.
285
This is intended for use with multi-line strings where it can
286
be hard to find the differences by eye.
288
# TODO: perhaps override assertEquals to call this for strings?
292
message = "texts not equal:\n"
293
raise AssertionError(message +
294
self._ndiff_strings(a, b))
296
def assertEqualMode(self, mode, mode_test):
297
self.assertEqual(mode, mode_test,
298
'mode mismatch %o != %o' % (mode, mode_test))
300
def assertStartsWith(self, s, prefix):
301
if not s.startswith(prefix):
302
raise AssertionError('string %r does not start with %r' % (s, prefix))
304
def assertEndsWith(self, s, suffix):
305
"""Asserts that s ends with suffix."""
306
if not s.endswith(suffix):
307
raise AssertionError('string %r does not end with %r' % (s, suffix))
309
def assertContainsRe(self, haystack, needle_re):
310
"""Assert that a contains something matching a regular expression."""
311
if not re.search(needle_re, haystack):
312
raise AssertionError('pattern "%s" not found in "%s"'
313
% (needle_re, haystack))
315
def assertSubset(self, sublist, superlist):
316
"""Assert that every entry in sublist is present in superlist."""
318
for entry in sublist:
319
if entry not in superlist:
320
missing.append(entry)
322
raise AssertionError("value(s) %r not present in container %r" %
323
(missing, superlist))
325
def assertIs(self, left, right):
326
if not (left is right):
327
raise AssertionError("%r is not %r." % (left, right))
329
def assertTransportMode(self, transport, path, mode):
330
"""Fail if a path does not have mode mode.
332
If modes are not supported on this transport, the assertion is ignored.
334
if not transport._can_roundtrip_unix_modebits():
336
path_stat = transport.stat(path)
337
actual_mode = stat.S_IMODE(path_stat.st_mode)
338
self.assertEqual(mode, actual_mode,
339
'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
341
def assertIsInstance(self, obj, kls):
342
"""Fail if obj is not an instance of kls"""
343
if not isinstance(obj, kls):
344
self.fail("%r is an instance of %s rather than %s" % (
345
obj, obj.__class__, kls))
347
def _startLogFile(self):
348
"""Send bzr and test log messages to a temporary file.
350
The file is removed as the test is torn down.
63
352
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
65
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)
353
encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
354
self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
355
self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
75
356
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())
357
self.addCleanup(self._finishLogFile)
359
def _finishLogFile(self):
360
"""Finished with the log file.
362
Read contents into memory, close, and delete.
364
bzrlib.trace.disable_test_log(self._log_nonce)
365
self._log_file.seek(0)
366
self._log_contents = self._log_file.read()
82
367
self._log_file.close()
368
os.remove(self._log_file_name)
369
self._log_file = self._log_file_name = None
371
def addCleanup(self, callable):
372
"""Arrange to run a callable when this case is torn down.
374
Callables are run in the reverse of the order they are registered,
375
ie last-in first-out.
377
if callable in self._cleanups:
378
raise ValueError("cleanup function %r already registered on %s"
380
self._cleanups.append(callable)
382
def _cleanEnvironment(self):
385
'APPDATA': os.getcwd(),
390
self.addCleanup(self._restoreEnvironment)
391
for name, value in new_env.iteritems():
392
self._captureVar(name, value)
395
def _captureVar(self, name, newvalue):
396
"""Set an environment variable, preparing it to be reset when finished."""
397
self.__old_env[name] = os.environ.get(name, None)
399
if name in os.environ:
402
os.environ[name] = newvalue
405
def _restoreVar(name, value):
407
if name in os.environ:
410
os.environ[name] = value
412
def _restoreEnvironment(self):
413
for name, value in self.__old_env.iteritems():
414
self._restoreVar(name, value)
83
418
unittest.TestCase.tearDown(self)
420
def _runCleanups(self):
421
"""Run registered cleanup functions.
423
This should only be called from TestCase.tearDown.
425
# TODO: Perhaps this should keep running cleanups even if
427
for cleanup_fn in reversed(self._cleanups):
86
430
def log(self, *args):
89
433
def _get_log(self):
90
434
"""Return as a string the log for this test"""
91
return open(self._log_file_name).read()
435
if self._log_file_name:
436
return open(self._log_file_name).read()
438
return self._log_contents
439
# TODO: Delete the log after it's been read in
441
def capture(self, cmd, retcode=0):
442
"""Shortcut that splits cmd into words, runs, and returns stdout"""
443
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
445
def run_bzr_captured(self, argv, retcode=0, stdin=None):
446
"""Invoke bzr and return (stdout, stderr).
448
Useful for code that wants to check the contents of the
449
output, the way error messages are presented, etc.
451
This should be the main method for tests that want to exercise the
452
overall behavior of the bzr application (rather than a unit test
453
or a functional test of the library.)
455
Much of the old code runs bzr by forking a new copy of Python, but
456
that is slower, harder to debug, and generally not necessary.
458
This runs bzr through the interface that catches and reports
459
errors, and with logging set to something approximating the
460
default, so that error reporting can be checked.
462
argv -- arguments to invoke bzr
463
retcode -- expected return code, or None for don't-care.
464
:param stdin: A string to be used as stdin for the command.
466
if stdin is not None:
467
stdin = StringIO(stdin)
470
self.log('run bzr: %s', ' '.join(argv))
471
# FIXME: don't call into logging here
472
handler = logging.StreamHandler(stderr)
473
handler.setFormatter(bzrlib.trace.QuietFormatter())
474
handler.setLevel(logging.INFO)
475
logger = logging.getLogger('')
476
logger.addHandler(handler)
477
old_stdin = getattr(bzrlib.ui.ui_factory, "stdin", None)
478
bzrlib.ui.ui_factory.stdin = stdin
480
result = self.apply_redirected(stdin, stdout, stderr,
481
bzrlib.commands.run_bzr_catch_errors,
484
logger.removeHandler(handler)
485
bzrlib.ui.ui_factory.stdin = old_stdin
486
out = stdout.getvalue()
487
err = stderr.getvalue()
489
self.log('output:\n%s', out)
491
self.log('errors:\n%s', err)
492
if retcode is not None:
493
self.assertEquals(result, retcode)
93
496
def run_bzr(self, *args, **kwargs):
94
497
"""Invoke bzr, as if it were run from the command line.
181
604
if contents != expect:
182
605
self.log("expected: %r" % expect)
183
606
self.log("actually: %r" % contents)
184
self.fail("contents of %s not as expected")
607
self.fail("contents of %s not as expected" % filename)
186
609
def _make_test_root(self):
191
610
if TestCaseInTempDir.TEST_ROOT is not None:
193
TestCaseInTempDir.TEST_ROOT = os.path.abspath(
194
tempfile.mkdtemp(suffix='.tmp',
195
prefix=self._TEST_NAME + '-',
614
root = u'test%04d.tmp' % i
618
if e.errno == errno.EEXIST:
623
# successfully created
624
TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
198
626
# make a fake bzr directory there to prevent any tests propagating
199
627
# up onto the source directory's real branch
200
os.mkdir(os.path.join(TestCaseInTempDir.TEST_ROOT, '.bzr'))
628
bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
203
631
super(TestCaseInTempDir, self).setUp()
205
632
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)
633
_currentdir = os.getcwdu()
634
# shorten the name, to avoid test failures due to path length
635
short_id = self.id().replace('bzrlib.tests.', '') \
636
.replace('__main__.', '')[-100:]
637
# it's possible the same test class is run several times for
638
# parameterized tests, so make sure the names don't collide.
642
candidate_dir = '%s/%s.%d' % (self.TEST_ROOT, short_id, i)
644
candidate_dir = '%s/%s' % (self.TEST_ROOT, short_id)
645
if os.path.exists(candidate_dir):
649
self.test_dir = candidate_dir
650
os.mkdir(self.test_dir)
651
os.chdir(self.test_dir)
653
os.environ['HOME'] = self.test_dir
654
os.environ['APPDATA'] = self.test_dir
655
def _leaveDirectory():
656
os.chdir(_currentdir)
657
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):
659
def build_tree(self, shape, line_endings='native', transport=None):
262
660
"""Build a test tree according to a pattern.
264
662
shape is a sequence of file specifications. If the final
265
663
character is '/', a directory is created.
267
665
This doesn't add anything to a branch.
666
:param line_endings: Either 'binary' or 'native'
667
in binary mode, exact contents are written
668
in native mode, the line endings match the
669
default platform endings.
671
:param transport: A transport to write to, for building trees on
672
VFS's. If the transport is readonly or None,
673
"." is opened automatically.
269
675
# XXX: It's OK to just create them using forward slashes on windows?
676
if transport is None or transport.is_readonly():
677
transport = get_transport(".")
271
678
for name in shape:
272
assert isinstance(name, basestring)
679
self.assert_(isinstance(name, basestring))
273
680
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=".*"):
681
transport.mkdir(urlescape(name[:-1]))
683
if line_endings == 'binary':
685
elif line_endings == 'native':
688
raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
689
content = "contents of %s%s" % (name, end)
690
transport.put(urlescape(name), StringIO(content))
692
def build_tree_contents(self, shape):
693
build_tree_contents(shape)
695
def failUnlessExists(self, path):
696
"""Fail unless path, which may be abs or relative, exists."""
697
self.failUnless(osutils.lexists(path))
699
def failIfExists(self, path):
700
"""Fail if path, which may be abs or relative, exists."""
701
self.failIf(osutils.lexists(path))
703
def assertFileEqual(self, content, path):
704
"""Fail if path does not contain 'content'."""
705
self.failUnless(osutils.lexists(path))
706
self.assertEqualDiff(content, open(path, 'r').read())
709
class TestCaseWithTransport(TestCaseInTempDir):
710
"""A test case that provides get_url and get_readonly_url facilities.
712
These back onto two transport servers, one for readonly access and one for
715
If no explicit class is provided for readonly access, a
716
ReadonlyTransportDecorator is used instead which allows the use of non disk
717
based read write transports.
719
If an explicit class is provided for readonly access, that server and the
720
readwrite one must both define get_url() as resolving to os.getcwd().
723
def __init__(self, methodName='testMethod'):
724
super(TestCaseWithTransport, self).__init__(methodName)
725
self.__readonly_server = None
727
self.transport_server = default_transport
728
self.transport_readonly_server = None
730
def get_readonly_url(self, relpath=None):
731
"""Get a URL for the readonly transport.
733
This will either be backed by '.' or a decorator to the transport
734
used by self.get_url()
735
relpath provides for clients to get a path relative to the base url.
736
These should only be downwards relative, not upwards.
738
base = self.get_readonly_server().get_url()
739
if relpath is not None:
740
if not base.endswith('/'):
742
base = base + relpath
745
def get_readonly_server(self):
746
"""Get the server instance for the readonly transport
748
This is useful for some tests with specific servers to do diagnostics.
750
if self.__readonly_server is None:
751
if self.transport_readonly_server is None:
752
# readonly decorator requested
753
# bring up the server
755
self.__readonly_server = ReadonlyServer()
756
self.__readonly_server.setUp(self.__server)
758
self.__readonly_server = self.transport_readonly_server()
759
self.__readonly_server.setUp()
760
self.addCleanup(self.__readonly_server.tearDown)
761
return self.__readonly_server
763
def get_server(self):
764
"""Get the read/write server instance.
766
This is useful for some tests with specific servers that need
769
if self.__server is None:
770
self.__server = self.transport_server()
771
self.__server.setUp()
772
self.addCleanup(self.__server.tearDown)
775
def get_url(self, relpath=None):
776
"""Get a URL for the readwrite transport.
778
This will either be backed by '.' or to an equivalent non-file based
780
relpath provides for clients to get a path relative to the base url.
781
These should only be downwards relative, not upwards.
783
base = self.get_server().get_url()
784
if relpath is not None and relpath != '.':
785
if not base.endswith('/'):
787
base = base + relpath
790
def get_transport(self):
791
"""Return a writeable transport for the test scratch space"""
792
t = get_transport(self.get_url())
793
self.assertFalse(t.is_readonly())
796
def get_readonly_transport(self):
797
"""Return a readonly transport for the test scratch space
799
This can be used to test that operations which should only need
800
readonly access in fact do not try to write.
802
t = get_transport(self.get_readonly_url())
803
self.assertTrue(t.is_readonly())
806
def make_branch(self, relpath, format=None):
807
"""Create a branch on the transport at relpath."""
808
repo = self.make_repository(relpath, format=format)
809
return repo.bzrdir.create_branch()
811
def make_bzrdir(self, relpath, format=None):
813
url = self.get_url(relpath)
814
segments = relpath.split('/')
815
if segments and segments[-1] not in ('', '.'):
816
parent = self.get_url('/'.join(segments[:-1]))
817
t = get_transport(parent)
819
t.mkdir(segments[-1])
820
except errors.FileExists:
823
format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
824
# FIXME: make this use a single transport someday. RBC 20060418
825
return format.initialize_on_transport(get_transport(relpath))
826
except errors.UninitializableFormat:
827
raise TestSkipped("Format %s is not initializable." % format)
829
def make_repository(self, relpath, shared=False, format=None):
830
"""Create a repository on our default transport at relpath."""
831
made_control = self.make_bzrdir(relpath, format=format)
832
return made_control.create_repository(shared=shared)
834
def make_branch_and_tree(self, relpath, format=None):
835
"""Create a branch on the transport and a tree locally.
839
# TODO: always use the local disk path for the working tree,
840
# this obviously requires a format that supports branch references
841
# so check for that by checking bzrdir.BzrDirFormat.get_default_format()
843
b = self.make_branch(relpath, format=format)
845
return b.bzrdir.create_workingtree()
846
except errors.NotLocalUrl:
847
# new formats - catch No tree error and create
848
# a branch reference and a checkout.
849
# old formats at that point - raise TestSkipped.
851
return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
853
def assertIsDirectory(self, relpath, transport):
854
"""Assert that relpath within transport is a directory.
856
This may not be possible on all transports; in that case it propagates
857
a TransportNotPossible.
860
mode = transport.stat(relpath).st_mode
861
except errors.NoSuchFile:
862
self.fail("path %s is not a directory; no such file"
864
if not stat.S_ISDIR(mode):
865
self.fail("path %s is not a directory; has mode %#o"
869
class ChrootedTestCase(TestCaseWithTransport):
870
"""A support class that provides readonly urls outside the local namespace.
872
This is done by checking if self.transport_server is a MemoryServer. if it
873
is then we are chrooted already, if it is not then an HttpServer is used
876
TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
877
be used without needed to redo it when a different
882
super(ChrootedTestCase, self).setUp()
883
if not self.transport_server == bzrlib.transport.memory.MemoryServer:
884
self.transport_readonly_server = bzrlib.transport.http.HttpServer
887
def filter_suite_by_re(suite, pattern):
889
filter_re = re.compile(pattern)
890
for test in iter_suite_tests(suite):
891
if filter_re.search(test.id()):
896
def run_suite(suite, name='test', verbose=False, pattern=".*",
897
stop_on_failure=False, keep_output=False,
899
TestCaseInTempDir._TEST_NAME = name
904
runner = TextTestRunner(stream=sys.stdout,
907
runner.stop_on_failure=stop_on_failure
909
suite = filter_suite_by_re(suite, pattern)
910
result = runner.run(suite)
911
# This is still a little bogus,
912
# but only a little. Folk not using our testrunner will
913
# have to delete their temp directories themselves.
914
test_root = TestCaseInTempDir.TEST_ROOT
915
if result.wasSuccessful() or not keep_output:
916
if test_root is not None:
917
print 'Deleting test root %s...' % test_root
919
osutils.rmtree(test_root)
923
print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
924
return result.wasSuccessful()
927
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
292
930
"""Run the whole test suite under the enhanced runner"""
293
return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
931
global default_transport
932
if transport is None:
933
transport = default_transport
934
old_transport = default_transport
935
default_transport = transport
938
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
939
stop_on_failure=stop_on_failure, keep_output=keep_output,
942
default_transport = old_transport
296
946
def test_suite():
297
947
"""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
948
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',
950
global MODULES_TO_DOCTEST
953
'bzrlib.tests.test_ancestry',
954
'bzrlib.tests.test_api',
955
'bzrlib.tests.test_bad_files',
956
'bzrlib.tests.test_branch',
957
'bzrlib.tests.test_bzrdir',
958
'bzrlib.tests.test_command',
959
'bzrlib.tests.test_commit',
960
'bzrlib.tests.test_commit_merge',
961
'bzrlib.tests.test_config',
962
'bzrlib.tests.test_conflicts',
963
'bzrlib.tests.test_decorators',
964
'bzrlib.tests.test_diff',
965
'bzrlib.tests.test_doc_generate',
966
'bzrlib.tests.test_errors',
967
'bzrlib.tests.test_escaped_store',
968
'bzrlib.tests.test_fetch',
969
'bzrlib.tests.test_gpg',
970
'bzrlib.tests.test_graph',
971
'bzrlib.tests.test_hashcache',
972
'bzrlib.tests.test_http',
973
'bzrlib.tests.test_identitymap',
974
'bzrlib.tests.test_inv',
975
'bzrlib.tests.test_knit',
976
'bzrlib.tests.test_lockdir',
977
'bzrlib.tests.test_lockable_files',
978
'bzrlib.tests.test_log',
979
'bzrlib.tests.test_merge',
980
'bzrlib.tests.test_merge3',
981
'bzrlib.tests.test_merge_core',
982
'bzrlib.tests.test_missing',
983
'bzrlib.tests.test_msgeditor',
984
'bzrlib.tests.test_nonascii',
985
'bzrlib.tests.test_options',
986
'bzrlib.tests.test_osutils',
987
'bzrlib.tests.test_patch',
988
'bzrlib.tests.test_permissions',
989
'bzrlib.tests.test_plugins',
990
'bzrlib.tests.test_progress',
991
'bzrlib.tests.test_reconcile',
992
'bzrlib.tests.test_repository',
993
'bzrlib.tests.test_revision',
994
'bzrlib.tests.test_revisionnamespaces',
995
'bzrlib.tests.test_revprops',
996
'bzrlib.tests.test_rio',
997
'bzrlib.tests.test_sampler',
998
'bzrlib.tests.test_selftest',
999
'bzrlib.tests.test_setup',
1000
'bzrlib.tests.test_sftp_transport',
1001
'bzrlib.tests.test_smart_add',
1002
'bzrlib.tests.test_source',
1003
'bzrlib.tests.test_store',
1004
'bzrlib.tests.test_symbol_versioning',
1005
'bzrlib.tests.test_testament',
1006
'bzrlib.tests.test_textfile',
1007
'bzrlib.tests.test_textmerge',
1008
'bzrlib.tests.test_trace',
1009
'bzrlib.tests.test_transactions',
1010
'bzrlib.tests.test_transform',
1011
'bzrlib.tests.test_transport',
1012
'bzrlib.tests.test_tsort',
1013
'bzrlib.tests.test_tuned_gzip',
1014
'bzrlib.tests.test_ui',
1015
'bzrlib.tests.test_upgrade',
1016
'bzrlib.tests.test_versionedfile',
1017
'bzrlib.tests.test_weave',
1018
'bzrlib.tests.test_whitebox',
1019
'bzrlib.tests.test_workingtree',
1020
'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)
1022
test_transport_implementations = [
1023
'bzrlib.tests.test_transport_implementations']
1025
TestCase.BZRPATH = osutils.pathjoin(
1026
osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
1027
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1028
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
339
1030
suite = TestSuite()
340
suite.addTest(TestLoader().loadTestsFromNames(testmod_names))
1031
# python2.4's TestLoader.loadTestsFromNames gives very poor
1032
# errors if it fails to load a named module - no indication of what's
1033
# actually wrong, just "no such module". We should probably override that
1034
# class, but for the moment just load them ourselves. (mbp 20051202)
1035
loader = TestLoader()
1036
from bzrlib.transport import TransportTestProviderAdapter
1037
adapter = TransportTestProviderAdapter()
1038
adapt_modules(test_transport_implementations, adapter, loader, suite)
1039
for mod_name in testmod_names:
1040
mod = _load_module_by_name(mod_name)
1041
suite.addTest(loader.loadTestsFromModule(mod))
1042
for package in packages_to_test():
1043
suite.addTest(package.test_suite())
341
1044
for m in MODULES_TO_TEST:
342
suite.addTest(TestLoader().loadTestsFromModule(m))
1045
suite.addTest(loader.loadTestsFromModule(m))
343
1046
for m in (MODULES_TO_DOCTEST):
344
1047
suite.addTest(DocTestSuite(m))
345
for p in bzrlib.plugin.all_plugins:
346
if hasattr(p, 'test_suite'):
347
suite.addTest(p.test_suite())
1048
for name, plugin in bzrlib.plugin.all_plugins().items():
1049
if getattr(plugin, 'test_suite', None) is not None:
1050
suite.addTest(plugin.test_suite())
1054
def adapt_modules(mods_list, adapter, loader, suite):
1055
"""Adapt the modules in mods_list using adapter and add to suite."""
1056
for mod_name in mods_list:
1057
mod = _load_module_by_name(mod_name)
1058
for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
1059
suite.addTests(adapter.adapt(test))
1062
def _load_module_by_name(mod_name):
1063
parts = mod_name.split('.')
1064
module = __import__(mod_name)
1066
# for historical reasons python returns the top-level module even though
1067
# it loads the submodule; we need to walk down to get the one we want.
1069
module = getattr(module, parts.pop(0))