~bzr-pqm/bzr/bzr.dev

608 by Martin Pool
- Split selftests out into a new module and start changing them
1
# Copyright (C) 2005 by Canonical Ltd
2
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.
7
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.
12
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
16
609 by Martin Pool
- cleanup test code
17
1185.1.29 by Robert Collins
merge merge tweaks from aaron, which includes latest .dev
18
from cStringIO import StringIO
1185.16.16 by Martin Pool
- add TestCase.assertEqualDiffs helper
19
import difflib
20
import errno
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
21
import logging
22
import os
1185.16.16 by Martin Pool
- add TestCase.assertEqualDiffs helper
23
import re
24
import shutil
1185.1.58 by Robert Collins
make selftest -v show the elapsed time for each test run.
25
import sys
1185.16.16 by Martin Pool
- add TestCase.assertEqualDiffs helper
26
import tempfile
27
import unittest
1185.1.58 by Robert Collins
make selftest -v show the elapsed time for each test run.
28
import time
1185.52.1 by James Henstridge
Don't encode unicode messages to UTF-8 in mutter() (the stream writer does it).
29
import codecs
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
30
1513 by Robert Collins
Blackbox tests are maintained within the bzrlib.tests.blackbox directory.
31
import bzrlib.branch
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
32
import bzrlib.commands
1514 by Robert Collins
Unbreak self.build_tree_shape in tests.
33
from bzrlib.errors import BzrError
1513 by Robert Collins
Blackbox tests are maintained within the bzrlib.tests.blackbox directory.
34
import bzrlib.inventory
35
import bzrlib.merge3
36
import bzrlib.osutils
37
import bzrlib.plugin
38
import bzrlib.store
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
39
import bzrlib.trace
1185.43.1 by Martin Pool
Remove direct logging calls from selftest
40
from bzrlib.trace import mutter
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
41
from bzrlib.tests.TestUtil import TestLoader, TestSuite
1514 by Robert Collins
Unbreak self.build_tree_shape in tests.
42
from bzrlib.tests.treeshape import build_tree_contents
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
43
855 by Martin Pool
- Patch from John to allow plugins to add their own tests.
44
MODULES_TO_TEST = []
1513 by Robert Collins
Blackbox tests are maintained within the bzrlib.tests.blackbox directory.
45
MODULES_TO_DOCTEST = [
46
                      bzrlib.branch,
47
                      bzrlib.commands,
48
                      bzrlib.errors,
49
                      bzrlib.inventory,
50
                      bzrlib.merge3,
51
                      bzrlib.osutils,
52
                      bzrlib.store,
53
                      ]
54
def packages_to_test():
55
    import bzrlib.tests.blackbox
56
    return [
57
            bzrlib.tests.blackbox
58
            ]
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
59
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
60
61
class EarlyStoppingTestResultAdapter(object):
62
    """An adapter for TestResult to stop at the first first failure or error"""
63
64
    def __init__(self, result):
65
        self._result = result
66
67
    def addError(self, test, err):
68
        self._result.addError(test, err)
69
        self._result.stop()
70
71
    def addFailure(self, test, err):
72
        self._result.addFailure(test, err)
73
        self._result.stop()
74
75
    def __getattr__(self, name):
76
        return getattr(self._result, name)
77
78
    def __setattr__(self, name, value):
79
        if name == '_result':
80
            object.__setattr__(self, name, value)
81
        return setattr(self._result, name, value)
82
83
84
class _MyResult(unittest._TextTestResult):
1185.43.2 by Martin Pool
Nicer display of verbose test results and progress
85
    """Custom TestResult.
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
86
1185.33.54 by Martin Pool
[merge] test renames and other fixes (John)
87
    Shows output in a different format, including displaying runtime for tests.
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
88
    """
89
1185.1.58 by Robert Collins
make selftest -v show the elapsed time for each test run.
90
    def _elapsedTime(self):
1185.43.2 by Martin Pool
Nicer display of verbose test results and progress
91
        return "%5dms" % (1000 * (time.time() - self._start_time))
1185.1.58 by Robert Collins
make selftest -v show the elapsed time for each test run.
92
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
93
    def startTest(self, test):
94
        unittest.TestResult.startTest(self, test)
1185.31.17 by John Arbash Meinel
Shorten test names in verbose mode in a logical way. Removed bzrlib.selftest prefix
95
        # In a short description, the important words are in
96
        # the beginning, but in an id, the important words are
97
        # at the end
1185.33.54 by Martin Pool
[merge] test renames and other fixes (John)
98
        SHOW_DESCRIPTIONS = False
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
99
        if self.showAll:
1185.33.74 by Martin Pool
pychecker cleanups
100
            width = bzrlib.osutils.terminal_width()
1185.33.60 by Martin Pool
Use full terminal width for verbose test output.
101
            name_width = width - 15
