/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Martin Pool
  • Date: 2006-10-06 02:04:17 UTC
  • mfrom: (1908.10.1 bench_usecases.merge2)
  • mto: This revision was merged to the branch mainline in revision 2068.
  • Revision ID: mbp@sourcefrog.net-20061006020417-4949ca86f4417a4d
merge additional fix from cfbolz

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005, 2006 by Canonical Ltd
2
 
 
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
29
import codecs
30
30
from cStringIO import StringIO
31
31
import difflib
 
32
import doctest
32
33
import errno
33
34
import logging
34
35
import os
35
36
import re
36
 
import shutil
 
37
import shlex
37
38
import stat
 
39
from subprocess import Popen, PIPE
38
40
import sys
39
41
import tempfile
40
42
import unittest
41
43
import time
42
44
 
43
45
 
 
46
from bzrlib import memorytree
44
47
import bzrlib.branch
45
48
import bzrlib.bzrdir as bzrdir
46
49
import bzrlib.commands
 
50
import bzrlib.bundle.serializer
47
51
import bzrlib.errors as errors
 
52
import bzrlib.export
48
53
import bzrlib.inventory
49
54
import bzrlib.iterablefile
50
55
import bzrlib.lockdir
 
56
try:
 
57
    import bzrlib.lsprof
 
58
except ImportError:
 
59
    # lsprof not available
 
60
    pass
51
61
from bzrlib.merge import merge_inner
52
62
import bzrlib.merge3
53
63
import bzrlib.osutils
54
64
import bzrlib.osutils as osutils
55
65
import bzrlib.plugin
 
66
import bzrlib.progress as progress
56
67
from bzrlib.revision import common_ancestor
57
68
import bzrlib.store
 
69
from bzrlib import symbol_versioning
58
70
import bzrlib.trace
59
 
from bzrlib.transport import urlescape, get_transport
 
71
from bzrlib.transport import get_transport
60
72
import bzrlib.transport
61
73
from bzrlib.transport.local import LocalRelpathServer
62
74
from bzrlib.transport.readonly import ReadonlyServer
63
75
from bzrlib.trace import mutter
64
 
from bzrlib.tests.TestUtil import TestLoader, TestSuite
 
76
from bzrlib.tests import TestUtil
 
77
from bzrlib.tests.TestUtil import (
 
78
                          TestSuite,
 
79
                          TestLoader,
 
80
                          )
65
81
from bzrlib.tests.treeshape import build_tree_contents
 
82
import bzrlib.urlutils as urlutils
66
83
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
67
84
 
68
85
default_transport = LocalRelpathServer
70
87
MODULES_TO_TEST = []
71
88
MODULES_TO_DOCTEST = [
72
89
                      bzrlib.branch,
 
90
                      bzrlib.bundle.serializer,
73
91
                      bzrlib.commands,
74
92
                      bzrlib.errors,
 
93
                      bzrlib.export,
75
94
                      bzrlib.inventory,
76
95
                      bzrlib.iterablefile,
77
96
                      bzrlib.lockdir,
78
97
                      bzrlib.merge3,
79
98
                      bzrlib.option,
80
99
                      bzrlib.osutils,
81
 
                      bzrlib.store
 
100
                      bzrlib.store,
 
101
                      bzrlib.transport,
82
102
                      ]
 
103
 
 
104
 
83
105
def packages_to_test():
84
106
    """Return a list of packages to test.
85
107
 
92
114
    import bzrlib.tests.bzrdir_implementations
93
115
    import bzrlib.tests.interrepository_implementations
94
116
    import bzrlib.tests.interversionedfile_implementations
 
117
    import bzrlib.tests.intertree_implementations
95
118
    import bzrlib.tests.repository_implementations
96
119
    import bzrlib.tests.revisionstore_implementations
 
120
    import bzrlib.tests.tree_implementations
97
121
    import bzrlib.tests.workingtree_implementations
98
122
    return [
99
123
            bzrlib.doc,
102
126
            bzrlib.tests.bzrdir_implementations,
103
127
            bzrlib.tests.interrepository_implementations,
104
128
            bzrlib.tests.interversionedfile_implementations,
 
129
            bzrlib.tests.intertree_implementations,
105
130
            bzrlib.tests.repository_implementations,
106
131
            bzrlib.tests.revisionstore_implementations,
 
132
            bzrlib.tests.tree_implementations,
107
133
            bzrlib.tests.workingtree_implementations,
108
134
            ]
109
135
 
114
140
    Shows output in a different format, including displaying runtime for tests.
115
141
    """
116
142
    stop_early = False
117
 
 
118
 
    def _elapsedTime(self):
119
 
        return "%5dms" % (1000 * (time.time() - self._start_time))
 
143
    
 
144
    def __init__(self, stream, descriptions, verbosity, pb=None,
 
145
                 bench_history=None):
 
146
        """Construct new TestResult.
 
147
 
 
148
        :param bench_history: Optionally, a writable file object to accumulate
 
149
            benchmark results.
 
150
        """
 
151
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
 
152
        self.pb = pb
 
153
        if bench_history is not None:
 
154
            from bzrlib.version import _get_bzr_source_tree
 
155
            src_tree = _get_bzr_source_tree()
 
156
            if src_tree:
 
157
                try:
 
158
                    revision_id = src_tree.get_parent_ids()[0]
 
159
                except IndexError:
 
160
                    # XXX: if this is a brand new tree, do the same as if there
 
161
                    # is no branch.
 
162
                    revision_id = ''
 
163
            else:
 
164
                # XXX: If there's no branch, what should we do?
 
165
                revision_id = ''
 
166
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
 
167
        self._bench_history = bench_history
 
168
    
 
169
    def extractBenchmarkTime(self, testCase):
 
170
        """Add a benchmark time for the current test case."""
 
171
        self._benchmarkTime = getattr(testCase, "_benchtime", None)
 
172
    
 
173
    def _elapsedTestTimeString(self):
 
174
        """Return a time string for the overall time the current test has taken."""
 
175
        return self._formatTime(time.time() - self._start_time)
 
176
 
 
177
    def _testTimeString(self):
 
178
        if self._benchmarkTime is not None:
 
179
            return "%s/%s" % (
 
180
                self._formatTime(self._benchmarkTime),
 
181
                self._elapsedTestTimeString())
 
182
        else:
 
183
            return "      %s" % self._elapsedTestTimeString()
 
184
 
 
185
    def _formatTime(self, seconds):
 
186
        """Format seconds as milliseconds with leading spaces."""
 
187
        return "%5dms" % (1000 * seconds)
 
188
 
 
189
    def _ellipsise_unimportant_words(self, a_string, final_width,
 
190
                                   keep_start=False):
 
191
        """Add ellipses (sp?) for overly long strings.
 
192
        
 
193
        :param keep_start: If true preserve the start of a_string rather
 
194
                           than the end of it.
 
195
        """
 
196
        if keep_start:
 
197
            if len(a_string) > final_width:
 
198
                result = a_string[:final_width-3] + '...'
 
199
            else:
 
200
                result = a_string
 
201
        else:
 
202
            if len(a_string) > final_width:
 
203
                result = '...' + a_string[3-final_width:]
 
204
            else:
 
205
                result = a_string
 
206
        return result.ljust(final_width)
120
207
 
121
208
    def startTest(self, test):
122
209
        unittest.TestResult.startTest(self, test)
124
211
        # the beginning, but in an id, the important words are
125
212
        # at the end
126
213
        SHOW_DESCRIPTIONS = False
 
214
 
 
215
        if not self.showAll and self.dots and self.pb is not None:
 
216
            final_width = 13
 
217
        else:
 
218
            final_width = osutils.terminal_width()
 
219
            final_width = final_width - 15 - 8
 
