~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007, 2008, 2009 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
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
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
 
18
18
# TODO: Perhaps there should be an API to find out if bzr running under the
26
26
# general style of bzrlib.  Please continue that consistency when adding e.g.
27
27
# new assertFoo() methods.
28
28
 
 
29
import atexit
29
30
import codecs
30
31
from cStringIO import StringIO
31
32
import difflib
32
33
import doctest
33
34
import errno
34
35
import logging
 
36
import math
35
37
import os
 
38
from pprint import pformat
 
39
import random
36
40
import re
37
41
import shlex
38
42
import stat
39
 
from subprocess import Popen, PIPE
 
43
from subprocess import Popen, PIPE, STDOUT
40
44
import sys
41
45
import tempfile
 
46
import threading
 
47
import time
42
48
import unittest
43
 
import time
44
 
 
45
 
 
46
 
from bzrlib import memorytree
 
49
import warnings
 
50
 
 
51
 
 
52
from bzrlib import (
 
53
    branchbuilder,
 
54
    bzrdir,
 
55
    debug,
 
56
    errors,
 
57
    hooks,
 
58
    lock as _mod_lock,
 
59
    memorytree,
 
60
    osutils,
 
61
    progress,
 
62
    ui,
 
63
    urlutils,
 
64
    registry,
 
65
    workingtree,
 
66
    )
47
67
import bzrlib.branch
48
 
import bzrlib.bzrdir as bzrdir
49
68
import bzrlib.commands
50
 
import bzrlib.bundle.serializer
51
 
import bzrlib.errors as errors
 
69
import bzrlib.timestamp
52
70
import bzrlib.export
53
71
import bzrlib.inventory
54
72
import bzrlib.iterablefile
60
78
    pass
61
79
from bzrlib.merge import merge_inner
62
80
import bzrlib.merge3
63
 
import bzrlib.osutils
64
 
import bzrlib.osutils as osutils
65
81
import bzrlib.plugin
66
 
import bzrlib.progress as progress
67
 
from bzrlib.revision import common_ancestor
 
82
from bzrlib.smart import client, request, server
68
83
import bzrlib.store
69
84
from bzrlib import symbol_versioning
 
85
from bzrlib.symbol_versioning import (
 
86
    DEPRECATED_PARAMETER,
 
87
    deprecated_function,
 
88
    deprecated_method,
 
89
    deprecated_passed,
 
90
    )
70
91
import bzrlib.trace
71
92
from bzrlib.transport import get_transport
72
93
import bzrlib.transport
75
96
from bzrlib.transport.readonly import ReadonlyServer
76
97
from bzrlib.trace import mutter, note
77
98
from bzrlib.tests import TestUtil
 
99
from bzrlib.tests.http_server import HttpServer
78
100
from bzrlib.tests.TestUtil import (
79
101
                          TestSuite,
80
102
                          TestLoader,
81
103
                          )
82
104
from bzrlib.tests.treeshape import build_tree_contents
83
 
import bzrlib.urlutils as urlutils
 
105
from bzrlib.ui import NullProgressView
 
106
from bzrlib.ui.text import TextUIFactory
 
107
import bzrlib.version_info_formats.format_custom
84
108
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
85
109
 
 
110
# Mark this python module as being part of the implementation
 
111
# of unittest: this gives us better tracebacks where the last
 
112
# shown frame is the test code, not our assertXYZ.
 
113
__unittest = 1
 
114
 
86
115
default_transport = LocalURLServer
87
116
 
88
 
MODULES_TO_TEST = []
89
 
MODULES_TO_DOCTEST = [
90
 
                      bzrlib.bundle.serializer,
91
 
                      bzrlib.errors,
92
 
                      bzrlib.export,
93
 
                      bzrlib.inventory,
94
 
                      bzrlib.iterablefile,
95
 
                      bzrlib.lockdir,
96
 
                      bzrlib.merge3,
97
 
                      bzrlib.option,
98
 
                      bzrlib.store,
99
 
                      ]
100
 
 
101
 
 
102
 
def packages_to_test():
103
 
    """Return a list of packages to test.
104
 
 
105
 
    The packages are not globally imported so that import failures are
106
 
    triggered when running selftest, not when importing the command.
107
 
    """
108
 
    import bzrlib.doc
109
 
    import bzrlib.tests.blackbox
110
 
    import bzrlib.tests.branch_implementations
111
 
    import bzrlib.tests.bzrdir_implementations
112
 
    import bzrlib.tests.interrepository_implementations
113
 
    import bzrlib.tests.interversionedfile_implementations
114
 
    import bzrlib.tests.intertree_implementations
115
 
    import bzrlib.tests.repository_implementations
116
 
    import bzrlib.tests.revisionstore_implementations
117
 
    import bzrlib.tests.tree_implementations
118
 
    import bzrlib.tests.workingtree_implementations
119
 
    return [
120
 
            bzrlib.doc,
121
 
            bzrlib.tests.blackbox,
122
 
            bzrlib.tests.branch_implementations,
123
 
            bzrlib.tests.bzrdir_implementations,
124
 
            bzrlib.tests.interrepository_implementations,
125
 
            bzrlib.tests.interversionedfile_implementations,
126
 
            bzrlib.tests.intertree_implementations,
127
 
            bzrlib.tests.repository_implementations,
128
 
            bzrlib.tests.revisionstore_implementations,
129
 
            bzrlib.tests.tree_implementations,
130
 
            bzrlib.tests.workingtree_implementations,
131
 
            ]
 
117
# Subunit result codes, defined here to prevent a hard dependency on subunit.
 
118
SUBUNIT_SEEK_SET = 0
 
119
SUBUNIT_SEEK_CUR = 1
132
120
 
133
121
 
134
122
class ExtendedTestResult(unittest._TextTestResult):
135
123
    """Accepts, reports and accumulates the results of running tests.
136
124
 
137
 
    Compared to this unittest version this class adds support for profiling,
138
 
    benchmarking, stopping as soon as a test fails,  and skipping tests.
139
 
    There are further-specialized subclasses for different types of display.
 
125
    Compared to the unittest version this class adds support for
 
126
    profiling, benchmarking, stopping as soon as a test fails,  and
 
127
    skipping tests.  There are further-specialized subclasses for
 
128
    different types of display.
 
129
 
 
130
    When a test finishes, in whatever way, it calls one of the addSuccess,
 
131
    addFailure or addError classes.  These in turn may redirect to a more
 
132
    specific case for the special test results supported by our extended
 
133
    tests.
 
134
 
 
135
    Note that just one of these objects is fed the results from many tests.
140
136
    """
141
137
 
142
138
    stop_early = False
143
 
    
 
139
 
144
140
    def __init__(self, stream, descriptions, verbosity,
145
141
                 bench_history=None,
146
 
                 num_tests=None,
 
142
                 strict=False,
147
143
                 ):
148
144
        """Construct new TestResult.
149
145
 
166
162
                revision_id = ''
167
163
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
168
164
        self._bench_history = bench_history
169
 
        self.ui = bzrlib.ui.ui_factory
170
 
        self.num_tests = num_tests
 
165
        self.ui = ui.ui_factory
 
166
        self.num_tests = 0
171
167
        self.error_count = 0
172
168
        self.failure_count = 0
 
169
        self.known_failure_count = 0
173
170
        self.skip_count = 0
 
171
        self.not_applicable_count = 0
 
172
        self.unsupported = {}
174
173
        self.count = 0
175
174
        self._overall_start_time = time.time()
176
 
    
177
 
    def extractBenchmarkTime(self, testCase):
 
175
        self._strict = strict
 
176
 
 
177
    def done(self):
 
178
        # nb: called stopTestRun in the version of this that Python merged
 
179
        # upstream, according to lifeless 20090803
 
180
        if self._strict:
 
181
            ok = self.wasStrictlySuccessful()
 
182
        else:
 
183
            ok = self.wasSuccessful()
 
184
        if ok:
 
185
            self.stream.write('tests passed\n')
 
186
        else:
 
187
            self.stream.write('tests failed\n')
 
188
        if TestCase._first_thread_leaker_id:
 
189
            self.stream.write(
 
190
                '%s is leaking threads among %d leaking tests.\n' % (
 
191
                TestCase._first_thread_leaker_id,
 
192
                TestCase._leaking_threads_tests))
 
193
 
 
194
    def _extractBenchmarkTime(self, testCase):
178
195
        """Add a benchmark time for the current test case."""
179
 
        self._benchmarkTime = getattr(testCase, "_benchtime", None)
180
 
    
 
196
        return getattr(testCase, "_benchtime", None)
 
197
 
181
198
    def _elapsedTestTimeString(self):
182
199
        """Return a time string for the overall time the current test has taken."""
183
200
        return self._formatTime(time.time() - self._start_time)
184
201
 
185
 
    def _testTimeString(self):
186
 
        if self._benchmarkTime is not None:
187
 
            return "%s/%s" % (
188
 
                self._formatTime(self._benchmarkTime),
189
 
                self._elapsedTestTimeString())
 
202
    def _testTimeString(self, testCase):
 
203
        benchmark_time = self._extractBenchmarkTime(testCase)
 
204
        if benchmark_time is not None:
 
205
            return self._formatTime(benchmark_time) + "*"
190
206
        else:
191
 
            return "      %s" % self._elapsedTestTimeString()
 
207
            return self._elapsedTestTimeString()
192
208
 
193
209
    def _formatTime(self, seconds):
194
210
        """Format seconds as milliseconds with leading spaces."""
195
 
        return "%5dms" % (1000 * seconds)
 
211
        # some benchmarks can take thousands of seconds to run, so we need 8
 
212
        # places
 
213
        return "%8dms" % (1000 * seconds)
196
214
 
197
215
    def _shortened_test_description(self, test):
198
216
        what = test.id()
199
 
        what = re.sub(r'^bzrlib\.(tests|benchmark)\.', '', what)
 
217
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
200
218
        return what
201
219
 
202
220
    def startTest(self, test):
203
221
        unittest.TestResult.startTest(self, test)
 
222
        if self.count == 0:
 
223
            self.startTests()
204
224
        self.report_test_start(test)
 
225
        test.number = self.count
205
226
        self._recordTestStartTime()
206
227
 
 
228
    def startTests(self):
 
229
        import platform
 
230
        if getattr(sys, 'frozen', None) is None:
 
231
            bzr_path = osutils.realpath(sys.argv[0])
 
232
        else:
 
233
            bzr_path = sys.executable
 
234
        self.stream.write(
 
235
            'testing: %s\n' % (bzr_path,))
 
236
        self.stream.write(
 
237
            '   %s\n' % (
 
238
                    bzrlib.__path__[0],))
 
239
        self.stream.write(
 
240
            '   bzr-%s python-%s %s\n' % (
 
241
                    bzrlib.version_string,
 
242
                    bzrlib._format_version_tuple(sys.version_info),
 
243
                    platform.platform(aliased=1),
 
244
                    ))
 
245
        self.stream.write('\n')
 
246
 
207
247
    def _recordTestStartTime(self):
208
248
        """Record that a test has started."""
209
249
        self._start_time = time.time()
210
250
 
 
251
    def _cleanupLogFile(self, test):
 
252
        # We can only do this if we have one of our TestCases, not if
 
253
        # we have a doctest.
 
254
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
255
        if setKeepLogfile is not None:
 
256
            setKeepLogfile()
 
257
 
211
258
    def addError(self, test, err):
212
 
        if isinstance(err[1], TestSkipped):
213
 
            return self.addSkipped(test, err)    
214
 
        unittest.TestResult.addError(self, test, err)
215
 
        # We can only do this if we have one of our TestCases, not if
216
 
        # we have a doctest.
217
 
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
218
 
        if setKeepLogfile is not None:
219
 
            setKeepLogfile()
220
 
        self.extractBenchmarkTime(test)
221
 
        self.report_error(test, err)
222
 
        if self.stop_early:
223
 
            self.stop()
 
259
        """Tell result that test finished with an error.
 
260
 
 
261
        Called from the TestCase run() method when the test
 
262
        fails with an unexpected error.
 
263
        """
 
264
        self._testConcluded(test)
 
265
        if isinstance(err[1], TestNotApplicable):
 
266
            return self._addNotApplicable(test, err)
 
267
        elif isinstance(err[1], UnavailableFeature):
 
268
            return self.addNotSupported(test, err[1].args[0])
 
269
        else:
 
270
            unittest.TestResult.addError(self, test, err)
 
271
            self.error_count += 1
 
272
            self.report_error(test, err)
 
273
            if self.stop_early:
 
274
                self.stop()
 
275
            self._cleanupLogFile(test)
224
276
 
225
277
    def addFailure(self, test, err):
226
 
        unittest.TestResult.addFailure(self, test, err)
227
 
        # We can only do this if we have one of our TestCases, not if
228
 
        # we have a doctest.
229
 
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
230
 
        if setKeepLogfile is not None:
231
 
            setKeepLogfile()
232
 
        self.extractBenchmarkTime(test)
233
 
        self.report_failure(test, err)
234
 
        if self.stop_early:
235
 
            self.stop()
 
278
        """Tell result that test failed.
 
279
 
 
280
        Called from the TestCase run() method when the test
 
281
        fails because e.g. an assert() method failed.
 
282
        """
 
283
        self._testConcluded(test)
 
284
        if isinstance(err[1], KnownFailure):
 
285
            return self._addKnownFailure(test, err)
 
286
        else:
 
287
            unittest.TestResult.addFailure(self, test, err)
 
288
            self.failure_count += 1
 
289
            self.report_failure(test, err)
 
290
            if self.stop_early:
 
291
                self.stop()
 
292
            self._cleanupLogFile(test)
236
293
 
237
294
    def addSuccess(self, test):
238
 
        self.extractBenchmarkTime(test)
 
295
        """Tell result that test completed successfully.
 
296
 
 
297
        Called from the TestCase run()
 
298
        """
 
299
        self._testConcluded(test)
239
300
        if self._bench_history is not None:
240
 
            if self._benchmarkTime is not None:
 
301
            benchmark_time = self._extractBenchmarkTime(test)
 
302
            if benchmark_time is not None:
241
303
                self._bench_history.write("%s %s\n" % (
242
 
                    self._formatTime(self._benchmarkTime),
 
304
                    self._formatTime(benchmark_time),
243
305
                    test.id()))
244
306
        self.report_success(test)
 
307
        self._cleanupLogFile(test)
245
308
        unittest.TestResult.addSuccess(self, test)
246
 
 
247
 
    def addSkipped(self, test, skip_excinfo):
248
 
        self.extractBenchmarkTime(test)
249
 
        self.report_skip(test, skip_excinfo)
250
 
        # seems best to treat this as success from point-of-view of unittest
251
 
        # -- it actually does nothing so it barely matters :)
 
309
        test._log_contents = ''
 
310
 
 
311
    def _testConcluded(self, test):
 
312
        """Common code when a test has finished.
 
313
 
 
314
        Called regardless of whether it succeded, failed, etc.
 
315
        """
 
316
        pass
 
317
 
 
318
    def _addKnownFailure(self, test, err):
 
319
        self.known_failure_count += 1
 
320
        self.report_known_failure(test, err)
 
321
 
 
322
    def addNotSupported(self, test, feature):
 
323
        """The test will not be run because of a missing feature.
 