102
            what = None
103
            if SHOW_DESCRIPTIONS:
104
                what = test.shortDescription()
105
                if what:
106
                    if len(what) > name_width:
107
                        what = what[:name_width-3] + '...'
108
            if what is None:
109
                what = test.id()
110
                if what.startswith('bzrlib.tests.'):
111
                    what = what[13:]
112
                if len(what) > name_width:
113
                    what = '...' + what[3-name_width:]
114
            what = what.ljust(name_width)
115
            self.stream.write(what)
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
116
        self.stream.flush()
1185.1.58 by Robert Collins
make selftest -v show the elapsed time for each test run.
117
        self._start_time = time.time()
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
118
119
    def addError(self, test, err):
1185.1.58 by Robert Collins
make selftest -v show the elapsed time for each test run.
120
        unittest.TestResult.addError(self, test, err)
121
        if self.showAll:
122
            self.stream.writeln("ERROR %s" % self._elapsedTime())
123
        elif self.dots:
124
            self.stream.write('E')
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
125
        self.stream.flush()
126
127
    def addFailure(self, test, err):
1185.1.58 by Robert Collins
make selftest -v show the elapsed time for each test run.
128
        unittest.TestResult.addFailure(self, test, err)
129
        if self.showAll:
1185.43.2 by Martin Pool
Nicer display of verbose test results and progress
130
            self.stream.writeln(" FAIL %s" % self._elapsedTime())
1185.1.58 by Robert Collins
make selftest -v show the elapsed time for each test run.
131
        elif self.dots:
132
            self.stream.write('F')
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
133
        self.stream.flush()
134
135
    def addSuccess(self, test):
136
        if self.showAll:
1185.43.2 by Martin Pool
Nicer display of verbose test results and progress
137
            self.stream.writeln('   OK %s' % self._elapsedTime())
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
138
        elif self.dots:
139
            self.stream.write('~')
140
        self.stream.flush()
141
        unittest.TestResult.addSuccess(self, test)
142
143
    def printErrorList(self, flavour, errors):
144
        for test, err in errors:
145
            self.stream.writeln(self.separator1)
146
            self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
147
            if hasattr(test, '_get_log'):
148
                self.stream.writeln()
149
                self.stream.writeln('log from this test:')
150
                print >>self.stream, test._get_log()
151
            self.stream.writeln(self.separator2)
152
            self.stream.writeln("%s" % err)
153
154
155
class TextTestRunner(unittest.TextTestRunner):
1185.16.58 by mbp at sourcefrog
- run all selftests by default
156
    stop_on_failure = False
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
157
158
    def _makeResult(self):
159
        result = _MyResult(self.stream, self.descriptions, self.verbosity)
1185.16.58 by mbp at sourcefrog
- run all selftests by default
160
        if self.stop_on_failure:
161
            result = EarlyStoppingTestResultAdapter(result)
162
        return result
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
163
164
1393.1.46 by Martin Pool
- bzr selftest arguments can be partial ids of tests to run
165
def iter_suite_tests(suite):
166
    """Return all tests in a suite, recursing through nested suites"""
167
    for item in suite._tests:
168
        if isinstance(item, unittest.TestCase):
169
            yield item
170
        elif isinstance(item, unittest.TestSuite):
171
            for r in iter_suite_tests(item):
172
                yield r
173
        else:
174
            raise Exception('unknown object %r inside test suite %r'
175
                            % (item, suite))
176
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
177
178
class TestSkipped(Exception):
179
    """Indicates that a test was intentionally skipped, rather than failing."""
180
    # XXX: Not used yet
181
182
1147 by Martin Pool
- split builtin commands into separate module bzrlib.builtins;
183
class CommandFailed(Exception):
184
    pass
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
185
186
class TestCase(unittest.TestCase):
187
    """Base class for bzr unit tests.
188
    
189
    Tests that need access to disk resources should subclass 
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
190
    TestCaseInTempDir not TestCase.
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
191
192
    Error and debug log messages are redirected from their usual
193
    location into a temporary file, the contents of which can be
1185.16.109 by mbp at sourcefrog
Clean up test log files when tests complete.
194
    retrieved by _get_log().  We use a real OS file, not an in-memory object,
195
    so that it can also capture file IO.  When the test completes this file
196
    is read into memory and removed from disk.
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
197
       
198
    There are also convenience functions to invoke bzr's command-line
1185.16.108 by mbp at sourcefrog
Add TestCase.addCleanup method.
199
    routine, and to build and check bzr trees.
200
   
201
    In addition to the usual method of overriding tearDown(), this class also
202
    allows subclasses to register functions into the _cleanups list, which is
203
    run in order as the object is torn down.  It's less likely this will be
204
    accidentally overlooked.
205
    """
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
206
207
    BZRPATH = 'bzr'