220
        what = None
 
221
        if SHOW_DESCRIPTIONS:
 
222
            what = test.shortDescription()
 
223
            if what:
 
224
                what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
 
225
        if what is None:
 
226
            what = test.id()
 
227
            if what.startswith('bzrlib.tests.'):
 
228
                what = what[13:]
 
229
            what = self._ellipsise_unimportant_words(what, final_width)
127
230
        if self.showAll:
128
 
            width = osutils.terminal_width()
129
 
            name_width = width - 15
130
 
            what = None
131
 
            if SHOW_DESCRIPTIONS:
132
 
                what = test.shortDescription()
133
 
                if what:
134
 
                    if len(what) > name_width:
135
 
                        what = what[:name_width-3] + '...'
136
 
            if what is None:
137
 
                what = test.id()
138
 
                if what.startswith('bzrlib.tests.'):
139
 
                    what = what[13:]
140
 
                if len(what) > name_width:
141
 
                    what = '...' + what[3-name_width:]
142
 
            what = what.ljust(name_width)
143
231
            self.stream.write(what)
 
232
        elif self.dots and self.pb is not None:
 
233
            self.pb.update(what, self.testsRun - 1, None)
144
234
        self.stream.flush()
 
235
        self._recordTestStartTime()
 
236
 
 
237
    def _recordTestStartTime(self):
 
238
        """Record that a test has started."""
145
239
        self._start_time = time.time()
146
240
 
147
241
    def addError(self, test, err):
148
242
        if isinstance(err[1], TestSkipped):
149
243
            return self.addSkipped(test, err)    
150
244
        unittest.TestResult.addError(self, test, err)
 
245
        # We can only do this if we have one of our TestCases, not if
 
246
        # we have a doctest.
 
247
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
248
        if setKeepLogfile is not None:
 
249
            setKeepLogfile()
 
250
        self.extractBenchmarkTime(test)
151
251
        if self.showAll:
152
 
            self.stream.writeln("ERROR %s" % self._elapsedTime())
153
 
        elif self.dots:
 
252
            self.stream.writeln("ERROR %s" % self._testTimeString())
 
253
        elif self.dots and self.pb is None:
154
254
            self.stream.write('E')
 
255
        elif self.dots:
 
256
            self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
 
257
            self.pb.note(self._ellipsise_unimportant_words(
 
258
                            test.id() + ': ERROR',
 
259
                            osutils.terminal_width()))
155
260
        self.stream.flush()
156
261
        if self.stop_early:
157
262
            self.stop()
158
263
 
159
264
    def addFailure(self, test, err):
160
265
        unittest.TestResult.addFailure(self, test, err)
 
266
        # We can only do this if we have one of our TestCases, not if
 
267
        # we have a doctest.
 
268
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
269
        if setKeepLogfile is not None:
 
270
            setKeepLogfile()
 
271
        self.extractBenchmarkTime(test)
161
272
        if self.showAll:
162
 
            self.stream.writeln(" FAIL %s" % self._elapsedTime())
163
 
        elif self.dots:
 
273
            self.stream.writeln(" FAIL %s" % self._testTimeString())
 
274
        elif self.dots and self.pb is None:
164
275
            self.stream.write('F')
 
276
        elif self.dots:
 
277
            self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
 
278
            self.pb.note(self._ellipsise_unimportant_words(
 
279
                            test.id() + ': FAIL',
 
280
                            osutils.terminal_width()))
165
281
        self.stream.flush()
166
282
        if self.stop_early:
167
283
            self.stop()
168
284
 
169
285
    def addSuccess(self, test):
 
286
        self.extractBenchmarkTime(test)
 
287
        if self._bench_history is not None:
 
288
            if self._benchmarkTime is not None:
 
289
                self._bench_history.write("%s %s\n" % (
 
290
                    self._formatTime(self._benchmarkTime),
 
291
                    test.id()))
170
292
        if self.showAll:
171
 
            self.stream.writeln('   OK %s' % self._elapsedTime())
172
 
        elif self.dots:
 
293
            self.stream.writeln('   OK %s' % self._testTimeString())
 
294
            for bench_called, stats in getattr(test, '_benchcalls', []):
 
295
                self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
296
                stats.pprint(file=self.stream)
 
297
        elif self.dots and self.pb is None:
173
298
            self.stream.write('~')
 
299
        elif self.dots:
 
300
            self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
174
301
        self.stream.flush()
175
302
        unittest.TestResult.addSuccess(self, test)
176
303
 
177
304
    def addSkipped(self, test, skip_excinfo):
 
305
        self.extractBenchmarkTime(test)
178
306
        if self.showAll:
179
 
            print >>self.stream, ' SKIP %s' % self._elapsedTime()
 
307
            print >>self.stream, ' SKIP %s' % self._testTimeString()
180
308
            print >>self.stream, '     %s' % skip_excinfo[1]
181
 
        elif self.dots:
 
309
        elif self.dots and self.pb is None:
182
310
            self.stream.write('S')
 
311
        elif self.dots:
 
312
            self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
183
313
        self.stream.flush()
184
314
        # seems best to treat this as success from point-of-view of unittest
185
315
        # -- it actually does nothing so it barely matters :)
186
 
        unittest.TestResult.addSuccess(self, test)
 
316
        try:
 
317
            test.tearDown()
 
318
        except KeyboardInterrupt:
 
319
            raise
 
320
        except:
 
321
            self.addError(test, test.__exc_info())
 
322
        else:
 
323
            unittest.TestResult.addSuccess(self, test)
187
324
 
188
325
    def printErrorList(self, flavour, errors):
189
326
        for test, err in errors:
200
337
            self.stream.writeln("%s" % err)
201
338
 
202
339
 
203
 
class TextTestRunner(unittest.TextTestRunner):
 
340
class TextTestRunner(object):
204
341
    stop_on_failure = False
205
342
 
 
343
    def __init__(self,
 
344
                 stream=sys.stderr,
 
345
                 descriptions=0,
 
346
                 verbosity=1,
 
347
                 keep_output=False,
 
348
                 pb=None,
 
349
                 bench_history=None):
 
350
        self.stream = unittest._WritelnDecorator(stream)
 
351
        self.descriptions = descriptions
 
352
        self.verbosity = verbosity
 
353
        self.keep_output = keep_output
 
354
        self.pb = pb
 
355
        self._bench_history = bench_history
 
356
 
206
357
    def _makeResult(self):
207
 
        result = _MyResult(self.stream, self.descriptions, self.verbosity)
 
358
        result = _MyResult(self.stream,
 
359
                           self.descriptions,
 
360
                           self.verbosity,
 
361
                           pb=self.pb,
 
362
                           bench_history=self._bench_history)
208
363
        result.stop_early = self.stop_on_failure
209
364
        return result
210
365
 
 
366
    def run(self, test):
 
367
        "Run the given test case or test suite."
 
368
        result = self._makeResult()
 
369
        startTime = time.time()
 
370
        if self.pb is not None:
 
371
            self.pb.update('Running tests', 0, test.countTestCases())
 
372
        test.run(result)
 
373
        stopTime = time.time()
 
374
        timeTaken = stopTime - startTime
 
375
        result.printErrors()
 
376
        self.stream.writeln(result.separator2)
 
377
        run = result.testsRun
 
378
        self.stream.writeln("Ran %d test%s in %.3fs" %
 
379
                            (run, run != 1 and "s" or "", timeTaken))
 
380
        self.stream.writeln()
 
381
        if not result.wasSuccessful():
 
382
            self.stream.write("FAILED (")
 
383
            failed, errored = map(len, (result.failures, result.errors))
 
384
            if failed:
 
385
                self.stream.write("failures=%d" % failed)
 
386
            if errored:
 
387
                if failed: self.stream.write(", ")
 