324
        """
 
325
        # this can be called in two different ways: it may be that the
 
326
        # test started running, and then raised (through addError)
 
327
        # UnavailableFeature.  Alternatively this method can be called
 
328
        # while probing for features before running the tests; in that
 
329
        # case we will see startTest and stopTest, but the test will never
 
330
        # actually run.
 
331
        self.unsupported.setdefault(str(feature), 0)
 
332
        self.unsupported[str(feature)] += 1
 
333
        self.report_unsupported(test, feature)
 
334
 
 
335
    def addSkip(self, test, reason):
 
336
        """A test has not run for 'reason'."""
 
337
        self.skip_count += 1
 
338
        self.report_skip(test, reason)
 
339
 
 
340
    def _addNotApplicable(self, test, skip_excinfo):
 
341
        if isinstance(skip_excinfo[1], TestNotApplicable):
 
342
            self.not_applicable_count += 1
 
343
            self.report_not_applicable(test, skip_excinfo)
252
344
        try:
253
345
            test.tearDown()
254
346
        except KeyboardInterrupt:
255
347
            raise
256
348
        except:
257
 
            self.addError(test, test.__exc_info())
 
349
            self.addError(test, test.exc_info())
258
350
        else:
 
351
            # seems best to treat this as success from point-of-view of unittest
 
352
            # -- it actually does nothing so it barely matters :)
259
353
            unittest.TestResult.addSuccess(self, test)
 
354
            test._log_contents = ''
260
355
 
261
356
    def printErrorList(self, flavour, errors):
262
357
        for test, err in errors:
263
358
            self.stream.writeln(self.separator1)
264
 
            self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
 
359
            self.stream.write("%s: " % flavour)
 
360
            self.stream.writeln(self.getDescription(test))
265
361
            if getattr(test, '_get_log', None) is not None:
266
 
                print >>self.stream
267
 
                print >>self.stream, \
268
 
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-')
269
 
                print >>self.stream, test._get_log()
270
 
                print >>self.stream, \
271
 
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-')
 
362
                log_contents = test._get_log()
 
363
                if log_contents:
 
364
                    self.stream.write('\n')
 
365
                    self.stream.write(
 
366
                            ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
 
367
                    self.stream.write('\n')
 
368
                    self.stream.write(log_contents)
 
369
                    self.stream.write('\n')
 
370
                    self.stream.write(
 
371
                            ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
 
372
                    self.stream.write('\n')
272
373
            self.stream.writeln(self.separator2)
273
374
            self.stream.writeln("%s" % err)
274
375
 
 
376
    def progress(self, offset, whence):
 
377
        """The test is adjusting the count of tests to run."""
 
378
        if whence == SUBUNIT_SEEK_SET:
 
379
            self.num_tests = offset
 
380
        elif whence == SUBUNIT_SEEK_CUR:
 
381
            self.num_tests += offset
 
382
        else:
 
383
            raise errors.BzrError("Unknown whence %r" % whence)
 
384
 
275
385
    def finished(self):
276
386
        pass
277
387
 
281
391
    def report_success(self, test):
282
392
        pass
283
393
 
 
394
    def wasStrictlySuccessful(self):
 
395
        if self.unsupported or self.known_failure_count:
 
396
            return False
 
397
        return self.wasSuccessful()
 
398
 
284
399
 
285
400
class TextTestResult(ExtendedTestResult):
286
401
    """Displays progress and results of tests in text form"""
287
402
 
288
 
    def __init__(self, *args, **kw):
289
 
        ExtendedTestResult.__init__(self, *args, **kw)
 
403
    def __init__(self, stream, descriptions, verbosity,
 
404
                 bench_history=None,
 
405
                 pb=None,
 
406
                 strict=None,
 
407
                 ):
 
408
        ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
 
409
            bench_history, strict)
 
410
        # We no longer pass them around, but just rely on the UIFactory stack
 
411
        # for state
 
412
        if pb is not None:
 
413
            warnings.warn("Passing pb to TextTestResult is deprecated")
290
414
        self.pb = self.ui.nested_progress_bar()
291
415
        self.pb.show_pct = False
292
416
        self.pb.show_spinner = False
293
 
        self.pb.show_eta = False, 
 
417
        self.pb.show_eta = False,
294
418
        self.pb.show_count = False
295
419
        self.pb.show_bar = False
 
420
        self.pb.update_latency = 0
 
421
        self.pb.show_transport_activity = False
 
422
 
 
423
    def done(self):
 
424
        # called when the tests that are going to run have run
 
425
        self.pb.clear()
 
426
        super(TextTestResult, self).done()
 
427
 
 
428
    def finished(self):
 
429
        self.pb.finished()
296
430
 
297
431
    def report_starting(self):
298
 
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
 
432
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
 
433
 
 
434
    def printErrors(self):
 
435
        # clear the pb to make room for the error listing
 
436
        self.pb.clear()
 
437
        super(TextTestResult, self).printErrors()
299
438
 
300
439
    def _progress_prefix_text(self):
301
 
        a = '[%d' % self.count
302
 
        if self.num_tests is not None:
 
440
        # the longer this text, the less space we have to show the test
 
441
        # name...
 
442
        a = '[%d' % self.count              # total that have been run
 
443
        # tests skipped as known not to be relevant are not important enough
 
444
        # to show here
 
445
        ## if self.skip_count:
 
446
        ##     a += ', %d skip' % self.skip_count
 
447
        ## if self.known_failure_count:
 
448
        ##     a += '+%dX' % self.known_failure_count
 
449
        if self.num_tests:
303
450
            a +='/%d' % self.num_tests
304
 
        a += ' in %ds' % (time.time() - self._overall_start_time)
 
451
        a += ' in '
 
452
        runtime = time.time() - self._overall_start_time
 
453
        if runtime >= 60:
 
454
            a += '%dm%ds' % (runtime / 60, runtime % 60)
 
455
        else:
 
456
            a += '%ds' % runtime
305
457
        if self.error_count:
306
 
            a += ', %d errors' % self.error_count
 
458
            a += ', %d err' % self.error_count
307
459
        if self.failure_count:
308
 
            a += ', %d failed' % self.failure_count
309
 
        if self.skip_count:
310
 
            a += ', %d skipped' % self.skip_count
 
460
            a += ', %d fail' % self.failure_count
 
461
        if self.unsupported:
 
462
            a += ', %d missing' % len(self.unsupported)
311
463
        a += ']'
312
464
        return a
313
465
 
315
467
        self.count += 1
316
468
        self.pb.update(
317
469
                self._progress_prefix_text()
318
 
                + ' ' 
 
470
                + ' '
319
471
                + self._shortened_test_description(test))
320
472
 
 
473
    def _test_description(self, test):
 
474
        return self._shortened_test_description(test)
 
475
 
321
476
    def report_error(self, test, err):
322
 
        self.error_count += 1
323
 
        self.pb.note('ERROR: %s\n    %s\n' % (
324
 
            self._shortened_test_description(test),
 
477
        self.pb.note('ERROR: %s\n    %s\n',
 
478
            self._test_description(test),
325
479
            err[1],
326
 
            ))
 
480
            )
327
481
 
328
482
    def report_failure(self, test, err):
329
 
        self.failure_count += 1
330
 
        self.pb.note('FAIL: %s\n    %s\n' % (
331
 
            self._shortened_test_description(test),
 
483
        self.pb.note('FAIL: %s\n    %s\n',
 
484
            self._test_description(test),
332
485
            err[1],
333
 
            ))
334
 
 
335
 
    def report_skip(self, test, skip_excinfo):
336
 
        self.skip_count += 1
337
 
        if False:
338
 
            # at the moment these are mostly not things we can fix
339
 
            # and so they just produce stipple; use the verbose reporter
340
 
            # to see them.
341
 
            if False:
342
 
                # show test and reason for skip
343
 
                self.pb.note('SKIP: %s\n    %s\n' % (
344
 
                    self._shortened_test_description(test),
345
 
                    skip_excinfo[1]))
346
 
            else:
347
 
                # since the class name was left behind in the still-visible
348
 
                # progress bar...
349
 
                self.pb.note('SKIP: %s' % (skip_excinfo[1]))
 
486
            )
 
487
 
 
488
    def report_known_failure(self, test, err):
 
489
        self.pb.note('XFAIL: %s\n%s\n',
 
490
            self._test_description(test), err[1])
 
491
 
 
492
    def report_skip(self, test, reason):
 
493
        pass
 
494
 
 
495
    def report_not_applicable(self, test, skip_excinfo):
 
496
        pass
 
497
 
 
498
    def report_unsupported(self, test, feature):
 
499
        """test cannot be run because feature is missing."""
350
500
 
351
501
    def report_cleaning_up(self):
352
 
        self.pb.update('cleaning up...')
353
 
 
354
 
    def finished(self):
355
 
        self.pb.finished()
 
502
        self.pb.update('Cleaning up')
356
503
 
357
504
 
358
505
class VerboseTestResult(ExtendedTestResult):
372
519
    def report_test_start(self, test):
373
520
        self.count += 1
374
521
        name = self._shortened_test_description(test)
375
 
        self.stream.write(self._ellipsize_to_right(name, 60))
 
522
        # width needs space for 6 char status, plus 1 for slash, plus an
 
523
        # 11-char time string, plus a trailing blank
 
524
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
 
525
        self.stream.write(self._ellipsize_to_right(name,
 
526
                          osutils.terminal_width()-18))
376
527
        self.stream.flush()
377
528
 
 
529
    def _error_summary(self, err):
 
530
        indent = ' ' * 4
 
531
        return '%s%s' % (indent, err[1])
 
532
 
378
533
    def report_error(self, test, err):
379
 
        self.error_count += 1
380
 
        self.stream.writeln('ERROR %s\n    %s' 
381
 
                % (self._testTimeString(), err[1]))
 
534
        self.stream.writeln('ERROR %s\n%s'
 
535
                % (self._testTimeString(test),
 
536
                   self._error_summary(err)))
382
537
 
383
538
    def report_failure(self, test, err):
384
 
        self.failure_count += 1
385
 
        self.stream.writeln('FAIL %s\n    %s'
386
 
                % (self._testTimeString(), err[1]))
 
539
        self.stream.writeln(' FAIL %s\n%s'
 
540
                % (self._testTimeString(test),
 
541
                   self._error_summary(err)))
 
542
 
 
543
    def report_known_failure(self, test, err):
 
544
        self.stream.writeln('XFAIL %s\n%s'
 
545
                % (self._testTimeString(test),
 
546
                   self._error_summary(err)))
387
547
 
388
548
    def report_success(self, test):
389
 
        self.stream.writeln('   OK %s' % self._testTimeString())
 
549
        self.stream.writeln('   OK %s' % self._testTimeString(test))
390
550
        for bench_called, stats in getattr(test, '_benchcalls', []):
391
551
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
392
552
            stats.pprint(file=self.stream)
 
553
        # flush the stream so that we get smooth output. This verbose mode is
 
554
        # used to show the output in PQM.
393
555
        self.stream.flush()
394
556
 
395
 
    def report_skip(self, test, skip_excinfo):
396
 
        print >>self.stream, ' SKIP %s' % self._testTimeString()
397
 
        print >>self.stream, '     %s' % skip_excinfo[1]
 
557
    def report_skip(self, test, reason):
 
558
        self.stream.writeln(' SKIP %s\n%s'
 
559
                % (self._testTimeString(test), reason))
 
560
 
 
561
    def report_not_applicable(self, test, skip_excinfo):
 
562
        self.stream.writeln('  N/A %s\n%s'
 
563
                % (self._testTimeString(test),
 
564
                   self._error_summary(skip_excinfo)))
 
565
 
 
566
    def report_unsupported(self, test, feature):
 
567
        """test cannot be run because feature is missing."""
 
568
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
 
569
                %(self._testTimeString(test), feature))
398
570
 
399
571
 
400
572
class TextTestRunner(object):
404
576
                 stream=sys.stderr,
405
577
                 descriptions=0,
406
578
                 verbosity=1,
407
 
                 keep_output=False,
408
 
                 bench_history=None):
 
579
                 bench_history=None,
 
580
                 list_only=False,
 
581
                 strict=False,
 
582
                 ):
409
583
        self.stream = unittest._WritelnDecorator(stream)
410
584
        self.descriptions = descriptions
411
585
        self.verbosity = verbosity
412
 
        self.keep_output = keep_output
413
586
        self._bench_history = bench_history
 
587
        self.list_only = list_only
 
588
        self._strict = strict
414
589
 
415
590
    def run(self, test):
416
591
        "Run the given test case or test suite."
423
598
                              self.descriptions,
424
599
                              self.verbosity,
425
600
                              bench_history=self._bench_history,
426
 
                              num_tests=test.countTestCases(),
 
601
                              strict=self._strict,
427
602
                              )
428
603
        result.stop_early = self.stop_on_failure
429
604
        result.report_starting()
430
 
        test.run(result)
 
605
        if self.list_only:
 
606
            if self.verbosity >= 2:
 
607
                self.stream.writeln("Listing tests only ...\n")
 
608
            run = 0
 
609
            for t in iter_suite_tests(test):
 
610
                self.stream.writeln("%s" % (t.id()))
 
611
                run += 1
 
612
            return None
 
613
        else:
 
614
            try:
 
615
                import testtools
 
616
            except ImportError:
 
617
                test.run(result)
 
618
            else:
 
619
                if isinstance(test, testtools.ConcurrentTestSuite):
 
620
                    # We need to catch bzr specific behaviors
 
621
                    test.run(BZRTransformingResult(result))
 
622
                else:
 
623
                    test.run(result)
 
624
            run = result.testsRun
 
625
            actionTaken = "Ran"
431
626
        stopTime = time.time()
432
627
        timeTaken = stopTime - startTime
433
628
        result.printErrors()
434
629
        self.stream.writeln(result.separator2)
435
 
        run = result.testsRun
436
 
        self.stream.writeln("Ran %d test%s in %.3fs" %
437
 
                            (run, run != 1 and "s" or "", timeTaken))
 
630
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
 
631
                            run, run != 1 and "s" or "", timeTaken))
438
632
        self.stream.writeln()
439
633
        if not result.wasSuccessful():
440
634
            self.stream.write("FAILED (")
444
638
            if errored:
445
639
                if failed: self.stream.write(", ")
446
640
                self.stream.write("errors=%d" % errored)
 
641
            if result.known_failure_count:
 
642
                if failed or errored: self.stream.write(", ")
 
643
                self.stream.write("known_failure_count=%d" %
 
644
                    result.known_failure_count)
447
645
            self.stream.writeln(")")
448
646
        else:
449
 
            self.stream.writeln("OK")
450
 
        result.report_cleaning_up()
451
 
        # This is still a little bogus, 
452
 
        # but only a little. Folk not using our testrunner will
453
 
        # have to delete their temp directories themselves.
454
 
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
455
 
        if result.wasSuccessful() or not self.keep_output:
456
 
            if test_root is not None:
457
 
                # If LANG=C we probably have created some bogus paths
458
 
                # which rmtree(unicode) will fail to delete
459
 
                # so make sure we are using rmtree(str) to delete everything
460
 
                # except on win32, where rmtree(str) will fail
461
 
                # since it doesn't have the property of byte-stream paths
462
 
                # (they are either ascii or mbcs)
463
 
                if sys.platform == 'win32':
464
 
                    # make sure we are using the unicode win32 api
465
 
                    test_root = unicode(test_root)
466
 
                else:
467
 
                    test_root = test_root.encode(
468
 
                        sys.getfilesystemencoding())
469
 
                osutils.rmtree(test_root)
470
 
        else:
471
 
            note("Failed tests working directories are in '%s'\n", test_root)
472
 
        TestCaseWithMemoryTransport.TEST_ROOT = None
 
647
            if result.known_failure_count:
 
648
                self.stream.writeln("OK (known_failures=%d)" %
 
649
                    result.known_failure_count)
 
650
            else:
 
651
                self.stream.writeln("OK")
 
652
        if result.skip_count > 0:
 
653
            skipped = result.skip_count
 
654
            self.stream.writeln('%d test%s skipped' %
 
655
                                (skipped, skipped != 1 and "s" or ""))
 
656
        if result.unsupported:
 
657
            for feature, count in sorted(result.unsupported.items()):
 
658
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
 
659
                    (feature, count))
473
660
        result.finished()
474
661
        return result
475
662
 
476
663
 
477
664
def iter_suite_tests(suite):
478
665
    """Return all tests in a suite, recursing through nested suites"""
479
 
    for item in suite._tests:
480
 
        if isinstance(item, unittest.TestCase):
481
 
            yield item
482
 
        elif isinstance(item, unittest.TestSuite):
 
666
    if isinstance(suite, unittest.TestCase):
 
667
        yield suite
 
668
    elif isinstance(suite, unittest.TestSuite):
 
669
        for item in suite:
483
670
            for r in iter_suite_tests(item):
484
671
                yield r
485
 
        else:
486
 
            raise Exception('unknown object %r inside test suite %r'
487
 
                            % (item, suite))
 
672
    else:
 
673
        raise Exception('unknown type %r for object %r'
 
674
                        % (type(suite), suite))
488
675
 
489
676
 
490
677
class TestSkipped(Exception):
491
678
    """Indicates that a test was intentionally skipped, rather than failing."""
492
679
 
493
680
 
 
681
class TestNotApplicable(TestSkipped):
 
682
    """A test is not applicable to the situation where it was run.
 
683
 
 
684
    This is only normally raised by parameterized tests, if they find that
 
685
    the instance they're constructed upon does not support one aspect
 
686
    of its interface.
 
687
    """
 
688
 
 
689
 
 
690
class KnownFailure(AssertionError):
 
691
    """Indicates that a test failed in a precisely expected manner.
 
692
 
 
693
    Such failures dont block the whole test suite from passing because they are
 
694
    indicators of partially completed code or of future work. We have an
 
695
    explicit error for them so that we can ensure that they are always visible:
 
696
    KnownFailures are always shown in the output of bzr selftest.
 
697
    """
 
698
 
 
699
 
 
700
class UnavailableFeature(Exception):
 
701
    """A feature required for this test was not available.
 
702
 
 
703
    The feature should be used to construct the exception.
 
704
    """
 
705
 
 
706
 
494
707
class CommandFailed(Exception):
495
708
    pass
496
709
 
497
710
 
498
711
class StringIOWrapper(object):
499
712
    """A wrapper around cStringIO which just adds an encoding attribute.
500
 
    
 
713
 
501
714
    Internally we can check sys.stdout to see what the output encoding
502
715
    should be. However, cStringIO has no encoding attribute that we can
503
716
    set. So we wrap it instead.
521
734
            return setattr(self._cstring, name, val)
522
735
 
523
736
 
 
737
class TestUIFactory(TextUIFactory):
 
738
    """A UI Factory for testing.
 
739
 
 
740
    Hide the progress bar but emit note()s.
 
741
    Redirect stdin.
 
742
    Allows get_password to be tested without real tty attached.
 
743
 
 
744
    See also CannedInputUIFactory which lets you provide programmatic input in
 
745
    a structured way.
 
746
    """
 
747
    # TODO: Capture progress events at the model level and allow them to be
 
748
    # observed by tests that care.
 
749
    #
 
750
    # XXX: Should probably unify more with CannedInputUIFactory or a
 
751
    # particular configuration of TextUIFactory, or otherwise have a clearer
 
752
    # idea of how they're supposed to be different.
 
753
    # See https://bugs.edge.launchpad.net/bzr/+bug/408213
 
754
 
 
755
    def __init__(self, stdout=None, stderr=None, stdin=None):
 
756
        if stdin is not None:
 
757
            # We use a StringIOWrapper to be able to test various
 
758
            # encodings, but the user is still responsible to
 
759
            # encode the string and to set the encoding attribute
 
760
            # of StringIOWrapper.
 
761
            stdin = StringIOWrapper(stdin)
 
762
        super(TestUIFactory, self).__init__(stdin, stdout, stderr)
 
763
 
 
764
    def get_non_echoed_password(self):
 
765
        """Get password from stdin without trying to handle the echo mode"""
 
766
        password = self.stdin.readline()
 
767
        if not password:
 
768
            raise EOFError
 
769
        if password[-1] == '\n':
 
770
            password = password[:-1]
 
771
        return password
 
772
 
 
773
    def make_progress_view(self):
 
774
        return NullProgressView()
 
775
 
 
776
 
524
777
class TestCase(unittest.TestCase):
525
778
    """Base class for bzr unit tests.
526
 
    
527
 
    Tests that need access to disk resources should subclass 
 
779
 
 
780
    Tests that need access to disk resources should subclass
528
781
    TestCaseInTempDir not TestCase.
529
782
 
530
783
    Error and debug log messages are redirected from their usual
532
785
    retrieved by _get_log().  We use a real OS file, not an in-memory object,
533
786
    so that it can also capture file IO.  When the test completes this file
534
787
    is read into memory and removed from disk.
535
 
       
 
788
 
536
789
    There are also convenience functions to invoke bzr's command-line
537
790
    routine, and to build and check bzr trees.
538
 
   
 
791
 
539
792
    In addition to the usual method of overriding tearDown(), this class also
540
793
    allows subclasses to register functions into the _cleanups list, which is
541
794
    run in order as the object is torn down.  It's less likely this will be
542
795
    accidentally overlooked.
543
796
    """
544
797
 
 
798
    _active_threads = None
 
799
    _leaking_threads_tests = 0
 
800
    _first_thread_leaker_id = None
545
801
    _log_file_name = None
546
802
    _log_contents = ''
547
803
    _keep_log_file = False
548
804
    # record lsprof data when performing benchmark calls.
549
805
    _gather_lsprof_in_benchmarks = False
 
806
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
 
807
                     '_log_contents', '_log_file_name', '_benchtime',
 
808
                     '_TestCase__testMethodName', '_TestCase__testMethodDoc',)
550
809
 
551
810
    def __init__(self, methodName='testMethod'):
552
811
        super(TestCase, self).__init__(methodName)
553
812
        self._cleanups = []
 
813
        self._bzr_test_setUp_run = False
 
814
        self._bzr_test_tearDown_run = False
554
815
 
555
816
    def setUp(self):
556
817
        unittest.TestCase.setUp(self)
 
818
        self._bzr_test_setUp_run = True
557
819
        self._cleanEnvironment()
558
 
        bzrlib.trace.disable_default_logging()
559
820
        self._silenceUI()
560
821
        self._startLogFile()
561
822
        self._benchcalls = []
562
823
        self._benchtime = None
 
824
        self._clear_hooks()
 
825
        self._track_locks()
 
826
        self._clear_debug_flags()
 
827
        TestCase._active_threads = threading.activeCount()
 
828
        self.addCleanup(self._check_leaked_threads)
 
829
 
 
830
    def debug(self):
 
831
        # debug a frame up.
 
832
        import pdb
 
833
        pdb.Pdb().set_trace(sys._getframe().f_back)
 
834
 
 
835
    def _check_leaked_threads(self):
 
836
        active = threading.activeCount()
 
837
        leaked_threads = active - TestCase._active_threads
 
838
        TestCase._active_threads = active
 
839
        if leaked_threads:
 
840
            TestCase._leaking_threads_tests += 1
 
841
            if TestCase._first_thread_leaker_id is None:
 
842
                TestCase._first_thread_leaker_id = self.id()
 
843
 
 
844
    def _clear_debug_flags(self):
 
845
        """Prevent externally set debug flags affecting tests.
 
846
 
 
847
        Tests that want to use debug flags can just set them in the
 
848
        debug_flags set during setup/teardown.
 
849
        """
 
850
        self._preserved_debug_flags = set(debug.debug_flags)
 
851
        if 'allow_debug' not in selftest_debug_flags:
 
852
            debug.debug_flags.clear()
 
853
        if 'disable_lock_checks' not in selftest_debug_flags:
 
854
            debug.debug_flags.add('strict_locks')
 
855
        self.addCleanup(self._restore_debug_flags)
 
856
 
 
857
    def _clear_hooks(self):
 
858
        # prevent hooks affecting tests
 
859
        self._preserved_hooks = {}
 
860
        for key, factory in hooks.known_hooks.items():
 
861
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
862
            current_hooks = hooks.known_hooks_key_to_object(key)
 
863
            self._preserved_hooks[parent] = (name, current_hooks)
 
864
        self.addCleanup(self._restoreHooks)
 
865
        for key, factory in hooks.known_hooks.items():
 
866
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
867
            setattr(parent, name, factory())
 
868
        # this hook should always be installed
 
869
        request._install_hook()
563
870
 
564
871
    def _silenceUI(self):
565
872
        """Turn off UI for duration of test"""
566
873
        # by default the UI is off; tests can turn it on if they want it.
567
 
        saved = bzrlib.ui.ui_factory
 
874
        saved = ui.ui_factory
568
875
        def _restore():
569
 
            bzrlib.ui.ui_factory = saved
570
 
        bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
 
876
            ui.ui_factory = saved
 
877
        ui.ui_factory = ui.SilentUIFactory()
571
878
        self.addCleanup(_restore)
572
879
 
 
880
    def _check_locks(self):
 
881
        """Check that all lock take/release actions have been paired."""
 
882
        # We always check for mismatched locks. If a mismatch is found, we
 
883
        # fail unless -Edisable_lock_checks is supplied to selftest, in which
 
884
        # case we just print a warning.
 
885
        # unhook:
 
886
        acquired_locks = [lock for action, lock in self._lock_actions
 
887
                          if action == 'acquired']
 
888
        released_locks = [lock for action, lock in self._lock_actions
 
889
                          if action == 'released']
 
890
        broken_locks = [lock for action, lock in self._lock_actions
 
891
                        if action == 'broken']
 
892
        # trivially, given the tests for lock acquistion and release, if we
 
893
        # have as many in each list, it should be ok. Some lock tests also
 
894
        # break some locks on purpose and should be taken into account by
 
895
        # considering that breaking a lock is just a dirty way of releasing it.
 
896
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
 
897
            message = ('Different number of acquired and '
 
898
                       'released or broken locks. (%s, %s + %s)' %
 
899
                       (acquired_locks, released_locks, broken_locks))
 
900
            if not self._lock_check_thorough:
 
901
                # Rather than fail, just warn
 
902
                print "Broken test %s: %s" % (self, message)
 
903
                return
 
904
            self.fail(message)
 
905
 
 
906
    def _track_locks(self):
 
907
        """Track lock activity during tests."""
 
908
        self._lock_actions = []
 
909
        if 'disable_lock_checks' in selftest_debug_flags:
 
910
            self._lock_check_thorough = False
 
911
        else:
 
912
            self._lock_check_thorough = True
 
913
            
 
914
        self.addCleanup(self._check_locks)
 
915
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
 
916
                                                self._lock_acquired, None)
 
917
        _mod_lock.Lock.hooks.install_named_hook('lock_released',
 
918
                                                self._lock_released, None)
 
919
        _mod_lock.Lock.hooks.install_named_hook('lock_broken',
 
920
                                                self._lock_broken, None)
 
921
 
 
922
    def _lock_acquired(self, result):
 
923
        self._lock_actions.append(('acquired', result))
 
924
 
 
925
    def _lock_released(self, result):
 
926
        self._lock_actions.append(('released', result))
 
927
 
 
928
    def _lock_broken(self, result):
 
929
        self._lock_actions.append(('broken', result))
 
930
 
573
931
    def _ndiff_strings(self, a, b):
574
932
        """Return ndiff between two strings containing lines.
575
 
        
 
933
 
576
934
        A trailing newline is added if missing to make the strings
577
935
        print properly."""
578
936
        if b and b[-1] != '\n':
585
943
                                  charjunk=lambda x: False)
586
944
        return ''.join(difflines)
587
945
 
 
946
    def assertEqual(self, a, b, message=''):
 
947
        try:
 
948
            if a == b:
 
949
                return
 
950
        except UnicodeError, e:
 
951
            # If we can't compare without getting a UnicodeError, then
 
952
            # obviously they are different
 
953
            mutter('UnicodeError: %s', e)
 
954
        if message:
 
955
            message += '\n'
 
956
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
 
957
            % (message,
 
958
               pformat(a), pformat(b)))
 
959
 
 
960
    assertEquals = assertEqual
 
961
 
588
962
    def assertEqualDiff(self, a, b, message=None):
589
963
        """Assert two texts are equal, if not raise an exception.
590
 
        
591
 
        This is intended for use with multi-line strings where it can 
 
964
 
 
965
        This is intended for use with multi-line strings where it can
592
966
        be hard to find the differences by eye.
593
967
        """
594
968
        # TODO: perhaps override assertEquals to call this for strings?
596
970
            return
597
971
        if message is None:
598
972
            message = "texts not equal:\n"
599
 
        raise AssertionError(message + 
600
 
                             self._ndiff_strings(a, b))      
601
 
        
 
973
        if a == b + '\n':
 
974
            message = 'first string is missing a final newline.\n'
 
975
        if a + '\n' == b:
 
976
            message = 'second string is missing a final newline.\n'
 
977
        raise AssertionError(message +
 
978
                             self._ndiff_strings(a, b))
 
979
 
602
980
    def assertEqualMode(self, mode, mode_test):
603
981
        self.assertEqual(mode, mode_test,
604
982
                         'mode mismatch %o != %o' % (mode, mode_test))
605
983
 
 
984
    def assertEqualStat(self, expected, actual):
 
985
        """assert that expected and actual are the same stat result.
 
986
 
 
987
        :param expected: A stat result.
 
988
        :param actual: A stat result.
 
989
        :raises AssertionError: If the expected and actual stat values differ
 
990
            other than by atime.
 
991
        """
 
992
        self.assertEqual(expected.st_size, actual.st_size)
 
993
        self.assertEqual(expected.st_mtime, actual.st_mtime)
 
994
        self.assertEqual(expected.st_ctime, actual.st_ctime)
 
995
        self.assertEqual(expected.st_dev, actual.st_dev)
 
996
        self.assertEqual(expected.st_ino, actual.st_ino)
 
997
        self.assertEqual(expected.st_mode, actual.st_mode)
 
998
 
 
999
    def assertLength(self, length, obj_with_len):
 
1000
        """Assert that obj_with_len is of length length."""
 
1001
        if len(obj_with_len) != length:
 
1002
            self.fail("Incorrect length: wanted %d, got %d for %r" % (
 
1003
                length, len(obj_with_len), obj_with_len))
 
1004
 
 
1005
    def assertPositive(self, val):
 
1006
        """Assert that val is greater than 0."""
 
1007
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
 
1008
 
 
1009
    def assertNegative(self, val):
 
1010
        """Assert that val is less than 0."""
 
1011
        self.assertTrue(val < 0, 'expected a negative value, but got %s' % val)
 
1012
 
606
1013
    def assertStartsWith(self, s, prefix):
607
1014
        if not s.startswith(prefix):
