15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from testsweet import TestCase, run_suite, InTempDir
19
28
import bzrlib.commands
21
34
MODULES_TO_TEST = []
22
35
MODULES_TO_DOCTEST = []
25
class BzrTestBase(InTempDir):
26
"""bzr-specific test base class"""
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()
27
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.
28
105
retcode = kwargs.get('retcode', 0)
29
self.assertEquals(bzrlib.commands.run_bzr(args), retcode)
32
def selftest(verbose=False):
33
from unittest import TestLoader, TestSuite
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):
113
Compare an inventory to a list of expected names.
115
Fail if they are not precisely equal.
118
shape = list(shape) # copy
119
for path, ie in inv.entries():
120
name = path.replace('\\', '/')
128
self.fail("expected paths not found in inventory: %r" % shape)
130
self.fail("unexpected paths found in inventory: %r" % extras)
132
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
133
a_callable=None, *args, **kwargs):
134
"""Call callable with redirected std io pipes.
136
Returns the return code."""
137
from StringIO import StringIO
138
if not callable(a_callable):
139
raise ValueError("a_callable must be callable.")
143
stdout = self._log_file
145
stderr = self._log_file
146
real_stdin = sys.stdin
147
real_stdout = sys.stdout
148
real_stderr = sys.stderr
153
return a_callable(*args, **kwargs)
155
sys.stdout = real_stdout
156
sys.stderr = real_stderr
157
sys.stdin = real_stdin
160
BzrTestBase = TestCase
163
class TestCaseInTempDir(TestCase):
164
"""Derived class that runs a test within a temporary directory.
166
This is useful for tests that need to create a branch, etc.
168
The directory is created in a slightly complex way: for each
169
Python invocation, a new temporary top-level directory is created.
170
All test cases create their own directory within that. If the
171
tests complete successfully, the directory is removed.
173
InTempDir is an old alias for FunctionalTestCase.
178
OVERRIDE_PYTHON = 'python'
180
def check_file_contents(self, filename, expect):
181
self.log("check contents of file %s" % filename)
182
contents = file(filename, 'r').read()
183
if contents != expect:
184
self.log("expected: %r" % expect)
185
self.log("actually: %r" % contents)
186
self.fail("contents of %s not as expected")
188
def _make_test_root(self):
189
if TestCaseInTempDir.TEST_ROOT is not None:
193
root = 'test%04d.tmp' % i
197
if e.errno == errno.EEXIST:
202
# successfully created
203
TestCaseInTempDir.TEST_ROOT = os.path.abspath(root)
205
# make a fake bzr directory there to prevent any tests propagating
206
# up onto the source directory's real branch
207
os.mkdir(os.path.join(TestCaseInTempDir.TEST_ROOT, '.bzr'))
210
super(TestCaseInTempDir, self).setUp()
212
self._make_test_root()
213
self._currentdir = os.getcwdu()
214
short_id = self.id().replace('bzrlib.selftest.', '') \
215
.replace('__main__.', '')
216
self.test_dir = os.path.join(self.TEST_ROOT, short_id)
217
os.mkdir(self.test_dir)
218
os.chdir(self.test_dir)
222
os.chdir(self._currentdir)
223
super(TestCaseInTempDir, self).tearDown()
225
def _formcmd(self, cmd):
226
if isinstance(cmd, basestring):
229
cmd[0] = self.BZRPATH
230
if self.OVERRIDE_PYTHON:
231
cmd.insert(0, self.OVERRIDE_PYTHON)
232
self.log('$ %r' % cmd)
235
def runcmd(self, cmd, retcode=0):
236
"""Run one command and check the return code.
238
Returns a tuple of (stdout,stderr) strings.
240
If a single string is based, it is split into words.
241
For commands that are not simple space-separated words, please
242
pass a list instead."""
243
cmd = self._formcmd(cmd)
244
self.log('$ ' + ' '.join(cmd))
245
actual_retcode = subprocess.call(cmd, stdout=self._log_file,
246
stderr=self._log_file)
247
if retcode != actual_retcode:
248
raise CommandFailed("test failed: %r returned %d, expected %d"
249
% (cmd, actual_retcode, retcode))
251
def backtick(self, cmd, retcode=0):
252
"""Run a command and return its output"""
253
cmd = self._formcmd(cmd)
254
child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=self._log_file)
255
outd, errd = child.communicate()
257
actual_retcode = child.wait()
259
outd = outd.replace('\r', '')
261
if retcode != actual_retcode:
262
raise CommandFailed("test failed: %r returned %d, expected %d"
263
% (cmd, actual_retcode, retcode))
269
def build_tree(self, shape):
270
"""Build a test tree according to a pattern.
272
shape is a sequence of file specifications. If the final
273
character is '/', a directory is created.
275
This doesn't add anything to a branch.
277
# XXX: It's OK to just create them using forward slashes on windows?
280
assert isinstance(name, basestring)
285
print >>f, "contents of", name
290
class MetaTestLog(TestCase):
291
def test_logging(self):
292
"""Test logs are captured when a test fails."""
293
logging.info('an info message')
294
warning('something looks dodgy...')
295
logging.debug('hello, test is running')
299
def selftest(verbose=False, pattern=".*"):
300
"""Run the whole test suite under the enhanced runner"""
301
return testsweet.run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
305
"""Build and return TestSuite for the whole program."""
306
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
34
307
import bzrlib, bzrlib.store, bzrlib.inventory, bzrlib.branch
35
308
import bzrlib.osutils, bzrlib.commands, bzrlib.merge3, bzrlib.plugin
36
309
from doctest import DocTestSuite
43
315
global MODULES_TO_TEST, MODULES_TO_DOCTEST
46
['bzrlib.selftest.whitebox',
318
['bzrlib.selftest.MetaTestLog',
319
'bzrlib.selftest.testinv',
47
320
'bzrlib.selftest.versioning',
48
'bzrlib.selftest.testfetch',
49
'bzrlib.selftest.testinv',
50
321
'bzrlib.selftest.testmerge3',
51
322
'bzrlib.selftest.testhashcache',
52
323
'bzrlib.selftest.teststatus',
53
324
'bzrlib.selftest.testlog',
54
'bzrlib.selftest.blackbox',
55
325
'bzrlib.selftest.testrevisionnamespaces',
56
326
'bzrlib.selftest.testbranch',
57
'bzrlib.selftest.testrevision',
327
# 'bzrlib.selftest.testrevision',
328
# 'bzrlib.selftest.test_merge_core',
329
'bzrlib.selftest.test_smart_add',
59
330
'bzrlib.selftest.testdiff',
331
# 'bzrlib.selftest.test_parent',
332
'bzrlib.selftest.test_xml',
333
# 'bzrlib.selftest.testfetch',
334
# 'bzrlib.selftest.whitebox',
335
'bzrlib.selftest.teststore',
336
# 'bzrlib.selftest.blackbox',
62
339
for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,