1185.16.14 by Martin Pool
- make TestCase._get_log work even if setup was aborted
208
    _log_file_name = None
1185.16.109 by mbp at sourcefrog
Clean up test log files when tests complete.
209
    _log_contents = ''
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
210
211
    def setUp(self):
212
        unittest.TestCase.setUp(self)
1185.16.108 by mbp at sourcefrog
Add TestCase.addCleanup method.
213
        self._cleanups = []
1185.16.110 by mbp at sourcefrog
Refactor test setup/teardown into cleanup callbacks
214
        self._cleanEnvironment()
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
215
        bzrlib.trace.disable_default_logging()
1185.16.109 by mbp at sourcefrog
Clean up test log files when tests complete.
216
        self._startLogFile()
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
217
1185.16.16 by Martin Pool
- add TestCase.assertEqualDiffs helper
218
    def _ndiff_strings(self, a, b):
1185.16.67 by Martin Pool
- assertEqualDiff handles strings without trailing newline
219
        """Return ndiff between two strings containing lines.
220
        
221
        A trailing newline is added if missing to make the strings
222
        print properly."""
223
        if b and b[-1] != '\n':
224
            b += '\n'
225
        if a and a[-1] != '\n':
226
            a += '\n'
1185.16.21 by Martin Pool
- tweak diff shown by assertEqualDiff
227
        difflines = difflib.ndiff(a.splitlines(True),
228
                                  b.splitlines(True),
229
                                  linejunk=lambda x: False,
230
                                  charjunk=lambda x: False)
231
        return ''.join(difflines)
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
232
1185.16.16 by Martin Pool
- add TestCase.assertEqualDiffs helper
233
    def assertEqualDiff(self, a, b):
234
        """Assert two texts are equal, if not raise an exception.
235
        
236
        This is intended for use with multi-line strings where it can 
237
        be hard to find the differences by eye.
238
        """
239
        # TODO: perhaps override assertEquals to call this for strings?
240
        if a == b:
241
            return
242
        raise AssertionError("texts not equal:\n" + 
243
                             self._ndiff_strings(a, b))      
1185.16.42 by Martin Pool
- Add assertContainsRe
244
245
    def assertContainsRe(self, haystack, needle_re):
246
        """Assert that a contains something matching a regular expression."""
247
        if not re.search(needle_re, haystack):
248
            raise AssertionError('pattern "%s" not found in "%s"'
249
                    % (needle_re, haystack))
1442.1.70 by Robert Collins
Add assertFileEqual to TestCaseInTempDir.
250
1185.16.109 by mbp at sourcefrog
Clean up test log files when tests complete.
251
    def _startLogFile(self):
252
        """Send bzr and test log messages to a temporary file.
253
254
        The file is removed as the test is torn down.
255
        """
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
256
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1185.52.1 by James Henstridge
Don't encode unicode messages to UTF-8 in mutter() (the stream writer does it).
257
        encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
258
        self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
1185.33.13 by Martin Pool
Hide more stuff in bzrlib.trace
259
        bzrlib.trace.enable_test_log(self._log_file)
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
260
        self._log_file_name = name
1185.16.109 by mbp at sourcefrog
Clean up test log files when tests complete.
261
        self.addCleanup(self._finishLogFile)
262
263
    def _finishLogFile(self):
264
        """Finished with the log file.
265
266
        Read contents into memory, close, and delete.
267
        """
1185.33.13 by Martin Pool
Hide more stuff in bzrlib.trace
268
        bzrlib.trace.disable_test_log()
1185.16.109 by mbp at sourcefrog
Clean up test log files when tests complete.
269
        self._log_file.seek(0)
270
        self._log_contents = self._log_file.read()
1185.16.122 by Martin Pool
[patch] Close test log file before deleting, needed on Windows
271
        self._log_file.close()
1185.16.109 by mbp at sourcefrog
Clean up test log files when tests complete.
272
        os.remove(self._log_file_name)
273
        self._log_file = self._log_file_name = None
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
274
1185.16.108 by mbp at sourcefrog
Add TestCase.addCleanup method.
275
    def addCleanup(self, callable):
276
        """Arrange to run a callable when this case is torn down.
277
278
        Callables are run in the reverse of the order they are registered, 
279
        ie last-in first-out.
280
        """
1185.16.109 by mbp at sourcefrog
Clean up test log files when tests complete.
281
        if callable in self._cleanups:
282
            raise ValueError("cleanup function %r already registered on %s" 
283
                    % (callable, self))
1185.16.108 by mbp at sourcefrog
Add TestCase.addCleanup method.
284
        self._cleanups.append(callable)
285
1185.16.110 by mbp at sourcefrog
Refactor test setup/teardown into cleanup callbacks
286
    def _cleanEnvironment(self):
