1
# Copyright (C) 2005 by Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
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)
25
from cStringIO import StringIO
40
import bzrlib.bzrdir as bzrdir
41
import bzrlib.commands
42
import bzrlib.errors as errors
43
import bzrlib.inventory
44
import bzrlib.iterablefile
47
import bzrlib.osutils as osutils
51
from bzrlib.transport import urlescape
52
import bzrlib.transport
53
from bzrlib.transport.local import LocalRelpathServer
54
from bzrlib.transport.readonly import ReadonlyServer
55
from bzrlib.trace import mutter
56
from bzrlib.tests.TestUtil import TestLoader, TestSuite
57
from bzrlib.tests.treeshape import build_tree_contents
58
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
60
default_transport = LocalRelpathServer
63
MODULES_TO_DOCTEST = [
74
def packages_to_test():
75
"""Return a list of packages to test.
77
The packages are not globally imported so that import failures are
78
triggered when running selftest, not when importing the command.
81
import bzrlib.tests.blackbox
82
import bzrlib.tests.branch_implementations
83
import bzrlib.tests.bzrdir_implementations
84
import bzrlib.tests.interrepository_implementations
85
import bzrlib.tests.repository_implementations
86
import bzrlib.tests.workingtree_implementations
89
bzrlib.tests.blackbox,
90
bzrlib.tests.branch_implementations,
91
bzrlib.tests.bzrdir_implementations,
92
bzrlib.tests.interrepository_implementations,
93
bzrlib.tests.repository_implementations,
94
bzrlib.tests.workingtree_implementations,
98
class _MyResult(unittest._TextTestResult):
101
Shows output in a different format, including displaying runtime for tests.
105
def _elapsedTime(self):
106
return "%5dms" % (1000 * (time.time() - self._start_time))
108
def startTest(self, test):
109
unittest.TestResult.startTest(self, test)
110
# In a short description, the important words are in
111
# the beginning, but in an id, the important words are
113
SHOW_DESCRIPTIONS = False
115
width = osutils.terminal_width()
116
name_width = width - 15
118
if SHOW_DESCRIPTIONS:
119
what = test.shortDescription()
121
if len(what) > name_width:
122
what = what[:name_width-3] + '...'
125
if what.startswith('bzrlib.tests.'):
127
if len(what) > name_width:
128
what = '...' + what[3-name_width:]
129
what = what.ljust(name_width)
130
self.stream.write(what)
132
self._start_time = time.time()
134
def addError(self, test, err):
135
if isinstance(err[1], TestSkipped):
136
return self.addSkipped(test, err)
137
unittest.TestResult.addError(self, test, err)
139
self.stream.writeln("ERROR %s" % self._elapsedTime())
141
self.stream.write('E')
146
def addFailure(self, test, err):
147
unittest.TestResult.addFailure(self, test, err)
149
self.stream.writeln(" FAIL %s" % self._elapsedTime())
151
self.stream.write('F')
156
def addSuccess(self, test):
158
self.stream.writeln(' OK %s' % self._elapsedTime())
160
self.stream.write('~')
162
unittest.TestResult.addSuccess(self, test)
164
def addSkipped(self, test, skip_excinfo):
166
print >>self.stream, ' SKIP %s' % self._elapsedTime()
167
print >>self.stream, ' %s' % skip_excinfo[1]
169
self.stream.write('S')
171
# seems best to treat this as success from point-of-view of unittest
172
# -- it actually does nothing so it barely matters :)
173
unittest.TestResult.addSuccess(self, test)
175
def printErrorList(self, flavour, errors):
176
for test, err in errors:
177
self.stream.writeln(self.separator1)
178
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
179
if getattr(test, '_get_log', None) is not None:
181
print >>self.stream, \
182
('vvvv[log from %s]' % test.id()).ljust(78,'-')
183
print >>self.stream, test._get_log()
184
print >>self.stream, \
185
('^^^^[log from %s]' % test.id()).ljust(78,'-')
186
self.stream.writeln(self.separator2)
187
self.stream.writeln("%s" % err)
190
class TextTestRunner(unittest.TextTestRunner):
191
stop_on_failure = False
193
def _makeResult(self):
194
result = _MyResult(self.stream, self.descriptions, self.verbosity)
195
result.stop_early = self.stop_on_failure
199
def iter_suite_tests(suite):
200
"""Return all tests in a suite, recursing through nested suites"""
201
for item in suite._tests:
202
if isinstance(item, unittest.TestCase):
204
elif isinstance(item, unittest.TestSuite):
205
for r in iter_suite_tests(item):
208
raise Exception('unknown object %r inside test suite %r'
212
class TestSkipped(Exception):
213
"""Indicates that a test was intentionally skipped, rather than failing."""
217
class CommandFailed(Exception):
220
class TestCase(unittest.TestCase):
221
"""Base class for bzr unit tests.
223
Tests that need access to disk resources should subclass
224
TestCaseInTempDir not TestCase.
226
Error and debug log messages are redirected from their usual
227
location into a temporary file, the contents of which can be
228
retrieved by _get_log(). We use a real OS file, not an in-memory object,
229
so that it can also capture file IO. When the test completes this file
230
is read into memory and removed from disk.
232
There are also convenience functions to invoke bzr's command-line
233
routine, and to build and check bzr trees.
235
In addition to the usual method of overriding tearDown(), this class also
236
allows subclasses to register functions into the _cleanups list, which is
237
run in order as the object is torn down. It's less likely this will be
238
accidentally overlooked.
242
_log_file_name = None
245
def __init__(self, methodName='testMethod'):
246
super(TestCase, self).__init__(methodName)
250
unittest.TestCase.setUp(self)
251
self._cleanEnvironment()
252
bzrlib.trace.disable_default_logging()
255
def _ndiff_strings(self, a, b):
256
"""Return ndiff between two strings containing lines.
258
A trailing newline is added if missing to make the strings
260
if b and b[-1] != '\n':
262
if a and a[-1] != '\n':
264
difflines = difflib.ndiff(a.splitlines(True),
266
linejunk=lambda x: False,
267
charjunk=lambda x: False)
268
return ''.join(difflines)
270
def assertEqualDiff(self, a, b, message=None):
271
"""Assert two texts are equal, if not raise an exception.
273
This is intended for use with multi-line strings where it can
274
be hard to find the differences by eye.
276
# TODO: perhaps override assertEquals to call this for strings?
280
message = "texts not equal:\n"
281
raise AssertionError(message +
282
self._ndiff_strings(a, b))
284
def assertEqualMode(self, mode, mode_test):
285
self.assertEqual(mode, mode_test,
286
'mode mismatch %o != %o' % (mode, mode_test))
288
def assertStartsWith(self, s, prefix):
289
if not s.startswith(prefix):
290
raise AssertionError('string %r does not start with %r' % (s, prefix))
292
def assertEndsWith(self, s, suffix):
293
if not s.endswith(prefix):
294
raise AssertionError('string %r does not end with %r' % (s, suffix))
296
def assertContainsRe(self, haystack, needle_re):
297
"""Assert that a contains something matching a regular expression."""
298
if not re.search(needle_re, haystack):
299
raise AssertionError('pattern "%s" not found in "%s"'
300
% (needle_re, haystack))
302
def AssertSubset(self, sublist, superlist):
303
"""Assert that every entry in sublist is present in superlist."""
305
for entry in sublist:
306
if entry not in superlist:
307
missing.append(entry)
309
raise AssertionError("value(s) %r not present in container %r" %
310
(missing, superlist))
312
def assertIs(self, left, right):
313
if not (left is right):
314
raise AssertionError("%r is not %r." % (left, right))
316
def assertTransportMode(self, transport, path, mode):
317
"""Fail if a path does not have mode mode.
319
If modes are not supported on this platform, the test is skipped.
321
if sys.platform == 'win32':
323
path_stat = transport.stat(path)
324
actual_mode = stat.S_IMODE(path_stat.st_mode)
325
self.assertEqual(mode, actual_mode,
326
'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
328
def _startLogFile(self):
329
"""Send bzr and test log messages to a temporary file.
331
The file is removed as the test is torn down.
333
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
334
encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
335
self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
336
self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
337
self._log_file_name = name
338
self.addCleanup(self._finishLogFile)
340
def _finishLogFile(self):
341
"""Finished with the log file.
343
Read contents into memory, close, and delete.
345
bzrlib.trace.disable_test_log(self._log_nonce)
346
self._log_file.seek(0)
347
self._log_contents = self._log_file.read()
348
self._log_file.close()
349
os.remove(self._log_file_name)
350
self._log_file = self._log_file_name = None
352
def addCleanup(self, callable):
353
"""Arrange to run a callable when this case is torn down.
355
Callables are run in the reverse of the order they are registered,
356
ie last-in first-out.
358
if callable in self._cleanups:
359
raise ValueError("cleanup function %r already registered on %s"
361
self._cleanups.append(callable)
363
def _cleanEnvironment(self):
366
'APPDATA': os.getcwd(),
371
self.addCleanup(self._restoreEnvironment)
372
for name, value in new_env.iteritems():
373
self._captureVar(name, value)
376
def _captureVar(self, name, newvalue):
377
"""Set an environment variable, preparing it to be reset when finished."""
378
self.__old_env[name] = os.environ.get(name, None)
380
if name in os.environ:
383
os.environ[name] = newvalue
386
def _restoreVar(name, value):
388
if name in os.environ:
391
os.environ[name] = value
393
def _restoreEnvironment(self):
394
for name, value in self.__old_env.iteritems():
395
self._restoreVar(name, value)
399
unittest.TestCase.tearDown(self)
401
def _runCleanups(self):
402
"""Run registered cleanup functions.
404
This should only be called from TestCase.tearDown.
406
# TODO: Perhaps this should keep running cleanups even if
408
for cleanup_fn in reversed(self._cleanups):
411
def log(self, *args):
415
"""Return as a string the log for this test"""
416
if self._log_file_name:
417
return open(self._log_file_name).read()
419
return self._log_contents
420
# TODO: Delete the log after it's been read in
422
def capture(self, cmd, retcode=0):
423
"""Shortcut that splits cmd into words, runs, and returns stdout"""
424
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
426
def run_bzr_captured(self, argv, retcode=0):
427
"""Invoke bzr and return (stdout, stderr).
429
Useful for code that wants to check the contents of the
430
output, the way error messages are presented, etc.
432
This should be the main method for tests that want to exercise the
433
overall behavior of the bzr application (rather than a unit test
434
or a functional test of the library.)
436
Much of the old code runs bzr by forking a new copy of Python, but
437
that is slower, harder to debug, and generally not necessary.
439
This runs bzr through the interface that catches and reports
440
errors, and with logging set to something approximating the
441
default, so that error reporting can be checked.
443
argv -- arguments to invoke bzr
444
retcode -- expected return code, or None for don't-care.
448
self.log('run bzr: %s', ' '.join(argv))
449
# FIXME: don't call into logging here
450
handler = logging.StreamHandler(stderr)
451
handler.setFormatter(bzrlib.trace.QuietFormatter())
452
handler.setLevel(logging.INFO)
453
logger = logging.getLogger('')
454
logger.addHandler(handler)
456
result = self.apply_redirected(None, stdout, stderr,
457
bzrlib.commands.run_bzr_catch_errors,
460
logger.removeHandler(handler)
461
out = stdout.getvalue()
462
err = stderr.getvalue()
464
self.log('output:\n%s', out)
466
self.log('errors:\n%s', err)
467
if retcode is not None:
468
self.assertEquals(result, retcode)
471
def run_bzr(self, *args, **kwargs):
472
"""Invoke bzr, as if it were run from the command line.
474
This should be the main method for tests that want to exercise the
475
overall behavior of the bzr application (rather than a unit test
476
or a functional test of the library.)
478
This sends the stdout/stderr results into the test's log,
479
where it may be useful for debugging. See also run_captured.
481
retcode = kwargs.pop('retcode', 0)
482
return self.run_bzr_captured(args, retcode)
484
def check_inventory_shape(self, inv, shape):
485
"""Compare an inventory to a list of expected names.
487
Fail if they are not precisely equal.
490
shape = list(shape) # copy
491
for path, ie in inv.entries():
492
name = path.replace('\\', '/')
500
self.fail("expected paths not found in inventory: %r" % shape)
502
self.fail("unexpected paths found in inventory: %r" % extras)
504
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
505
a_callable=None, *args, **kwargs):
506
"""Call callable with redirected std io pipes.
508
Returns the return code."""
509
if not callable(a_callable):
510
raise ValueError("a_callable must be callable.")
514
if getattr(self, "_log_file", None) is not None:
515
stdout = self._log_file
519
if getattr(self, "_log_file", None is not None):
520
stderr = self._log_file
523
real_stdin = sys.stdin
524
real_stdout = sys.stdout
525
real_stderr = sys.stderr
530
return a_callable(*args, **kwargs)
532
sys.stdout = real_stdout
533
sys.stderr = real_stderr
534
sys.stdin = real_stdin
537
BzrTestBase = TestCase
540
class TestCaseInTempDir(TestCase):
541
"""Derived class that runs a test within a temporary directory.
543
This is useful for tests that need to create a branch, etc.
545
The directory is created in a slightly complex way: for each
546
Python invocation, a new temporary top-level directory is created.
547
All test cases create their own directory within that. If the
548
tests complete successfully, the directory is removed.
550
InTempDir is an old alias for FunctionalTestCase.
555
OVERRIDE_PYTHON = 'python'
557
def check_file_contents(self, filename, expect):
558
self.log("check contents of file %s" % filename)
559
contents = file(filename, 'r').read()
560
if contents != expect:
561
self.log("expected: %r" % expect)
562
self.log("actually: %r" % contents)
563
self.fail("contents of %s not as expected" % filename)
565
def _make_test_root(self):
566
if TestCaseInTempDir.TEST_ROOT is not None:
570
root = u'test%04d.tmp' % i
574
if e.errno == errno.EEXIST:
579
# successfully created
580
TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
582
# make a fake bzr directory there to prevent any tests propagating
583
# up onto the source directory's real branch
584
bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
587
super(TestCaseInTempDir, self).setUp()
588
self._make_test_root()
589
_currentdir = os.getcwdu()
590
short_id = self.id().replace('bzrlib.tests.', '') \
591
.replace('__main__.', '')
592
self.test_dir = osutils.pathjoin(self.TEST_ROOT, short_id)
593
os.mkdir(self.test_dir)
594
os.chdir(self.test_dir)
595
os.environ['HOME'] = self.test_dir
596
os.environ['APPDATA'] = self.test_dir
597
def _leaveDirectory():
598
os.chdir(_currentdir)
599
self.addCleanup(_leaveDirectory)
601
def build_tree(self, shape, line_endings='native', transport=None):
602
"""Build a test tree according to a pattern.
604
shape is a sequence of file specifications. If the final
605
character is '/', a directory is created.
607
This doesn't add anything to a branch.
608
:param line_endings: Either 'binary' or 'native'
609
in binary mode, exact contents are written
610
in native mode, the line endings match the
611
default platform endings.
613
:param transport: A transport to write to, for building trees on
614
VFS's. If the transport is readonly or None,
615
"." is opened automatically.
617
# XXX: It's OK to just create them using forward slashes on windows?
618
if transport is None or transport.is_readonly():
619
transport = bzrlib.transport.get_transport(".")
621
self.assert_(isinstance(name, basestring))
623
transport.mkdir(urlescape(name[:-1]))
625
if line_endings == 'binary':
627
elif line_endings == 'native':
630
raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
631
content = "contents of %s%s" % (name, end)
632
transport.put(urlescape(name), StringIO(content))
634
def build_tree_contents(self, shape):
635
build_tree_contents(shape)
637
def failUnlessExists(self, path):
638
"""Fail unless path, which may be abs or relative, exists."""
639
self.failUnless(osutils.lexists(path))
641
def failIfExists(self, path):
642
"""Fail if path, which may be abs or relative, exists."""
643
self.failIf(osutils.lexists(path))
645
def assertFileEqual(self, content, path):
646
"""Fail if path does not contain 'content'."""
647
self.failUnless(osutils.lexists(path))
648
self.assertEqualDiff(content, open(path, 'r').read())
651
class TestCaseWithTransport(TestCaseInTempDir):
652
"""A test case that provides get_url and get_readonly_url facilities.
654
These back onto two transport servers, one for readonly access and one for
657
If no explicit class is provided for readonly access, a
658
ReadonlyTransportDecorator is used instead which allows the use of non disk
659
based read write transports.
661
If an explicit class is provided for readonly access, that server and the
662
readwrite one must both define get_url() as resolving to os.getcwd().
665
def __init__(self, methodName='testMethod'):
666
super(TestCaseWithTransport, self).__init__(methodName)
667
self.__readonly_server = None
669
self.transport_server = default_transport
670
self.transport_readonly_server = None
672
def get_readonly_url(self, relpath=None):
673
"""Get a URL for the readonly transport.
675
This will either be backed by '.' or a decorator to the transport
676
used by self.get_url()
677
relpath provides for clients to get a path relative to the base url.
678
These should only be downwards relative, not upwards.
680
base = self.get_readonly_server().get_url()
681
if relpath is not None:
682
if not base.endswith('/'):
684
base = base + relpath
687
def get_readonly_server(self):
688
"""Get the server instance for the readonly transport
690
This is useful for some tests with specific servers to do diagnostics.
692
if self.__readonly_server is None:
693
if self.transport_readonly_server is None:
694
# readonly decorator requested
695
# bring up the server
697
self.__readonly_server = ReadonlyServer()
698
self.__readonly_server.setUp(self.__server)
700
self.__readonly_server = self.transport_readonly_server()
701
self.__readonly_server.setUp()
702
self.addCleanup(self.__readonly_server.tearDown)
703
return self.__readonly_server
705
def get_server(self):
706
"""Get the read/write server instance.
708
This is useful for some tests with specific servers that need
711
if self.__server is None:
712
self.__server = self.transport_server()
713
self.__server.setUp()
714
self.addCleanup(self.__server.tearDown)
717
def get_url(self, relpath=None):
718
"""Get a URL for the readwrite transport.
720
This will either be backed by '.' or to an equivalent non-file based
722
relpath provides for clients to get a path relative to the base url.
723
These should only be downwards relative, not upwards.
725
base = self.get_server().get_url()
726
if relpath is not None and relpath != '.':
727
if not base.endswith('/'):
729
base = base + relpath
732
def make_branch(self, relpath):
733
"""Create a branch on the transport at relpath."""
734
repo = self.make_repository(relpath)
735
return repo.bzrdir.create_branch()
737
def make_bzrdir(self, relpath):
739
url = self.get_url(relpath)
740
segments = url.split('/')
741
if segments and segments[-1] not in ('', '.'):
742
parent = '/'.join(segments[:-1])
743
t = bzrlib.transport.get_transport(parent)
745
t.mkdir(segments[-1])
746
except errors.FileExists:
748
return bzrlib.bzrdir.BzrDir.create(url)
749
except errors.UninitializableFormat:
750
raise TestSkipped("Format %s is not initializable.")
752
def make_repository(self, relpath, shared=False):
753
"""Create a repository on our default transport at relpath."""
754
made_control = self.make_bzrdir(relpath)
755
return made_control.create_repository(shared=shared)
757
def make_branch_and_tree(self, relpath):
758
"""Create a branch on the transport and a tree locally.
762
# TODO: always use the local disk path for the working tree,
763
# this obviously requires a format that supports branch references
764
# so check for that by checking bzrdir.BzrDirFormat.get_default_format()
766
b = self.make_branch(relpath)
768
return b.bzrdir.create_workingtree()
769
except errors.NotLocalUrl:
770
# new formats - catch No tree error and create
771
# a branch reference and a checkout.
772
# old formats at that point - raise TestSkipped.
774
return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
777
class ChrootedTestCase(TestCaseWithTransport):
778
"""A support class that provides readonly urls outside the local namespace.
780
This is done by checking if self.transport_server is a MemoryServer. if it
781
is then we are chrooted already, if it is not then an HttpServer is used
784
TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
785
be used without needed to redo it when a different
790
super(ChrootedTestCase, self).setUp()
791
if not self.transport_server == bzrlib.transport.memory.MemoryServer:
792
self.transport_readonly_server = bzrlib.transport.http.HttpServer
795
def filter_suite_by_re(suite, pattern):
797
filter_re = re.compile(pattern)
798
for test in iter_suite_tests(suite):
799
if filter_re.search(test.id()):
804
def run_suite(suite, name='test', verbose=False, pattern=".*",
805
stop_on_failure=False, keep_output=False,
807
TestCaseInTempDir._TEST_NAME = name
812
runner = TextTestRunner(stream=sys.stdout,
815
runner.stop_on_failure=stop_on_failure
817
suite = filter_suite_by_re(suite, pattern)
818
result = runner.run(suite)
819
# This is still a little bogus,
820
# but only a little. Folk not using our testrunner will
821
# have to delete their temp directories themselves.
822
if result.wasSuccessful() or not keep_output:
823
if TestCaseInTempDir.TEST_ROOT is not None:
824
shutil.rmtree(TestCaseInTempDir.TEST_ROOT)
826
print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
827
return result.wasSuccessful()
830
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
833
"""Run the whole test suite under the enhanced runner"""
834
global default_transport
835
if transport is None:
836
transport = default_transport
837
old_transport = default_transport
838
default_transport = transport
841
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
842
stop_on_failure=stop_on_failure, keep_output=keep_output,
845
default_transport = old_transport
850
"""Build and return TestSuite for the whole program."""
851
from doctest import DocTestSuite
853
global MODULES_TO_DOCTEST
856
'bzrlib.tests.test_ancestry',
857
'bzrlib.tests.test_annotate',
858
'bzrlib.tests.test_api',
859
'bzrlib.tests.test_bad_files',
860
'bzrlib.tests.test_basis_inventory',
861
'bzrlib.tests.test_branch',
862
'bzrlib.tests.test_bzrdir',
863
'bzrlib.tests.test_command',
864
'bzrlib.tests.test_commit',
865
'bzrlib.tests.test_commit_merge',
866
'bzrlib.tests.test_config',
867
'bzrlib.tests.test_conflicts',
868
'bzrlib.tests.test_decorators',
869
'bzrlib.tests.test_diff',
870
'bzrlib.tests.test_doc_generate',
871
'bzrlib.tests.test_errors',
872
'bzrlib.tests.test_fetch',
873
'bzrlib.tests.test_gpg',
874
'bzrlib.tests.test_graph',
875
'bzrlib.tests.test_hashcache',
876
'bzrlib.tests.test_http',
877
'bzrlib.tests.test_identitymap',
878
'bzrlib.tests.test_inv',
879
'bzrlib.tests.test_lockable_files',
880
'bzrlib.tests.test_log',
881
'bzrlib.tests.test_merge',
882
'bzrlib.tests.test_merge3',
883
'bzrlib.tests.test_merge_core',
884
'bzrlib.tests.test_missing',
885
'bzrlib.tests.test_msgeditor',
886
'bzrlib.tests.test_nonascii',
887
'bzrlib.tests.test_options',
888
'bzrlib.tests.test_osutils',
889
'bzrlib.tests.test_permissions',
890
'bzrlib.tests.test_plugins',
891
'bzrlib.tests.test_repository',
892
'bzrlib.tests.test_revision',
893
'bzrlib.tests.test_revisionnamespaces',
894
'bzrlib.tests.test_revprops',
895
'bzrlib.tests.test_reweave',
896
'bzrlib.tests.test_rio',
897
'bzrlib.tests.test_sampler',
898
'bzrlib.tests.test_selftest',
899
'bzrlib.tests.test_setup',
900
'bzrlib.tests.test_sftp_transport',
901
'bzrlib.tests.test_smart_add',
902
'bzrlib.tests.test_source',
903
'bzrlib.tests.test_store',
904
'bzrlib.tests.test_symbol_versioning',
905
'bzrlib.tests.test_testament',
906
'bzrlib.tests.test_trace',
907
'bzrlib.tests.test_transactions',
908
'bzrlib.tests.test_transform',
909
'bzrlib.tests.test_transport',
910
'bzrlib.tests.test_tsort',
911
'bzrlib.tests.test_ui',
912
'bzrlib.tests.test_uncommit',
913
'bzrlib.tests.test_upgrade',
914
'bzrlib.tests.test_versionedfile',
915
'bzrlib.tests.test_weave',
916
'bzrlib.tests.test_whitebox',
917
'bzrlib.tests.test_workingtree',
918
'bzrlib.tests.test_xml',
920
test_transport_implementations = [
921
'bzrlib.tests.test_transport_implementations']
923
TestCase.BZRPATH = osutils.pathjoin(
924
osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
925
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
926
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
929
# python2.4's TestLoader.loadTestsFromNames gives very poor
930
# errors if it fails to load a named module - no indication of what's
931
# actually wrong, just "no such module". We should probably override that
932
# class, but for the moment just load them ourselves. (mbp 20051202)
933
loader = TestLoader()
934
from bzrlib.transport import TransportTestProviderAdapter
935
adapter = TransportTestProviderAdapter()
936
adapt_modules(test_transport_implementations, adapter, loader, suite)
937
for mod_name in testmod_names:
938
mod = _load_module_by_name(mod_name)
939
suite.addTest(loader.loadTestsFromModule(mod))
940
for package in packages_to_test():
941
suite.addTest(package.test_suite())
942
for m in MODULES_TO_TEST:
943
suite.addTest(loader.loadTestsFromModule(m))
944
for m in (MODULES_TO_DOCTEST):
945
suite.addTest(DocTestSuite(m))
946
for name, plugin in bzrlib.plugin.all_plugins().items():
947
if getattr(plugin, 'test_suite', None) is not None:
948
suite.addTest(plugin.test_suite())
952
def adapt_modules(mods_list, adapter, loader, suite):
953
"""Adapt the modules in mods_list using adapter and add to suite."""
954
for mod_name in mods_list:
955
mod = _load_module_by_name(mod_name)
956
for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
957
suite.addTests(adapter.adapt(test))
960
def _load_module_by_name(mod_name):
961
parts = mod_name.split('.')
962
module = __import__(mod_name)
964
# for historical reasons python returns the top-level module even though
965
# it loads the submodule; we need to walk down to get the one we want.
967
module = getattr(module, parts.pop(0))