608
1015
            raise AssertionError('string %r does not start with %r' % (s, prefix))
612
1019
        if not s.endswith(suffix):
613
1020
            raise AssertionError('string %r does not end with %r' % (s, suffix))
614
1021
 
615
 
    def assertContainsRe(self, haystack, needle_re):
 
1022
    def assertContainsRe(self, haystack, needle_re, flags=0):
616
1023
        """Assert that a contains something matching a regular expression."""
617
 
        if not re.search(needle_re, haystack):
618
 
            raise AssertionError('pattern "%s" not found in "%s"'
619
 
                    % (needle_re, haystack))
 
1024
        if not re.search(needle_re, haystack, flags):
 
1025
            if '\n' in haystack or len(haystack) > 60:
 
1026
                # a long string, format it in a more readable way
 
1027
                raise AssertionError(
 
1028
                        'pattern "%s" not found in\n"""\\\n%s"""\n'
 
1029
                        % (needle_re, haystack))
 
1030
            else:
 
1031
                raise AssertionError('pattern "%s" not found in "%s"'
 
1032
                        % (needle_re, haystack))
620
1033
 
621
 
    def assertNotContainsRe(self, haystack, needle_re):
 
1034
    def assertNotContainsRe(self, haystack, needle_re, flags=0):
622
1035
        """Assert that a does not match a regular expression"""
623
 
        if re.search(needle_re, haystack):
 
1036
        if re.search(needle_re, haystack, flags):
624
1037
            raise AssertionError('pattern "%s" found in "%s"'
625
1038
                    % (needle_re, haystack))
626
1039
 
627
1040
    def assertSubset(self, sublist, superlist):
628
1041
        """Assert that every entry in sublist is present in superlist."""
629
 
        missing = []
630
 
        for entry in sublist:
631
 
            if entry not in superlist:
632
 
                missing.append(entry)
 
1042
        missing = set(sublist) - set(superlist)
633
1043
        if len(missing) > 0:
634
 
            raise AssertionError("value(s) %r not present in container %r" % 
 
1044
            raise AssertionError("value(s) %r not present in container %r" %
635
1045
                                 (missing, superlist))
636
1046
 
637
 
    def assertIs(self, left, right):
 
1047
    def assertListRaises(self, excClass, func, *args, **kwargs):
 
1048
        """Fail unless excClass is raised when the iterator from func is used.
 
1049
 
 
1050
        Many functions can return generators this makes sure
 
1051
        to wrap them in a list() call to make sure the whole generator
 
1052
        is run, and that the proper exception is raised.
 
1053
        """
 
1054
        try:
 
1055
            list(func(*args, **kwargs))
 
1056
        except excClass, e:
 
1057
            return e
 
1058
        else:
 
1059
            if getattr(excClass,'__name__', None) is not None:
 
1060
                excName = excClass.__name__
 
1061
            else:
 
1062
                excName = str(excClass)
 
1063
            raise self.failureException, "%s not raised" % excName
 
1064
 
 
1065
    def assertRaises(self, excClass, callableObj, *args, **kwargs):
 
1066
        """Assert that a callable raises a particular exception.
 
1067
 
 
1068
        :param excClass: As for the except statement, this may be either an
 
1069
            exception class, or a tuple of classes.
 
1070
        :param callableObj: A callable, will be passed ``*args`` and
 
1071
            ``**kwargs``.
 
1072
 
 
1073
        Returns the exception so that you can examine it.
 
1074
        """
 
1075
        try:
 
1076
            callableObj(*args, **kwargs)
 
1077
        except excClass, e:
 
1078
            return e
 
1079
        else:
 
1080
            if getattr(excClass,'__name__', None) is not None:
 
1081
                excName = excClass.__name__
 
1082
            else:
 
1083
                # probably a tuple
 
1084
                excName = str(excClass)
 
1085
            raise self.failureException, "%s not raised" % excName
 
1086
 
 
1087
    def assertIs(self, left, right, message=None):
638
1088
        if not (left is right):
639
 
            raise AssertionError("%r is not %r." % (left, right))
 
1089
            if message is not None:
 
1090
                raise AssertionError(message)
 
1091
            else:
 
1092
                raise AssertionError("%r is not %r." % (left, right))
 
1093
 
 
1094
    def assertIsNot(self, left, right, message=None):
 
1095
        if (left is right):
 
1096
            if message is not None:
 
1097
                raise AssertionError(message)
 
1098
            else:
 
1099
                raise AssertionError("%r is %r." % (left, right))
640
1100
 
641
1101
    def assertTransportMode(self, transport, path, mode):
642
 
        """Fail if a path does not have mode mode.
643
 
        
 
1102
        """Fail if a path does not have mode "mode".
 
1103
 
644
1104
        If modes are not supported on this transport, the assertion is ignored.
645
1105
        """
646
1106
        if not transport._can_roundtrip_unix_modebits():
648
1108
        path_stat = transport.stat(path)
649
1109
        actual_mode = stat.S_IMODE(path_stat.st_mode)
650
1110
        self.assertEqual(mode, actual_mode,
651
 
            'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
652
 
 
653
 
    def assertIsInstance(self, obj, kls):
654
 
        """Fail if obj is not an instance of kls"""
 
1111
                         'mode of %r incorrect (%s != %s)'
 
1112
                         % (path, oct(mode), oct(actual_mode)))
 
1113
 
 
1114
    def assertIsSameRealPath(self, path1, path2):
 
1115
        """Fail if path1 and path2 points to different files"""
 
1116
        self.assertEqual(osutils.realpath(path1),
 
1117
                         osutils.realpath(path2),
 
1118
                         "apparent paths:\na = %s\nb = %s\n," % (path1, path2))
 
1119
 
 
1120
    def assertIsInstance(self, obj, kls, msg=None):
 
1121
        """Fail if obj is not an instance of kls
 
1122
        
 
1123
        :param msg: Supplementary message to show if the assertion fails.
 
1124
        """
655
1125
        if not isinstance(obj, kls):
656
 
            self.fail("%r is an instance of %s rather than %s" % (
657
 
                obj, obj.__class__, kls))
658
 
 
659
 
    def _capture_warnings(self, a_callable, *args, **kwargs):
 
1126
            m = "%r is an instance of %s rather than %s" % (
 
1127
                obj, obj.__class__, kls)
 
1128
            if msg:
 
1129
                m += ": " + msg
 
1130
            self.fail(m)
 
1131
 
 
1132
    def expectFailure(self, reason, assertion, *args, **kwargs):
 
1133
        """Invoke a test, expecting it to fail for the given reason.
 
1134
 
 
1135
        This is for assertions that ought to succeed, but currently fail.
 
1136
        (The failure is *expected* but not *wanted*.)  Please be very precise
 
1137
        about the failure you're expecting.  If a new bug is introduced,
 
1138
        AssertionError should be raised, not KnownFailure.
 
1139
 
 
1140
        Frequently, expectFailure should be followed by an opposite assertion.
 
1141
        See example below.
 
1142
 
 
1143
        Intended to be used with a callable that raises AssertionError as the
 
1144
        'assertion' parameter.  args and kwargs are passed to the 'assertion'.
 
1145
 
 
1146
        Raises KnownFailure if the test fails.  Raises AssertionError if the
 
1147
        test succeeds.
 
1148
 
 
1149
        example usage::
 
1150
 
 
1151
          self.expectFailure('Math is broken', self.assertNotEqual, 54,
 
1152
                             dynamic_val)
 
1153
          self.assertEqual(42, dynamic_val)
 
1154
 
 
1155
          This means that a dynamic_val of 54 will cause the test to raise
 
1156
          a KnownFailure.  Once math is fixed and the expectFailure is removed,
 
1157
          only a dynamic_val of 42 will allow the test to pass.  Anything other
 
1158
          than 54 or 42 will cause an AssertionError.
 
1159
        """
 
1160
        try:
 
1161
            assertion(*args, **kwargs)
 
1162
        except AssertionError:
 
1163
            raise KnownFailure(reason)
 
1164
        else:
 
1165
            self.fail('Unexpected success.  Should have failed: %s' % reason)
 
1166
 
 
1167
    def assertFileEqual(self, content, path):
 
1168
        """Fail if path does not contain 'content'."""
 
1169
        self.failUnlessExists(path)
 
1170
        f = file(path, 'rb')
 
1171
        try:
 
1172
            s = f.read()
 
1173
        finally:
 
1174
            f.close()
 
1175
        self.assertEqualDiff(content, s)
 
1176
 
 
1177
    def failUnlessExists(self, path):
 
1178
        """Fail unless path or paths, which may be abs or relative, exist."""
 
1179
        if not isinstance(path, basestring):
 
1180
            for p in path:
 
1181
                self.failUnlessExists(p)
 
1182
        else:
 
1183
            self.failUnless(osutils.lexists(path),path+" does not exist")
 
1184
 
 
1185
    def failIfExists(self, path):
 
1186
        """Fail if path or paths, which may be abs or relative, exist."""
 
1187
        if not isinstance(path, basestring):
 
1188
            for p in path:
 
1189
                self.failIfExists(p)
 
1190
        else:
 
1191
            self.failIf(osutils.lexists(path),path+" exists")
 
1192
 
 
1193
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
660
1194
        """A helper for callDeprecated and applyDeprecated.
661
1195
 
662
1196
        :param a_callable: A callable to call.
663
1197
        :param args: The positional arguments for the callable
664
1198
        :param kwargs: The keyword arguments for the callable
665
1199
        :return: A tuple (warnings, result). result is the result of calling
666
 
            a_callable(*args, **kwargs).
 
1200
            a_callable(``*args``, ``**kwargs``).
667
1201
        """
668
1202
        local_warnings = []
669
1203
        def capture_warnings(msg, cls=None, stacklevel=None):
682
1216
    def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
683
1217
        """Call a deprecated callable without warning the user.
684
1218
 
 
1219
        Note that this only captures warnings raised by symbol_versioning.warn,
 
1220
        not other callers that go direct to the warning module.
 
1221
 
 
1222
        To test that a deprecated method raises an error, do something like
 
1223
        this::
 
1224
 
 
1225
            self.assertRaises(errors.ReservedId,
 
1226
                self.applyDeprecated,
 
1227
                deprecated_in((1, 5, 0)),
 
1228
                br.append_revision,
 
1229
                'current:')
 
1230
 
685
1231
        :param deprecation_format: The deprecation format that the callable
686
 
            should have been deprecated with. This is the same type as the 
687
 
            parameter to deprecated_method/deprecated_function. If the 
 
1232
            should have been deprecated with. This is the same type as the
 
1233
            parameter to deprecated_method/deprecated_function. If the
688
1234
            callable is not deprecated with this format, an assertion error
689
1235
            will be raised.
690
1236
        :param a_callable: A callable to call. This may be a bound method or
691
 
            a regular function. It will be called with *args and **kwargs.
 
1237
            a regular function. It will be called with ``*args`` and
 
1238
            ``**kwargs``.
692
1239
        :param args: The positional arguments for the callable
693
1240
        :param kwargs: The keyword arguments for the callable
694
 
        :return: The result of a_callable(*args, **kwargs)
 
1241
        :return: The result of a_callable(``*args``, ``**kwargs``)
695
1242
        """
696
 
        call_warnings, result = self._capture_warnings(a_callable,
 
1243
        call_warnings, result = self._capture_deprecation_warnings(a_callable,
697
1244
            *args, **kwargs)
698
1245
        expected_first_warning = symbol_versioning.deprecation_string(
699
1246
            a_callable, deprecation_format)
700
1247
        if len(call_warnings) == 0:
701
 
            self.fail("No assertion generated by call to %s" %
 
1248
            self.fail("No deprecation warning generated by call to %s" %
702
1249
                a_callable)
703
1250
        self.assertEqual(expected_first_warning, call_warnings[0])
704
1251
        return result
705
1252
 
 
1253
    def callCatchWarnings(self, fn, *args, **kw):
 
1254
        """Call a callable that raises python warnings.
 
1255
 
 
1256
        The caller's responsible for examining the returned warnings.
 
1257
 
 
1258
        If the callable raises an exception, the exception is not
 
1259
        caught and propagates up to the caller.  In that case, the list
 
1260
        of warnings is not available.
 
1261
 
 
1262
        :returns: ([warning_object, ...], fn_result)
 
1263
        """
 
1264
        # XXX: This is not perfect, because it completely overrides the
 
1265
        # warnings filters, and some code may depend on suppressing particular
 
1266
        # warnings.  It's the easiest way to insulate ourselves from -Werror,
 
1267
        # though.  -- Andrew, 20071062
 
1268
        wlist = []
 
1269
        def _catcher(message, category, filename, lineno, file=None, line=None):
 
1270
            # despite the name, 'message' is normally(?) a Warning subclass
 
1271
            # instance
 
1272
            wlist.append(message)
 
1273
        saved_showwarning = warnings.showwarning
 
1274
        saved_filters = warnings.filters
 
1275
        try:
 
1276
            warnings.showwarning = _catcher
 
1277
            warnings.filters = []
 
1278
            result = fn(*args, **kw)
 
1279
        finally:
 
1280
            warnings.showwarning = saved_showwarning
 
1281
            warnings.filters = saved_filters
 
1282
        return wlist, result
 
1283
 
706
1284
    def callDeprecated(self, expected, callable, *args, **kwargs):
707
1285
        """Assert that a callable is deprecated in a particular way.
708
1286
 
709
 
        This is a very precise test for unusual requirements. The 
 
1287
        This is a very precise test for unusual requirements. The
710
1288
        applyDeprecated helper function is probably more suited for most tests
711
1289
        as it allows you to simply specify the deprecation format being used
712
1290
        and will ensure that that is issued for the function being called.
713
1291
 
 
1292
        Note that this only captures warnings raised by symbol_versioning.warn,
 
1293
        not other callers that go direct to the warning module.  To catch
 
1294
        general warnings, use callCatchWarnings.
 
1295
 
714
1296
        :param expected: a list of the deprecation warnings expected, in order
715
1297
        :param callable: The callable to call
716
1298
        :param args: The positional arguments for the callable
717
1299
        :param kwargs: The keyword arguments for the callable
718
1300
        """
719
 
        call_warnings, result = self._capture_warnings(callable,
 
1301
        call_warnings, result = self._capture_deprecation_warnings(callable,
720
1302
            *args, **kwargs)
721
1303
        self.assertEqual(expected, call_warnings)
722
1304
        return result
728
1310
        """
729
1311
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
730
1312
        self._log_file = os.fdopen(fileno, 'w+')
731
 
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
 
1313
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
732
1314
        self._log_file_name = name
733
1315
        self.addCleanup(self._finishLogFile)
734
1316
 
739
1321
        """
740
1322
        if self._log_file is None:
741
1323
            return
742
 
        bzrlib.trace.disable_test_log(self._log_nonce)
 
1324
        bzrlib.trace.pop_log_file(self._log_memento)
743
1325
        self._log_file.close()
744
1326
        self._log_file = None
745
1327
        if not self._keep_log_file:
750
1332
        """Make the logfile not be deleted when _finishLogFile is called."""
751
1333
        self._keep_log_file = True
752
1334
 
753
 
    def addCleanup(self, callable):
 
1335
    def thisFailsStrictLockCheck(self):
 
1336
        """It is known that this test would fail with -Dstrict_locks.
 
1337
 
 
1338
        By default, all tests are run with strict lock checking unless
 
1339
        -Edisable_lock_checks is supplied. However there are some tests which
 
1340
        we know fail strict locks at this point that have not been fixed.
 
1341
        They should call this function to disable the strict checking.
 
1342
 
 
1343
        This should be used sparingly, it is much better to fix the locking
 
1344
        issues rather than papering over the problem by calling this function.
 
1345
        """
 
1346
        debug.debug_flags.discard('strict_locks')
 
1347
 
 
1348
    def addCleanup(self, callable, *args, **kwargs):
754
1349
        """Arrange to run a callable when this case is torn down.
755
1350
 
756
 
        Callables are run in the reverse of the order they are registered, 
 
1351
        Callables are run in the reverse of the order they are registered,
757
1352
        ie last-in first-out.
758
1353
        """
759
 
        if callable in self._cleanups:
760
 
            raise ValueError("cleanup function %r already registered on %s" 
761
 
                    % (callable, self))
762
 
        self._cleanups.append(callable)
 
1354
        self._cleanups.append((callable, args, kwargs))
763
1355
 
764
1356
    def _cleanEnvironment(self):
765
1357
        new_env = {
766
1358
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
767
1359
            'HOME': os.getcwd(),
768
 
            'APPDATA': os.getcwd(),
 
1360
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
1361
            # tests do check our impls match APPDATA
 
1362
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
1363
            'VISUAL': None,
 
1364
            'EDITOR': None,
769
1365
            'BZR_EMAIL': None,
770
1366
            'BZREMAIL': None, # may still be present in the environment
771
1367
            'EMAIL': None,
772
1368
            'BZR_PROGRESS_BAR': None,
 
1369
            'BZR_LOG': None,
 
1370
            'BZR_PLUGIN_PATH': None,
 
1371
            # Make sure that any text ui tests are consistent regardless of
 
1372
            # the environment the test case is run in; you may want tests that
 
1373
            # test other combinations.  'dumb' is a reasonable guess for tests
 
1374
            # going to a pipe or a StringIO.
 
1375
            'TERM': 'dumb',
 
1376
            'LINES': '25',
 
1377
            'COLUMNS': '80',
 
1378
            # SSH Agent
 
1379
            'SSH_AUTH_SOCK': None,
 
1380
            # Proxies
 
1381
            'http_proxy': None,
 
1382
            'HTTP_PROXY': None,
 
1383
            'https_proxy': None,
 
1384
            'HTTPS_PROXY': None,
 
1385
            'no_proxy': None,
 
1386
            'NO_PROXY': None,
 
1387
            'all_proxy': None,
 
1388
            'ALL_PROXY': None,
 
1389
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
1390
            # least. If you do (care), please update this comment
 
1391
            # -- vila 20080401
 
1392
            'ftp_proxy': None,
 
1393
            'FTP_PROXY': None,
 
1394
            'BZR_REMOTE_PATH': None,
773
1395
        }
774
1396
        self.__old_env = {}
775
1397
        self.addCleanup(self._restoreEnvironment)
780
1402
        """Set an environment variable, and reset it when finished."""
781
1403
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
782
1404
 
 
1405
    def _restore_debug_flags(self):
 
1406
        debug.debug_flags.clear()
 
1407
        debug.debug_flags.update(self._preserved_debug_flags)
 
1408
 
783
1409
    def _restoreEnvironment(self):
784
1410
        for name, value in self.__old_env.iteritems():
785
1411
            osutils.set_or_unset_env(name, value)
786
1412
 
 
1413
    def _restoreHooks(self):
 
1414
        for klass, (name, hooks) in self._preserved_hooks.items():
 
1415
            setattr(klass, name, hooks)
 
1416
 
 
1417
    def knownFailure(self, reason):
 
1418
        """This test has failed for some known reason."""
 
1419
        raise KnownFailure(reason)
 
1420
 
 
1421
    def _do_skip(self, result, reason):
 
1422
        addSkip = getattr(result, 'addSkip', None)
 
1423
        if not callable(addSkip):
 
1424
            result.addError(self, sys.exc_info())
 
1425
        else:
 
1426
            addSkip(self, reason)
 
1427
 
 
1428
    def run(self, result=None):
 
1429
        if result is None: result = self.defaultTestResult()
 
1430
        for feature in getattr(self, '_test_needs_features', []):
 
1431
            if not feature.available():
 
1432
                result.startTest(self)
 
1433
                if getattr(result, 'addNotSupported', None):
 
1434
                    result.addNotSupported(self, feature)
 
1435
                else:
 
1436
                    result.addSuccess(self)
 
1437
                result.stopTest(self)
 
1438
                return result
 
1439
        try:
 
1440
            try:
 
1441
                result.startTest(self)
 
1442
                absent_attr = object()
 
1443
                # Python 2.5
 
1444
                method_name = getattr(self, '_testMethodName', absent_attr)
 
1445
                if method_name is absent_attr:
 
1446
                    # Python 2.4
 
1447
                    method_name = getattr(self, '_TestCase__testMethodName')
 
1448
                testMethod = getattr(self, method_name)
 
1449
                try:
 
1450
                    try:
 
1451
                        self.setUp()
 
1452
                        if not self._bzr_test_setUp_run:
 
1453
                            self.fail(
 
1454
                                "test setUp did not invoke "
 
1455
                                "bzrlib.tests.TestCase's setUp")
 
1456
                    except KeyboardInterrupt:
 
1457
                        self._runCleanups()
 
1458
                        raise
 
1459
                    except TestSkipped, e:
 
1460
                        self._do_skip(result, e.args[0])
 
1461
                        self.tearDown()
 
1462
                        return result
 
1463
                    except:
 
1464
                        result.addError(self, sys.exc_info())
 
1465
                        self._runCleanups()
 
1466
                        return result
 
1467
 
 
1468
                    ok = False
 
1469
                    try:
 
1470
                        testMethod()
 
1471
                        ok = True
 
1472
                    except self.failureException:
 
1473
                        result.addFailure(self, sys.exc_info())
 
1474
                    except TestSkipped, e:
 
1475
                        if not e.args:
 
1476
                            reason = "No reason given."
 
1477
                        else:
 
1478
                            reason = e.args[0]
 
1479
                        self._do_skip(result, reason)
 
1480
                    except KeyboardInterrupt:
 
1481
                        self._runCleanups()
 
1482
                        raise
 
1483
                    except:
 
1484
                        result.addError(self, sys.exc_info())
 
1485
 
 
1486
                    try:
 
1487
                        self.tearDown()
 
1488
                        if not self._bzr_test_tearDown_run:
 
1489
                            self.fail(
 
1490
                                "test tearDown did not invoke "
 
1491
                                "bzrlib.tests.TestCase's tearDown")
 
1492
                    except KeyboardInterrupt:
 
1493
                        self._runCleanups()
 
1494
                        raise
 
1495
                    except:
 
1496
                        result.addError(self, sys.exc_info())
 
1497
                        self._runCleanups()
 
1498
                        ok = False
 
1499
                    if ok: result.addSuccess(self)
 
1500
                finally:
 
1501
                    result.stopTest(self)
 
1502
                return result
 
1503
            except TestNotApplicable:
 
1504
                # Not moved from the result [yet].
 
1505
                self._runCleanups()
 
1506
                raise
 
1507
            except KeyboardInterrupt:
 
1508
                self._runCleanups()
 
1509
                raise
 
1510
        finally:
 
1511
            saved_attrs = {}
 
1512
            for attr_name in self.attrs_to_keep:
 
1513
                if attr_name in self.__dict__:
 
1514
                    saved_attrs[attr_name] = self.__dict__[attr_name]
 
1515
            self.__dict__ = saved_attrs
 
1516
 
787
1517
    def tearDown(self):
788
1518
        self._runCleanups()
 
1519
        self._log_contents = ''
 
1520
        self._bzr_test_tearDown_run = True
789
1521
        unittest.TestCase.tearDown(self)
790
1522
 
791
1523
    def time(self, callable, *args, **kwargs):
792
1524
        """Run callable and accrue the time it takes to the benchmark time.
793
 
        
 
1525
 
794
1526
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
795
1527
        this will cause lsprofile statistics to be gathered and stored in
796
1528
        self._benchcalls.
811
1543
            self._benchtime += time.time() - start
812
1544
 
813
1545
    def _runCleanups(self):
814
 
        """Run registered cleanup functions. 
 
1546
        """Run registered cleanup functions.
815
1547
 
816
1548
        This should only be called from TestCase.tearDown.
817
1549
        """
818
 
        # TODO: Perhaps this should keep running cleanups even if 
 
1550
        # TODO: Perhaps this should keep running cleanups even if
819
1551
        # one of them fails?
820
 
        for cleanup_fn in reversed(self._cleanups):
821
 
            cleanup_fn()
 
1552
 
 
1553
        # Actually pop the cleanups from the list so tearDown running
 
1554
        # twice is safe (this happens for skipped tests).
 
1555
        while self._cleanups:
 
1556
            cleanup, args, kwargs = self._cleanups.pop()
 
1557
            cleanup(*args, **kwargs)
822
1558
 
823
1559
    def log(self, *args):
824
1560
        mutter(*args)
825
1561
 
826
1562
    def _get_log(self, keep_log_file=False):
827
 
        """Return as a string the log for this test. If the file is still
828
 
        on disk and keep_log_file=False, delete the log file and store the
829
 
        content in self._log_contents."""
 
1563
        """Get the log from bzrlib.trace calls from this test.
 
1564
 
 
1565
        :param keep_log_file: When True, if the log is still a file on disk
 
1566
            leave it as a file on disk. When False, if the log is still a file
 
1567
            on disk, the log file is deleted and the log preserved as
 
1568
            self._log_contents.
 
1569
        :return: A string containing the log.
 
1570
        """
830
1571
        # flush the log file, to get all content
831
1572
        import bzrlib.trace
832
 
        bzrlib.trace._trace_file.flush()
 
1573
        if bzrlib.trace._trace_file:
 
1574
            bzrlib.trace._trace_file.flush()
833
1575
        if self._log_contents:
 
1576
            # XXX: this can hardly contain the content flushed above --vila
 
1577
            # 20080128
834
1578
            return self._log_contents
835
1579
        if self._log_file_name is not None:
836
1580
            logfile = open(self._log_file_name)
840
1584
                logfile.close()
841
1585
            if not keep_log_file:
842
1586
                self._log_contents = log_contents
843
 
                os.remove(self._log_file_name)
 
1587
                try:
 
1588
                    os.remove(self._log_file_name)
 
1589
                except OSError, e:
 
1590
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
 
1591
                        sys.stderr.write(('Unable to delete log file '
 
1592
                                             ' %r\n' % self._log_file_name))
 
1593
                    else:
 
1594
                        raise
844
1595
            return log_contents
845
1596
        else:
846
1597
            return "DELETED log file to reduce memory footprint"
847
1598
 
848
 
    def capture(self, cmd, retcode=0):
849
 
        """Shortcut that splits cmd into words, runs, and returns stdout"""
850
 
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
851
 
 
852
 
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
853
 
                         working_dir=None):
854
 
        """Invoke bzr and return (stdout, stderr).
855
 
 
856
 
        Useful for code that wants to check the contents of the
857
 
        output, the way error messages are presented, etc.
858
 
 
859
 
        This should be the main method for tests that want to exercise the
860
 
        overall behavior of the bzr application (rather than a unit test
861
 
        or a functional test of the library.)
862
 
 
863
 
        Much of the old code runs bzr by forking a new copy of Python, but
864
 
        that is slower, harder to debug, and generally not necessary.
865
 
 
866
 
        This runs bzr through the interface that catches and reports
867
 
        errors, and with logging set to something approximating the
868
 
        default, so that error reporting can be checked.
869
 
 
870
 
        :param argv: arguments to invoke bzr
871
 
        :param retcode: expected return code, or None for don't-care.
872
 
        :param encoding: encoding for sys.stdout and sys.stderr
873
 
        :param stdin: A string to be used as stdin for the command.
874
 
        :param working_dir: Change to this directory before running
 
1599
    def requireFeature(self, feature):
 
1600
        """This test requires a specific feature is available.
 
1601
 
 
1602
        :raises UnavailableFeature: When feature is not available.
875
1603
        """
 
1604
        if not feature.available():
 
1605
            raise UnavailableFeature(feature)
 
1606
 
 
1607
    def _run_bzr_autosplit(self, args, retcode, encoding, stdin,
 
1608
            working_dir):
 
1609
        """Run bazaar command line, splitting up a string command line."""
 
1610
        if isinstance(args, basestring):
 
1611
            # shlex don't understand unicode strings,
 
1612
            # so args should be plain string (bialix 20070906)
 
1613
            args = list(shlex.split(str(args)))
 
1614
        return self._run_bzr_core(args, retcode=retcode,
 
1615
                encoding=encoding, stdin=stdin, working_dir=working_dir,
 
1616
                )
 
1617
 
 
1618
    def _run_bzr_core(self, args, retcode, encoding, stdin,
 
1619
            working_dir):
876
1620
        if encoding is None:
877
 
            encoding = bzrlib.user_encoding
878
 
        if stdin is not None:
879
 
            stdin = StringIO(stdin)
 
1621
            encoding = osutils.get_user_encoding()
880
1622
        stdout = StringIOWrapper()
881
1623
        stderr = StringIOWrapper()
882
1624
        stdout.encoding = encoding
883
1625
        stderr.encoding = encoding
884
1626
 
885
 
        self.log('run bzr: %r', argv)
 
1627
        self.log('run bzr: %r', args)
886
1628
        # FIXME: don't call into logging here
887
1629
        handler = logging.StreamHandler(stderr)
888
1630
        handler.setLevel(logging.INFO)
889
1631
        logger = logging.getLogger('')
890
1632
        logger.addHandler(handler)
891
 
        old_ui_factory = bzrlib.ui.ui_factory
892
 
        bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
893
 
            stdout=stdout,
894
 
            stderr=stderr)