1185.38.3 by John Arbash Meinel
Refactored environment cleaning code
287
        new_env = {
288
            'HOME': os.getcwd(),
289
            'APPDATA': os.getcwd(),
290
            'BZREMAIL': None,
291
            'EMAIL': None,
292
        }
1185.38.4 by John Arbash Meinel
Making old_env a private member
293
        self.__old_env = {}
1185.16.110 by mbp at sourcefrog
Refactor test setup/teardown into cleanup callbacks
294
        self.addCleanup(self._restoreEnvironment)
1185.38.3 by John Arbash Meinel
Refactored environment cleaning code
295
        for name, value in new_env.iteritems():
296
            self._captureVar(name, value)
297
298
299
    def _captureVar(self, name, newvalue):
300
        """Set an environment variable, preparing it to be reset when finished."""
1185.38.4 by John Arbash Meinel
Making old_env a private member
301
        self.__old_env[name] = os.environ.get(name, None)
1185.38.3 by John Arbash Meinel
Refactored environment cleaning code
302
        if newvalue is None:
303
            if name in os.environ:
304
                del os.environ[name]
305
        else:
306
            os.environ[name] = newvalue
1185.16.110 by mbp at sourcefrog
Refactor test setup/teardown into cleanup callbacks
307
1185.38.2 by John Arbash Meinel
[patch] Aaron Bentley's HOME fix.
308
    @staticmethod
309
    def _restoreVar(name, value):
310
        if value is None:
1185.38.3 by John Arbash Meinel
Refactored environment cleaning code
311
            if name in os.environ:
312
                del os.environ[name]
1185.38.2 by John Arbash Meinel
[patch] Aaron Bentley's HOME fix.
313
        else:
314
            os.environ[name] = value
315
1185.16.110 by mbp at sourcefrog
Refactor test setup/teardown into cleanup callbacks
316
    def _restoreEnvironment(self):
1185.38.4 by John Arbash Meinel
Making old_env a private member
317
        for name, value in self.__old_env.iteritems():
1185.38.3 by John Arbash Meinel
Refactored environment cleaning code
318
            self._restoreVar(name, value)
1185.16.110 by mbp at sourcefrog
Refactor test setup/teardown into cleanup callbacks
319
320
    def tearDown(self):
1185.16.108 by mbp at sourcefrog
Add TestCase.addCleanup method.
321
        self._runCleanups()
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
322
        unittest.TestCase.tearDown(self)
323
1185.16.108 by mbp at sourcefrog
Add TestCase.addCleanup method.
324
    def _runCleanups(self):
325
        """Run registered cleanup functions. 
326
327
        This should only be called from TestCase.tearDown.
328
        """
1185.33.74 by Martin Pool
pychecker cleanups
329
        for cleanup_fn in reversed(self._cleanups):
330
            cleanup_fn()
1185.16.108 by mbp at sourcefrog
Add TestCase.addCleanup method.
331
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
332
    def log(self, *args):
1185.43.1 by Martin Pool
Remove direct logging calls from selftest
333
        mutter(*args)
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
334
335
    def _get_log(self):
336
        """Return as a string the log for this test"""
1185.16.14 by Martin Pool
- make TestCase._get_log work even if setup was aborted
337
        if self._log_file_name:
338
            return open(self._log_file_name).read()
339
        else:
1185.16.109 by mbp at sourcefrog
Clean up test log files when tests complete.
340
            return self._log_contents
1185.43.1 by Martin Pool
Remove direct logging calls from selftest
341
        # TODO: Delete the log after it's been read in
1185.3.18 by Martin Pool
- add new helper TestBase.run_bzr_captured
342
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
343
    def capture(self, cmd, retcode=0):
1185.3.26 by Martin Pool
- remove remaining external executions of bzr
344
        """Shortcut that splits cmd into words, runs, and returns stdout"""
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
345
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
1185.3.26 by Martin Pool
- remove remaining external executions of bzr
346
1185.3.18 by Martin Pool
- add new helper TestBase.run_bzr_captured
347
    def run_bzr_captured(self, argv, retcode=0):
1185.22.7 by Michael Ellerman
Fix error in run_bzr_captured() doco
348
        """Invoke bzr and return (stdout, stderr).
1185.3.18 by Martin Pool
- add new helper TestBase.run_bzr_captured
349
350
        Useful for code that wants to check the contents of the
351
        output, the way error messages are presented, etc.
352
353
        This should be the main method for tests that want to exercise the
354
        overall behavior of the bzr application (rather than a unit test
355
        or a functional test of the library.)
356
357
        Much of the old code runs bzr by forking a new copy of Python, but
358
        that is slower, harder to debug, and generally not necessary.
359
1185.3.20 by Martin Pool
- run_bzr_captured also includes logged errors in
360
        This runs bzr through the interface that catches and reports
361
        errors, and with logging set to something approximating the
362
        default, so that error reporting can be checked.
363
1185.3.18 by Martin Pool
- add new helper TestBase.run_bzr_captured
364
        argv -- arguments to invoke bzr
365
        retcode -- expected return code, or None for don't-care.
366
        """