388
                self.stream.write("errors=%d" % errored)
 
389
            self.stream.writeln(")")
 
390
        else:
 
391
            self.stream.writeln("OK")
 
392
        if self.pb is not None:
 
393
            self.pb.update('Cleaning up', 0, 1)
 
394
        # This is still a little bogus, 
 
395
        # but only a little. Folk not using our testrunner will
 
396
        # have to delete their temp directories themselves.
 
397
        test_root = TestCaseInTempDir.TEST_ROOT
 
398
        if result.wasSuccessful() or not self.keep_output:
 
399
            if test_root is not None:
 
400
                # If LANG=C we probably have created some bogus paths
 
401
                # which rmtree(unicode) will fail to delete
 
402
                # so make sure we are using rmtree(str) to delete everything
 
403
                # except on win32, where rmtree(str) will fail
 
404
                # since it doesn't have the property of byte-stream paths
 
405
                # (they are either ascii or mbcs)
 
406
                if sys.platform == 'win32':
 
407
                    # make sure we are using the unicode win32 api
 
408
                    test_root = unicode(test_root)
 
409
                else:
 
410
                    test_root = test_root.encode(
 
411
                        sys.getfilesystemencoding())
 
412
                osutils.rmtree(test_root)
 
413
        else:
 
414
            if self.pb is not None:
 
415
                self.pb.note("Failed tests working directories are in '%s'\n",
 
416
                             test_root)
 
417
            else:
 
418
                self.stream.writeln(
 
419
                    "Failed tests working directories are in '%s'\n" %
 
420
                    test_root)
 
421
        TestCaseInTempDir.TEST_ROOT = None
 
422
        if self.pb is not None:
 
423
            self.pb.clear()
 
424
        return result
 
425
 
211
426
 
212
427
def iter_suite_tests(suite):
213
428
    """Return all tests in a suite, recursing through nested suites"""
224
439
 
225
440
class TestSkipped(Exception):
226
441
    """Indicates that a test was intentionally skipped, rather than failing."""
227
 
    # XXX: Not used yet
228
442
 
229
443
 
230
444
class CommandFailed(Exception):
231
445
    pass
232
446
 
 
447
 
 
448
class StringIOWrapper(object):
 
449
    """A wrapper around cStringIO which just adds an encoding attribute.
 
450
    
 
451
    Internally we can check sys.stdout to see what the output encoding
 
452
    should be. However, cStringIO has no encoding attribute that we can
 
453
    set. So we wrap it instead.
 
454
    """
 
455
    encoding='ascii'
 
456
    _cstring = None
 
457
 
 
458
    def __init__(self, s=None):
 
459
        if s is not None:
 
460
            self.__dict__['_cstring'] = StringIO(s)
 
461
        else:
 
462
            self.__dict__['_cstring'] = StringIO()
 
463
 
 
464
    def __getattr__(self, name, getattr=getattr):
 
465
        return getattr(self.__dict__['_cstring'], name)
 
466
 
 
467
    def __setattr__(self, name, val):
 
468
        if name == 'encoding':
 
469
            self.__dict__['encoding'] = val
 
470
        else:
 
471
            return setattr(self._cstring, name, val)
 
472
 
 
473
 
233
474
class TestCase(unittest.TestCase):
234
475
    """Base class for bzr unit tests.
235
476
    
251
492
    accidentally overlooked.
252
493
    """
253
494
 
254
 
    BZRPATH = 'bzr'
255
495
    _log_file_name = None
256
496
    _log_contents = ''
 
497
    _keep_log_file = False
 
498
    # record lsprof data when performing benchmark calls.
 
499
    _gather_lsprof_in_benchmarks = False
257
500
 
258
501
    def __init__(self, methodName='testMethod'):
259
502
        super(TestCase, self).__init__(methodName)
264
507
        self._cleanEnvironment()
265
508
        bzrlib.trace.disable_default_logging()
266
509
        self._startLogFile()
 
510
        self._benchcalls = []
 
511
        self._benchtime = None
267
512
 
268
513
    def _ndiff_strings(self, a, b):
269
514
        """Return ndiff between two strings containing lines.
303
548
            raise AssertionError('string %r does not start with %r' % (s, prefix))
304
549
 
305
550
    def assertEndsWith(self, s, suffix):
306
 
        if not s.endswith(prefix):
 
551
        """Asserts that s ends with suffix."""
 
552
        if not s.endswith(suffix):
307
553
            raise AssertionError('string %r does not end with %r' % (s, suffix))
308
554
 
309
555
    def assertContainsRe(self, haystack, needle_re):
312
558
            raise AssertionError('pattern "%s" not found in "%s"'
313
559
                    % (needle_re, haystack))
314
560
 
 
561
    def assertNotContainsRe(self, haystack, needle_re):
 
562
        """Assert that a does not match a regular expression"""
 
563
        if re.search(needle_re, haystack):
 
564
            raise AssertionError('pattern "%s" found in "%s"'
 
565
                    % (needle_re, haystack))
 
566
 
315
567
    def assertSubset(self, sublist, superlist):
316
568
        """Assert that every entry in sublist is present in superlist."""
317
569
        missing = []
341
593
    def assertIsInstance(self, obj, kls):
342
594
        """Fail if obj is not an instance of kls"""
343
595
        if not isinstance(obj, kls):
344
 
            self.fail("%r is not an instance of %s" % (obj, kls))
 
596
            self.fail("%r is an instance of %s rather than %s" % (
 
597
                obj, obj.__class__, kls))
 
598
 
 
599
    def _capture_warnings(self, a_callable, *args, **kwargs):
 
600
        """A helper for callDeprecated and applyDeprecated.
 
601
 
 
602
        :param a_callable: A callable to call.
 
603
        :param args: The positional arguments for the callable
 
604
        :param kwargs: The keyword arguments for the callable
 
605
        :return: A tuple (warnings, result). result is the result of calling
 
606
            a_callable(*args, **kwargs).
 
607
        """
 
608
        local_warnings = []
 
609
        def capture_warnings(msg, cls, stacklevel=None):
 
610
            # we've hooked into a deprecation specific callpath,
 
611
            # only deprecations should getting sent via it.
 
612
            self.assertEqual(cls, DeprecationWarning)
 
613
            local_warnings.append(msg)
 
614
        original_warning_method = symbol_versioning.warn
 
615
        symbol_versioning.set_warning_method(capture_warnings)
 
616
        try:
 
617
            result = a_callable(*args, **kwargs)
 
618
        finally:
 
619
            symbol_versioning.set_warning_method(original_warning_method)
 
620
        return (local_warnings, result)
 
621
 
 
622
    def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
 
623
        """Call a deprecated callable without warning the user.
 
624
 
 
625
        :param deprecation_format: The deprecation format that the callable
 
626
            should have been deprecated with. This is the same type as the 
 
627
            parameter to deprecated_method/deprecated_function. If the 
 
628
            callable is not deprecated with this format, an assertion error
 
629
            will be raised.
 
630
        :param a_callable: A callable to call. This may be a bound method or
 
631
            a regular function. It will be called with *args and **kwargs.
 
632
        :param args: The positional arguments for the callable
 
633
        :param kwargs: The keyword arguments for the callable
 
634
        :return: The result of a_callable(*args, **kwargs)
 
635
        """
 
636
        call_warnings, result = self._capture_warnings(a_callable,
 
637
            *args, **kwargs)
 
638
        expected_first_warning = symbol_versioning.deprecation_string(
 
639
            a_callable, deprecation_format)
 
640
        if len(call_warnings) == 0:
 
641
            self.fail("No assertion generated by call to %s" %
 
642
                a_callable)
 
643
        self.assertEqual(expected_first_warning, call_warnings[0])
 
644
        return result
 
645
 
 
646
    def callDeprecated(self, expected, callable, *args, **kwargs):
 
647
        """Assert that a callable is deprecated in a particular way.
 