895
 
        bzrlib.ui.ui_factory.stdin = stdin
 
1633
        old_ui_factory = ui.ui_factory
 
1634
        ui.ui_factory = TestUIFactory(stdin=stdin, stdout=stdout, stderr=stderr)
896
1635
 
897
1636
        cwd = None
898
1637
        if working_dir is not None:
900
1639
            os.chdir(working_dir)
901
1640
 
902
1641
        try:
903
 
            result = self.apply_redirected(stdin, stdout, stderr,
904
 
                                           bzrlib.commands.run_bzr_catch_errors,
905
 
                                           argv)
 
1642
            result = self.apply_redirected(ui.ui_factory.stdin,
 
1643
                stdout, stderr,
 
1644
                bzrlib.commands.run_bzr_catch_user_errors,
 
1645
                args)
906
1646
        finally:
907
1647
            logger.removeHandler(handler)
908
 
            bzrlib.ui.ui_factory = old_ui_factory
 
1648
            ui.ui_factory = old_ui_factory
909
1649
            if cwd is not None:
910
1650
                os.chdir(cwd)
911
1651
 
916
1656
        if err:
917
1657
            self.log('errors:\n%r', err)
918
1658
        if retcode is not None:
919
 
            self.assertEquals(retcode, result)
 
1659
            self.assertEquals(retcode, result,
 
1660
                              message='Unexpected return code')
920
1661
        return out, err
921
1662
 
922
 
    def run_bzr(self, *args, **kwargs):
 
1663
    def run_bzr(self, args, retcode=0, encoding=None, stdin=None,
 
1664
                working_dir=None, error_regexes=[], output_encoding=None):
923
1665
        """Invoke bzr, as if it were run from the command line.
924
1666
 
 
1667
        The argument list should not include the bzr program name - the
 
1668
        first argument is normally the bzr command.  Arguments may be
 
1669
        passed in three ways:
 
1670
 
 
1671
        1- A list of strings, eg ["commit", "a"].  This is recommended
 
1672
        when the command contains whitespace or metacharacters, or
 
1673
        is built up at run time.
 
1674
 
 
1675
        2- A single string, eg "add a".  This is the most convenient
 
1676
        for hardcoded commands.
 
1677
 
 
1678
        This runs bzr through the interface that catches and reports
 
1679
        errors, and with logging set to something approximating the
 
1680
        default, so that error reporting can be checked.
 
1681
 
925
1682
        This should be the main method for tests that want to exercise the
926
1683
        overall behavior of the bzr application (rather than a unit test
927
1684
        or a functional test of the library.)
929
1686
        This sends the stdout/stderr results into the test's log,
930
1687
        where it may be useful for debugging.  See also run_captured.
931
1688
 
932
 
        :param stdin: A string to be used as stdin for the command.
 
1689
        :keyword stdin: A string to be used as stdin for the command.
 
1690
        :keyword retcode: The status code the command should return;
 
1691
            default 0.
 
1692
        :keyword working_dir: The directory to run the command in
 
1693
        :keyword error_regexes: A list of expected error messages.  If
 
1694
            specified they must be seen in the error output of the command.
933
1695
        """
934
 
        retcode = kwargs.pop('retcode', 0)
935
 
        encoding = kwargs.pop('encoding', None)
936
 
        stdin = kwargs.pop('stdin', None)
937
 
        working_dir = kwargs.pop('working_dir', None)
938
 
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
939
 
                                     stdin=stdin, working_dir=working_dir)
940
 
 
941
 
    def run_bzr_decode(self, *args, **kwargs):
942
 
        if 'encoding' in kwargs:
943
 
            encoding = kwargs['encoding']
944
 
        else:
945
 
            encoding = bzrlib.user_encoding
946
 
        return self.run_bzr(*args, **kwargs)[0].decode(encoding)
 
1696
        out, err = self._run_bzr_autosplit(
 
1697
            args=args,
 
1698
            retcode=retcode,
 
1699
            encoding=encoding,
 
1700
            stdin=stdin,
 
1701
            working_dir=working_dir,
 
1702
            )
 
1703
        self.assertIsInstance(error_regexes, (list, tuple))
 
1704
        for regex in error_regexes:
 
1705
            self.assertContainsRe(err, regex)
 
1706
        return out, err
947
1707
 
948
1708
    def run_bzr_error(self, error_regexes, *args, **kwargs):
949
1709
        """Run bzr, and check that stderr contains the supplied regexes
950
 
        
951
 
        :param error_regexes: Sequence of regular expressions which 
 
1710
 
 
1711
        :param error_regexes: Sequence of regular expressions which
952
1712
            must each be found in the error output. The relative ordering
953
1713
            is not enforced.
954
1714
        :param args: command-line arguments for bzr
955
1715
        :param kwargs: Keyword arguments which are interpreted by run_bzr
956
1716
            This function changes the default value of retcode to be 3,
957
1717
            since in most cases this is run when you expect bzr to fail.
958
 
        :return: (out, err) The actual output of running the command (in case you
959
 
                 want to do more inspection)
960
 
 
961
 
        Examples of use:
 
1718
 
 
1719
        :return: (out, err) The actual output of running the command (in case
 
1720
            you want to do more inspection)
 
1721
 
 
1722
        Examples of use::
 
1723
 
962
1724
            # Make sure that commit is failing because there is nothing to do
963
1725
            self.run_bzr_error(['no changes to commit'],
964
 
                               'commit', '-m', 'my commit comment')
 
1726
                               ['commit', '-m', 'my commit comment'])
965
1727
            # Make sure --strict is handling an unknown file, rather than
966
1728
            # giving us the 'nothing to do' error
967
1729
            self.build_tree(['unknown'])
968
1730
            self.run_bzr_error(['Commit refused because there are unknown files'],
969
 
                               'commit', '--strict', '-m', 'my commit comment')
 
1731
                               ['commit', --strict', '-m', 'my commit comment'])
970
1732
        """
971
1733
        kwargs.setdefault('retcode', 3)
 
1734
        kwargs['error_regexes'] = error_regexes
972
1735
        out, err = self.run_bzr(*args, **kwargs)
973
 
        for regex in error_regexes:
974
 
            self.assertContainsRe(err, regex)
975
1736
        return out, err
976
1737
 
977
1738
    def run_bzr_subprocess(self, *args, **kwargs):
978
1739
        """Run bzr in a subprocess for testing.
979
1740
 
980
 
        This starts a new Python interpreter and runs bzr in there. 
 
1741
        This starts a new Python interpreter and runs bzr in there.
981
1742
        This should only be used for tests that have a justifiable need for
982
1743
        this isolation: e.g. they are testing startup time, or signal
983
 
        handling, or early startup code, etc.  Subprocess code can't be 
 
1744
        handling, or early startup code, etc.  Subprocess code can't be
984
1745
        profiled or debugged so easily.
985
1746
 
986
 
        :param retcode: The status code that is expected.  Defaults to 0.  If
 
1747
        :keyword retcode: The status code that is expected.  Defaults to 0.  If
987
1748
            None is supplied, the status code is not checked.
988
 
        :param env_changes: A dictionary which lists changes to environment
 
1749
        :keyword env_changes: A dictionary which lists changes to environment
989
1750
            variables. A value of None will unset the env variable.
990
1751
            The values must be strings. The change will only occur in the
991
1752
            child, so you don't need to fix the environment after running.
992
 
        :param universal_newlines: Convert CRLF => LF
993
 
        :param allow_plugins: By default the subprocess is run with
 
1753
        :keyword universal_newlines: Convert CRLF => LF
 
1754
        :keyword allow_plugins: By default the subprocess is run with
994
1755
            --no-plugins to ensure test reproducibility. Also, it is possible
995
1756
            for system-wide plugins to create unexpected output on stderr,
996
1757
            which can cause unnecessary test failures.
998
1759
        env_changes = kwargs.get('env_changes', {})
999
1760
        working_dir = kwargs.get('working_dir', None)
1000
1761
        allow_plugins = kwargs.get('allow_plugins', False)
 
1762
        if len(args) == 1:
 
1763
            if isinstance(args[0], list):
 
1764
                args = args[0]
 
1765
            elif isinstance(args[0], basestring):
 
1766
                args = list(shlex.split(args[0]))
 
1767
        else:
 
1768
            raise ValueError("passing varargs to run_bzr_subprocess")
1001
1769
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
1002
1770
                                            working_dir=working_dir,
1003
1771
                                            allow_plugins=allow_plugins)
1020
1788
        profiled or debugged so easily.
1021
1789
 
1022
1790
        :param process_args: a list of arguments to pass to the bzr executable,
1023
 
            for example `['--version']`.
 
1791
            for example ``['--version']``.
1024
1792
        :param env_changes: A dictionary which lists changes to environment
1025
1793
            variables. A value of None will unset the env variable.
1026
1794
            The values must be strings. The change will only occur in the
1059
1827
            # so we will avoid using it on all platforms, just to
1060
1828
            # make sure the code path is used, and we don't break on win32
1061
1829
            cleanup_environment()
1062
 
            command = [sys.executable, bzr_path]
 
1830
            command = [sys.executable]
 
1831
            # frozen executables don't need the path to bzr
 
1832
            if getattr(sys, "frozen", None) is None:
 
1833
                command.append(bzr_path)
1063
1834
            if not allow_plugins:
1064
1835
                command.append('--no-plugins')
1065
1836
            command.extend(process_args)
1124
1895
        shape = list(shape)             # copy
1125
1896
        for path, ie in inv.entries():
1126
1897
            name = path.replace('\\', '/')
1127
 
            if ie.kind == 'dir':
 
1898
            if ie.kind == 'directory':
1128
1899
                name = name + '/'
1129
1900
            if name in shape:
1130
1901
                shape.remove(name)
1167
1938
            sys.stderr = real_stderr
1168
1939
            sys.stdin = real_stdin
1169
1940
 
1170
 
    @symbol_versioning.deprecated_method(symbol_versioning.zero_eleven)
1171
 
    def merge(self, branch_from, wt_to):
1172
 
        """A helper for tests to do a ui-less merge.
1173
 
 
1174
 
        This should move to the main library when someone has time to integrate
1175
 
        it in.
1176
 
        """
1177
 
        # minimal ui-less merge.
1178
 
        wt_to.branch.fetch(branch_from)
1179
 
        base_rev = common_ancestor(branch_from.last_revision(),
1180
 
                                   wt_to.branch.last_revision(),
1181
 
                                   wt_to.branch.repository)
1182
 
        merge_inner(wt_to.branch, branch_from.basis_tree(),
1183
 
                    wt_to.branch.repository.revision_tree(base_rev),
1184
 
                    this_tree=wt_to)
1185
 
        wt_to.add_parent_tree_id(branch_from.last_revision())
1186
 
 
1187
 
 
1188
 
BzrTestBase = TestCase
 
1941
    def reduceLockdirTimeout(self):
 
1942
        """Reduce the default lock timeout for the duration of the test, so that
 
1943
        if LockContention occurs during a test, it does so quickly.
 
1944
 
 
1945
        Tests that expect to provoke LockContention errors should call this.
 
1946
        """
 
1947
        orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
 
1948
        def resetTimeout():
 
1949
            bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
 
1950
        self.addCleanup(resetTimeout)
 
1951
        bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
 
1952
 
 
1953
    def make_utf8_encoded_stringio(self, encoding_type=None):
 
1954
        """Return a StringIOWrapper instance, that will encode Unicode
 
1955
        input to UTF-8.
 
1956
        """
 
1957
        if encoding_type is None:
 
1958
            encoding_type = 'strict'
 
1959
        sio = StringIO()
 
1960
        output_encoding = 'utf-8'
 
1961
        sio = codecs.getwriter(output_encoding)(sio, errors=encoding_type)
 
1962
        sio.encoding = output_encoding
 
1963
        return sio
 
1964
 
 
1965
    def disable_verb(self, verb):
 
1966
        """Disable a smart server verb for one test."""
 
1967
        from bzrlib.smart import request
 
1968
        request_handlers = request.request_handlers
 
1969
        orig_method = request_handlers.get(verb)
 
1970
        request_handlers.remove(verb)
 
1971
        def restoreVerb():
 
1972
            request_handlers.register(verb, orig_method)
 
1973
        self.addCleanup(restoreVerb)
 
1974
 
 
1975
 
 
1976
class CapturedCall(object):
 
1977
    """A helper for capturing smart server calls for easy debug analysis."""
 
1978
 
 
1979
    def __init__(self, params, prefix_length):
 
1980
        """Capture the call with params and skip prefix_length stack frames."""
 
1981
        self.call = params
 
1982
        import traceback
 
1983
        # The last 5 frames are the __init__, the hook frame, and 3 smart
 
1984
        # client frames. Beyond this we could get more clever, but this is good
 
1985
        # enough for now.
 
1986
        stack = traceback.extract_stack()[prefix_length:-5]
 
1987
        self.stack = ''.join(traceback.format_list(stack))
 
1988
 
 
1989
    def __str__(self):
 
1990
        return self.call.method
 
1991
 
 
1992
    def __repr__(self):
 
1993
        return self.call.method
 
1994
 
 
1995
    def stack(self):
 
1996
        return self.stack
1189
1997
 
1190
1998
 
1191
1999
class TestCaseWithMemoryTransport(TestCase):
1202
2010
    file defaults for the transport in tests, nor does it obey the command line
1203
2011
    override, so tests that accidentally write to the common directory should
1204
2012
    be rare.
 
2013
 
 
2014
    :cvar TEST_ROOT: Directory containing all temporary directories, plus
 
2015
    a .bzr directory that stops us ascending higher into the filesystem.
1205
2016
    """
1206
2017
 
1207
2018
    TEST_ROOT = None
1208
2019
    _TEST_NAME = 'test'
1209
2020
 
1210
 
 
1211
2021
    def __init__(self, methodName='runTest'):
1212
 
        # allow test parameterisation after test construction and before test
1213
 
        # execution. Variables that the parameteriser sets need to be 
 
2022
        # allow test parameterization after test construction and before test
 
2023
        # execution. Variables that the parameterizer sets need to be
1214
2024
        # ones that are not set by setUp, or setUp will trash them.
1215
2025
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
1216
 
        self.transport_server = default_transport
 
2026
        self.vfs_transport_factory = default_transport
 
2027
        self.transport_server = None
1217
2028
        self.transport_readonly_server = None
1218
 
 
1219
 
    def failUnlessExists(self, path):
1220
 
        """Fail unless path, which may be abs or relative, exists."""
1221
 
        self.failUnless(osutils.lexists(path))
1222
 
 
1223
 
    def failIfExists(self, path):
1224
 
        """Fail if path, which may be abs or relative, exists."""
1225
 
        self.failIf(osutils.lexists(path))
1226
 
        
1227
 
    def get_transport(self):
1228
 
        """Return a writeable transport for the test scratch space"""
1229
 
        t = get_transport(self.get_url())
 
2029
        self.__vfs_server = None
 
2030
 
 
2031
    def get_transport(self, relpath=None):
 
2032
        """Return a writeable transport.
 
2033
 
 
2034
        This transport is for the test scratch space relative to
 
2035
        "self._test_root"
 
2036
 
 
2037
        :param relpath: a path relative to the base url.
 
2038
        """
 
2039
        t = get_transport(self.get_url(relpath))
1230
2040
        self.assertFalse(t.is_readonly())
1231
2041
        return t
1232
2042
 
1233
 
    def get_readonly_transport(self):
 
2043
    def get_readonly_transport(self, relpath=None):
1234
2044
        """Return a readonly transport for the test scratch space
1235
 
        
 
2045
 
1236
2046
        This can be used to test that operations which should only need
1237
2047
        readonly access in fact do not try to write.
 
2048
 
 
2049
        :param relpath: a path relative to the base url.
1238
2050
        """
1239
 
        t = get_transport(self.get_readonly_url())
 
2051
        t = get_transport(self.get_readonly_url(relpath))
1240
2052
        self.assertTrue(t.is_readonly())
1241
2053
        return t
1242
2054
 
 
2055
    def create_transport_readonly_server(self):
 
2056
        """Create a transport server from class defined at init.
 
2057
 
 
2058
        This is mostly a hook for daughter classes.
 
2059
        """
 
2060
        return self.transport_readonly_server()
 
2061
 
1243
2062
    def get_readonly_server(self):
1244
2063
        """Get the server instance for the readonly transport
1245
2064
 
1249
2068
            if self.transport_readonly_server is None:
1250
2069
                # readonly decorator requested
1251
2070
                # bring up the server
1252
 
                self.get_url()
1253
2071
                self.__readonly_server = ReadonlyServer()
1254
 
                self.__readonly_server.setUp(self.__server)
 
2072
                self.__readonly_server.setUp(self.get_vfs_only_server())
1255
2073
            else:
1256
 
                self.__readonly_server = self.transport_readonly_server()
1257
 
                self.__readonly_server.setUp()
 
2074
                self.__readonly_server = self.create_transport_readonly_server()
 
2075
                self.__readonly_server.setUp(self.get_vfs_only_server())
1258
2076
            self.addCleanup(self.__readonly_server.tearDown)
1259
2077
        return self.__readonly_server
1260
2078
 
1261
2079
    def get_readonly_url(self, relpath=None):
1262
2080
        """Get a URL for the readonly transport.