367
        stdout = StringIO()
368
        stderr = StringIO()
369
        self.log('run bzr: %s', ' '.join(argv))
1185.43.5 by Martin Pool
Update log message quoting
370
        # FIXME: don't call into logging here
1185.3.20 by Martin Pool
- run_bzr_captured also includes logged errors in
371
        handler = logging.StreamHandler(stderr)
372
        handler.setFormatter(bzrlib.trace.QuietFormatter())
373
        handler.setLevel(logging.INFO)
374
        logger = logging.getLogger('')
375
        logger.addHandler(handler)
376
        try:
377
            result = self.apply_redirected(None, stdout, stderr,
378
                                           bzrlib.commands.run_bzr_catch_errors,
379
                                           argv)
380
        finally:
381
            logger.removeHandler(handler)
1185.3.18 by Martin Pool
- add new helper TestBase.run_bzr_captured
382
        out = stdout.getvalue()
383
        err = stderr.getvalue()
384
        if out:
385
            self.log('output:\n%s', out)
386
        if err:
387
            self.log('errors:\n%s', err)
388
        if retcode is not None:
389
            self.assertEquals(result, retcode)
390
        return out, err
391
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
392
    def run_bzr(self, *args, **kwargs):
1119 by Martin Pool
doc
393
        """Invoke bzr, as if it were run from the command line.
394
395
        This should be the main method for tests that want to exercise the
396
        overall behavior of the bzr application (rather than a unit test
397
        or a functional test of the library.)
398
1185.3.18 by Martin Pool
- add new helper TestBase.run_bzr_captured
399
        This sends the stdout/stderr results into the test's log,
400
        where it may be useful for debugging.  See also run_captured.
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
401
        """
1185.3.18 by Martin Pool
- add new helper TestBase.run_bzr_captured
402
        retcode = kwargs.pop('retcode', 0)
1185.3.21 by Martin Pool
TestBase.run_bzr doesn't need to be deprecated
403
        return self.run_bzr_captured(args, retcode)
1185.3.18 by Martin Pool
- add new helper TestBase.run_bzr_captured
404
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
405
    def check_inventory_shape(self, inv, shape):
1291 by Martin Pool
- add test for moving files between directories
406
        """Compare an inventory to a list of expected names.
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
407
408
        Fail if they are not precisely equal.
409
        """
410
        extras = []
411
        shape = list(shape)             # copy
412
        for path, ie in inv.entries():
413
            name = path.replace('\\', '/')
414
            if ie.kind == 'dir':
415
                name = name + '/'
416
            if name in shape:
417
                shape.remove(name)
418
            else:
419
                extras.append(name)
420
        if shape:
421
            self.fail("expected paths not found in inventory: %r" % shape)
422
        if extras:
423
            self.fail("unexpected paths found in inventory: %r" % extras)
424
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
425
    def apply_redirected(self, stdin=None, stdout=None, stderr=None,
426
                         a_callable=None, *args, **kwargs):
427
        """Call callable with redirected std io pipes.
428
429
        Returns the return code."""
430
        if not callable(a_callable):
431
            raise ValueError("a_callable must be callable.")
432
        if stdin is None:
433
            stdin = StringIO("")
434
        if stdout is None:
974.1.70 by Aaron Bentley
Fixed selftest spewage (Brian M. Carlson)
435
            if hasattr(self, "_log_file"):
436
                stdout = self._log_file
437
            else:
438
                stdout = StringIO()
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
439
        if stderr is None:
974.1.70 by Aaron Bentley
Fixed selftest spewage (Brian M. Carlson)
440
            if hasattr(self, "_log_file"):
441
                stderr = self._log_file
442
            else:
443
                stderr = StringIO()
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
444
        real_stdin = sys.stdin
445
        real_stdout = sys.stdout
446
        real_stderr = sys.stderr
447
        try:
448
            sys.stdout = stdout
449
            sys.stderr = stderr
450
            sys.stdin = stdin
1160 by Martin Pool
- tiny refactoring
451
            return a_callable(*args, **kwargs)
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
452
        finally:
453
            sys.stdout = real_stdout
454
            sys.stderr = real_stderr
455
            sys.stdin = real_stdin
456
457
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
458
BzrTestBase = TestCase
459
460
     
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
461
class TestCaseInTempDir(TestCase):
462
    """Derived class that runs a test within a temporary directory.
463
464
    This is useful for tests that need to create a branch, etc.
465
466
    The directory is created in a slightly complex way: for each
467
    Python invocation, a new temporary top-level directory is created.
468
    All test cases create their own directory within that.  If the
469
    tests complete successfully, the directory is removed.
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
470
471
    InTempDir is an old alias for FunctionalTestCase.
472
    """
