15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from testsweet import TestBase, run_suite, InTempDir
28
import bzrlib.commands
20
34
MODULES_TO_TEST = []
21
35
MODULES_TO_DOCTEST = []
24
from unittest import TestLoader, TestSuite
37
from logging import debug, warning, error
39
class CommandFailed(Exception):
42
class TestCase(unittest.TestCase):
43
"""Base class for bzr unit tests.
45
Tests that need access to disk resources should subclass
46
TestCaseInTempDir not TestCase.
48
Error and debug log messages are redirected from their usual
49
location into a temporary file, the contents of which can be
50
retrieved by _get_log().
52
There are also convenience functions to invoke bzr's command-line
53
routine, and to build and check bzr trees."""
58
# this replaces the default testsweet.TestCase; we don't want logging changed
59
unittest.TestCase.setUp(self)
60
bzrlib.trace.disable_default_logging()
61
self._enable_file_logging()
64
def _enable_file_logging(self):
65
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
67
self._log_file = os.fdopen(fileno, 'w+')
69
hdlr = logging.StreamHandler(self._log_file)
70
hdlr.setLevel(logging.DEBUG)
71
hdlr.setFormatter(logging.Formatter('%(levelname)8s %(message)s'))
72
logging.getLogger('').addHandler(hdlr)
73
logging.getLogger('').setLevel(logging.DEBUG)
75
debug('opened log file %s', name)
77
self._log_file_name = name
81
logging.getLogger('').removeHandler(self._log_hdlr)
82
bzrlib.trace.enable_default_logging()
83
logging.debug('%s teardown', self.id())
84
self._log_file.close()
85
unittest.TestCase.tearDown(self)
92
"""Return as a string the log for this test"""
93
return open(self._log_file_name).read()
95
def run_bzr(self, *args, **kwargs):
96
"""Invoke bzr, as if it were run from the command line.
98
This should be the main method for tests that want to exercise the
99
overall behavior of the bzr application (rather than a unit test
100
or a functional test of the library.)
102
Much of the old code runs bzr by forking a new copy of Python, but
103
that is slower, harder to debug, and generally not necessary.
105
retcode = kwargs.get('retcode', 0)
106
result = self.apply_redirected(None, None, None,
107
bzrlib.commands.run_bzr, args)
108
self.assertEquals(result, retcode)
111
def check_inventory_shape(self, inv, shape):
112
"""Compare an inventory to a list of expected names.
114
Fail if they are not precisely equal.
117
shape = list(shape) # copy
118
for path, ie in inv.entries():
119
name = path.replace('\\', '/')
127
self.fail("expected paths not found in inventory: %r" % shape)
129
self.fail("unexpected paths found in inventory: %r" % extras)
131
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
132
a_callable=None, *args, **kwargs):
133
"""Call callable with redirected std io pipes.
135
Returns the return code."""
136
from StringIO import StringIO
137
if not callable(a_callable):
138
raise ValueError("a_callable must be callable.")
142
stdout = self._log_file
144
stderr = self._log_file
145
real_stdin = sys.stdin
146
real_stdout = sys.stdout
147
real_stderr = sys.stderr
152
return a_callable(*args, **kwargs)
154
sys.stdout = real_stdout
155
sys.stderr = real_stderr
156
sys.stdin = real_stdin
159
BzrTestBase = TestCase
162
class TestCaseInTempDir(TestCase):
163
"""Derived class that runs a test within a temporary directory.
165
This is useful for tests that need to create a branch, etc.
167
The directory is created in a slightly complex way: for each
168
Python invocation, a new temporary top-level directory is created.
169
All test cases create their own directory within that. If the
170
tests complete successfully, the directory is removed.
172
InTempDir is an old alias for FunctionalTestCase.
177
OVERRIDE_PYTHON = 'python'
179
def check_file_contents(self, filename, expect):
180
self.log("check contents of file %s" % filename)
181
contents = file(filename, 'r').read()
182
if contents != expect:
183
self.log("expected: %r" % expect)
184
self.log("actually: %r" % contents)
185
self.fail("contents of %s not as expected")
187
def _make_test_root(self):
188
if TestCaseInTempDir.TEST_ROOT is not None:
192
root = 'test%04d.tmp' % i
196
if e.errno == errno.EEXIST:
201
# successfully created
202
TestCaseInTempDir.TEST_ROOT = os.path.abspath(root)
204
# make a fake bzr directory there to prevent any tests propagating
205
# up onto the source directory's real branch
206
os.mkdir(os.path.join(TestCaseInTempDir.TEST_ROOT, '.bzr'))
209
super(TestCaseInTempDir, self).setUp()
211
self._make_test_root()
212
self._currentdir = os.getcwdu()
213
short_id = self.id().replace('bzrlib.selftest.', '') \
214
.replace('__main__.', '')
215
self.test_dir = os.path.join(self.TEST_ROOT, short_id)
216
os.mkdir(self.test_dir)
217
os.chdir(self.test_dir)
221
os.chdir(self._currentdir)
222
super(TestCaseInTempDir, self).tearDown()
224
def _formcmd(self, cmd):
225
if isinstance(cmd, basestring):
228
cmd[0] = self.BZRPATH
229
if self.OVERRIDE_PYTHON:
230
cmd.insert(0, self.OVERRIDE_PYTHON)
231
self.log('$ %r' % cmd)
234
def runcmd(self, cmd, retcode=0):
235
"""Run one command and check the return code.
237
Returns a tuple of (stdout,stderr) strings.
239
If a single string is based, it is split into words.
240
For commands that are not simple space-separated words, please
241
pass a list instead."""
242
cmd = self._formcmd(cmd)
243
self.log('$ ' + ' '.join(cmd))
244
actual_retcode = subprocess.call(cmd, stdout=self._log_file,
245
stderr=self._log_file)
246
if retcode != actual_retcode:
247
raise CommandFailed("test failed: %r returned %d, expected %d"
248
% (cmd, actual_retcode, retcode))
250
def backtick(self, cmd, retcode=0):
251
"""Run a command and return its output"""
252
cmd = self._formcmd(cmd)
253
child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=self._log_file)
254
outd, errd = child.communicate()
256
actual_retcode = child.wait()
258
outd = outd.replace('\r', '')
260
if retcode != actual_retcode:
261
raise CommandFailed("test failed: %r returned %d, expected %d"
262
% (cmd, actual_retcode, retcode))
268
def build_tree(self, shape):
269
"""Build a test tree according to a pattern.
271
shape is a sequence of file specifications. If the final
272
character is '/', a directory is created.
274
This doesn't add anything to a branch.
276
# XXX: It's OK to just create them using forward slashes on windows?
279
assert isinstance(name, basestring)
284
print >>f, "contents of", name
289
class MetaTestLog(TestCase):
290
def test_logging(self):
291
"""Test logs are captured when a test fails."""
292
logging.info('an info message')
293
warning('something looks dodgy...')
294
logging.debug('hello, test is running')
298
def selftest(verbose=False, pattern=".*"):
299
"""Run the whole test suite under the enhanced runner"""
300
return testsweet.run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
304
"""Build and return TestSuite for the whole program."""
305
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
25
306
import bzrlib, bzrlib.store, bzrlib.inventory, bzrlib.branch
26
307
import bzrlib.osutils, bzrlib.commands, bzrlib.merge3, bzrlib.plugin
27
global MODULES_TO_TEST, MODULES_TO_DOCTEST
29
import bzrlib.selftest.whitebox
30
import bzrlib.selftest.blackbox
31
import bzrlib.selftest.versioning
32
import bzrlib.selftest.testmerge3
33
import bzrlib.selftest.testhashcache
34
import bzrlib.selftest.testrevisionnamespaces
35
import bzrlib.selftest.testbranch
36
import bzrlib.selftest.teststatus
37
import bzrlib.selftest.testinv
38
import bzrlib.merge_core
39
308
from doctest import DocTestSuite
314
global MODULES_TO_TEST, MODULES_TO_DOCTEST
317
['bzrlib.selftest.MetaTestLog',
318
'bzrlib.selftest.testinv',
319
'bzrlib.selftest.test_commit',
320
'bzrlib.selftest.test_commit_merge',
321
'bzrlib.selftest.versioning',
322
'bzrlib.selftest.testmerge3',
323
'bzrlib.selftest.testhashcache',
324
'bzrlib.selftest.teststatus',
325
'bzrlib.selftest.testlog',
326
'bzrlib.selftest.testrevisionnamespaces',
327
'bzrlib.selftest.testbranch',
328
'bzrlib.selftest.testrevision',
329
'bzrlib.selftest.test_merge_core',
330
'bzrlib.selftest.test_smart_add',
331
'bzrlib.selftest.testdiff',
332
'bzrlib.selftest.test_parent',
333
'bzrlib.selftest.test_xml',
334
'bzrlib.selftest.test_weave',
335
'bzrlib.selftest.testfetch',
336
'bzrlib.selftest.whitebox',
337
'bzrlib.selftest.teststore',
338
'bzrlib.selftest.blackbox',
46
341
for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,
47
342
bzrlib.osutils, bzrlib.commands, bzrlib.merge3):
48
343
if m not in MODULES_TO_DOCTEST:
49
344
MODULES_TO_DOCTEST.append(m)
51
for m in (bzrlib.selftest.whitebox,
52
bzrlib.selftest.versioning,
53
bzrlib.selftest.testinv,
54
bzrlib.selftest.testmerge3,
55
bzrlib.selftest.testhashcache,
56
bzrlib.selftest.teststatus,
57
bzrlib.selftest.blackbox,
58
bzrlib.selftest.testhashcache,
59
bzrlib.selftest.testrevisionnamespaces,
60
bzrlib.selftest.testbranch,
62
if m not in MODULES_TO_TEST:
63
MODULES_TO_TEST.append(m)
66
TestBase.BZRPATH = os.path.join(os.path.realpath(os.path.dirname(bzrlib.__path__[0])), 'bzr')
67
print '%-30s %s' % ('bzr binary', TestBase.BZRPATH)
346
TestCase.BZRPATH = os.path.join(os.path.realpath(os.path.dirname(bzrlib.__path__[0])), 'bzr')
347
print '%-30s %s' % ('bzr binary', TestCase.BZRPATH)
71
349
suite = TestSuite()
73
# should also test bzrlib.merge_core, but they seem to be out of date with
77
# XXX: python2.3's TestLoader() doesn't seem to find all the
78
# tests; don't know why
350
suite.addTest(TestLoader().loadTestsFromNames(testmod_names))
79
351
for m in MODULES_TO_TEST:
80
352
suite.addTest(TestLoader().loadTestsFromModule(m))
82
353
for m in (MODULES_TO_DOCTEST):
83
354
suite.addTest(DocTestSuite(m))
85
355
for p in bzrlib.plugin.all_plugins:
86
356
if hasattr(p, 'test_suite'):
87
357
suite.addTest(p.test_suite())
89
suite.addTest(unittest.makeSuite(bzrlib.merge_core.MergeTest, 'test_'))
91
return run_suite(suite, 'testbzr')