1263
2081
 
1264
 
        This will either be backed by '.' or a decorator to the transport 
 
2082
        This will either be backed by '.' or a decorator to the transport
1265
2083
        used by self.get_url()
1266
2084
        relpath provides for clients to get a path relative to the base url.
1267
2085
        These should only be downwards relative, not upwards.
1268
2086
        """
1269
2087
        base = self.get_readonly_server().get_url()
1270
 
        if relpath is not None:
1271
 
            if not base.endswith('/'):
1272
 
                base = base + '/'
1273
 
            base = base + relpath
1274
 
        return base
 
2088
        return self._adjust_url(base, relpath)
1275
2089
 
1276
 
    def get_server(self):
1277
 
        """Get the read/write server instance.
 
2090
    def get_vfs_only_server(self):
 
2091
        """Get the vfs only read/write server instance.
1278
2092
 
1279
2093
        This is useful for some tests with specific servers that need
1280
2094
        diagnostics.
1282
2096
        For TestCaseWithMemoryTransport this is always a MemoryServer, and there
1283
2097
        is no means to override it.
1284
2098
        """
 
2099
        if self.__vfs_server is None:
 
2100
            self.__vfs_server = MemoryServer()
 
2101
            self.__vfs_server.setUp()
 
2102
            self.addCleanup(self.__vfs_server.tearDown)
 
2103
        return self.__vfs_server
 
2104
 
 
2105
    def get_server(self):
 
2106
        """Get the read/write server instance.
 
2107
 
 
2108
        This is useful for some tests with specific servers that need
 
2109
        diagnostics.
 
2110
 
 
2111
        This is built from the self.transport_server factory. If that is None,
 
2112
        then the self.get_vfs_server is returned.
 
2113
        """
1285
2114
        if self.__server is None:
1286
 
            self.__server = MemoryServer()
1287
 
            self.__server.setUp()
 
2115
            if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
 
2116
                return self.get_vfs_only_server()
 
2117
            else:
 
2118
                # bring up a decorated means of access to the vfs only server.
 
2119
                self.__server = self.transport_server()
 
2120
                try:
 
2121
                    self.__server.setUp(self.get_vfs_only_server())
 
2122
                except TypeError, e:
 
2123
                    # This should never happen; the try:Except here is to assist
 
2124
                    # developers having to update code rather than seeing an
 
2125
                    # uninformative TypeError.
 
2126
                    raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
1288
2127
            self.addCleanup(self.__server.tearDown)
1289
2128
        return self.__server
1290
2129
 
1291
 
    def get_url(self, relpath=None):
 
2130
    def _adjust_url(self, base, relpath):
1292
2131
        """Get a URL (or maybe a path) for the readwrite transport.
1293
2132
 
1294
2133
        This will either be backed by '.' or to an equivalent non-file based
1296
2135
        relpath provides for clients to get a path relative to the base url.
1297
2136
        These should only be downwards relative, not upwards.
1298
2137
        """
1299
 
        base = self.get_server().get_url()
1300
2138
        if relpath is not None and relpath != '.':
1301
2139
            if not base.endswith('/'):
1302
2140
                base = base + '/'
1310
2148
                base += urlutils.escape(relpath)
1311
2149
        return base
1312
2150
 
 
2151
    def get_url(self, relpath=None):
 
2152
        """Get a URL (or maybe a path) for the readwrite transport.
 
2153
 
 
2154
        This will either be backed by '.' or to an equivalent non-file based
 
2155
        facility.
 
2156
        relpath provides for clients to get a path relative to the base url.
 
2157
        These should only be downwards relative, not upwards.
 
2158
        """
 
2159
        base = self.get_server().get_url()
 
2160
        return self._adjust_url(base, relpath)
 
2161
 
 
2162
    def get_vfs_only_url(self, relpath=None):
 
2163
        """Get a URL (or maybe a path for the plain old vfs transport.
 
2164
 
 
2165
        This will never be a smart protocol.  It always has all the
 
2166
        capabilities of the local filesystem, but it might actually be a
 
2167
        MemoryTransport or some other similar virtual filesystem.
 
2168
 
 
2169
        This is the backing transport (if any) of the server returned by
 
2170
        get_url and get_readonly_url.
 
2171
 
 
2172
        :param relpath: provides for clients to get a path relative to the base
 
2173
            url.  These should only be downwards relative, not upwards.
 
2174
        :return: A URL
 
2175
        """
 
2176
        base = self.get_vfs_only_server().get_url()
 
2177
        return self._adjust_url(base, relpath)
 
2178
 
 
2179
    def _create_safety_net(self):
 
2180
        """Make a fake bzr directory.
 
2181
 
 
2182
        This prevents any tests propagating up onto the TEST_ROOT directory's
 
2183
        real branch.
 
2184
        """
 
2185
        root = TestCaseWithMemoryTransport.TEST_ROOT
 
2186
        bzrdir.BzrDir.create_standalone_workingtree(root)
 
2187
 
 
2188
    def _check_safety_net(self):
 
2189
        """Check that the safety .bzr directory have not been touched.
 
2190
 
 
2191
        _make_test_root have created a .bzr directory to prevent tests from
 
2192
        propagating. This method ensures than a test did not leaked.
 
2193
        """
 
2194
        root = TestCaseWithMemoryTransport.TEST_ROOT
 
2195
        wt = workingtree.WorkingTree.open(root)
 
2196
        last_rev = wt.last_revision()
 
2197
        if last_rev != 'null:':
 
2198
            # The current test have modified the /bzr directory, we need to
 
2199
            # recreate a new one or all the followng tests will fail.
 
2200
            # If you need to inspect its content uncomment the following line
 
2201
            # import pdb; pdb.set_trace()
 
2202
            _rmtree_temp_dir(root + '/.bzr')
 
2203
            self._create_safety_net()
 
2204
            raise AssertionError('%s/.bzr should not be modified' % root)
 
2205
 
1313
2206
    def _make_test_root(self):
1314
 
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1315
 
            return
1316
 
        i = 0
1317
 
        while True:
1318
 
            root = u'test%04d.tmp' % i
1319
 
            try:
1320
 
                os.mkdir(root)
1321
 
            except OSError, e:
1322
 
                if e.errno == errno.EEXIST:
1323
 
                    i += 1
1324
 
                    continue
1325
 
                else:
1326
 
                    raise
1327
 
            # successfully created
1328
 
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
1329
 
            break
1330
 
        # make a fake bzr directory there to prevent any tests propagating
1331
 
        # up onto the source directory's real branch
1332
 
        bzrdir.BzrDir.create_standalone_workingtree(
1333
 
            TestCaseWithMemoryTransport.TEST_ROOT)
 
2207
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
 
2208
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
 
2209
            TestCaseWithMemoryTransport.TEST_ROOT = root
 
2210
 
 
2211
            self._create_safety_net()
 
2212
 
 
2213
            # The same directory is used by all tests, and we're not
 
2214
            # specifically told when all tests are finished.  This will do.
 
2215
            atexit.register(_rmtree_temp_dir, root)
 
2216
 
 
2217
        self.addCleanup(self._check_safety_net)
1334
2218
 
1335
2219
    def makeAndChdirToTestDir(self):
1336
2220
        """Create a temporary directories for this one test.
1337
 
        
 
2221
 
1338
2222
        This must set self.test_home_dir and self.test_dir and chdir to
1339
2223
        self.test_dir.
1340
 
        
 
2224
 
1341
2225
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1342
2226
        """
1343
2227
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1344
2228
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1345
2229
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1346
 
        
 
2230
 
1347
2231
    def make_branch(self, relpath, format=None):
1348
2232
        """Create a branch on the transport at relpath."""
1349
2233
        repo = self.make_repository(relpath, format=format)
1356
2240
            segments = maybe_a_url.rsplit('/', 1)
1357
2241
            t = get_transport(maybe_a_url)
1358
2242
            if len(segments) > 1 and segments[-1] not in ('', '.'):
1359
 
                try:
1360
 
                    t.mkdir('.')
1361
 
                except errors.FileExists:
1362
 
                    pass
 
2243
                t.ensure_base()
1363
2244
            if format is None:
1364
 
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
2245
                format = 'default'
 
2246
            if isinstance(format, basestring):
 
2247
                format = bzrdir.format_registry.make_bzrdir(format)
1365
2248
            return format.initialize_on_transport(t)
1366
2249
        except errors.UninitializableFormat:
1367
2250
            raise TestSkipped("Format %s is not initializable." % format)
1368
2251
 
1369
2252
    def make_repository(self, relpath, shared=False, format=None):
1370
 
        """Create a repository on our default transport at relpath."""
 
2253
        """Create a repository on our default transport at relpath.
 
2254
 
 
2255
        Note that relpath must be a relative path, not a full url.
 
2256
        """
 
2257
        # FIXME: If you create a remoterepository this returns the underlying
 
2258
        # real format, which is incorrect.  Actually we should make sure that
 
2259
        # RemoteBzrDir returns a RemoteRepository.
 
2260
        # maybe  mbp 20070410
1371
2261
        made_control = self.make_bzrdir(relpath, format=format)
1372
2262
        return made_control.create_repository(shared=shared)
1373
2263
 
 
2264
    def make_smart_server(self, path):
 
2265
        smart_server = server.SmartTCPServer_for_testing()
 
2266
        smart_server.setUp(self.get_server())
 
2267
        remote_transport = get_transport(smart_server.get_url()).clone(path)
 
2268
        self.addCleanup(smart_server.tearDown)
 
2269
        return remote_transport
 
2270
 
1374
2271
    def make_branch_and_memory_tree(self, relpath, format=None):
1375
2272
        """Create a branch on the default transport and a MemoryTree for it."""
1376
2273
        b = self.make_branch(relpath, format=format)
1377
2274
        return memorytree.MemoryTree.create_on_branch(b)
1378
2275
 
 
2276
    def make_branch_builder(self, relpath, format=None):
 
2277
        branch = self.make_branch(relpath, format=format)
 
2278
        return branchbuilder.BranchBuilder(branch=branch)
 
2279
 
1379
2280
    def overrideEnvironmentForTesting(self):
1380
2281
        os.environ['HOME'] = self.test_home_dir
1381
 
        os.environ['APPDATA'] = self.test_home_dir
1382
 
        
 
2282
        os.environ['BZR_HOME'] = self.test_home_dir
 
2283
 
1383
2284
    def setUp(self):
1384
2285
        super(TestCaseWithMemoryTransport, self).setUp()
1385
2286
        self._make_test_root()
1391
2292
        self.overrideEnvironmentForTesting()
1392
2293
        self.__readonly_server = None
1393
2294
        self.__server = None
1394
 
 
1395
 
     
 
2295
        self.reduceLockdirTimeout()
 
2296
 
 
2297
    def setup_smart_server_with_call_log(self):
 
2298
        """Sets up a smart server as the transport server with a call log."""
 
2299
        self.transport_server = server.SmartTCPServer_for_testing
 
2300
        self.hpss_calls = []
 
2301
        import traceback
 
2302
        # Skip the current stack down to the caller of
 
2303
        # setup_smart_server_with_call_log
 
2304
        prefix_length = len(traceback.extract_stack()) - 2
 
2305
        def capture_hpss_call(params):
 
2306
            self.hpss_calls.append(
 
2307
                CapturedCall(params, prefix_length))
 
2308
        client._SmartClient.hooks.install_named_hook(
 
2309
            'call', capture_hpss_call, None)
 
2310
 
 
2311
    def reset_smart_call_log(self):
 
2312
        self.hpss_calls = []
 
2313
 
 
2314
 
1396
2315
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1397
2316
    """Derived class that runs a test within a temporary directory.
1398
2317
 
1403
2322
    All test cases create their own directory within that.  If the
1404
2323
    tests complete successfully, the directory is removed.
1405
2324
 
1406
 
    InTempDir is an old alias for FunctionalTestCase.
 
2325
    :ivar test_base_dir: The path of the top-level directory for this
 
2326
    test, which contains a home directory and a work directory.
 
2327
 
 
2328
    :ivar test_home_dir: An initially empty directory under test_base_dir
 
2329
    which is used as $HOME for this test.
 
2330
 
 
2331
    :ivar test_dir: A directory under test_base_dir used as the current
 
2332
    directory when the test proper is run.
1407
2333
    """
1408
2334
 
1409
2335
    OVERRIDE_PYTHON = 'python'
1416
2342
            self.log("actually: %r" % contents)
1417
2343
            self.fail("contents of %s not as expected" % filename)
1418
2344
 
 
2345
    def _getTestDirPrefix(self):
 
2346
        # create a directory within the top level test directory
 
2347
        if sys.platform in ('win32', 'cygwin'):
 
2348
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
 
2349
            # windows is likely to have path-length limits so use a short name
 
2350
            name_prefix = name_prefix[-30:]
 
2351
        else:
 
2352
            name_prefix = re.sub('[/]', '_', self.id())
 
2353
        return name_prefix
 
2354
 
1419
2355
    def makeAndChdirToTestDir(self):
1420
2356
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
1421
 
        
 
2357
 
1422
2358
        For TestCaseInTempDir we create a temporary directory based on the test
1423
2359
        name and then create two subdirs - test and home under it.
1424
2360
        """
1425
 
        # shorten the name, to avoid test failures due to path length
1426
 
        short_id = self.id().replace('bzrlib.tests.', '') \
1427
 
                   .replace('__main__.', '')[-100:]
1428
 
        # it's possible the same test class is run several times for
1429
 
        # parameterized tests, so make sure the names don't collide.  
1430
 
        i = 0
1431
 
        while True:
1432
 
            if i > 0:
1433
 
                candidate_dir = '%s/%s.%d' % (self.TEST_ROOT, short_id, i)
1434
 
            else:
1435
 
                candidate_dir = '%s/%s' % (self.TEST_ROOT, short_id)
1436
 
            if os.path.exists(candidate_dir):
1437
 
                i = i + 1
1438
 
                continue
1439
 
            else:
1440
 
                os.mkdir(candidate_dir)
1441
 
                self.test_home_dir = candidate_dir + '/home'
1442
 
                os.mkdir(self.test_home_dir)
1443
 
                self.test_dir = candidate_dir + '/work'
1444
 
                os.mkdir(self.test_dir)
1445
 
                os.chdir(self.test_dir)
 
2361
        name_prefix = osutils.pathjoin(TestCaseWithMemoryTransport.TEST_ROOT,
 
2362
            self._getTestDirPrefix())
 
2363
        name = name_prefix
 
2364
        for i in range(100):
 
2365
            if os.path.exists(name):
 
2366
                name = name_prefix + '_' + str(i)
 
2367
            else:
 
2368
                os.mkdir(name)
1446
2369
                break
1447
 
 
1448
 
    def build_tree(self, shape, line_endings='native', transport=None):
 
2370
        # now create test and home directories within this dir
 
2371
        self.test_base_dir = name
 
2372
        self.test_home_dir = self.test_base_dir + '/home'
 
2373
        os.mkdir(self.test_home_dir)
 
2374
        self.test_dir = self.test_base_dir + '/work'
 
2375
        os.mkdir(self.test_dir)
 
2376
        os.chdir(self.test_dir)
 
2377
        # put name of test inside
 
2378
        f = file(self.test_base_dir + '/name', 'w')
 
2379
        try:
 
2380
            f.write(self.id())
 
2381
        finally:
 
2382
            f.close()
 
2383
        self.addCleanup(self.deleteTestDir)
 
2384
 
 
2385
    def deleteTestDir(self):
 
2386
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
2387
        _rmtree_temp_dir(self.test_base_dir)
 
2388
 
 
2389
    def build_tree(self, shape, line_endings='binary', transport=None):
1449
2390
        """Build a test tree according to a pattern.
1450
2391
 
1451
2392
        shape is a sequence of file specifications.  If the final
1454
2395
        This assumes that all the elements in the tree being built are new.
1455
2396
 
1456
2397
        This doesn't add anything to a branch.
 
2398
 
 
2399
        :type shape:    list or tuple.
1457
2400
        :param line_endings: Either 'binary' or 'native'
1458
 
                             in binary mode, exact contents are written
1459
 
                             in native mode, the line endings match the
1460
 
                             default platform endings.
1461
 
 
1462
 
        :param transport: A transport to write to, for building trees on 
1463
 
                          VFS's. If the transport is readonly or None,
1464
 
                          "." is opened automatically.
 
2401
            in binary mode, exact contents are written in native mode, the
 
2402
            line endings match the default platform endings.
 
2403
        :param transport: A transport to write to, for building trees on VFS's.
 
2404
            If the transport is readonly or None, "." is opened automatically.
 
2405
        :return: None
1465
2406
        """
 
2407
        if type(shape) not in (list, tuple):
 
2408
            raise AssertionError("Parameter 'shape' should be "
 
2409
                "a list or a tuple. Got %r instead" % (shape,))
1466
2410
        # It's OK to just create them using forward slashes on windows.
1467
2411
        if transport is None or transport.is_readonly():
1468
2412
            transport = get_transport(".")
1469
2413
        for name in shape:
1470
 
            self.assert_(isinstance(name, basestring))
 
2414
            self.assertIsInstance(name, basestring)
1471
2415
            if name[-1] == '/':
1472
2416
                transport.mkdir(urlutils.escape(name[:-1]))
1473
2417
            else:
1476
2420
                elif line_endings == 'native':
1477
2421
                    end = os.linesep
1478
2422
                else:
1479
 
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
 
2423
                    raise errors.BzrError(
 
2424
                        'Invalid line ending request %r' % line_endings)
1480
2425
                content = "contents of %s%s" % (name.encode('utf-8'), end)
1481
 
                # Technically 'put()' is the right command. However, put
1482
 
                # uses an AtomicFile, which requires an extra rename into place
1483
 
                # As long as the files didn't exist in the past, append() will
1484
 
                # do the same thing as put()
1485
 
                # On jam's machine, make_kernel_like_tree is:
1486
 
                #   put:    4.5-7.5s (averaging 6s)
1487
 
                #   append: 2.9-4.5s
1488
 
                #   put_non_atomic: 2.9-4.5s
1489
2426
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
1490
2427
 
1491
2428
    def build_tree_contents(self, shape):
1492
2429
        build_tree_contents(shape)
1493
2430
 
1494
 
    def assertFileEqual(self, content, path):
1495
 
        """Fail if path does not contain 'content'."""
1496
 
        self.failUnless(osutils.lexists(path))
1497
 
        # TODO: jam 20060427 Shouldn't this be 'rb'?
1498
 
        self.assertEqualDiff(content, open(path, 'r').read())
 
2431
    def assertInWorkingTree(self, path, root_path='.', tree=None):
 
2432
        """Assert whether path or paths are in the WorkingTree"""
 
2433
        if tree is None:
 
2434
            tree = workingtree.WorkingTree.open(root_path)
 
2435
        if not isinstance(path, basestring):
 
2436
            for p in path:
 
2437
                self.assertInWorkingTree(p, tree=tree)
 
2438
        else:
 
2439
            self.assertIsNot(tree.path2id(path), None,
 
2440
                path+' not in working tree.')
 
2441
 
 
2442
    def assertNotInWorkingTree(self, path, root_path='.', tree=None):
 
2443
        """Assert whether path or paths are not in the WorkingTree"""
 
2444
        if tree is None:
 
2445
            tree = workingtree.WorkingTree.open(root_path)
 
2446
        if not isinstance(path, basestring):
 
2447
            for p in path:
 
2448
                self.assertNotInWorkingTree(p,tree=tree)
 
2449
        else:
 
2450
            self.assertIs(tree.path2id(path), None, path+' in working tree.')
1499
2451
 
1500
2452
 
1501
2453
class TestCaseWithTransport(TestCaseInTempDir):
1508
2460
    ReadonlyTransportDecorator is used instead which allows the use of non disk
1509
2461
    based read write transports.
1510
2462
 
1511
 
    If an explicit class is provided for readonly access, that server and the 
 
2463
    If an explicit class is provided for readonly access, that server and the
1512
2464
    readwrite one must both define get_url() as resolving to os.getcwd().
1513
2465
    """
1514
2466
 
1515
 
    def get_server(self):
 
2467
    def get_vfs_only_server(self):
1516
2468
        """See TestCaseWithMemoryTransport.
1517
2469
 
1518
2470
        This is useful for some tests with specific servers that need
1519
2471
        diagnostics.
1520
2472
        """
1521
 
        if self.__server is None:
1522
 
            self.__server = self.transport_server()
1523
 
            self.__server.setUp()
1524
 
            self.addCleanup(self.__server.tearDown)
1525
 
        return self.__server
 
2473
        if self.__vfs_server is None:
 
2474
            self.__vfs_server = self.vfs_transport_factory()
 
2475
            self.__vfs_server.setUp()
 
2476
            self.addCleanup(self.__vfs_server.tearDown)
 
2477
        return self.__vfs_server
1526
2478
 
1527
2479
    def make_branch_and_tree(self, relpath, format=None):
1528
2480
        """Create a branch on the transport and a tree locally.
1529
2481
 
1530
2482
        If the transport is not a LocalTransport, the Tree can't be created on
1531
 
        the transport.  In that case the working tree is created in the local
1532
 
        directory, and the returned tree's branch and repository will also be
1533
 
        accessed locally.
1534
 
 
1535
 
        This will fail if the original default transport for this test
1536
 
        case wasn't backed by the working directory, as the branch won't
1537
 
        be on disk for us to open it.  
 
2483
        the transport.  In that case if the vfs_transport_factory is
 
2484
        LocalURLServer the working tree is created in the local
 
2485
        directory backing the transport, and the returned tree's branch and
 
2486
        repository will also be accessed locally. Otherwise a lightweight
 
2487
        checkout is created and returned.
1538
2488
 
1539
2489
        :param format: The BzrDirFormat.
1540
2490
        :returns: the WorkingTree.
1548
2498
            return b.bzrdir.create_workingtree()
1549
2499
        except errors.NotLocalUrl:
1550
2500
            # We can only make working trees locally at the moment.  If the
1551
 
            # transport can't support them, then reopen the branch on a local
1552
 
            # transport, and create the working tree there.  
1553
 
            #
1554
 
            # Possibly we should instead keep
1555
 
            # the non-disk-backed branch and create a local checkout?
1556
 
            bd = bzrdir.BzrDir.open(relpath)
1557
 
            return bd.create_workingtree()
 
2501
            # transport can't support them, then we keep the non-disk-backed
 
2502
            # branch and create a local checkout.
 
2503
            if self.vfs_transport_factory is LocalURLServer:
 
2504
                # the branch is colocated on disk, we cannot create a checkout.
 
2505
                # hopefully callers will expect this.
 
2506
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
 
2507
                wt = local_controldir.create_workingtree()
 
2508
                if wt.branch._format != b._format:
 
2509
                    wt._branch = b
 
2510
                    # Make sure that assigning to wt._branch fixes wt.branch,
 
2511
                    # in case the implementation details of workingtree objects
 
2512
                    # change.
 
2513
                    self.assertIs(b, wt.branch)
 
2514
                return wt
 
2515
            else:
 
2516
                return b.create_checkout(relpath, lightweight=True)
1558
2517
 
1559
2518
    def assertIsDirectory(self, relpath, transport):
1560
2519
        """Assert that relpath within transport is a directory.