648
 
 
649
        This is a very precise test for unusual requirements. The 
 
650
        applyDeprecated helper function is probably more suited for most tests
 
651
        as it allows you to simply specify the deprecation format being used
 
652
        and will ensure that that is issued for the function being called.
 
653
 
 
654
        :param expected: a list of the deprecation warnings expected, in order
 
655
        :param callable: The callable to call
 
656
        :param args: The positional arguments for the callable
 
657
        :param kwargs: The keyword arguments for the callable
 
658
        """
 
659
        call_warnings, result = self._capture_warnings(callable,
 
660
            *args, **kwargs)
 
661
        self.assertEqual(expected, call_warnings)
 
662
        return result
345
663
 
346
664
    def _startLogFile(self):
347
665
        """Send bzr and test log messages to a temporary file.
349
667
        The file is removed as the test is torn down.
350
668
        """
351
669
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
352
 
        encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
353
 
        self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
 
670
        self._log_file = os.fdopen(fileno, 'w+')
354
671
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
355
672
        self._log_file_name = name
356
673
        self.addCleanup(self._finishLogFile)
358
675
    def _finishLogFile(self):
359
676
        """Finished with the log file.
360
677
 
361
 
        Read contents into memory, close, and delete.
 
678
        Close the file and delete it, unless setKeepLogfile was called.
362
679
        """
 
680
        if self._log_file is None:
 
681
            return
363
682
        bzrlib.trace.disable_test_log(self._log_nonce)
364
 
        self._log_file.seek(0)
365
 
        self._log_contents = self._log_file.read()
366
683
        self._log_file.close()
367
 
        os.remove(self._log_file_name)
368
 
        self._log_file = self._log_file_name = None
 
684
        self._log_file = None
 
685
        if not self._keep_log_file:
 
686
            os.remove(self._log_file_name)
 
687
            self._log_file_name = None
 
688
 
 
689
    def setKeepLogfile(self):
 
690
        """Make the logfile not be deleted when _finishLogFile is called."""
 
691
        self._keep_log_file = True
369
692
 
370
693
    def addCleanup(self, callable):
371
694
        """Arrange to run a callable when this case is torn down.
380
703
 
381
704
    def _cleanEnvironment(self):
382
705
        new_env = {
 
706
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
383
707
            'HOME': os.getcwd(),
384
708
            'APPDATA': os.getcwd(),
385
 
            'BZREMAIL': None,
 
709
            'BZR_EMAIL': None,
 
710
            'BZREMAIL': None, # may still be present in the environment
386
711
            'EMAIL': None,
 
712
            'BZR_PROGRESS_BAR': None,
387
713
        }
388
714
        self.__old_env = {}
389
715
        self.addCleanup(self._restoreEnvironment)
390
716
        for name, value in new_env.iteritems():
391
717
            self._captureVar(name, value)
392
718
 
393
 
 
394
719
    def _captureVar(self, name, newvalue):
395
 
        """Set an environment variable, preparing it to be reset when finished."""
396
 
        self.__old_env[name] = os.environ.get(name, None)
397
 
        if newvalue is None:
398
 
            if name in os.environ:
399
 
                del os.environ[name]
400
 
        else:
401
 
            os.environ[name] = newvalue
402
 
 
403
 
    @staticmethod
404
 
    def _restoreVar(name, value):
405
 
        if value is None:
406
 
            if name in os.environ:
407
 
                del os.environ[name]
408
 
        else:
409
 
            os.environ[name] = value
 
720
        """Set an environment variable, and reset it when finished."""
 
721
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
410
722
 
411
723
    def _restoreEnvironment(self):
412
724
        for name, value in self.__old_env.iteritems():
413
 
            self._restoreVar(name, value)
 
725
            osutils.set_or_unset_env(name, value)
414
726
 
415
727
    def tearDown(self):
416
728
        self._runCleanups()
417
729
        unittest.TestCase.tearDown(self)
418
730
 
 
731
    def time(self, callable, *args, **kwargs):
 
732
        """Run callable and accrue the time it takes to the benchmark time.
 
733
        
 
734
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
 
735
        this will cause lsprofile statistics to be gathered and stored in
 
736
        self._benchcalls.
 
737
        """
 
738
        if self._benchtime is None:
 
739
            self._benchtime = 0
 
740
        start = time.time()
 
741
        try:
 
742
            if not self._gather_lsprof_in_benchmarks:
 
743
                return callable(*args, **kwargs)
 
744
            else:
 
745
                # record this benchmark
 
746
                ret, stats = bzrlib.lsprof.profile(callable, *args, **kwargs)
 
747
                stats.sort()
 
748
                self._benchcalls.append(((callable, args, kwargs), stats))
 
749
                return ret
 
750
        finally:
 
751
            self._benchtime += time.time() - start
 
752
 
419
753
    def _runCleanups(self):
420
754
        """Run registered cleanup functions. 
421
755
 
429
763
    def log(self, *args):
430
764
        mutter(*args)
431
765
 
432
 
    def _get_log(self):
433
 
        """Return as a string the log for this test"""
434
 
        if self._log_file_name:
435
 
            return open(self._log_file_name).read()
436
 
        else:
 
766
    def _get_log(self, keep_log_file=False):
 
767
        """Return as a string the log for this test. If the file is still
 
768
        on disk and keep_log_file=False, delete the log file and store the
 
769
        content in self._log_contents."""
 
770
        # flush the log file, to get all content
 
771
        import bzrlib.trace
 
772
        bzrlib.trace._trace_file.flush()
 
773
        if self._log_contents:
437
774
            return self._log_contents
438
 
        # TODO: Delete the log after it's been read in
 
775
        if self._log_file_name is not None:
 
776
            logfile = open(self._log_file_name)
 
777
            try:
 
778
                log_contents = logfile.read()
 
779
            finally:
 
780
                logfile.close()
 
781
            if not keep_log_file:
 
782
                self._log_contents = log_contents
 
783
                os.remove(self._log_file_name)
 
784
            return log_contents
 
785
        else:
 
786
            return "DELETED log file to reduce memory footprint"
439
787
 
440
788
    def capture(self, cmd, retcode=0):
441
789
        """Shortcut that splits cmd into words, runs, and returns stdout"""
442
790
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
443
791
 
444
 
    def run_bzr_captured(self, argv, retcode=0):
 
792
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
 
793
                         working_dir=None):
445
794
        """Invoke bzr and return (stdout, stderr).
446
795
 
447
796
        Useful for code that wants to check the contents of the
458
807
        errors, and with logging set to something approximating the
459
808
        default, so that error reporting can be checked.
460
809
 
461
 
        argv -- arguments to invoke bzr
462
 
        retcode -- expected return code, or None for don't-care.
 
810
        :param argv: arguments to invoke bzr
 
811
        :param retcode: expected return code, or None for don't-care.
 
812
        :param encoding: encoding for sys.stdout and sys.stderr
 
813
        :param stdin: A string to be used as stdin for the command.
 
814
        :param working_dir: Change to this directory before running