473
474
    TEST_ROOT = None
475
    _TEST_NAME = 'test'
476
    OVERRIDE_PYTHON = 'python'
477
478
    def check_file_contents(self, filename, expect):
479
        self.log("check contents of file %s" % filename)
480
        contents = file(filename, 'r').read()
481
        if contents != expect:
482
            self.log("expected: %r" % expect)
483
            self.log("actually: %r" % contents)
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
484
            self.fail("contents of %s not as expected" % filename)
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
485
486
    def _make_test_root(self):
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
487
        if TestCaseInTempDir.TEST_ROOT is not None:
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
488
            return
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
489
        i = 0
490
        while True:
1185.16.147 by Martin Pool
[patch] Test base directory must be unicode (from Alexander)
491
            root = u'test%04d.tmp' % i
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
492
            try:
493
                os.mkdir(root)
494
            except OSError, e:
495
                if e.errno == errno.EEXIST:
496
                    i += 1
497
                    continue
498
                else:
499
                    raise
500
            # successfully created
501
            TestCaseInTempDir.TEST_ROOT = os.path.abspath(root)
502
            break
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
503
        # make a fake bzr directory there to prevent any tests propagating
504
        # up onto the source directory's real branch
1141 by Martin Pool
- rename FunctionalTest to TestCaseInTempDir
505
        os.mkdir(os.path.join(TestCaseInTempDir.TEST_ROOT, '.bzr'))
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
506
507
    def setUp(self):
1185.16.110 by mbp at sourcefrog
Refactor test setup/teardown into cleanup callbacks
508
        super(TestCaseInTempDir, self).setUp()
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
509
        self._make_test_root()
1185.16.110 by mbp at sourcefrog
Refactor test setup/teardown into cleanup callbacks
510
        _currentdir = os.getcwdu()
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
511
        short_id = self.id().replace('bzrlib.tests.', '') \
1218 by Martin Pool
- fix up import
512
                   .replace('__main__.', '')
1212 by Martin Pool
- use shorter test directory names
513
        self.test_dir = os.path.join(self.TEST_ROOT, short_id)
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
514
        os.mkdir(self.test_dir)
515
        os.chdir(self.test_dir)
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
516
        os.environ['HOME'] = self.test_dir
1185.16.110 by mbp at sourcefrog
Refactor test setup/teardown into cleanup callbacks
517
        def _leaveDirectory():
518
            os.chdir(_currentdir)
519
        self.addCleanup(_leaveDirectory)
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
520
        
1185.38.7 by John Arbash Meinel
Updated build_tree to use fixed line-endings for tests which read the file contents and compare
521
    def build_tree(self, shape, line_endings='native'):
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
522
        """Build a test tree according to a pattern.
523
524
        shape is a sequence of file specifications.  If the final
525
        character is '/', a directory is created.
526
527
        This doesn't add anything to a branch.
1185.38.7 by John Arbash Meinel
Updated build_tree to use fixed line-endings for tests which read the file contents and compare
528
        :param line_endings: Either 'binary' or 'native'
529
                             in binary mode, exact contents are written
530
                             in native mode, the line endings match the
531
                             default platform endings.
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
532
        """
533
        # XXX: It's OK to just create them using forward slashes on windows?
534
        for name in shape:
1185.16.145 by Martin Pool
Remove all assert statements from test cases.
535
            self.assert_(isinstance(name, basestring))
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
536
            if name[-1] == '/':
537
                os.mkdir(name[:-1])
538
            else:
1185.38.7 by John Arbash Meinel
Updated build_tree to use fixed line-endings for tests which read the file contents and compare
539
                if line_endings == 'binary':
540
                    f = file(name, 'wb')
541
                elif line_endings == 'native':
542
                    f = file(name, 'wt')
543
                else:
544
                    raise BzrError('Invalid line ending request %r' % (line_endings,))
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
545
                print >>f, "contents of", name
546
                f.close()
547
1185.16.53 by Martin Pool
- annotate improvements from Goffreddo, with extra bug fixes and tests
548
    def build_tree_contents(self, shape):
1514 by Robert Collins
Unbreak self.build_tree_shape in tests.
549
        build_tree_contents(shape)
1185.16.53 by Martin Pool
- annotate improvements from Goffreddo, with extra bug fixes and tests
550
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
551
    def failUnlessExists(self, path):
552
        """Fail unless path, which may be abs or relative, exists."""
1185.33.74 by Martin Pool
pychecker cleanups
553
        self.failUnless(bzrlib.osutils.lexists(path))
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
554
        