1571
2530
            self.fail("path %s is not a directory; has mode %#o"
1572
2531
                      % (relpath, mode))
1573
2532
 
 
2533
    def assertTreesEqual(self, left, right):
 
2534
        """Check that left and right have the same content and properties."""
 
2535
        # we use a tree delta to check for equality of the content, and we
 
2536
        # manually check for equality of other things such as the parents list.
 
2537
        self.assertEqual(left.get_parent_ids(), right.get_parent_ids())
 
2538
        differences = left.changes_from(right)
 
2539
        self.assertFalse(differences.has_changed(),
 
2540
            "Trees %r and %r are different: %r" % (left, right, differences))
 
2541
 
1574
2542
    def setUp(self):
1575
2543
        super(TestCaseWithTransport, self).setUp()
1576
 
        self.__server = None
 
2544
        self.__vfs_server = None
1577
2545
 
1578
2546
 
1579
2547
class ChrootedTestCase(TestCaseWithTransport):
1584
2552
    for readonly urls.
1585
2553
 
1586
2554
    TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
1587
 
                       be used without needed to redo it when a different 
 
2555
                       be used without needed to redo it when a different
1588
2556
                       subclass is in use ?
1589
2557
    """
1590
2558
 
1591
2559
    def setUp(self):
1592
2560
        super(ChrootedTestCase, self).setUp()
1593
 
        if not self.transport_server == bzrlib.transport.memory.MemoryServer:
1594
 
            self.transport_readonly_server = bzrlib.transport.http.HttpServer
 
2561
        if not self.vfs_transport_factory == MemoryServer:
 
2562
            self.transport_readonly_server = HttpServer
 
2563
 
 
2564
 
 
2565
def condition_id_re(pattern):
 
2566
    """Create a condition filter which performs a re check on a test's id.
 
2567
 
 
2568
    :param pattern: A regular expression string.
 
2569
    :return: A callable that returns True if the re matches.
 
2570
    """
 
2571
    filter_re = osutils.re_compile_checked(pattern, 0,
 
2572
        'test filter')
 
2573
    def condition(test):
 
2574
        test_id = test.id()
 
2575
        return filter_re.search(test_id)
 
2576
    return condition
 
2577
 
 
2578
 
 
2579
def condition_isinstance(klass_or_klass_list):
 
2580
    """Create a condition filter which returns isinstance(param, klass).
 
2581
 
 
2582
    :return: A callable which when called with one parameter obj return the
 
2583
        result of isinstance(obj, klass_or_klass_list).
 
2584
    """
 
2585
    def condition(obj):
 
2586
        return isinstance(obj, klass_or_klass_list)
 
2587
    return condition
 
2588
 
 
2589
 
 
2590
def condition_id_in_list(id_list):
 
2591
    """Create a condition filter which verify that test's id in a list.
 
2592
 
 
2593
    :param id_list: A TestIdList object.
 
2594
    :return: A callable that returns True if the test's id appears in the list.
 
2595
    """
 
2596
    def condition(test):
 
2597
        return id_list.includes(test.id())
 
2598
    return condition
 
2599
 
 
2600
 
 
2601
def condition_id_startswith(starts):
 
2602
    """Create a condition filter verifying that test's id starts with a string.
 
2603
 
 
2604
    :param starts: A list of string.
 
2605
    :return: A callable that returns True if the test's id starts with one of
 
2606
        the given strings.
 
2607
    """
 
2608
    def condition(test):
 
2609
        for start in starts:
 
2610
            if test.id().startswith(start):
 
2611
                return True
 
2612
        return False
 
2613
    return condition
 
2614
 
 
2615
 
 
2616
def exclude_tests_by_condition(suite, condition):
 
2617
    """Create a test suite which excludes some tests from suite.
 
2618
 
 
2619
    :param suite: The suite to get tests from.
 
2620
    :param condition: A callable whose result evaluates True when called with a
 
2621
        test case which should be excluded from the result.
 
2622
    :return: A suite which contains the tests found in suite that fail
 
2623
        condition.
 
2624
    """
 
2625
    result = []
 
2626
    for test in iter_suite_tests(suite):
 
2627
        if not condition(test):
 
2628
            result.append(test)
 
2629
    return TestUtil.TestSuite(result)
 
2630
 
 
2631
 
 
2632
def filter_suite_by_condition(suite, condition):
 
2633
    """Create a test suite by filtering another one.
 
2634
 
 
2635
    :param suite: The source suite.
 
2636
    :param condition: A callable whose result evaluates True when called with a
 
2637
        test case which should be included in the result.
 
2638
    :return: A suite which contains the tests found in suite that pass
 
2639
        condition.
 
2640
    """
 
2641
    result = []
 
2642
    for test in iter_suite_tests(suite):
 
2643
        if condition(test):
 
2644
            result.append(test)
 
2645
    return TestUtil.TestSuite(result)
1595
2646
 
1596
2647
 
1597
2648
def filter_suite_by_re(suite, pattern):
1598
 
    result = TestUtil.TestSuite()
1599
 
    filter_re = re.compile(pattern)
 
2649
    """Create a test suite by filtering another one.
 
2650
 
 
2651
    :param suite:           the source suite
 
2652
    :param pattern:         pattern that names must match
 
2653
    :returns: the newly created suite
 
2654
    """
 
2655
    condition = condition_id_re(pattern)
 
2656
    result_suite = filter_suite_by_condition(suite, condition)
 
2657
    return result_suite
 
2658
 
 
2659
 
 
2660
def filter_suite_by_id_list(suite, test_id_list):
 
2661
    """Create a test suite by filtering another one.
 
2662
 
 
2663
    :param suite: The source suite.
 
2664
    :param test_id_list: A list of the test ids to keep as strings.
 
2665
    :returns: the newly created suite
 
2666
    """
 
2667
    condition = condition_id_in_list(test_id_list)
 
2668
    result_suite = filter_suite_by_condition(suite, condition)
 
2669
    return result_suite
 
2670
 
 
2671
 
 
2672
def filter_suite_by_id_startswith(suite, start):
 
2673
    """Create a test suite by filtering another one.
 
2674
 
 
2675
    :param suite: The source suite.
 
2676
    :param start: A list of string the test id must start with one of.
 
2677
    :returns: the newly created suite
 
2678
    """
 
2679
    condition = condition_id_startswith(start)
 
2680
    result_suite = filter_suite_by_condition(suite, condition)
 
2681
    return result_suite
 
2682
 
 
2683
 
 
2684
def exclude_tests_by_re(suite, pattern):
 
2685
    """Create a test suite which excludes some tests from suite.
 
2686
 
 
2687
    :param suite: The suite to get tests from.
 
2688
    :param pattern: A regular expression string. Test ids that match this
 
2689
        pattern will be excluded from the result.
 
2690
    :return: A TestSuite that contains all the tests from suite without the
 
2691
        tests that matched pattern. The order of tests is the same as it was in
 
2692
        suite.
 
2693
    """
 
2694
    return exclude_tests_by_condition(suite, condition_id_re(pattern))
 
2695
 
 
2696
 
 
2697
def preserve_input(something):
 
2698
    """A helper for performing test suite transformation chains.
 
2699
 
 
2700
    :param something: Anything you want to preserve.
 
2701
    :return: Something.
 
2702
    """
 
2703
    return something
 
2704
 
 
2705
 
 
2706
def randomize_suite(suite):
 
2707
    """Return a new TestSuite with suite's tests in random order.
 
2708
 
 
2709
    The tests in the input suite are flattened into a single suite in order to
 
2710
    accomplish this. Any nested TestSuites are removed to provide global
 
2711
    randomness.
 
2712
    """
 
2713
    tests = list(iter_suite_tests(suite))
 
2714
    random.shuffle(tests)
 
2715
    return TestUtil.TestSuite(tests)
 
2716
 
 
2717
 
 
2718
def split_suite_by_condition(suite, condition):
 
2719
    """Split a test suite into two by a condition.
 
2720
 
 
2721
    :param suite: The suite to split.
 
2722
    :param condition: The condition to match on. Tests that match this
 
2723
        condition are returned in the first test suite, ones that do not match
 
2724
        are in the second suite.
 
2725
    :return: A tuple of two test suites, where the first contains tests from
 
2726
        suite matching the condition, and the second contains the remainder
 
2727
        from suite. The order within each output suite is the same as it was in
 
2728
        suite.
 
2729
    """
 
2730
    matched = []
 
2731
    did_not_match = []
1600
2732
    for test in iter_suite_tests(suite):
1601
 
        if filter_re.search(test.id()):
1602
 
            result.addTest(test)
1603
 
    return result
 
2733
        if condition(test):
 
2734
            matched.append(test)
 
2735
        else:
 
2736
            did_not_match.append(test)
 
2737
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
 
2738
 
 
2739
 
 
2740
def split_suite_by_re(suite, pattern):
 
2741
    """Split a test suite into two by a regular expression.
 
2742
 
 
2743
    :param suite: The suite to split.
 
2744
    :param pattern: A regular expression string. Test ids that match this
 
2745
        pattern will be in the first test suite returned, and the others in the
 
2746
        second test suite returned.
 
2747
    :return: A tuple of two test suites, where the first contains tests from
 
2748
        suite matching pattern, and the second contains the remainder from
 
2749
        suite. The order within each output suite is the same as it was in
 
2750
        suite.
 
2751
    """
 
2752
    return split_suite_by_condition(suite, condition_id_re(pattern))
1604
2753
 
1605
2754
 
1606
2755
def run_suite(suite, name='test', verbose=False, pattern=".*",
1607
 
              stop_on_failure=False, keep_output=False,
1608
 
              transport=None, lsprof_timed=None, bench_history=None):
 
2756
              stop_on_failure=False,
 
2757
              transport=None, lsprof_timed=None, bench_history=None,
 
2758
              matching_tests_first=None,
 
2759
              list_only=False,
 
2760
              random_seed=None,
 
2761
              exclude_pattern=None,
 
2762
              strict=False,
 
2763
              runner_class=None,
 
2764
              suite_decorators=None,
 
2765
              stream=None):
 
2766
    """Run a test suite for bzr selftest.
 
2767
 
 
2768
    :param runner_class: The class of runner to use. Must support the
 
2769
        constructor arguments passed by run_suite which are more than standard
 
2770
        python uses.
 
2771
    :return: A boolean indicating success.
 
2772
    """
1609
2773
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
1610
2774
    if verbose:
1611
2775
        verbosity = 2
1612
2776
    else:
1613
2777
        verbosity = 1
1614
 
    runner = TextTestRunner(stream=sys.stdout,
 
2778
    if runner_class is None:
 
2779
        runner_class = TextTestRunner
 
2780
    if stream is None:
 
2781
        stream = sys.stdout
 
2782
    runner = runner_class(stream=stream,
1615
2783
                            descriptions=0,
1616
2784
                            verbosity=verbosity,
1617
 
                            keep_output=keep_output,
1618
 
                            bench_history=bench_history)
 
2785
                            bench_history=bench_history,
 
2786
                            list_only=list_only,
 
2787
                            strict=strict,
 
2788
                            )
1619
2789
    runner.stop_on_failure=stop_on_failure
1620
 
    if pattern != '.*':
1621
 
        suite = filter_suite_by_re(suite, pattern)
 
2790
    # built in decorator factories:
 
2791
    decorators = [
 
2792
        random_order(random_seed, runner),
 
2793
        exclude_tests(exclude_pattern),
 
2794
        ]
 
2795
    if matching_tests_first:
 
2796
        decorators.append(tests_first(pattern))
 
2797
    else:
 
2798
        decorators.append(filter_tests(pattern))
 
2799
    if suite_decorators:
 
2800
        decorators.extend(suite_decorators)
 
2801
    # tell the result object how many tests will be running: (except if
 
2802
    # --parallel=fork is being used. Robert said he will provide a better
 
2803
    # progress design later -- vila 20090817)
 
2804
    if fork_decorator not in decorators:
 
2805
        decorators.append(CountingDecorator)
 
2806
    for decorator in decorators:
 
2807
        suite = decorator(suite)
1622
2808
    result = runner.run(suite)
1623
 
    return result.wasSuccessful()
 
2809
    if list_only:
 
2810
        return True
 
2811
    result.done()
 
2812
    if strict:
 
2813
        return result.wasStrictlySuccessful()
 
2814
    else:
 
2815
        return result.wasSuccessful()
 
2816
 
 
2817
 
 
2818
# A registry where get() returns a suite decorator.
 
2819
parallel_registry = registry.Registry()
 
2820
 
 
2821
 
 
2822
def fork_decorator(suite):
 
2823
    concurrency = osutils.local_concurrency()
 
2824
    if concurrency == 1:
 
2825
        return suite
 
2826
    from testtools import ConcurrentTestSuite
 
2827
    return ConcurrentTestSuite(suite, fork_for_tests)
 
2828
parallel_registry.register('fork', fork_decorator)
 
2829
 
 
2830
 
 
2831
def subprocess_decorator(suite):
 
2832
    concurrency = osutils.local_concurrency()
 
2833
    if concurrency == 1:
 
2834
        return suite
 
2835
    from testtools import ConcurrentTestSuite
 
2836
    return ConcurrentTestSuite(suite, reinvoke_for_tests)
 
2837
parallel_registry.register('subprocess', subprocess_decorator)
 
2838
 
 
2839
 
 
2840
def exclude_tests(exclude_pattern):
 
2841
    """Return a test suite decorator that excludes tests."""
 
2842
    if exclude_pattern is None:
 
2843
        return identity_decorator
 
2844
    def decorator(suite):
 
2845
        return ExcludeDecorator(suite, exclude_pattern)
 
2846
    return decorator
 
2847
 
 
2848
 
 
2849
def filter_tests(pattern):
 
2850
    if pattern == '.*':
 
2851
        return identity_decorator
 
2852
    def decorator(suite):
 
2853
        return FilterTestsDecorator(suite, pattern)
 
2854
    return decorator
 
2855
 
 
2856
 
 
2857
def random_order(random_seed, runner):
 
2858
    """Return a test suite decorator factory for randomising tests order.
 
2859
    
 
2860
    :param random_seed: now, a string which casts to a long, or a long.
 
2861
    :param runner: A test runner with a stream attribute to report on.
 
2862
    """
 
2863
    if random_seed is None:
 
2864
        return identity_decorator
 
2865
    def decorator(suite):
 
2866
        return RandomDecorator(suite, random_seed, runner.stream)
 
2867
    return decorator
 
2868
 
 
2869
 
 
2870
def tests_first(pattern):
 
2871
    if pattern == '.*':
 
2872
        return identity_decorator
 
2873
    def decorator(suite):
 
2874
        return TestFirstDecorator(suite, pattern)
 
2875
    return decorator
 
2876
 
 
2877
 
 
2878
def identity_decorator(suite):
 
2879
    """Return suite."""
 
2880
    return suite
 
2881
 
 
2882
 
 
2883
class TestDecorator(TestSuite):
 
2884
    """A decorator for TestCase/TestSuite objects.
 
2885
    
 
2886
    Usually, subclasses should override __iter__(used when flattening test
 
2887
    suites), which we do to filter, reorder, parallelise and so on, run() and
 
2888
    debug().
 
2889
    """
 
2890
 
 
2891
    def __init__(self, suite):
 
2892
        TestSuite.__init__(self)
 
2893
        self.addTest(suite)
 
2894
 
 
2895
    def countTestCases(self):
 
2896
        cases = 0
 
2897
        for test in self:
 
2898
            cases += test.countTestCases()
 
2899
        return cases
 
2900
 
 
2901
    def debug(self):
 
2902
        for test in self:
 
2903
            test.debug()
 
2904
 
 
2905
    def run(self, result):
 
2906
        # Use iteration on self, not self._tests, to allow subclasses to hook
 
2907
        # into __iter__.
 
2908
        for test in self:
 
2909
            if result.shouldStop:
 
2910
                break
 
2911
            test.run(result)
 
2912
        return result
 
2913
 
 
2914
 
 
2915
class CountingDecorator(TestDecorator):
 
2916
    """A decorator which calls result.progress(self.countTestCases)."""
 
2917
 
 
2918
    def run(self, result):
 
2919
        progress_method = getattr(result, 'progress', None)
 
2920
        if callable(progress_method):
 
2921
            progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
 
2922
        return super(CountingDecorator, self).run(result)
 
2923
 
 
2924
 
 
2925
class ExcludeDecorator(TestDecorator):
 
2926
    """A decorator which excludes test matching an exclude pattern."""
 
2927
 
 
2928
    def __init__(self, suite, exclude_pattern):
 
2929
        TestDecorator.__init__(self, suite)
 
2930
        self.exclude_pattern = exclude_pattern
 
2931
        self.excluded = False
 
2932
 
 
2933
    def __iter__(self):
 
2934
        if self.excluded:
 
2935
            return iter(self._tests)
 
2936
        self.excluded = True
 
2937
        suite = exclude_tests_by_re(self, self.exclude_pattern)
 
2938
        del self._tests[:]
 
2939
        self.addTests(suite)
 
2940
        return iter(self._tests)
 
2941
 
 
2942
 
 
2943
class FilterTestsDecorator(TestDecorator):
 
2944
    """A decorator which filters tests to those matching a pattern."""
 
2945
 
 
2946
    def __init__(self, suite, pattern):
 
2947
        TestDecorator.__init__(self, suite)
 
2948
        self.pattern = pattern
 
2949
        self.filtered = False
 
2950
 
 
2951
    def __iter__(self):
 
2952
        if self.filtered:
 
2953
            return iter(self._tests)
 
2954
        self.filtered = True
 
2955
        suite = filter_suite_by_re(self, self.pattern)
 
2956
        del self._tests[:]
 
2957
        self.addTests(suite)
 
2958
        return iter(self._tests)
 
2959
 
 
2960
 
 
2961
class RandomDecorator(TestDecorator):
 
2962
    """A decorator which randomises the order of its tests."""
 
2963
 
 
2964
    def __init__(self, suite, random_seed, stream):
 
2965
        TestDecorator.__init__(self, suite)
 
2966
        self.random_seed = random_seed
 
2967
        self.randomised = False
 
2968
        self.stream = stream
 
2969
 
 
2970
    def __iter__(self):
 
2971
        if self.randomised:
 
2972
            return iter(self._tests)
 
2973
        self.randomised = True
 
2974
        self.stream.writeln("Randomizing test order using seed %s\n" %
 
2975
            (self.actual_seed()))
 
2976
        # Initialise the random number generator.
 
2977
        random.seed(self.actual_seed())
 
2978
        suite = randomize_suite(self)
 
2979
        del self._tests[:]
 
2980
        self.addTests(suite)
 
2981
        return iter(self._tests)
 
2982
 
 
2983
    def actual_seed(self):
 
2984
        if self.random_seed == "now":
 
2985
            # We convert the seed to a long to make it reuseable across
 
2986
            # invocations (because the user can reenter it).
 
2987
            self.random_seed = long(time.time())
 
2988
        else:
 
2989
            # Convert the seed to a long if we can
 
2990
            try:
 
2991
                self.random_seed = long(self.random_seed)
 
2992
            except:
 
2993
                pass
 
2994
        return self.random_seed
 
2995
 
 
2996
 
 
2997
class TestFirstDecorator(TestDecorator):
 
2998
    """A decorator which moves named tests to the front."""
 
2999
 
 
3000
    def __init__(self, suite, pattern):
 
3001
        TestDecorator.__init__(self, suite)
 
3002
        self.pattern = pattern
 
3003
        self.filtered = False
 
3004
 
 
3005
    def __iter__(self):
 
3006
        if self.filtered:
 
3007
            return iter(self._tests)
 
3008
        self.filtered = True
 
3009
        suites = split_suite_by_re(self, self.pattern)
 
3010
        del self._tests[:]
 
3011
        self.addTests(suites)
 
3012
        return iter(self._tests)
 
3013
 
 
3014
 
 
3015
def partition_tests(suite, count):
 
3016
    """Partition suite into count lists of tests."""
 
3017
    result = []
 
3018
    tests = list(iter_suite_tests(suite))
 
3019
    tests_per_process = int(math.ceil(float(len(tests)) / count))
 
3020
    for block in range(count):
 
3021
        low_test = block * tests_per_process
 
3022
        high_test = low_test + tests_per_process
 
3023
        process_tests = tests[low_test:high_test]
 
3024
        result.append(process_tests)
 
3025
    return result
 
3026
 
 
3027
 
 
3028
def fork_for_tests(suite):
 
3029
    """Take suite and start up one runner per CPU by forking()
 
3030
 
 
3031
    :return: An iterable of TestCase-like objects which can each have
 
3032
        run(result) called on them to feed tests to result.
 
3033
    """
 
3034
    concurrency = osutils.local_concurrency()
 
3035
    result = []
 
3036
    from subunit import TestProtocolClient, ProtocolTestCase
 
3037
    try:
 
3038
        from subunit.test_results import AutoTimingTestResultDecorator
 
3039
    except ImportError:
 
3040
        AutoTimingTestResultDecorator = lambda x:x
 
3041
    class TestInOtherProcess(ProtocolTestCase):
 
3042
        # Should be in subunit, I think. RBC.
 
3043
        def __init__(self, stream, pid):
 
3044
            ProtocolTestCase.__init__(self, stream)
 
3045
            self.pid = pid
 
3046
 
 
3047
        def run(self, result):
 
3048
            try:
 
3049
                ProtocolTestCase.run(self, result)
 
3050
            finally:
 
3051
                os.waitpid(self.pid, os.WNOHANG)
 
3052
 
 
3053
    test_blocks = partition_tests(suite, concurrency)
 
3054
    for process_tests in test_blocks:
 
3055
        process_suite = TestSuite()
 
3056
        process_suite.addTests(process_tests)
 
3057
        c2pread, c2pwrite = os.pipe()
 
3058
        pid = os.fork()
 
3059
        if pid == 0:
 
3060
            try:
 
3061
                os.close(c2pread)
 
3062
                # Leave stderr and stdout open so we can see test noise
 
3063
                # Close stdin so that the child goes away if it decides to
 
3064
                # read from stdin (otherwise its a roulette to see what
 
3065
                # child actually gets keystrokes for pdb etc).
 
3066
                sys.stdin.close()
 
3067
                sys.stdin = None
 
3068
                stream = os.fdopen(c2pwrite, 'wb', 1)
 
3069
                subunit_result = AutoTimingTestResultDecorator(
 
3070
                    TestProtocolClient(stream))
 
3071
                process_suite.run(subunit_result)
 
3072
            finally:
 
3073
                os._exit(0)
 
3074
        else:
 
3075
            os.close(c2pwrite)
 
3076
            stream = os.fdopen(c2pread, 'rb', 1)
 
3077
            test = TestInOtherProcess(stream, pid)
 
3078
            result.append(test)
 
3079
    return result
 
3080
 
 
3081
 
 
3082
def reinvoke_for_tests(suite):
 
3083
    """Take suite and start up one runner per CPU using subprocess().
 