463
815
        """
464
 
        stdout = StringIO()
465
 
        stderr = StringIO()
466
 
        self.log('run bzr: %s', ' '.join(argv))
 
816
        if encoding is None:
 
817
            encoding = bzrlib.user_encoding
 
818
        if stdin is not None:
 
819
            stdin = StringIO(stdin)
 
820
        stdout = StringIOWrapper()
 
821
        stderr = StringIOWrapper()
 
822
        stdout.encoding = encoding
 
823
        stderr.encoding = encoding
 
824
 
 
825
        self.log('run bzr: %r', argv)
467
826
        # FIXME: don't call into logging here
468
827
        handler = logging.StreamHandler(stderr)
469
 
        handler.setFormatter(bzrlib.trace.QuietFormatter())
470
828
        handler.setLevel(logging.INFO)
471
829
        logger = logging.getLogger('')
472
830
        logger.addHandler(handler)
 
831
        old_ui_factory = bzrlib.ui.ui_factory
 
832
        bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
 
833
            stdout=stdout,
 
834
            stderr=stderr)
 
835
        bzrlib.ui.ui_factory.stdin = stdin
 
836
 
 
837
        cwd = None
 
838
        if working_dir is not None:
 
839
            cwd = osutils.getcwd()
 
840
            os.chdir(working_dir)
 
841
 
473
842
        try:
474
 
            result = self.apply_redirected(None, stdout, stderr,
 
843
            result = self.apply_redirected(stdin, stdout, stderr,
475
844
                                           bzrlib.commands.run_bzr_catch_errors,
476
845
                                           argv)
477
846
        finally:
478
847
            logger.removeHandler(handler)
 
848
            bzrlib.ui.ui_factory = old_ui_factory
 
849
            if cwd is not None:
 
850
                os.chdir(cwd)
 
851
 
479
852
        out = stdout.getvalue()
480
853
        err = stderr.getvalue()
481
854
        if out:
482
 
            self.log('output:\n%s', out)
 
855
            self.log('output:\n%r', out)
483
856
        if err:
484
 
            self.log('errors:\n%s', err)
 
857
            self.log('errors:\n%r', err)
485
858
        if retcode is not None:
486
 
            self.assertEquals(result, retcode)
 
859
            self.assertEquals(retcode, result)
487
860
        return out, err
488
861
 
489
862
    def run_bzr(self, *args, **kwargs):
495
868
 
496
869
        This sends the stdout/stderr results into the test's log,
497
870
        where it may be useful for debugging.  See also run_captured.
 
871
 
 
872
        :param stdin: A string to be used as stdin for the command.
498
873
        """
499
874
        retcode = kwargs.pop('retcode', 0)
500
 
        return self.run_bzr_captured(args, retcode)
 
875
        encoding = kwargs.pop('encoding', None)
 
876
        stdin = kwargs.pop('stdin', None)
 
877
        working_dir = kwargs.pop('working_dir', None)
 
878
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
 
879
                                     stdin=stdin, working_dir=working_dir)
 
880
 
 
881
    def run_bzr_decode(self, *args, **kwargs):
 
882
        if 'encoding' in kwargs:
 
883
            encoding = kwargs['encoding']
 
884
        else:
 
885
            encoding = bzrlib.user_encoding
 
886
        return self.run_bzr(*args, **kwargs)[0].decode(encoding)
 
887
 
 
888
    def run_bzr_error(self, error_regexes, *args, **kwargs):
 
889
        """Run bzr, and check that stderr contains the supplied regexes
 
890
        
 
891
        :param error_regexes: Sequence of regular expressions which 
 
892
            must each be found in the error output. The relative ordering
 
893
            is not enforced.
 
894
        :param args: command-line arguments for bzr
 
895
        :param kwargs: Keyword arguments which are interpreted by run_bzr
 
896
            This function changes the default value of retcode to be 3,
 
897
            since in most cases this is run when you expect bzr to fail.
 
898
        :return: (out, err) The actual output of running the command (in case you
 
899
                 want to do more inspection)
 
900
 
 
901
        Examples of use:
 
902
            # Make sure that commit is failing because there is nothing to do
 
903
            self.run_bzr_error(['no changes to commit'],
 
904
                               'commit', '-m', 'my commit comment')
 
905
            # Make sure --strict is handling an unknown file, rather than
 
906
            # giving us the 'nothing to do' error
 
907
            self.build_tree(['unknown'])
 
908
            self.run_bzr_error(['Commit refused because there are unknown files'],
 
909
                               'commit', '--strict', '-m', 'my commit comment')
 
910
        """
 
911
        kwargs.setdefault('retcode', 3)
 
912
        out, err = self.run_bzr(*args, **kwargs)
 
913
        for regex in error_regexes:
 
914
            self.assertContainsRe(err, regex)
 
915
        return out, err
 
916
 
 
917
    def run_bzr_subprocess(self, *args, **kwargs):
 
918
        """Run bzr in a subprocess for testing.
 
919
 
 
920
        This starts a new Python interpreter and runs bzr in there. 
 
921
        This should only be used for tests that have a justifiable need for
 
922
        this isolation: e.g. they are testing startup time, or signal
 
923
        handling, or early startup code, etc.  Subprocess code can't be 
 
924
        profiled or debugged so easily.
 
925
 
 
926
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
927
            None is supplied, the status code is not checked.
 
928
        :param env_changes: A dictionary which lists changes to environment
 
929
            variables. A value of None will unset the env variable.
 
930
            The values must be strings. The change will only occur in the
 
931
            child, so you don't need to fix the environment after running.
 
932
        :param universal_newlines: Convert CRLF => LF
 
933
        """
 
934
        env_changes = kwargs.get('env_changes', {})
 
935
        working_dir = kwargs.get('working_dir', None)
 
936
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
 
937
                                            working_dir=working_dir)
 
938
        # We distinguish between retcode=None and retcode not passed.
 
939
        supplied_retcode = kwargs.get('retcode', 0)
 
940
        return self.finish_bzr_subprocess(process, retcode=supplied_retcode,
 
941
            universal_newlines=kwargs.get('universal_newlines', False),
 
942
            process_args=args)
 
943
 
 
944
    def start_bzr_subprocess(self, process_args, env_changes=None,
 
945
                             skip_if_plan_to_signal=False,
 
946
                             working_dir=None):
 
947
        """Start bzr in a subprocess for testing.
 
948
 
 
949
        This starts a new Python interpreter and runs bzr in there.
 
950
        This should only be used for tests that have a justifiable need for
 
951
        this isolation: e.g. they are testing startup time, or signal
 
952
        handling, or early startup code, etc.  Subprocess code can't be
 
953
        profiled or debugged so easily.
 
954
 
 
955
        :param process_args: a list of arguments to pass to the bzr executable,
 
956
            for example `['--version']`.
 
957
        :param env_changes: A dictionary which lists changes to environment
 
958
            variables. A value of None will unset the env variable.
 
959
            The values must be strings. The change will only occur in the
 
960
            child, so you don't need to fix the environment after running.
 
961
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
962
            is not available.
 
963
 
 
964
        :returns: Popen object for the started process.
 
965
        """
 
966
        if skip_if_plan_to_signal:
 
967
            if not getattr(os, 'kill', None):
 
968
                raise TestSkipped("os.kill not available.")
 
969
 
 
970
        if env_changes is None:
 
971
            env_changes = {}
 
972
        old_env = {}
 
973
 
 
974
        def cleanup_environment():
 
975
            for env_var, value in env_changes.iteritems():
 
976
                old_env[env_var] = osutils.set_or_unset_env(env_var, value)
 
977
 
 
978
        def restore_environment():
 
979
            for env_var, value in old_env.iteritems():
 
980
                osutils.set_or_unset_env(env_var, value)
 
981
 
 
982
        bzr_path = self.get_bzr_path()
 
983
 
 
984
        cwd = None
 
985
        if working_dir is not None:
 
986
            cwd = osutils.getcwd()
 
987
            os.chdir(working_dir)
 
988
 
 
989
        try:
 
990
            # win32 subprocess doesn't support preexec_fn
 
991
            # so we will avoid using it on all platforms, just to
 
992
            # make sure the code path is used, and we don't break on win32
 
993
            cleanup_environment()
 
