15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
import bzrlib.commands
18
from testsweet import TestBase, run_suite, InTempDir
34
20
MODULES_TO_TEST = []
35
21
MODULES_TO_DOCTEST = []
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)4.4s %(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
80
logging.getLogger('').removeHandler(self._log_hdlr)
81
bzrlib.trace.enable_default_logging()
82
logging.debug('%s teardown', self.id())
83
self._log_file.close()
84
unittest.TestCase.tearDown(self)
90
"""Return as a string the log for this test"""
91
return open(self._log_file_name).read()
93
def run_bzr(self, *args, **kwargs):
94
"""Invoke bzr, as if it were run from the command line.
96
This should be the main method for tests that want to exercise the
97
overall behavior of the bzr application (rather than a unit test
98
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)
109
def check_inventory_shape(self, inv, shape):
111
Compare an inventory to a list of expected names.
113
Fail if they are not precisely equal.
116
shape = list(shape) # copy
117
for path, ie in inv.entries():
118
name = path.replace('\\', '/')
126
self.fail("expected paths not found in inventory: %r" % shape)
128
self.fail("unexpected paths found in inventory: %r" % extras)
130
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
131
a_callable=None, *args, **kwargs):
132
"""Call callable with redirected std io pipes.
134
Returns the return code."""
135
from StringIO import StringIO
136
if not callable(a_callable):
137
raise ValueError("a_callable must be callable.")
141
if hasattr(self, "_log_file"):
142
stdout = self._log_file
146
if hasattr(self, "_log_file"):
147
stderr = self._log_file
150
real_stdin = sys.stdin
151
real_stdout = sys.stdout
152
real_stderr = sys.stderr
157
return a_callable(*args, **kwargs)
159
sys.stdout = real_stdout
160
sys.stderr = real_stderr
161
sys.stdin = real_stdin
164
BzrTestBase = TestCase
167
class TestCaseInTempDir(TestCase):
168
"""Derived class that runs a test within a temporary directory.
170
This is useful for tests that need to create a branch, etc.
172
The directory is created in a slightly complex way: for each
173
Python invocation, a new temporary top-level directory is created.
174
All test cases create their own directory within that. If the
175
tests complete successfully, the directory is removed.
177
InTempDir is an old alias for FunctionalTestCase.
182
OVERRIDE_PYTHON = 'python'
184
def check_file_contents(self, filename, expect):
185
self.log("check contents of file %s" % filename)
186
contents = file(filename, 'r').read()
187
if contents != expect:
188
self.log("expected: %r" % expect)
189
self.log("actually: %r" % contents)
190
self.fail("contents of %s not as expected")
192
def _make_test_root(self):
193
if TestCaseInTempDir.TEST_ROOT is not None:
197
root = 'test%04d.tmp' % i
201
if e.errno == errno.EEXIST:
206
# successfully created
207
TestCaseInTempDir.TEST_ROOT = os.path.abspath(root)
209
# make a fake bzr directory there to prevent any tests propagating
210
# up onto the source directory's real branch
211
os.mkdir(os.path.join(TestCaseInTempDir.TEST_ROOT, '.bzr'))
214
super(TestCaseInTempDir, self).setUp()
216
self._make_test_root()
217
self._currentdir = os.getcwdu()
218
self.test_dir = os.path.join(self.TEST_ROOT, self.id())
219
os.mkdir(self.test_dir)
220
os.chdir(self.test_dir)
224
os.chdir(self._currentdir)
225
super(TestCaseInTempDir, self).tearDown()
227
def _formcmd(self, cmd):
228
if isinstance(cmd, basestring):
231
cmd[0] = self.BZRPATH
232
if self.OVERRIDE_PYTHON:
233
cmd.insert(0, self.OVERRIDE_PYTHON)
234
self.log('$ %r' % cmd)
237
def runcmd(self, cmd, retcode=0):
238
"""Run one command and check the return code.
240
Returns a tuple of (stdout,stderr) strings.
242
If a single string is based, it is split into words.
243
For commands that are not simple space-separated words, please
244
pass a list instead."""
245
cmd = self._formcmd(cmd)
246
self.log('$ ' + ' '.join(cmd))
247
actual_retcode = subprocess.call(cmd, stdout=self._log_file,
248
stderr=self._log_file)
249
if retcode != actual_retcode:
250
raise CommandFailed("test failed: %r returned %d, expected %d"
251
% (cmd, actual_retcode, retcode))
253
def backtick(self, cmd, retcode=0):
254
"""Run a command and return its output"""
255
cmd = self._formcmd(cmd)
256
child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=self._log_file)
257
outd, errd = child.communicate()
259
actual_retcode = child.wait()
261
outd = outd.replace('\r', '')
263
if retcode != actual_retcode:
264
raise CommandFailed("test failed: %r returned %d, expected %d"
265
% (cmd, actual_retcode, retcode))
271
def build_tree(self, shape):
272
"""Build a test tree according to a pattern.
274
shape is a sequence of file specifications. If the final
275
character is '/', a directory is created.
277
This doesn't add anything to a branch.
279
# XXX: It's OK to just create them using forward slashes on windows?
282
assert isinstance(name, basestring)
287
print >>f, "contents of", name
292
class MetaTestLog(TestCase):
293
def test_logging(self):
294
"""Test logs are captured when a test fails."""
295
logging.info('an info message')
296
warning('something looks dodgy...')
297
logging.debug('hello, test is running')
301
def selftest(verbose=False, pattern=".*"):
302
return testsweet.run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
306
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
24
from unittest import TestLoader, TestSuite
307
25
import bzrlib, bzrlib.store, bzrlib.inventory, bzrlib.branch
308
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
309
38
from doctest import DocTestSuite
315
global MODULES_TO_TEST, MODULES_TO_DOCTEST
318
['bzrlib.selftest.MetaTestLog',
319
'bzrlib.selftest.test_parent',
320
'bzrlib.selftest.testinv',
321
'bzrlib.selftest.testfetch',
322
'bzrlib.selftest.versioning',
323
'bzrlib.selftest.whitebox',
324
'bzrlib.selftest.testmerge3',
325
'bzrlib.selftest.testmerge',
326
'bzrlib.selftest.testhashcache',
327
'bzrlib.selftest.teststatus',
328
'bzrlib.selftest.testlog',
329
'bzrlib.selftest.blackbox',
330
'bzrlib.selftest.testrevisionnamespaces',
331
'bzrlib.selftest.testbranch',
332
'bzrlib.selftest.testremotebranch',
333
'bzrlib.selftest.testrevision',
334
'bzrlib.selftest.test_merge_core',
335
'bzrlib.selftest.test_smart_add',
336
'bzrlib.selftest.testdiff',
337
'bzrlib.selftest.test_xml',
339
'bzrlib.selftest.teststore',
340
'bzrlib.selftest.testtransport',
341
'bzrlib.selftest.testgraph',
344
45
for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,
345
46
bzrlib.osutils, bzrlib.commands, bzrlib.merge3):
346
47
if m not in MODULES_TO_DOCTEST:
347
48
MODULES_TO_DOCTEST.append(m)
349
TestCase.BZRPATH = os.path.join(os.path.realpath(os.path.dirname(bzrlib.__path__[0])), 'bzr')
350
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)
352
69
suite = TestSuite()
353
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
354
77
for m in MODULES_TO_TEST:
355
78
suite.addTest(TestLoader().loadTestsFromModule(m))
356
80
for m in (MODULES_TO_DOCTEST):
357
81
suite.addTest(DocTestSuite(m))
358
83
for p in bzrlib.plugin.all_plugins:
359
84
if hasattr(p, 'test_suite'):
360
85
suite.addTest(p.test_suite())
87
suite.addTest(unittest.makeSuite(bzrlib.merge_core.MergeTest, 'test_'))
89
return run_suite(suite, 'testbzr')