3084
 
 
3085
    :return: An iterable of TestCase-like objects which can each have
 
3086
        run(result) called on them to feed tests to result.
 
3087
    """
 
3088
    concurrency = osutils.local_concurrency()
 
3089
    result = []
 
3090
    from subunit import ProtocolTestCase
 
3091
    class TestInSubprocess(ProtocolTestCase):
 
3092
        def __init__(self, process, name):
 
3093
            ProtocolTestCase.__init__(self, process.stdout)
 
3094
            self.process = process
 
3095
            self.process.stdin.close()
 
3096
            self.name = name
 
3097
 
 
3098
        def run(self, result):
 
3099
            try:
 
3100
                ProtocolTestCase.run(self, result)
 
3101
            finally:
 
3102
                self.process.wait()
 
3103
                os.unlink(self.name)
 
3104
            # print "pid %d finished" % finished_process
 
3105
    test_blocks = partition_tests(suite, concurrency)
 
3106
    for process_tests in test_blocks:
 
3107
        # ugly; currently reimplement rather than reuses TestCase methods.
 
3108
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
3109
        if not os.path.isfile(bzr_path):
 
3110
            # We are probably installed. Assume sys.argv is the right file
 
3111
            bzr_path = sys.argv[0]
 
3112
        fd, test_list_file_name = tempfile.mkstemp()
 
3113
        test_list_file = os.fdopen(fd, 'wb', 1)
 
3114
        for test in process_tests:
 
3115
            test_list_file.write(test.id() + '\n')
 
3116
        test_list_file.close()
 
3117
        try:
 
3118
            argv = [bzr_path, 'selftest', '--load-list', test_list_file_name,
 
3119
                '--subunit']
 
3120
            if '--no-plugins' in sys.argv:
 
3121
                argv.append('--no-plugins')
 
3122
            # stderr=STDOUT would be ideal, but until we prevent noise on
 
3123
            # stderr it can interrupt the subunit protocol.
 
3124
            process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
 
3125
                bufsize=1)
 
3126
            test = TestInSubprocess(process, test_list_file_name)
 
3127
            result.append(test)
 
3128
        except:
 
3129
            os.unlink(test_list_file_name)
 
3130
            raise
 
3131
    return result
 
3132
 
 
3133
 
 
3134
class BZRTransformingResult(unittest.TestResult):
 
3135
 
 
3136
    def __init__(self, target):
 
3137
        unittest.TestResult.__init__(self)
 
3138
        self.result = target
 
3139
 
 
3140
    def startTest(self, test):
 
3141
        self.result.startTest(test)
 
3142
 
 
3143
    def stopTest(self, test):
 
3144
        self.result.stopTest(test)
 
3145
 
 
3146
    def addError(self, test, err):
 
3147
        feature = self._error_looks_like('UnavailableFeature: ', err)
 
3148
        if feature is not None:
 
3149
            self.result.addNotSupported(test, feature)
 
3150
        else:
 
3151
            self.result.addError(test, err)
 
3152
 
 
3153
    def addFailure(self, test, err):
 
3154
        known = self._error_looks_like('KnownFailure: ', err)
 
3155
        if known is not None:
 
3156
            self.result._addKnownFailure(test, [KnownFailure,
 
3157
                                                KnownFailure(known), None])
 
3158
        else:
 
3159
            self.result.addFailure(test, err)
 
3160
 
 
3161
    def addSkip(self, test, reason):
 
3162
        self.result.addSkip(test, reason)
 
3163
 
 
3164
    def addSuccess(self, test):
 
3165
        self.result.addSuccess(test)
 
3166
 
 
3167
    def _error_looks_like(self, prefix, err):
 
3168
        """Deserialize exception and returns the stringify value."""
 
3169
        import subunit
 
3170
        value = None
 
3171
        typ, exc, _ = err
 
3172
        if isinstance(exc, subunit.RemoteException):
 
3173
            # stringify the exception gives access to the remote traceback
 
3174
            # We search the last line for 'prefix'
 
3175
            lines = str(exc).split('\n')
 
3176
            while lines and not lines[-1]:
 
3177
                lines.pop(-1)
 
3178
            if lines:
 
3179
                if lines[-1].startswith(prefix):
 
3180
                    value = lines[-1][len(prefix):]
 
3181
        return value
 
3182
 
 
3183
 
 
3184
# Controlled by "bzr selftest -E=..." option
 
3185
# Currently supported:
 
3186
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
 
3187
#                           preserves any flags supplied at the command line.
 
3188
#   -Edisable_lock_checks   Turns errors in mismatched locks into simple prints
 
3189
#                           rather than failing tests. And no longer raise
 
3190
#                           LockContention when fctnl locks are not being used
 
3191
#                           with proper exclusion rules.
 
3192
selftest_debug_flags = set()
1624
3193
 
1625
3194
 
1626
3195
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
1627
 
             keep_output=False,
1628
3196
             transport=None,
1629
3197
             test_suite_factory=None,
1630
3198
             lsprof_timed=None,
1631
 
             bench_history=None):
 
3199
             bench_history=None,
 
3200
             matching_tests_first=None,
 
3201
             list_only=False,
 
3202
             random_seed=None,
 
3203
             exclude_pattern=None,
 
3204
             strict=False,
 
3205
             load_list=None,
 
3206
             debug_flags=None,
 
3207
             starting_with=None,
 
3208
             runner_class=None,
 
3209
             suite_decorators=None,
 
3210
             stream=None,
 
3211
             ):
1632
3212
    """Run the whole test suite under the enhanced runner"""
1633
3213
    # XXX: Very ugly way to do this...
1634
3214
    # Disable warning about old formats because we don't want it to disturb
1641
3221
        transport = default_transport
1642
3222
    old_transport = default_transport
1643
3223
    default_transport = transport
 
3224
    global selftest_debug_flags
 
3225
    old_debug_flags = selftest_debug_flags
 
3226
    if debug_flags is not None:
 
3227
        selftest_debug_flags = set(debug_flags)
1644
3228
    try:
 
3229
        if load_list is None:
 
3230
            keep_only = None
 
3231
        else:
 
3232
            keep_only = load_test_id_list(load_list)
 
3233
        if starting_with:
 
3234
            starting_with = [test_prefix_alias_registry.resolve_alias(start)
 
3235
                             for start in starting_with]
1645
3236
        if test_suite_factory is None:
1646
 
            suite = test_suite()
 
3237
            # Reduce loading time by loading modules based on the starting_with
 
3238
            # patterns.
 
3239
            suite = test_suite(keep_only, starting_with)
1647
3240
        else:
1648
3241
            suite = test_suite_factory()
 
3242
        if starting_with:
 
3243
            # But always filter as requested.
 
3244
            suite = filter_suite_by_id_startswith(suite, starting_with)
1649
3245
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
1650
 
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
 
3246
                     stop_on_failure=stop_on_failure,
1651
3247
                     transport=transport,
1652
3248
                     lsprof_timed=lsprof_timed,
1653
 
                     bench_history=bench_history)
 
3249
                     bench_history=bench_history,
 
3250
                     matching_tests_first=matching_tests_first,
 
3251
                     list_only=list_only,
 
3252
                     random_seed=random_seed,
 
3253
                     exclude_pattern=exclude_pattern,
 
3254
                     strict=strict,
 
3255
                     runner_class=runner_class,
 
3256
                     suite_decorators=suite_decorators,
 
3257
                     stream=stream,
 
3258
                     )
1654
3259
    finally:
1655
3260
        default_transport = old_transport
1656
 
 
1657
 
 
1658
 
def test_suite():
 
3261
        selftest_debug_flags = old_debug_flags
 
3262
 
 
3263
 
 
3264
def load_test_id_list(file_name):
 
3265
    """Load a test id list from a text file.
 
3266
 
 
3267
    The format is one test id by line.  No special care is taken to impose
 
3268
    strict rules, these test ids are used to filter the test suite so a test id
 
3269
    that do not match an existing test will do no harm. This allows user to add
 
3270
    comments, leave blank lines, etc.
 
3271
    """
 
3272
    test_list = []
 
3273
    try:
 
3274
        ftest = open(file_name, 'rt')
 
3275
    except IOError, e:
 
3276
        if e.errno != errno.ENOENT:
 
3277
            raise
 
3278
        else:
 
3279
            raise errors.NoSuchFile(file_name)
 
3280
 
 
3281
    for test_name in ftest.readlines():
 
3282
        test_list.append(test_name.strip())
 
3283
    ftest.close()
 
3284
    return test_list
 
3285
 
 
3286
 
 
3287
def suite_matches_id_list(test_suite, id_list):
 
3288
    """Warns about tests not appearing or appearing more than once.
 
3289
 
 
3290
    :param test_suite: A TestSuite object.
 
3291
    :param test_id_list: The list of test ids that should be found in
 
3292
         test_suite.
 
3293
 
 
3294
    :return: (absents, duplicates) absents is a list containing the test found
 
3295
        in id_list but not in test_suite, duplicates is a list containing the
 
3296
        test found multiple times in test_suite.
 
3297
 
 
3298
    When using a prefined test id list, it may occurs that some tests do not
 
3299
    exist anymore or that some tests use the same id. This function warns the
 
3300
    tester about potential problems in his workflow (test lists are volatile)
 
3301
    or in the test suite itself (using the same id for several tests does not
 
3302
    help to localize defects).
 
3303
    """
 
3304
    # Build a dict counting id occurrences
 
3305
    tests = dict()
 
3306
    for test in iter_suite_tests(test_suite):
 
3307
        id = test.id()
 
3308
        tests[id] = tests.get(id, 0) + 1
 
3309
 
 
3310
    not_found = []
 
3311
    duplicates = []
 
3312
    for id in id_list:
 
3313
        occurs = tests.get(id, 0)
 
3314
        if not occurs:
 
3315
            not_found.append(id)
 
3316
        elif occurs > 1:
 
3317
            duplicates.append(id)
 
3318
 
 
3319
    return not_found, duplicates
 
3320
 
 
3321
 
 
3322
class TestIdList(object):
 
3323
    """Test id list to filter a test suite.
 
3324
 
 
3325
    Relying on the assumption that test ids are built as:
 
3326
    <module>[.<class>.<method>][(<param>+)], <module> being in python dotted
 
3327
    notation, this class offers methods to :
 
3328
    - avoid building a test suite for modules not refered to in the test list,
 
3329
    - keep only the tests listed from the module test suite.
 
3330
    """
 
3331
 
 
3332
    def __init__(self, test_id_list):
 
3333
        # When a test suite needs to be filtered against us we compare test ids
 
3334
        # for equality, so a simple dict offers a quick and simple solution.
 
3335
        self.tests = dict().fromkeys(test_id_list, True)
 
3336
 
 
3337
        # While unittest.TestCase have ids like:
 
3338
        # <module>.<class>.<method>[(<param+)],
 
3339
        # doctest.DocTestCase can have ids like:
 
3340
        # <module>
 
3341
        # <module>.<class>
 
3342
        # <module>.<function>
 
3343
        # <module>.<class>.<method>
 
3344
 
 
3345
        # Since we can't predict a test class from its name only, we settle on
 
3346
        # a simple constraint: a test id always begins with its module name.
 
3347
 
 
3348
        modules = {}
 
3349
        for test_id in test_id_list:
 
3350
            parts = test_id.split('.')
 
3351
            mod_name = parts.pop(0)
 
3352
            modules[mod_name] = True
 
3353
            for part in parts:
 
3354
                mod_name += '.' + part
 
3355
                modules[mod_name] = True
 
3356
        self.modules = modules
 
3357
 
 
3358
    def refers_to(self, module_name):
 
3359
        """Is there tests for the module or one of its sub modules."""
 
3360
        return self.modules.has_key(module_name)
 
3361
 
 
3362
    def includes(self, test_id):
 
3363
        return self.tests.has_key(test_id)
 
3364
 
 
3365
 
 
3366
class TestPrefixAliasRegistry(registry.Registry):
 
3367
    """A registry for test prefix aliases.
 
3368
 
 
3369
    This helps implement shorcuts for the --starting-with selftest
 
3370
    option. Overriding existing prefixes is not allowed but not fatal (a
 
3371
    warning will be emitted).
 
3372
    """
 
3373
 
 
3374
    def register(self, key, obj, help=None, info=None,
 
3375
                 override_existing=False):
 
3376
        """See Registry.register.
 
3377
 
 
3378
        Trying to override an existing alias causes a warning to be emitted,
 
3379
        not a fatal execption.
 
3380
        """
 
3381
        try:
 
3382
            super(TestPrefixAliasRegistry, self).register(
 
3383
                key, obj, help=help, info=info, override_existing=False)
 
3384
        except KeyError:
 
3385
            actual = self.get(key)
 
3386
            note('Test prefix alias %s is already used for %s, ignoring %s'
 
3387
                 % (key, actual, obj))
 
3388
 
 
3389
    def resolve_alias(self, id_start):
 
3390
        """Replace the alias by the prefix in the given string.
 
3391
 
 
3392
        Using an unknown prefix is an error to help catching typos.
 
3393
        """
 
3394
        parts = id_start.split('.')
 
3395
        try:
 
3396
            parts[0] = self.get(parts[0])
 
3397
        except KeyError:
 
3398
            raise errors.BzrCommandError(
 
3399
                '%s is not a known test prefix alias' % parts[0])
 
3400
        return '.'.join(parts)
 
3401
 
 
3402
 
 
3403
test_prefix_alias_registry = TestPrefixAliasRegistry()
 
3404
"""Registry of test prefix aliases."""
 
3405
 
 
3406
 
 
3407
# This alias allows to detect typos ('bzrlin.') by making all valid test ids
 
3408
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
 
3409
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
 
3410
 
 
3411
# Obvious higest levels prefixes, feel free to add your own via a plugin
 
3412
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
 
3413
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
 
3414
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
 
3415
test_prefix_alias_registry.register('bb', 'bzrlib.tests.blackbox')
 
3416
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
 
3417
 
 
3418
 
 
3419
def test_suite(keep_only=None, starting_with=None):
1659
3420
    """Build and return TestSuite for the whole of bzrlib.
1660
 
    
 
3421
 
 
3422
    :param keep_only: A list of test ids limiting the suite returned.
 
3423
 
 
3424
    :param starting_with: An id limiting the suite returned to the tests
 
3425
         starting with it.
 
3426
 
1661
3427
    This function can be replaced if you need to change the default test
1662
3428
    suite on a global basis, but it is not encouraged.