994
            process = Popen([sys.executable, bzr_path] + list(process_args),
 
995
                             stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
996
        finally:
 
997
            restore_environment()
 
998
            if cwd is not None:
 
999
                os.chdir(cwd)
 
1000
 
 
1001
        return process
 
1002
 
 
1003
    def get_bzr_path(self):
 
1004
        """Return the path of the 'bzr' executable for this test suite."""
 
1005
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
1006
        if not os.path.isfile(bzr_path):
 
1007
            # We are probably installed. Assume sys.argv is the right file
 
1008
            bzr_path = sys.argv[0]
 
1009
        return bzr_path
 
1010
 
 
1011
    def finish_bzr_subprocess(self, process, retcode=0, send_signal=None,
 
1012
                              universal_newlines=False, process_args=None):
 
1013
        """Finish the execution of process.
 
1014
 
 
1015
        :param process: the Popen object returned from start_bzr_subprocess.
 
1016
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
1017
            None is supplied, the status code is not checked.
 
1018
        :param send_signal: an optional signal to send to the process.
 
1019
        :param universal_newlines: Convert CRLF => LF
 
1020
        :returns: (stdout, stderr)
 
1021
        """
 
1022
        if send_signal is not None:
 
1023
            os.kill(process.pid, send_signal)
 
1024
        out, err = process.communicate()
 
1025
 
 
1026
        if universal_newlines:
 
1027
            out = out.replace('\r\n', '\n')
 
1028
            err = err.replace('\r\n', '\n')
 
1029
 
 
1030
        if retcode is not None and retcode != process.returncode:
 
1031
            if process_args is None:
 
1032
                process_args = "(unknown args)"
 
1033
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1034
            mutter('Error for bzr %s:\n%s', process_args, err)
 
1035
            self.fail('Command bzr %s failed with retcode %s != %s'
 
1036
                      % (process_args, retcode, process.returncode))
 
1037
        return [out, err]
501
1038
 
502
1039
    def check_inventory_shape(self, inv, shape):
503
1040
        """Compare an inventory to a list of expected names.
551
1088
            sys.stderr = real_stderr
552
1089
            sys.stdin = real_stdin
553
1090
 
 
1091
    @symbol_versioning.deprecated_method(symbol_versioning.zero_eleven)
554
1092
    def merge(self, branch_from, wt_to):
555
1093
        """A helper for tests to do a ui-less merge.
556
1094
 
562
1100
        base_rev = common_ancestor(branch_from.last_revision(),
563
1101
                                   wt_to.branch.last_revision(),
564
1102
                                   wt_to.branch.repository)
565
 
        merge_inner(wt_to.branch, branch_from.basis_tree(), 
 
1103
        merge_inner(wt_to.branch, branch_from.basis_tree(),
566
1104
                    wt_to.branch.repository.revision_tree(base_rev),
567
1105
                    this_tree=wt_to)
568
 
        wt_to.add_pending_merge(branch_from.last_revision())
 
1106
        wt_to.add_parent_tree_id(branch_from.last_revision())
569
1107
 
570
1108
 
571
1109
BzrTestBase = TestCase
636
1174
                i = i + 1
637
1175
                continue
638
1176
            else:
639
 
                self.test_dir = candidate_dir
 
1177
                os.mkdir(candidate_dir)
 
1178
                self.test_home_dir = candidate_dir + '/home'
 
1179
                os.mkdir(self.test_home_dir)
 
1180
                self.test_dir = candidate_dir + '/work'
640
1181
                os.mkdir(self.test_dir)
641
1182
                os.chdir(self.test_dir)
642
1183
                break
643
 
        os.environ['HOME'] = self.test_dir
644
 
        os.environ['APPDATA'] = self.test_dir
 
1184
        os.environ['HOME'] = self.test_home_dir
 
1185
        os.environ['APPDATA'] = self.test_home_dir
645
1186
        def _leaveDirectory():
646
1187
            os.chdir(_currentdir)
647
1188
        self.addCleanup(_leaveDirectory)
652
1193
        shape is a sequence of file specifications.  If the final
653
1194
        character is '/', a directory is created.
654
1195
 
 
1196
        This assumes that all the elements in the tree being built are new.
 
1197
 
655
1198
        This doesn't add anything to a branch.
656
1199
        :param line_endings: Either 'binary' or 'native'
657
1200
                             in binary mode, exact contents are written
662
1205
                          VFS's. If the transport is readonly or None,
663
1206
                          "." is opened automatically.
664
1207
        """
665
 
        # XXX: It's OK to just create them using forward slashes on windows?
 
1208
        # It's OK to just create them using forward slashes on windows.
666
1209
        if transport is None or transport.is_readonly():
667
1210
            transport = get_transport(".")
668
1211
        for name in shape:
669
1212
            self.assert_(isinstance(name, basestring))
670
1213
            if name[-1] == '/':
671
 
                transport.mkdir(urlescape(name[:-1]))
 
1214
                transport.mkdir(urlutils.escape(name[:-1]))
672
1215
            else:
673
1216
                if line_endings == 'binary':
674
1217
                    end = '\n'
676
1219
                    end = os.linesep
677
1220
                else:
678
1221
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
679
 
                content = "contents of %s%s" % (name, end)
680
 
                transport.put(urlescape(name), StringIO(content))
 
1222
                content = "contents of %s%s" % (name.encode('utf-8'), end)
 
1223
                # Technically 'put()' is the right command. However, put
 
1224
                # uses an AtomicFile, which requires an extra rename into place
 
1225
                # As long as the files didn't exist in the past, append() will
 
1226
                # do the same thing as put()
 
1227
                # On jam's machine, make_kernel_like_tree is:
 
1228
                #   put:    4.5-7.5s (averaging 6s)
 
1229
                #   append: 2.9-4.5s
 
1230
                #   put_non_atomic: 2.9-4.5s
 
1231
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
681
1232
 
682
1233
    def build_tree_contents(self, shape):
683
1234
        build_tree_contents(shape)
693
1244
    def assertFileEqual(self, content, path):
694
1245
        """Fail if path does not contain 'content'."""
695
1246
        self.failUnless(osutils.lexists(path))
 
1247
        # TODO: jam 20060427 Shouldn't this be 'rb'?
696
1248
        self.assertEqualDiff(content, open(path, 'r').read())
697
1249
 
698
1250
 
763
1315
        return self.__server
764
1316
 
765
1317
    def get_url(self, relpath=None):
766
 
        """Get a URL for the readwrite transport.
 
1318
        """Get a URL (or maybe a path) for the readwrite transport.
767
1319
 
768
1320
        This will either be backed by '.' or to an equivalent non-file based
769
1321
        facility.
774
1326
        if relpath is not None and relpath != '.':
775
1327
            if not base.endswith('/'):
776
1328
                base = base + '/'
777
 
            base = base + relpath
 
1329
            # XXX: Really base should be a url; we did after all call
 
1330
            # get_url()!  But sometimes it's just a path (from
 
1331
            # LocalAbspathServer), and it'd be wrong to append urlescaped data
 
1332
            # to a non-escaped local path.
 
1333
            if base.startswith('./') or base.startswith('/'):
 
1334
                base += relpath
 
1335
            else:
 
1336
                base += urlutils.escape(relpath)
778
1337
        return base
779
1338
 
780
1339
    def get_transport(self):
793
1352
        self.assertTrue(t.is_readonly())
794
1353
        return t
795
1354
 
796
 
    def make_branch(self, relpath):
 
1355
    def make_branch(self, relpath, format=None):
797
1356
        """Create a branch on the transport at relpath."""
798
 
        repo = self.make_repository(relpath)
 
1357
        repo = self.make_repository(relpath, format=format)
799
1358
        return repo.bzrdir.create_branch()
800
1359
 
801
 
    def make_bzrdir(self, relpath):
 
1360
    def make_bzrdir(self, relpath, format=None):
802
1361
        try:
803
 
            url = self.get_url(relpath)
804
 
            segments = relpath.split('/')
805
 
            if segments and segments[-1] not in ('', '.'):
806
 
                parent = self.get_url('/'.join(segments[:-1]))
807
 
                t = get_transport(parent)
 
1362
            # might be a relative or absolute path
 
1363
            maybe_a_url = self.get_url(relpath)
 
1364
            segments = maybe_a_url.rsplit('/', 1)
 
1365
            t = get_transport(maybe_a_url)
 
1366
            if len(segments) > 1 and segments[-1] not in ('', '.'):
808
1367
                try:
809
 
                    t.mkdir(segments[-1])
 
1368
                    t.mkdir('.')
810
1369
                except errors.FileExists:
811
1370
                    pass
812
 
            return bzrlib.bzrdir.BzrDir.create(url)
 
1371
            if format is None:
 
1372
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
1373
            return format.initialize_on_transport(t)
813
1374
        except errors.UninitializableFormat:
814
 
            raise TestSkipped("Format %s is not initializable.")
 
1375
            raise TestSkipped("Format %s is not initializable." % format)
815
1376
 
816
 
    def make_repository(self, relpath, shared=False):
 
1377
    def make_repository(self, relpath, shared=False, format=None):
817
1378
        """Create a repository on our default transport at relpath."""
818
 
        made_control = self.make_bzrdir(relpath)
 
1379
        made_control = self.make_bzrdir(relpath, format=format)
819
1380
        return made_control.create_repository(shared=shared)
820
1381
 
821
 
    def make_branch_and_tree(self, relpath):
 
1382
    def make_branch_and_memory_tree(self, relpath):
 
1383
        """Create a branch on the default transport and a MemoryTree for it."""
 
1384
        b = self.make_branch(relpath)
 
1385
        return memorytree.MemoryTree.create_on_branch(b)
 
1386
 
 
1387
    def make_branch_and_tree(self, relpath, format=None):
822
1388
        """Create a branch on the transport and a tree locally.
823
1389
 
824
 
        Returns the tree.
 
1390
        If the transport is not a LocalTransport, the Tree can't be created on
 
1391
        the transport.  In that case the working tree is created in the local
 
1392
        directory, and the returned tree's branch and repository will also be
 
1393
        accessed locally.
 
1394
 
 
1395
        This will fail if the original default transport for this test
 
1396
        case wasn't backed by the working directory, as the branch won't
 
1397
        be on disk for us to open it.  
 
1398
 
 
1399
        :param format: The BzrDirFormat.
 
1400
        :returns: the WorkingTree.
825
1401
        """
826
1402
        # TODO: always use the local disk path for the working tree,
827
1403
        # this obviously requires a format that supports branch references
828
1404
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
829
1405
        # RBC 20060208
830
 
        b = self.make_branch(relpath)
 
1406
        b = self.make_branch(relpath, format=format)
831
1407
        try:
832
1408
            return b.bzrdir.create_workingtree()
833
1409
        except errors.NotLocalUrl:
834
 
            # new formats - catch No tree error and create
835
 
            # a branch reference and a checkout.
836
 
            # old formats at that point - raise TestSkipped.
837
 
            # TODO: rbc 20060208
838
 
            return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
 
1410
            # We can only make working trees locally at the moment.  If the
 
1411
            # transport can't support them, then reopen the branch on a local
 
1412
            # transport, and create the working tree there.  
 
1413
            #
 
1414
            # Possibly we should instead keep
 
1415
            # the non-disk-backed branch and create a local checkout?
 
1416
            bd = bzrdir.BzrDir.open(relpath)
 
1417
            return bd.create_workingtree()
839
1418
 
840
1419
    def assertIsDirectory(self, relpath, transport):
841
1420
        """Assert that relpath within transport is a directory.
872
1451
 
873
1452
 
874
1453
def filter_suite_by_re(suite, pattern):
875
 
    result = TestSuite()
 
1454
    result = TestUtil.TestSuite()
876
1455
    filter_re = re.compile(pattern)
877
1456
    for test in iter_suite_tests(suite):
878
1457
        if filter_re.search(test.id()):
882
1461
 
883
1462
def run_suite(suite, name='test', verbose=False, pattern=".*",
884
1463
              stop_on_failure=False, keep_output=False,
885
 
              transport=None):
 
1464
              transport=None, lsprof_timed=None, bench_history=None):
886
1465
    TestCaseInTempDir._TEST_NAME = name
 
1466
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
887
1467
    if verbose:
888
1468
        verbosity = 2
 
1469
        pb = None
889
1470
    else:
890
1471
        verbosity = 1
 
1472
        pb = progress.ProgressBar()
891
1473
    runner = TextTestRunner(stream=sys.stdout,
892
1474
                            descriptions=0,
893
 
                            verbosity=verbosity)
 
1475
                            verbosity=verbosity,
 
1476
                            keep_output=keep_output,
 
1477
                            pb=pb,
 
1478
                            bench_history=bench_history)