1442.1.70 by Robert Collins
Add assertFileEqual to TestCaseInTempDir.
555
    def assertFileEqual(self, content, path):
556
        """Fail if path does not contain 'content'."""
1185.33.74 by Martin Pool
pychecker cleanups
557
        self.failUnless(bzrlib.osutils.lexists(path))
1442.1.70 by Robert Collins
Add assertFileEqual to TestCaseInTempDir.
558
        self.assertEqualDiff(content, open(path, 'r').read())
559
        
1123 by Martin Pool
* move bzr-specific code from testsweet into bzrlib.selftest
560
1393.1.46 by Martin Pool
- bzr selftest arguments can be partial ids of tests to run
561
def filter_suite_by_re(suite, pattern):
1185.33.74 by Martin Pool
pychecker cleanups
562
    result = TestSuite()
1393.1.46 by Martin Pool
- bzr selftest arguments can be partial ids of tests to run
563
    filter_re = re.compile(pattern)
564
    for test in iter_suite_tests(suite):
1185.1.57 by Robert Collins
nuke --pattern to selftest, replace with regexp.search calls.
565
        if filter_re.search(test.id()):
1393.1.46 by Martin Pool
- bzr selftest arguments can be partial ids of tests to run
566
            result.addTest(test)
567
    return result
568
569
1185.16.58 by mbp at sourcefrog
- run all selftests by default
570
def run_suite(suite, name='test', verbose=False, pattern=".*",
1185.35.20 by Aaron Bentley
Only keep test failure directories if --keep-output is specified
571
              stop_on_failure=False, keep_output=False):
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
572
    TestCaseInTempDir._TEST_NAME = name
573
    if verbose:
574
        verbosity = 2
575
    else:
576
        verbosity = 1
577
    runner = TextTestRunner(stream=sys.stdout,
578
                            descriptions=0,
579
                            verbosity=verbosity)
1185.16.58 by mbp at sourcefrog
- run all selftests by default
580
    runner.stop_on_failure=stop_on_failure
1393.1.46 by Martin Pool
- bzr selftest arguments can be partial ids of tests to run
581
    if pattern != '.*':
582
        suite = filter_suite_by_re(suite, pattern)
583
    result = runner.run(suite)
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
584
    # This is still a little bogus, 
585
    # but only a little. Folk not using our testrunner will
586
    # have to delete their temp directories themselves.
1185.35.20 by Aaron Bentley
Only keep test failure directories if --keep-output is specified
587
    if result.wasSuccessful() or not keep_output:
1393.1.6 by Martin Pool
- fold testsweet into bzrlib.selftest
588
        if TestCaseInTempDir.TEST_ROOT is not None:
589
            shutil.rmtree(TestCaseInTempDir.TEST_ROOT) 
590
    else:
591
        print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
592
    return result.wasSuccessful()
593
594
1185.35.20 by Aaron Bentley
Only keep test failure directories if --keep-output is specified
595
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
596
             keep_output=False):
1204 by Martin Pool
doc
597
    """Run the whole test suite under the enhanced runner"""
1185.16.58 by mbp at sourcefrog
- run all selftests by default
598
    return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern,
1185.35.20 by Aaron Bentley
Only keep test failure directories if --keep-output is specified
599
                     stop_on_failure=stop_on_failure, keep_output=keep_output)
1092.1.17 by Robert Collins
remove TEST_CLASSES dead code and provide a bzrlib.test_suite() convenience method
600
601
602
def test_suite():
1204 by Martin Pool
doc
603
    """Build and return TestSuite for the whole program."""
721 by Martin Pool
- framework for running external commands from unittest suite
604
    from doctest import DocTestSuite