1663
3429
    """
1664
3430
    testmod_names = [
 
3431
                   'bzrlib.doc',
 
3432
                   'bzrlib.tests.blackbox',
 
3433
                   'bzrlib.tests.commands',
 
3434
                   'bzrlib.tests.per_branch',
 
3435
                   'bzrlib.tests.per_bzrdir',
 
3436
                   'bzrlib.tests.per_interrepository',
 
3437
                   'bzrlib.tests.per_intertree',
 
3438
                   'bzrlib.tests.per_inventory',
 
3439
                   'bzrlib.tests.per_interbranch',
 
3440
                   'bzrlib.tests.per_lock',
 
3441
                   'bzrlib.tests.per_transport',
 
3442
                   'bzrlib.tests.per_tree',
 
3443
                   'bzrlib.tests.per_pack_repository',
 
3444
                   'bzrlib.tests.per_repository',
 
3445
                   'bzrlib.tests.per_repository_chk',
 
3446
                   'bzrlib.tests.per_repository_reference',
 
3447
                   'bzrlib.tests.per_versionedfile',
 
3448
                   'bzrlib.tests.per_workingtree',
 
3449
                   'bzrlib.tests.test__annotator',
 
3450
                   'bzrlib.tests.test__chk_map',
 
3451
                   'bzrlib.tests.test__dirstate_helpers',
 
3452
                   'bzrlib.tests.test__groupcompress',
 
3453
                   'bzrlib.tests.test__known_graph',
 
3454
                   'bzrlib.tests.test__rio',
 
3455
                   'bzrlib.tests.test__walkdirs_win32',
1665
3456
                   'bzrlib.tests.test_ancestry',
 
3457
                   'bzrlib.tests.test_annotate',
1666
3458
                   'bzrlib.tests.test_api',
1667
3459
                   'bzrlib.tests.test_atomicfile',
1668
3460
                   'bzrlib.tests.test_bad_files',
 
3461
                   'bzrlib.tests.test_bencode',
 
3462
                   'bzrlib.tests.test_bisect_multi',
1669
3463
                   'bzrlib.tests.test_branch',
 
3464
                   'bzrlib.tests.test_branchbuilder',
 
3465
                   'bzrlib.tests.test_btree_index',
 
3466
                   'bzrlib.tests.test_bugtracker',
1670
3467
                   'bzrlib.tests.test_bundle',
1671
3468
                   'bzrlib.tests.test_bzrdir',
 
3469
                   'bzrlib.tests.test__chunks_to_lines',
1672
3470
                   'bzrlib.tests.test_cache_utf8',
1673
 
                   'bzrlib.tests.test_command',
 
3471
                   'bzrlib.tests.test_chk_map',
 
3472
                   'bzrlib.tests.test_chk_serializer',
 
3473
                   'bzrlib.tests.test_chunk_writer',
 
3474
                   'bzrlib.tests.test_clean_tree',
 
3475
                   'bzrlib.tests.test_commands',
1674
3476
                   'bzrlib.tests.test_commit',
1675
3477
                   'bzrlib.tests.test_commit_merge',
1676
3478
                   'bzrlib.tests.test_config',
1677
3479
                   'bzrlib.tests.test_conflicts',
 
3480
                   'bzrlib.tests.test_counted_lock',
 
3481
                   'bzrlib.tests.test_crash',
1678
3482
                   'bzrlib.tests.test_decorators',
 
3483
                   'bzrlib.tests.test_delta',
 
3484
                   'bzrlib.tests.test_debug',
 
3485
                   'bzrlib.tests.test_deprecated_graph',
1679
3486
                   'bzrlib.tests.test_diff',
1680
 
                   'bzrlib.tests.test_doc_generate',
 
3487
                   'bzrlib.tests.test_directory_service',
 
3488
                   'bzrlib.tests.test_dirstate',
 
3489
                   'bzrlib.tests.test_email_message',
 
3490
                   'bzrlib.tests.test_eol_filters',
1681
3491
                   'bzrlib.tests.test_errors',
1682
 
                   'bzrlib.tests.test_escaped_store',
 
3492
                   'bzrlib.tests.test_export',
 
3493
                   'bzrlib.tests.test_extract',
1683
3494
                   'bzrlib.tests.test_fetch',
 
3495
                   'bzrlib.tests.test_fifo_cache',
 
3496
                   'bzrlib.tests.test_filters',
1684
3497
                   'bzrlib.tests.test_ftp_transport',
 
3498
                   'bzrlib.tests.test_foreign',
 
3499
                   'bzrlib.tests.test_generate_docs',
 
3500
                   'bzrlib.tests.test_generate_ids',
 
3501
                   'bzrlib.tests.test_globbing',
1685
3502
                   'bzrlib.tests.test_gpg',
1686
3503
                   'bzrlib.tests.test_graph',
 
3504
                   'bzrlib.tests.test_groupcompress',
1687
3505
                   'bzrlib.tests.test_hashcache',
 
3506
                   'bzrlib.tests.test_help',
 
3507
                   'bzrlib.tests.test_hooks',
1688
3508
                   'bzrlib.tests.test_http',
1689
3509
                   'bzrlib.tests.test_http_response',
 
3510
                   'bzrlib.tests.test_https_ca_bundle',
1690
3511
                   'bzrlib.tests.test_identitymap',
1691
3512
                   'bzrlib.tests.test_ignores',
 
3513
                   'bzrlib.tests.test_index',
 
3514
                   'bzrlib.tests.test_info',
1692
3515
                   'bzrlib.tests.test_inv',
 
3516
                   'bzrlib.tests.test_inventory_delta',
1693
3517
                   'bzrlib.tests.test_knit',
1694
3518
                   'bzrlib.tests.test_lazy_import',
1695
3519
                   'bzrlib.tests.test_lazy_regex',
 
3520
                   'bzrlib.tests.test_lock',
 
3521
                   'bzrlib.tests.test_lockable_files',
1696
3522
                   'bzrlib.tests.test_lockdir',
1697
 
                   'bzrlib.tests.test_lockable_files',
1698
3523
                   'bzrlib.tests.test_log',
 
3524
                   'bzrlib.tests.test_lru_cache',
 
3525
                   'bzrlib.tests.test_lsprof',
 
3526
                   'bzrlib.tests.test_mail_client',
1699
3527
                   'bzrlib.tests.test_memorytree',
1700
3528
                   'bzrlib.tests.test_merge',
1701
3529
                   'bzrlib.tests.test_merge3',
1702
3530
                   'bzrlib.tests.test_merge_core',
 
3531
                   'bzrlib.tests.test_merge_directive',
1703
3532
                   'bzrlib.tests.test_missing',
1704
3533
                   'bzrlib.tests.test_msgeditor',
 
3534
                   'bzrlib.tests.test_multiparent',
 
3535
                   'bzrlib.tests.test_mutabletree',
1705
3536
                   'bzrlib.tests.test_nonascii',
1706
3537
                   'bzrlib.tests.test_options',
1707
3538
                   'bzrlib.tests.test_osutils',
 
3539
                   'bzrlib.tests.test_osutils_encodings',
 
3540
                   'bzrlib.tests.test_pack',
1708
3541
                   'bzrlib.tests.test_patch',
1709
3542
                   'bzrlib.tests.test_patches',
1710
3543
                   'bzrlib.tests.test_permissions',
1711
3544
                   'bzrlib.tests.test_plugins',
1712
3545
                   'bzrlib.tests.test_progress',
 
3546
                   'bzrlib.tests.test_read_bundle',
1713
3547
                   'bzrlib.tests.test_reconcile',
 
3548
                   'bzrlib.tests.test_reconfigure',
1714
3549
                   'bzrlib.tests.test_registry',
 
3550
                   'bzrlib.tests.test_remote',
 
3551
                   'bzrlib.tests.test_rename_map',
1715
3552
                   'bzrlib.tests.test_repository',
1716
3553
                   'bzrlib.tests.test_revert',
1717
3554
                   'bzrlib.tests.test_revision',
1718
 
                   'bzrlib.tests.test_revisionnamespaces',
 
3555
                   'bzrlib.tests.test_revisionspec',
1719
3556
                   'bzrlib.tests.test_revisiontree',
1720
3557
                   'bzrlib.tests.test_rio',
 
3558
                   'bzrlib.tests.test_rules',
1721
3559
                   'bzrlib.tests.test_sampler',
1722
3560
                   'bzrlib.tests.test_selftest',
 
3561
                   'bzrlib.tests.test_serializer',
1723
3562
                   'bzrlib.tests.test_setup',
1724
3563
                   'bzrlib.tests.test_sftp_transport',
 
3564
                   'bzrlib.tests.test_shelf',
 
3565
                   'bzrlib.tests.test_shelf_ui',
 
3566
                   'bzrlib.tests.test_smart',
1725
3567
                   'bzrlib.tests.test_smart_add',
 
3568
                   'bzrlib.tests.test_smart_request',
1726
3569
                   'bzrlib.tests.test_smart_transport',
 
3570
                   'bzrlib.tests.test_smtp_connection',
1727
3571
                   'bzrlib.tests.test_source',
 
3572
                   'bzrlib.tests.test_ssh_transport',
1728
3573
                   'bzrlib.tests.test_status',
1729
3574
                   'bzrlib.tests.test_store',
 
3575
                   'bzrlib.tests.test_strace',
 
3576
                   'bzrlib.tests.test_subsume',
 
3577
                   'bzrlib.tests.test_switch',
1730
3578
                   'bzrlib.tests.test_symbol_versioning',
 
3579
                   'bzrlib.tests.test_tag',
1731
3580
                   'bzrlib.tests.test_testament',
1732
3581
                   'bzrlib.tests.test_textfile',
1733
3582
                   'bzrlib.tests.test_textmerge',
 
3583
                   'bzrlib.tests.test_timestamp',
1734
3584
                   'bzrlib.tests.test_trace',
1735
3585
                   'bzrlib.tests.test_transactions',
1736
3586
                   'bzrlib.tests.test_transform',
1737
3587
                   'bzrlib.tests.test_transport',
 
3588
                   'bzrlib.tests.test_transport_log',
1738
3589
                   'bzrlib.tests.test_tree',
1739
3590
                   'bzrlib.tests.test_treebuilder',
1740
3591
                   'bzrlib.tests.test_tsort',
1741
3592
                   'bzrlib.tests.test_tuned_gzip',
1742
3593
                   'bzrlib.tests.test_ui',
 
3594
                   'bzrlib.tests.test_uncommit',
1743
3595
                   'bzrlib.tests.test_upgrade',
 
3596
                   'bzrlib.tests.test_upgrade_stacked',
1744
3597
                   'bzrlib.tests.test_urlutils',
1745
 
                   'bzrlib.tests.test_versionedfile',
1746
3598
                   'bzrlib.tests.test_version',
1747
3599
                   'bzrlib.tests.test_version_info',
1748
3600
                   'bzrlib.tests.test_weave',
1749
3601
                   'bzrlib.tests.test_whitebox',
 
3602
                   'bzrlib.tests.test_win32utils',
1750
3603
                   'bzrlib.tests.test_workingtree',
 
3604
                   'bzrlib.tests.test_workingtree_4',
 
3605
                   'bzrlib.tests.test_wsgi',
1751
3606
                   'bzrlib.tests.test_xml',
1752
3607
                   ]
1753
 
    test_transport_implementations = [
1754
 
        'bzrlib.tests.test_transport_implementations',
1755
 
        'bzrlib.tests.test_read_bundle',
1756
 
        ]
1757
 
    suite = TestUtil.TestSuite()
 
3608
 
1758
3609
    loader = TestUtil.TestLoader()
 
3610
 
 
3611
    if keep_only is not None:
 
3612
        id_filter = TestIdList(keep_only)
 
3613
    if starting_with:
 
3614
        # We take precedence over keep_only because *at loading time* using
 
3615
        # both options means we will load less tests for the same final result.
 
3616
        def interesting_module(name):
 
3617
            for start in starting_with:
 
3618
                if (
 
3619
                    # Either the module name starts with the specified string
 
3620
                    name.startswith(start)
 
3621
                    # or it may contain tests starting with the specified string
 
3622
                    or start.startswith(name)
 
3623
                    ):
 
3624
                    return True
 
3625
            return False
 
3626
        loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
 
3627
 
 
3628
    elif keep_only is not None:
 
3629
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
 
3630
        def interesting_module(name):
 
3631
            return id_filter.refers_to(name)
 
3632
 
 
3633
    else:
 
3634
        loader = TestUtil.TestLoader()
 
3635
        def interesting_module(name):
 
3636
            # No filtering, all modules are interesting
 
3637
            return True
 
3638
 
 
3639
    suite = loader.suiteClass()
 
3640
 
 
3641
    # modules building their suite with loadTestsFromModuleNames
1759
3642
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
1760
 
    from bzrlib.transport import TransportTestProviderAdapter
1761
 
    adapter = TransportTestProviderAdapter()
1762
 
    adapt_modules(test_transport_implementations, adapter, loader, suite)
1763
 
    for package in packages_to_test():
1764
 
        suite.addTest(package.test_suite())
1765
 
    for m in MODULES_TO_TEST:
1766
 
        suite.addTest(loader.loadTestsFromModule(m))
1767
 
    for m in MODULES_TO_DOCTEST:
 
3643
 
 
3644
    modules_to_doctest = [
 
3645
        'bzrlib',
 
3646
        'bzrlib.branchbuilder',
 
3647
        'bzrlib.export',
 
3648
        'bzrlib.inventory',
 
3649
        'bzrlib.iterablefile',
 
3650
        'bzrlib.lockdir',
 
3651
        'bzrlib.merge3',
 
3652
        'bzrlib.option',
 
3653
        'bzrlib.symbol_versioning',
 
3654
        'bzrlib.tests',
 
3655
        'bzrlib.timestamp',
 
3656
        'bzrlib.version_info_formats.format_custom',
 
3657
        ]
 
3658
 
 
3659
    for mod in modules_to_doctest:
 
3660
        if not interesting_module(mod):
 
3661
            # No tests to keep here, move along
 
3662
            continue
1768
3663
        try:
1769
 
            suite.addTest(doctest.DocTestSuite(m))
 
3664
            # note that this really does mean "report only" -- doctest
 
3665
            # still runs the rest of the examples
 
3666
            doc_suite = doctest.DocTestSuite(mod,
 
3667
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
1770
3668
        except ValueError, e:
1771
 
            print '**failed to get doctest for: %s\n%s' %(m,e)
 
3669
            print '**failed to get doctest for: %s\n%s' % (mod, e)
1772
3670
            raise
1773
 
    for name, plugin in bzrlib.plugin.all_plugins().items():
1774
 
        if getattr(plugin, 'test_suite', None) is not None:
1775
 
            suite.addTest(plugin.test_suite())
 
3671
        if len(doc_suite._tests) == 0:
 
3672
            raise errors.BzrError("no doctests found in %s" % (mod,))
 
3673
        suite.addTest(doc_suite)
 
3674
 
 
3675
    default_encoding = sys.getdefaultencoding()
 
3676
    for name, plugin in bzrlib.plugin.plugins().items():
 
3677
        if not interesting_module(plugin.module.__name__):
 
3678
            continue
 
3679
        plugin_suite = plugin.test_suite()
 
3680
        # We used to catch ImportError here and turn it into just a warning,
 
3681
        # but really if you don't have --no-plugins this should be a failure.
 
3682
        # mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
 
3683
        if plugin_suite is None:
 
3684
            plugin_suite = plugin.load_plugin_tests(loader)
 
3685
        if plugin_suite is not None:
 
3686
            suite.addTest(plugin_suite)
 
3687
        if default_encoding != sys.getdefaultencoding():
 
3688
            bzrlib.trace.warning(
 
3689
                'Plugin "%s" tried to reset default encoding to: %s', name,
 
3690
                sys.getdefaultencoding())
 
3691
            reload(sys)
 
3692
            sys.setdefaultencoding(default_encoding)
 
3693
 
 
3694
    if keep_only is not None:
 
3695
        # Now that the referred modules have loaded their tests, keep only the
 
3696
        # requested ones.
 
3697
        suite = filter_suite_by_id_list(suite, id_filter)
 
3698
        # Do some sanity checks on the id_list filtering
 
3699
        not_found, duplicates = suite_matches_id_list(suite, keep_only)
 
3700
        if starting_with:
 
3701
            # The tester has used both keep_only and starting_with, so he is
 
3702
            # already aware that some tests are excluded from the list, there
 
3703
            # is no need to tell him which.
 
3704
            pass
 
3705
        else:
 
3706
            # Some tests mentioned in the list are not in the test suite. The
 
3707
            # list may be out of date, report to the tester.
 
3708
            for id in not_found:
 
3709
                bzrlib.trace.warning('"%s" not found in the test suite', id)
 
3710
        for id in duplicates:
 
3711
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
 
3712
 
1776
3713
    return suite
1777
3714
 
1778
3715
 
1779
 
def adapt_modules(mods_list, adapter, loader, suite):
1780
 
    """Adapt the modules in mods_list using adapter and add to suite."""
1781
 
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
1782
 
        suite.addTests(adapter.adapt(test))
 
3716
def multiply_scenarios(scenarios_left, scenarios_right):
 
3717
    """Multiply two sets of scenarios.
 
3718
 
 
3719
    :returns: the cartesian product of the two sets of scenarios, that is
 
3720
        a scenario for every possible combination of a left scenario and a
 
3721
        right scenario.
 
3722
    """
 
3723
    return [
 
3724
        ('%s,%s' % (left_name, right_name),
 
3725
         dict(left_dict.items() + right_dict.items()))
 
3726
        for left_name, left_dict in scenarios_left
 
3727
        for right_name, right_dict in scenarios_right]
 
3728
 
 
3729
 
 
3730
def multiply_tests(tests, scenarios, result):
 
3731
    """Multiply tests_list by scenarios into result.
 
3732
 
 
3733
    This is the core workhorse for test parameterisation.
 
3734
 
 
3735
    Typically the load_tests() method for a per-implementation test suite will
 
3736
    call multiply_tests and return the result.
 
3737
 
 
3738
    :param tests: The tests to parameterise.
 
3739
    :param scenarios: The scenarios to apply: pairs of (scenario_name,
 
3740
        scenario_param_dict).
 
3741
    :param result: A TestSuite to add created tests to.
 
3742
 
 
3743
    This returns the passed in result TestSuite with the cross product of all
 
3744
    the tests repeated once for each scenario.  Each test is adapted by adding
 
3745
    the scenario name at the end of its id(), and updating the test object's
 
3746
    __dict__ with the scenario_param_dict.
 
3747
 
 
3748
    >>> import bzrlib.tests.test_sampler
 
3749
    >>> r = multiply_tests(
 
3750
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
 
3751
    ...     [('one', dict(param=1)),
 
3752
    ...      ('two', dict(param=2))],
 
3753
    ...     TestSuite())
 
3754
    >>> tests = list(iter_suite_tests(r))
 
3755
    >>> len(tests)
 
3756
    2
 
3757
    >>> tests[0].id()
 
3758
    'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
 
3759
    >>> tests[0].param
 
3760
    1
 
3761
    >>> tests[1].param
 
3762
    2
 
3763
    """
 
3764
    for test in iter_suite_tests(tests):
 
3765
        apply_scenarios(test, scenarios, result)
 
3766
    return result
 
3767
 
 
3768
 
 
3769
def apply_scenarios(test, scenarios, result):
 
3770
    """Apply the scenarios in scenarios to test and add to result.
 
3771
 
 
3772
    :param test: The test to apply scenarios to.
 
3773
    :param scenarios: An iterable of scenarios to apply to test.
 
3774
    :return: result
 
3775
    :seealso: apply_scenario
 
3776
    """
 
3777
    for scenario in scenarios:
 
3778
        result.addTest(apply_scenario(test, scenario))
 
3779
    return result
 
3780
 
 
3781
 
 
3782
def apply_scenario(test, scenario):
 
3783
    """Copy test and apply scenario to it.
 
3784
 
 
3785
    :param test: A test to adapt.
 
3786
    :param scenario: A tuple describing the scenarion.
 
3787
        The first element of the tuple is the new test id.
 
3788
        The second element is a dict containing attributes to set on the
 
3789
        test.
 
3790
    :return: The adapted test.
 
3791
    """
 
3792
    new_id = "%s(%s)" % (test.id(), scenario[0])
 
3793
    new_test = clone_test(test, new_id)
 
3794
    for name, value in scenario[1].items():
 
3795
        setattr(new_test, name, value)
 
3796
    return new_test
 
3797
 
 
3798
 
 
3799
def clone_test(test, new_id):
 
3800
    """Clone a test giving it a new id.
 
3801
 
 
3802
    :param test: The test to clone.
 
3803
    :param new_id: The id to assign to it.
 
3804
    :return: The new test.
 
3805
    """
 
3806
    from copy import deepcopy
 
3807
    new_test = deepcopy(test)
 
3808
    new_test.id = lambda: new_id
 
3809
    return new_test
 
3810
 
 
3811
 
 
3812
def _rmtree_temp_dir(dirname):
 
3813
    # If LANG=C we probably have created some bogus paths
 
3814
    # which rmtree(unicode) will fail to delete
 
3815
    # so make sure we are using rmtree(str) to delete everything
 
3816
    # except on win32, where rmtree(str) will fail
 
3817
    # since it doesn't have the property of byte-stream paths
 
3818
    # (they are either ascii or mbcs)
 
3819
    if sys.platform == 'win32':
 
3820
        # make sure we are using the unicode win32 api
 
3821
        dirname = unicode(dirname)
 
3822
    else:
 
3823
        dirname = dirname.encode(sys.getfilesystemencoding())
 
3824
    try:
 
3825
        osutils.rmtree(dirname)
 
3826
    except OSError, e:
 
3827
        # We don't want to fail here because some useful display will be lost
 
3828
        # otherwise. Polluting the tmp dir is bad, but not giving all the
 
3829
        # possible info to the test runner is even worse.
 
3830
        sys.stderr.write('Unable to remove testing dir %s\n%s'
 
3831
                         % (os.path.basename(dirname), e))
 
3832
 
 
3833
 
 
3834
class Feature(object):
 
3835
    """An operating system Feature."""
 
3836
 
 
3837
    def __init__(self):
 
3838
        self._available = None
 
3839
 
 
3840
    def available(self):
 
3841
        """Is the feature available?
 
3842
 
 
3843
        :return: True if the feature is available.
 
3844
        """
 
3845
        if self._available is None:
 
3846
            self._available = self._probe()
 
3847
        return self._available
 
3848
 
 
3849
    def _probe(self):
 
3850
        """Implement this method in concrete features.
 
3851
 
 
3852
        :return: True if the feature is available.
 
3853
        """
 
3854
        raise NotImplementedError
 
3855
 
 
3856
    def __str__(self):
 
3857
        if getattr(self, 'feature_name', None):
 
3858
            return self.feature_name()
 
3859
        return self.__class__.__name__
 
3860
 
 
3861
 
 
3862
class _SymlinkFeature(Feature):
 
3863
 
 
3864
    def _probe(self):
 
3865
        return osutils.has_symlinks()
 
3866
 
 
3867
    def feature_name(self):
 
3868
        return 'symlinks'
 
3869
 
 
3870
SymlinkFeature = _SymlinkFeature()
 
3871
 
 
3872
 
 
3873
class _HardlinkFeature(Feature):
 
3874
 
 
3875
    def _probe(self):
 
3876
        return osutils.has_hardlinks()
 
3877
 
 
3878
    def feature_name(self):
 
3879
        return 'hardlinks'
 
3880
 
 
3881
HardlinkFeature = _HardlinkFeature()
 
3882
 
 
3883
 
 
3884
class _OsFifoFeature(Feature):
 
3885
 
 
3886
    def _probe(self):
 
3887
        return getattr(os, 'mkfifo', None)
 
3888
 
 
3889
    def feature_name(self):
 
3890
        return 'filesystem fifos'
 
3891
 
 
3892
OsFifoFeature = _OsFifoFeature()
 
3893
 
 
3894
 
 
3895
class _UnicodeFilenameFeature(Feature):
 
3896
    """Does the filesystem support Unicode filenames?"""
 
3897
 
 
3898
    def _probe(self):
 
3899
        try:
 
3900
            # Check for character combinations unlikely to be covered by any
 
3901
            # single non-unicode encoding. We use the characters
 
3902
            # - greek small letter alpha (U+03B1) and
 
3903
            # - braille pattern dots-123456 (U+283F).
 
3904
            os.stat(u'\u03b1\u283f')
 
3905
        except UnicodeEncodeError:
 
3906
            return False
 
3907
        except (IOError, OSError):
 
3908
            # The filesystem allows the Unicode filename but the file doesn't
 
3909
            # exist.
 
3910
            return True
 
3911
        else:
 
3912
            # The filesystem allows the Unicode filename and the file exists,
 
3913
            # for some reason.
 
3914
            return True
 
3915
 
 
3916
UnicodeFilenameFeature = _UnicodeFilenameFeature()
 
3917
 
 
3918
 
 
3919
def probe_unicode_in_user_encoding():
 
3920
    """Try to encode several unicode strings to use in unicode-aware tests.
 
3921
    Return first successfull match.
 
3922
 
 
3923
    :return:  (unicode value, encoded plain string value) or (None, None)
 
3924
    """
 
3925
    possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
 
3926
    for uni_val in possible_vals:
 
3927
        try:
 
3928
            str_val = uni_val.encode(osutils.get_user_encoding())
 
3929
        except UnicodeEncodeError:
 
3930
            # Try a different character
 
3931
            pass
 
3932
        else:
 
3933
            return uni_val, str_val
 
3934
    return None, None
 
3935
 
 
3936
 
 
3937
def probe_bad_non_ascii(encoding):
 
3938
    """Try to find [bad] character with code [128..255]
 
3939
    that cannot be decoded to unicode in some encoding.
 
3940
    Return None if all non-ascii characters is valid
 
3941
    for given encoding.
 
3942
    """
 
3943
    for i in xrange(128, 256):
 
3944
        char = chr(i)
 
3945
        try:
 
3946
            char.decode(encoding)
 
3947
        except UnicodeDecodeError:
 
3948
            return char
 
3949
    return None
 
3950
 
 
3951
 
 
3952
class _HTTPSServerFeature(Feature):
 
3953
    """Some tests want an https Server, check if one is available.
 
3954
 
 
3955
    Right now, the only way this is available is under python2.6 which provides
 
3956
    an ssl module.
 
3957
    """
 
3958
 
 
3959
    def _probe(self):
 
3960
        try:
 
3961
            import ssl
 
3962
            return True
 
3963
        except ImportError:
 
3964
            return False
 
3965
 
 
3966
    def feature_name(self):
 
3967
        return 'HTTPSServer'
 
3968
 
 
3969
 
 
3970
HTTPSServerFeature = _HTTPSServerFeature()
 
3971
 
 
3972
 
 
3973
class _UnicodeFilename(Feature):
 
3974
    """Does the filesystem support Unicode filenames?"""
 
3975
 
 
3976
    def _probe(self):
 
3977
        try:
 
3978
            os.stat(u'\u03b1')
 
3979
        except UnicodeEncodeError:
 
3980
            return False
 
3981
        except (IOError, OSError):
 
3982
            # The filesystem allows the Unicode filename but the file doesn't
 
3983
            # exist.
 
3984
            return True
 
3985
        else:
 
3986
            # The filesystem allows the Unicode filename and the file exists,
 
3987
            # for some reason.
 
3988
            return True
 
3989
 
 
3990
UnicodeFilename = _UnicodeFilename()
 
3991
 
 
3992
 
 
3993
class _UTF8Filesystem(Feature):
 
3994
    """Is the filesystem UTF-8?"""
 
3995
 
 
3996
    def _probe(self):
 
3997
        if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
 
3998
            return True
 
3999
        return False
 
4000
 
 
4001
UTF8Filesystem = _UTF8Filesystem()
 
4002
 
 
4003
 
 
4004
class _CaseInsCasePresFilenameFeature(Feature):
 
4005
    """Is the file-system case insensitive, but case-preserving?"""
 
4006
 
 
4007
    def _probe(self):
 
4008
        fileno, name = tempfile.mkstemp(prefix='MixedCase')
 
4009
        try:
 
4010
            # first check truly case-preserving for created files, then check
 
4011
            # case insensitive when opening existing files.
 
4012
            name = osutils.normpath(name)
 
4013
            base, rel = osutils.split(name)
 
4014
            found_rel = osutils.canonical_relpath(base, name)
 
4015
            return (found_rel == rel
 
4016
                    and os.path.isfile(name.upper())
 
4017
                    and os.path.isfile(name.lower()))
 
4018
        finally:
 
4019
            os.close(fileno)
 
4020
            os.remove(name)
 
4021
 
 
4022
    def feature_name(self):
 
4023
        return "case-insensitive case-preserving filesystem"
 
4024
 
 
4025
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
 
4026
 
 
4027
 
 
4028
class _CaseInsensitiveFilesystemFeature(Feature):
 
4029
    """Check if underlying filesystem is case-insensitive but *not* case
 
4030
    preserving.
 
4031
    """
 
4032
    # Note that on Windows, Cygwin, MacOS etc, the file-systems are far
 
4033
    # more likely to be case preserving, so this case is rare.
 
4034
 
 
4035
    def _probe(self):
 
4036
        if CaseInsCasePresFilenameFeature.available():
 
4037
            return False
 
4038
 
 
4039
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
 
4040
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
 
4041
            TestCaseWithMemoryTransport.TEST_ROOT = root
 
4042
        else:
 
4043
            root = TestCaseWithMemoryTransport.TEST_ROOT
 
4044
        tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
 
4045
            dir=root)
 
4046
        name_a = osutils.pathjoin(tdir, 'a')
 
4047
        name_A = osutils.pathjoin(tdir, 'A')
 
4048
        os.mkdir(name_a)
 
4049
        result = osutils.isdir(name_A)
 
4050
        _rmtree_temp_dir(tdir)
 
4051
        return result
 
4052
 
 
4053
    def feature_name(self):
 
4054
        return 'case-insensitive filesystem'
 
4055
 
 
4056
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
 
4057
 
 
4058
 
 
4059
class _SubUnitFeature(Feature):
 
4060
    """Check if subunit is available."""
 
4061
 
 
4062
    def _probe(self):
 
4063
        try:
 
4064
            import subunit
 
4065
            return True
 
4066
        except ImportError:
 
4067
            return False
 
4068
 
 
4069
    def feature_name(self):
 
4070
        return 'subunit'
 
4071
 
 
4072
SubUnitFeature = _SubUnitFeature()
 
4073
# Only define SubUnitBzrRunner if subunit is available.
 
4074
try:
 
4075
    from subunit import TestProtocolClient
 
4076
    try:
 
4077
        from subunit.test_results import AutoTimingTestResultDecorator
 
4078
    except ImportError:
 
4079
        AutoTimingTestResultDecorator = lambda x:x
 
4080
    class SubUnitBzrRunner(TextTestRunner):
 
4081
        def run(self, test):
 
4082
            result = AutoTimingTestResultDecorator(
 
4083
                TestProtocolClient(self.stream))
 
4084
            test.run(result)
 
4085
            return result
 
4086
except ImportError:
 
4087
    pass