894
1479
    runner.stop_on_failure=stop_on_failure
895
1480
    if pattern != '.*':
896
1481
        suite = filter_suite_by_re(suite, pattern)
897
1482
    result = runner.run(suite)
898
 
    # This is still a little bogus, 
899
 
    # but only a little. Folk not using our testrunner will
900
 
    # have to delete their temp directories themselves.
901
 
    test_root = TestCaseInTempDir.TEST_ROOT
902
 
    if result.wasSuccessful() or not keep_output:
903
 
        if test_root is not None:
904
 
            print 'Deleting test root %s...' % test_root
905
 
            try:
906
 
                shutil.rmtree(test_root)
907
 
            finally:
908
 
                print
909
 
    else:
910
 
        print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
911
1483
    return result.wasSuccessful()
912
1484
 
913
1485
 
914
1486
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
915
1487
             keep_output=False,
916
 
             transport=None):
 
1488
             transport=None,
 
1489
             test_suite_factory=None,
 
1490
             lsprof_timed=None,
 
1491
             bench_history=None):
917
1492
    """Run the whole test suite under the enhanced runner"""
 
1493
    # XXX: Very ugly way to do this...
 
1494
    # Disable warning about old formats because we don't want it to disturb
 
1495
    # any blackbox tests.
 
1496
    from bzrlib import repository
 
1497
    repository._deprecation_warning_done = True
 
1498
 
918
1499
    global default_transport
919
1500
    if transport is None:
920
1501
        transport = default_transport
921
1502
    old_transport = default_transport
922
1503
    default_transport = transport
923
 
    suite = test_suite()
924
1504
    try:
 
1505
        if test_suite_factory is None:
 
1506
            suite = test_suite()
 
1507
        else:
 
1508
            suite = test_suite_factory()
925
1509
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
926
1510
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
927
 
                     transport=transport)
 
1511
                     transport=transport,
 
1512
                     lsprof_timed=lsprof_timed,
 
1513
                     bench_history=bench_history)
928
1514
    finally:
929
1515
        default_transport = old_transport
930
1516
 
931
1517
 
932
 
 
933
1518
def test_suite():
934
 
    """Build and return TestSuite for the whole program."""
935
 
    from doctest import DocTestSuite
936
 
 
937
 
    global MODULES_TO_DOCTEST