605
1513 by Robert Collins
Blackbox tests are maintained within the bzrlib.tests.blackbox directory.
606
    global MODULES_TO_DOCTEST
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
607
1185.51.1 by Martin Pool
Better message when failing to import a test suite.
608
    testmod_names = [ \
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
609
                   'bzrlib.tests.test_api',
610
                   'bzrlib.tests.test_gpg',
611
                   'bzrlib.tests.test_identitymap',
612
                   'bzrlib.tests.test_inv',
613
                   'bzrlib.tests.test_ancestry',
614
                   'bzrlib.tests.test_commit',
615
                   'bzrlib.tests.test_command',
616
                   'bzrlib.tests.test_commit_merge',
617
                   'bzrlib.tests.test_config',
618
                   'bzrlib.tests.test_merge3',
619
                   'bzrlib.tests.test_merge',
620
                   'bzrlib.tests.test_hashcache',
621
                   'bzrlib.tests.test_status',
622
                   'bzrlib.tests.test_log',
623
                   'bzrlib.tests.test_revisionnamespaces',
624
                   'bzrlib.tests.test_branch',
625
                   'bzrlib.tests.test_revision',
626
                   'bzrlib.tests.test_revision_info',
627
                   'bzrlib.tests.test_merge_core',
628
                   'bzrlib.tests.test_smart_add',
629
                   'bzrlib.tests.test_bad_files',
630
                   'bzrlib.tests.test_diff',
631
                   'bzrlib.tests.test_parent',
632
                   'bzrlib.tests.test_xml',
633
                   'bzrlib.tests.test_weave',
634
                   'bzrlib.tests.test_fetch',
635
                   'bzrlib.tests.test_whitebox',
636
                   'bzrlib.tests.test_store',
637
                   'bzrlib.tests.test_sampler',
638
                   'bzrlib.tests.test_transactions',
639
                   'bzrlib.tests.test_transport',
640
                   'bzrlib.tests.test_sftp',
641
                   'bzrlib.tests.test_graph',
642
                   'bzrlib.tests.test_workingtree',
643
                   'bzrlib.tests.test_upgrade',
644
                   'bzrlib.tests.test_uncommit',
1185.49.22 by John Arbash Meinel
Added get_password to the UIFactory, using it inside of sftp.py
645
                   'bzrlib.tests.test_ui',
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
646
                   'bzrlib.tests.test_conflicts',
647
                   'bzrlib.tests.test_testament',
648
                   'bzrlib.tests.test_annotate',
649
                   'bzrlib.tests.test_revprops',
650
                   'bzrlib.tests.test_options',
651
                   'bzrlib.tests.test_http',
652
                   'bzrlib.tests.test_nonascii',
1515 by Robert Collins
* Plugins with the same name in different directories in the bzr plugin
653
                   'bzrlib.tests.test_plugins',
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
654
                   'bzrlib.tests.test_reweave',
655
                   'bzrlib.tests.test_tsort',
656
                   'bzrlib.tests.test_trace',
1185.47.1 by Martin Pool
[broken] start converting basic_io to more rfc822-like format
657
                   'bzrlib.tests.test_rio',
1185.33.72 by Martin Pool
Fix commit message template for non-ascii files, and add test for handling of
658
                   'bzrlib.tests.test_msgeditor',
1185.51.1 by Martin Pool
Better message when failing to import a test suite.
659
                   'bzrlib.tests.test_selftest',
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
660
                   ]
661
1185.51.1 by Martin Pool
Better message when failing to import a test suite.
662
    print '%10s: %s' % ('bzr', os.path.realpath(sys.argv[0]))
663
    print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
744 by Martin Pool
- show nicer descriptions while running tests
664
    print
721 by Martin Pool
- framework for running external commands from unittest suite
665
    suite = TestSuite()
1185.51.1 by Martin Pool
Better message when failing to import a test suite.
666
    # python2.4's TestLoader.loadTestsFromNames gives very poor 
667
    # errors if it fails to load a named module - no indication of what's
668
    # actually wrong, just "no such module".  We should probably override that
669
    # class, but for the moment just load them ourselves. (mbp 20051202)
670
    loader = TestLoader()
671
    for mod_name in testmod_names:
672
        mod = _load_module_by_name(mod_name)
673
        suite.addTest(loader.loadTestsFromModule(mod))
1513 by Robert Collins
Blackbox tests are maintained within the bzrlib.tests.blackbox directory.
674
    for package in packages_to_test():
675
        suite.addTest(package.test_suite())
855 by Martin Pool
- Patch from John to allow plugins to add their own tests.
676
    for m in MODULES_TO_TEST:
1185.51.1 by Martin Pool
Better message when failing to import a test suite.
677
        suite.addTest(loader.loadTestsFromModule(m))
855 by Martin Pool
- Patch from John to allow plugins to add their own tests.
678
    for m in (MODULES_TO_DOCTEST):
721 by Martin Pool
- framework for running external commands from unittest suite
679
        suite.addTest(DocTestSuite(m))
1516 by Robert Collins
* bzrlib.plugin.all_plugins has been changed from an attribute to a
680
    for name, plugin in bzrlib.plugin.all_plugins().items():
681
        if hasattr(plugin, 'test_suite'):
682
            suite.addTest(plugin.test_suite())
1092.1.17 by Robert Collins
remove TEST_CLASSES dead code and provide a bzrlib.test_suite() convenience method
683
    return suite
764 by Martin Pool
- log messages from a particular test are printed if that test fails
684
1185.51.1 by Martin Pool
Better message when failing to import a test suite.
685
686
def _load_module_by_name(mod_name):
687
    parts = mod_name.split('.')
688
    module = __import__(mod_name)
689
    del parts[0]
690
    # for historical reasons python returns the top-level module even though
691
    # it loads the submodule; we need to walk down to get the one we want.
692
    while parts:
693
        module = getattr(module, parts.pop(0))
694
    return module