15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
from testsweet import run_suite
25
import bzrlib.commands
18
from testsweet import TestBase, run_suite, InTempDir
30
20
MODULES_TO_TEST = []
31
21
MODULES_TO_DOCTEST = []
33
from logging import debug, warning, error
36
class TestCase(unittest.TestCase):
37
"""Base class for bzr unit tests.
39
Tests that need access to disk resources should subclass
40
FunctionalTestCase not TestCase.
42
Error and debug log messages are redirected from their usual
43
location into a temporary file, the contents of which can be
44
retrieved by _get_log().
46
There are also convenience functions to invoke bzr's command-line
47
routine, and to build and check bzr trees."""
52
# this replaces the default testsweet.TestCase; we don't want logging changed
53
unittest.TestCase.setUp(self)
54
bzrlib.trace.disable_default_logging()
55
self._enable_file_logging()
58
def _enable_file_logging(self):
59
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
61
self._log_file = os.fdopen(fileno, 'w+')
63
hdlr = logging.StreamHandler(self._log_file)
64
hdlr.setLevel(logging.DEBUG)
65
hdlr.setFormatter(logging.Formatter('%(levelname)4.4s %(message)s'))
66
logging.getLogger('').addHandler(hdlr)
67
logging.getLogger('').setLevel(logging.DEBUG)
69
debug('opened log file %s', name)
71
self._log_file_name = name
75
logging.getLogger('').removeHandler(self._log_hdlr)
76
bzrlib.trace.enable_default_logging()
77
logging.debug('%s teardown', self.id())
78
self._log_file.close()
79
unittest.TestCase.tearDown(self)
86
"""Return as a string the log for this test"""
87
return open(self._log_file_name).read()
89
def run_bzr(self, *args, **kwargs):
90
"""Invoke bzr, as if it were run from the command line.
92
This should be the main method for tests that want to exercise the
93
overall behavior of the bzr application (rather than a unit test
94
or a functional test of the library.)
96
Much of the old code runs bzr by forking a new copy of Python, but
97
that is slower, harder to debug, and generally not necessary.
99
retcode = kwargs.get('retcode', 0)
100
result = self.apply_redirected(None, None, None,
101
bzrlib.commands.run_bzr, args)
102
self.assertEquals(result, retcode)
104
def check_inventory_shape(self, inv, shape):
106
Compare an inventory to a list of expected names.
108
Fail if they are not precisely equal.
111
shape = list(shape) # copy
112
for path, ie in inv.entries():
113
name = path.replace('\\', '/')
121
self.fail("expected paths not found in inventory: %r" % shape)
123
self.fail("unexpected paths found in inventory: %r" % extras)
125
BzrTestBase = TestCase
128
class FunctionalTestCase(TestCase):
129
"""Base class for tests that perform function testing - running bzr,
130
using files on disk, and similar activities.
132
InTempDir is an old alias for FunctionalTestCase.
137
OVERRIDE_PYTHON = 'python'
139
def check_file_contents(self, filename, expect):
140
self.log("check contents of file %s" % filename)
141
contents = file(filename, 'r').read()
142
if contents != expect:
143
self.log("expected: %r" % expect)
144
self.log("actually: %r" % contents)
145
self.fail("contents of %s not as expected")
147
def _make_test_root(self):
152
if FunctionalTestCase.TEST_ROOT is not None:
154
FunctionalTestCase.TEST_ROOT = os.path.abspath(
155
tempfile.mkdtemp(suffix='.tmp',
156
prefix=self._TEST_NAME + '-',
159
# make a fake bzr directory there to prevent any tests propagating
160
# up onto the source directory's real branch
161
os.mkdir(os.path.join(FunctionalTestCase.TEST_ROOT, '.bzr'))
164
super(FunctionalTestCase, self).setUp()
166
self._make_test_root()
167
self._currentdir = os.getcwdu()
168
self.test_dir = os.path.join(self.TEST_ROOT, self.id())
169
os.mkdir(self.test_dir)
170
os.chdir(self.test_dir)
174
os.chdir(self._currentdir)
175
super(FunctionalTestCase, self).tearDown()
177
def _formcmd(self, cmd):
178
if isinstance(cmd, basestring):
181
cmd[0] = self.BZRPATH
182
if self.OVERRIDE_PYTHON:
183
cmd.insert(0, self.OVERRIDE_PYTHON)
184
self.log('$ %r' % cmd)
187
def runcmd(self, cmd, retcode=0):
188
"""Run one command and check the return code.
190
Returns a tuple of (stdout,stderr) strings.
192
If a single string is based, it is split into words.
193
For commands that are not simple space-separated words, please
194
pass a list instead."""
197
from subprocess import call
198
except ImportError, e:
201
cmd = self._formcmd(cmd)
202
self.log('$ ' + ' '.join(cmd))
203
actual_retcode = call(cmd, stdout=self._log_file, stderr=self._log_file)
204
if retcode != actual_retcode:
205
raise CommandFailed("test failed: %r returned %d, expected %d"
206
% (cmd, actual_retcode, retcode))
208
def backtick(self, cmd, retcode=0):
209
"""Run a command and return its output"""
212
from subprocess import Popen, PIPE
213
except ImportError, e:
217
cmd = self._formcmd(cmd)
218
child = Popen(cmd, stdout=PIPE, stderr=self._log_file)
219
outd, errd = child.communicate()
221
actual_retcode = child.wait()
223
outd = outd.replace('\r', '')
225
if retcode != actual_retcode:
226
raise CommandFailed("test failed: %r returned %d, expected %d"
227
% (cmd, actual_retcode, retcode))
233
def build_tree(self, shape):
234
"""Build a test tree according to a pattern.
236
shape is a sequence of file specifications. If the final
237
character is '/', a directory is created.
239
This doesn't add anything to a branch.
241
# XXX: It's OK to just create them using forward slashes on windows?
244
assert isinstance(name, basestring)
249
print >>f, "contents of", name
253
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
254
a_callable=None, *args, **kwargs):
255
"""Call callable with redirected std io pipes.
257
Returns the return code."""
258
from StringIO import StringIO
259
if not callable(a_callable):
260
raise ValueError("a_callable must be callable.")
264
stdout = self._log_file
266
stderr = self._log_file
267
real_stdin = sys.stdin
268
real_stdout = sys.stdout
269
real_stderr = sys.stderr
275
result = a_callable(*args, **kwargs)
277
sys.stdout = real_stdout
278
sys.stderr = real_stderr
279
sys.stdin = real_stdin
283
InTempDir = FunctionalTestCase
286
class MetaTestLog(TestCase):
287
def test_logging(self):
288
"""Test logs are captured when a test fails."""
289
logging.info('an info message')
290
warning('something looks dodgy...')
291
logging.debug('hello, test is running')
295
def selftest(verbose=False, pattern=".*"):
296
return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
300
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
24
from unittest import TestLoader, TestSuite
301
25
import bzrlib, bzrlib.store, bzrlib.inventory, bzrlib.branch
302
26
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.merge_core
303
38
from doctest import DocTestSuite
309
global MODULES_TO_TEST, MODULES_TO_DOCTEST
312
['bzrlib.selftest.MetaTestLog',
313
'bzrlib.selftest.testinv',
314
'bzrlib.selftest.testfetch',
315
'bzrlib.selftest.versioning',
316
'bzrlib.selftest.whitebox',
317
'bzrlib.selftest.testmerge3',
318
'bzrlib.selftest.testhashcache',
319
'bzrlib.selftest.teststatus',
320
'bzrlib.selftest.testlog',
321
'bzrlib.selftest.blackbox',
322
'bzrlib.selftest.testrevisionnamespaces',
323
'bzrlib.selftest.testbranch',
324
'bzrlib.selftest.testrevision',
325
'bzrlib.selftest.test_merge_core',
326
'bzrlib.selftest.test_smart_add',
327
'bzrlib.selftest.testdiff',
331
45
for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,
332
46
bzrlib.osutils, bzrlib.commands, bzrlib.merge3):
333
47
if m not in MODULES_TO_DOCTEST:
334
48
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)
50
for m in (bzrlib.selftest.whitebox,
51
bzrlib.selftest.versioning,
52
bzrlib.selftest.testmerge3,
53
bzrlib.selftest.testhashcache,
54
bzrlib.selftest.teststatus,
55
bzrlib.selftest.blackbox,
56
bzrlib.selftest.testhashcache,
57
bzrlib.selftest.testrevisionnamespaces,
58
bzrlib.selftest.testbranch,
60
if m not in MODULES_TO_TEST:
61
MODULES_TO_TEST.append(m)
64
TestBase.BZRPATH = os.path.join(os.path.realpath(os.path.dirname(bzrlib.__path__[0])), 'bzr')
65
print '%-30s %s' % ('bzr binary', TestBase.BZRPATH)
339
69
suite = TestSuite()
340
suite.addTest(TestLoader().loadTestsFromNames(testmod_names))
71
# should also test bzrlib.merge_core, but they seem to be out of date with
75
# XXX: python2.3's TestLoader() doesn't seem to find all the
76
# tests; don't know why
341
77
for m in MODULES_TO_TEST:
342
78
suite.addTest(TestLoader().loadTestsFromModule(m))
343
80
for m in (MODULES_TO_DOCTEST):
344
81
suite.addTest(DocTestSuite(m))
345
83
for p in bzrlib.plugin.all_plugins:
346
84
if hasattr(p, 'test_suite'):
347
85
suite.addTest(p.test_suite())
87
suite.addTest(unittest.makeSuite(bzrlib.merge_core.MergeTest, 'test_'))
89
return run_suite(suite, 'testbzr')