938
 
 
939
 
    testmod_names = [ \
 
1519
    """Build and return TestSuite for the whole of bzrlib.
 
1520
    
 
1521
    This function can be replaced if you need to change the default test
 
1522
    suite on a global basis, but it is not encouraged.
 
1523
    """
 
1524
    testmod_names = [
940
1525
                   'bzrlib.tests.test_ancestry',
941
 
                   'bzrlib.tests.test_annotate',
942
1526
                   'bzrlib.tests.test_api',
 
1527
                   'bzrlib.tests.test_atomicfile',
943
1528
                   'bzrlib.tests.test_bad_files',
944
 
                   'bzrlib.tests.test_basis_inventory',
945
1529
                   'bzrlib.tests.test_branch',
 
1530
                   'bzrlib.tests.test_bundle',
946
1531
                   'bzrlib.tests.test_bzrdir',
 
1532
                   'bzrlib.tests.test_cache_utf8',
947
1533
                   'bzrlib.tests.test_command',
948
1534
                   'bzrlib.tests.test_commit',
949
1535
                   'bzrlib.tests.test_commit_merge',
955
1541
                   'bzrlib.tests.test_errors',
956
1542
                   'bzrlib.tests.test_escaped_store',
957
1543
                   'bzrlib.tests.test_fetch',
 
1544
                   'bzrlib.tests.test_ftp_transport',
958
1545
                   'bzrlib.tests.test_gpg',
959
1546
                   'bzrlib.tests.test_graph',
960
1547
                   'bzrlib.tests.test_hashcache',
961
1548
                   'bzrlib.tests.test_http',
 
1549
                   'bzrlib.tests.test_http_response',
962
1550
                   'bzrlib.tests.test_identitymap',
 
1551
                   'bzrlib.tests.test_ignores',
963
1552
                   'bzrlib.tests.test_inv',
964
1553
                   'bzrlib.tests.test_knit',
 
1554
                   'bzrlib.tests.test_lazy_import',
965
1555
                   'bzrlib.tests.test_lockdir',
966
1556
                   'bzrlib.tests.test_lockable_files',
967
1557
                   'bzrlib.tests.test_log',
 
1558
                   'bzrlib.tests.test_memorytree',
968
1559
                   'bzrlib.tests.test_merge',
969
1560
                   'bzrlib.tests.test_merge3',
970
1561
                   'bzrlib.tests.test_merge_core',
973
1564
                   'bzrlib.tests.test_nonascii',
974
1565
                   'bzrlib.tests.test_options',
975
1566
                   'bzrlib.tests.test_osutils',
 
1567
                   'bzrlib.tests.test_patch',
 
1568
                   'bzrlib.tests.test_patches',
976
1569
                   'bzrlib.tests.test_permissions',
977
1570
                   'bzrlib.tests.test_plugins',
978
1571
                   'bzrlib.tests.test_progress',
979
1572
                   'bzrlib.tests.test_reconcile',
980
1573
                   'bzrlib.tests.test_repository',
 
1574
                   'bzrlib.tests.test_revert',
981
1575
                   'bzrlib.tests.test_revision',
982
1576
                   'bzrlib.tests.test_revisionnamespaces',
983
 
                   'bzrlib.tests.test_revprops',
 
1577
                   'bzrlib.tests.test_revisiontree',
984
1578
                   'bzrlib.tests.test_rio',
985
1579
                   'bzrlib.tests.test_sampler',
986
1580
                   'bzrlib.tests.test_selftest',
987
1581
                   'bzrlib.tests.test_setup',
988
1582
                   'bzrlib.tests.test_sftp_transport',
989
1583
                   'bzrlib.tests.test_smart_add',
 
1584
                   'bzrlib.tests.test_smart_transport',
990
1585
                   'bzrlib.tests.test_source',
 
1586
                   'bzrlib.tests.test_status',
991
1587
                   'bzrlib.tests.test_store',
992
1588
                   'bzrlib.tests.test_symbol_versioning',
993
1589
                   'bzrlib.tests.test_testament',
 
1590
                   'bzrlib.tests.test_textfile',
 
1591
                   'bzrlib.tests.test_textmerge',
994
1592
                   'bzrlib.tests.test_trace',
995
1593
                   'bzrlib.tests.test_transactions',
996
1594
                   'bzrlib.tests.test_transform',
997
1595
                   'bzrlib.tests.test_transport',
 
1596
                   'bzrlib.tests.test_tree',
 
1597
                   'bzrlib.tests.test_treebuilder',
998
1598
                   'bzrlib.tests.test_tsort',
 
1599
                   'bzrlib.tests.test_tuned_gzip',
999
1600
                   'bzrlib.tests.test_ui',
1000
1601
                   'bzrlib.tests.test_upgrade',
 
1602
                   'bzrlib.tests.test_urlutils',
1001
1603
                   'bzrlib.tests.test_versionedfile',
 
1604
                   'bzrlib.tests.test_version',
 
1605
                   'bzrlib.tests.test_version_info',
1002
1606
                   'bzrlib.tests.test_weave',
1003
1607
                   'bzrlib.tests.test_whitebox',
1004
1608
                   'bzrlib.tests.test_workingtree',
1005
1609
                   'bzrlib.tests.test_xml',
1006
1610
                   ]
1007
1611
    test_transport_implementations = [
1008
 
        'bzrlib.tests.test_transport_implementations']
1009
 
 
1010
 
    TestCase.BZRPATH = osutils.pathjoin(
1011
 
            osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
1012
 
    print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1013
 
    print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1014
 
    print
1015
 
    suite = TestSuite()
1016
 
    # python2.4's TestLoader.loadTestsFromNames gives very poor 
1017
 
    # errors if it fails to load a named module - no indication of what's
1018
 
    # actually wrong, just "no such module".  We should probably override that
1019
 
    # class, but for the moment just load them ourselves. (mbp 20051202)
1020
 
    loader = TestLoader()
 
1612
        'bzrlib.tests.test_transport_implementations',
 
1613
        'bzrlib.tests.test_read_bundle',
 
1614
        ]
 
1615
    suite = TestUtil.TestSuite()
 
1616
    loader = TestUtil.TestLoader()
 
1617
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1021
1618
    from bzrlib.transport import TransportTestProviderAdapter
1022
1619
    adapter = TransportTestProviderAdapter()
1023
1620
    adapt_modules(test_transport_implementations, adapter, loader, suite)
1024
 
    for mod_name in testmod_names:
1025
 
        mod = _load_module_by_name(mod_name)
1026
 
        suite.addTest(loader.loadTestsFromModule(mod))
1027
1621
    for package in packages_to_test():
1028
1622
        suite.addTest(package.test_suite())
1029
1623
    for m in MODULES_TO_TEST:
1030
1624
        suite.addTest(loader.loadTestsFromModule(m))
1031
 
    for m in (MODULES_TO_DOCTEST):
1032
 
        suite.addTest(DocTestSuite(m))
 
1625
    for m in MODULES_TO_DOCTEST:
 
1626
        suite.addTest(doctest.DocTestSuite(m))
1033
1627
    for name, plugin in bzrlib.plugin.all_plugins().items():
1034
1628
        if getattr(plugin, 'test_suite', None) is not None:
1035
1629
            suite.addTest(plugin.test_suite())
1038
1632
 
1039
1633
def adapt_modules(mods_list, adapter, loader, suite):
1040
1634
    """Adapt the modules in mods_list using adapter and add to suite."""
1041
 
    for mod_name in mods_list:
1042
 
        mod = _load_module_by_name(mod_name)
1043
 
        for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
1044
 
            suite.addTests(adapter.adapt(test))
1045
 
 
1046
 
 
1047
 
def _load_module_by_name(mod_name):
1048
 
    parts = mod_name.split('.')
1049
 
    module = __import__(mod_name)
1050
 
    del parts[0]
1051
 
    # for historical reasons python returns the top-level module even though
1052
 
    # it loads the submodule; we need to walk down to get the one we want.
1053
 
    while parts:
1054
 
        module = getattr(module, parts.pop(0))
1055
 
    return module
 
1635
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
 
1636
        suite.addTests(adapter.adapt(test))