~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-09-01 08:02:42 UTC
  • mfrom: (5390.3.3 faster-revert-593560)
  • Revision ID: pqm@pqm.ubuntu.com-20100901080242-esg62ody4frwmy66
(spiv) Avoid repeatedly calling self.target.all_file_ids() in
 InterTree.iter_changes. (Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2005-2010 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
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
"""Testing framework extensions"""
17
18
 
18
19
# TODO: Perhaps there should be an API to find out if bzr running under the
19
20
# test suite -- some plugins might want to avoid making intrusive changes if
28
29
 
29
30
import atexit
30
31
import codecs
 
32
import copy
31
33
from cStringIO import StringIO
32
34
import difflib
33
35
import doctest
34
36
import errno
 
37
import itertools
35
38
import logging
36
39
import math
37
40
import os
38
 
from pprint import pformat
 
41
import pprint
39
42
import random
40
43
import re
41
44
import shlex
42
45
import stat
43
 
from subprocess import Popen, PIPE, STDOUT
 
46
import subprocess
44
47
import sys
45
48
import tempfile
46
49
import threading
47
50
import time
 
51
import traceback
48
52
import unittest
49
53
import warnings
50
54
 
 
55
import testtools
 
56
# nb: check this before importing anything else from within it
 
57
_testtools_version = getattr(testtools, '__version__', ())
 
58
if _testtools_version < (0, 9, 2):
 
59
    raise ImportError("need at least testtools 0.9.2: %s is %r"
 
60
        % (testtools.__file__, _testtools_version))
 
61
from testtools import content
51
62
 
52
63
from bzrlib import (
53
64
    branchbuilder,
54
65
    bzrdir,
 
66
    chk_map,
 
67
    config,
55
68
    debug,
56
69
    errors,
57
70
    hooks,
62
75
    ui,
63
76
    urlutils,
64
77
    registry,
 
78
    transport as _mod_transport,
65
79
    workingtree,
66
80
    )
67
81
import bzrlib.branch
85
99
from bzrlib.symbol_versioning import (
86
100
    DEPRECATED_PARAMETER,
87
101
    deprecated_function,
 
102
    deprecated_in,
88
103
    deprecated_method,
89
104
    deprecated_passed,
90
105
    )
91
106
import bzrlib.trace
92
 
from bzrlib.transport import get_transport
93
 
import bzrlib.transport
94
 
from bzrlib.transport.local import LocalURLServer
95
 
from bzrlib.transport.memory import MemoryServer
96
 
from bzrlib.transport.readonly import ReadonlyServer
 
107
from bzrlib.transport import (
 
108
    memory,
 
109
    pathfilter,
 
110
    )
97
111
from bzrlib.trace import mutter, note
98
 
from bzrlib.tests import TestUtil
99
 
from bzrlib.tests.http_server import HttpServer
100
 
from bzrlib.tests.TestUtil import (
101
 
                          TestSuite,
102
 
                          TestLoader,
103
 
                          )
104
 
from bzrlib.tests.treeshape import build_tree_contents
 
112
from bzrlib.tests import (
 
113
    test_server,
 
114
    TestUtil,
 
115
    treeshape,
 
116
    )
 
117
from bzrlib.ui import NullProgressView
105
118
from bzrlib.ui.text import TextUIFactory
106
119
import bzrlib.version_info_formats.format_custom
107
120
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
111
124
# shown frame is the test code, not our assertXYZ.
112
125
__unittest = 1
113
126
 
114
 
default_transport = LocalURLServer
115
 
 
116
 
 
117
 
class ExtendedTestResult(unittest._TextTestResult):
 
127
default_transport = test_server.LocalURLServer
 
128
 
 
129
 
 
130
_unitialized_attr = object()
 
131
"""A sentinel needed to act as a default value in a method signature."""
 
132
 
 
133
 
 
134
# Subunit result codes, defined here to prevent a hard dependency on subunit.
 
135
SUBUNIT_SEEK_SET = 0
 
136
SUBUNIT_SEEK_CUR = 1
 
137
 
 
138
 
 
139
class ExtendedTestResult(testtools.TextTestResult):
118
140
    """Accepts, reports and accumulates the results of running tests.
119
141
 
120
142
    Compared to the unittest version this class adds support for
134
156
 
135
157
    def __init__(self, stream, descriptions, verbosity,
136
158
                 bench_history=None,
137
 
                 num_tests=None,
138
159
                 strict=False,
139
160
                 ):
140
161
        """Construct new TestResult.
142
163
        :param bench_history: Optionally, a writable file object to accumulate
143
164
            benchmark results.
144
165
        """
145
 
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
 
166
        testtools.TextTestResult.__init__(self, stream)
146
167
        if bench_history is not None:
147
168
            from bzrlib.version import _get_bzr_source_tree
148
169
            src_tree = _get_bzr_source_tree()
159
180
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
160
181
        self._bench_history = bench_history
161
182
        self.ui = ui.ui_factory
162
 
        self.num_tests = num_tests
 
183
        self.num_tests = 0
163
184
        self.error_count = 0
164
185
        self.failure_count = 0
165
186
        self.known_failure_count = 0
170
191
        self._overall_start_time = time.time()
171
192
        self._strict = strict
172
193
 
173
 
    def done(self):
 
194
    def stopTestRun(self):
 
195
        run = self.testsRun
 
196
        actionTaken = "Ran"
 
197
        stopTime = time.time()
 
198
        timeTaken = stopTime - self.startTime
 
199
        # GZ 2010-07-19: Seems testtools has no printErrors method, and though
 
200
        #                the parent class method is similar have to duplicate
 
201
        self._show_list('ERROR', self.errors)
 
202
        self._show_list('FAIL', self.failures)
 
203
        self.stream.write(self.sep2)
 
204
        self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
 
205
                            run, run != 1 and "s" or "", timeTaken))
 
206
        if not self.wasSuccessful():
 
207
            self.stream.write("FAILED (")
 
208
            failed, errored = map(len, (self.failures, self.errors))
 
209
            if failed:
 
210
                self.stream.write("failures=%d" % failed)
 
211
            if errored:
 
212
                if failed: self.stream.write(", ")
 
213
                self.stream.write("errors=%d" % errored)
 
214
            if self.known_failure_count:
 
215
                if failed or errored: self.stream.write(", ")
 
216
                self.stream.write("known_failure_count=%d" %
 
217
                    self.known_failure_count)
 
218
            self.stream.write(")\n")
 
219
        else:
 
220
            if self.known_failure_count:
 
221
                self.stream.write("OK (known_failures=%d)\n" %
 
222
                    self.known_failure_count)
 
223
            else:
 
224
                self.stream.write("OK\n")
 
225
        if self.skip_count > 0:
 
226
            skipped = self.skip_count
 
227
            self.stream.write('%d test%s skipped\n' %
 
228
                                (skipped, skipped != 1 and "s" or ""))
 
229
        if self.unsupported:
 
230
            for feature, count in sorted(self.unsupported.items()):
 
231
                self.stream.write("Missing feature '%s' skipped %d tests.\n" %
 
232
                    (feature, count))
174
233
        if self._strict:
175
234
            ok = self.wasStrictlySuccessful()
176
235
        else:
177
236
            ok = self.wasSuccessful()
178
 
        if ok:
179
 
            self.stream.write('tests passed\n')
180
 
        else:
181
 
            self.stream.write('tests failed\n')
182
237
        if TestCase._first_thread_leaker_id:
183
238
            self.stream.write(
184
239
                '%s is leaking threads among %d leaking tests.\n' % (
185
240
                TestCase._first_thread_leaker_id,
186
241
                TestCase._leaking_threads_tests))
187
 
 
188
 
    def _extractBenchmarkTime(self, testCase):
 
242
            # We don't report the main thread as an active one.
 
243
            self.stream.write(
 
244
                '%d non-main threads were left active in the end.\n'
 
245
                % (TestCase._active_threads - 1))
 
246
 
 
247
    def getDescription(self, test):
 
248
        return test.id()
 
249
 
 
250
    def _extractBenchmarkTime(self, testCase, details=None):
189
251
        """Add a benchmark time for the current test case."""
 
252
        if details and 'benchtime' in details:
 
253
            return float(''.join(details['benchtime'].iter_bytes()))
190
254
        return getattr(testCase, "_benchtime", None)
191
255
 
192
256
    def _elapsedTestTimeString(self):
208
272
 
209
273
    def _shortened_test_description(self, test):
210
274
        what = test.id()
211
 
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
 
275
        what = re.sub(r'^bzrlib\.tests\.', '', what)
212
276
        return what
213
277
 
214
278
    def startTest(self, test):
215
 
        unittest.TestResult.startTest(self, test)
 
279
        super(ExtendedTestResult, self).startTest(test)
216
280
        if self.count == 0:
217
281
            self.startTests()
218
282
        self.report_test_start(test)
220
284
        self._recordTestStartTime()
221
285
 
222
286
    def startTests(self):
223
 
        self.stream.write(
224
 
            'testing: %s\n' % (osutils.realpath(sys.argv[0]),))
225
 
        self.stream.write(
226
 
            '   %s (%s python%s)\n' % (
227
 
                    bzrlib.__path__[0],
 
287
        import platform
 
288
        if getattr(sys, 'frozen', None) is None:
 
289
            bzr_path = osutils.realpath(sys.argv[0])
 
290
        else:
 
291
            bzr_path = sys.executable
 
292
        self.stream.write(
 
293
            'bzr selftest: %s\n' % (bzr_path,))
 
294
        self.stream.write(
 
295
            '   %s\n' % (
 
296
                    bzrlib.__path__[0],))
 
297
        self.stream.write(
 
298
            '   bzr-%s python-%s %s\n' % (
228
299
                    bzrlib.version_string,
229
300
                    bzrlib._format_version_tuple(sys.version_info),
 
301
                    platform.platform(aliased=1),
230
302
                    ))
231
303
        self.stream.write('\n')
232
304
 
247
319
        Called from the TestCase run() method when the test
248
320
        fails with an unexpected error.
249
321
        """
250
 
        self._testConcluded(test)
251
 
        if isinstance(err[1], TestNotApplicable):
252
 
            return self._addNotApplicable(test, err)
253
 
        elif isinstance(err[1], UnavailableFeature):
254
 
            return self.addNotSupported(test, err[1].args[0])
255
 
        else:
256
 
            unittest.TestResult.addError(self, test, err)
257
 
            self.error_count += 1
258
 
            self.report_error(test, err)
259
 
            if self.stop_early:
260
 
                self.stop()
261
 
            self._cleanupLogFile(test)
 
322
        self._post_mortem()
 
323
        super(ExtendedTestResult, self).addError(test, err)
 
324
        self.error_count += 1
 
325
        self.report_error(test, err)
 
326
        if self.stop_early:
 
327
            self.stop()
 
328
        self._cleanupLogFile(test)
262
329
 
263
330
    def addFailure(self, test, err):
264
331
        """Tell result that test failed.
266
333
        Called from the TestCase run() method when the test
267
334
        fails because e.g. an assert() method failed.
268
335
        """
269
 
        self._testConcluded(test)
270
 
        if isinstance(err[1], KnownFailure):
271
 
            return self._addKnownFailure(test, err)
272
 
        else:
273
 
            unittest.TestResult.addFailure(self, test, err)
274
 
            self.failure_count += 1
275
 
            self.report_failure(test, err)
276
 
            if self.stop_early:
277
 
                self.stop()
278
 
            self._cleanupLogFile(test)
 
336
        self._post_mortem()
 
337
        super(ExtendedTestResult, self).addFailure(test, err)
 
338
        self.failure_count += 1
 
339
        self.report_failure(test, err)
 
340
        if self.stop_early:
 
341
            self.stop()
 
342
        self._cleanupLogFile(test)
279
343
 
280
 
    def addSuccess(self, test):
 
344
    def addSuccess(self, test, details=None):
281
345
        """Tell result that test completed successfully.
282
346
 
283
347
        Called from the TestCase run()
284
348
        """
285
 
        self._testConcluded(test)
286
349
        if self._bench_history is not None:
287
 
            benchmark_time = self._extractBenchmarkTime(test)
 
350
            benchmark_time = self._extractBenchmarkTime(test, details)
288
351
            if benchmark_time is not None:
289
352
                self._bench_history.write("%s %s\n" % (
290
353
                    self._formatTime(benchmark_time),
291
354
                    test.id()))
292
355
        self.report_success(test)
293
356
        self._cleanupLogFile(test)
294
 
        unittest.TestResult.addSuccess(self, test)
 
357
        super(ExtendedTestResult, self).addSuccess(test)
295
358
        test._log_contents = ''
296
359
 
297
 
    def _testConcluded(self, test):
298
 
        """Common code when a test has finished.
299
 
 
300
 
        Called regardless of whether it succeded, failed, etc.
301
 
        """
302
 
        pass
303
 
 
304
 
    def _addKnownFailure(self, test, err):
 
360
    def addExpectedFailure(self, test, err):
305
361
        self.known_failure_count += 1
306
362
        self.report_known_failure(test, err)
307
363
 
309
365
        """The test will not be run because of a missing feature.
310
366
        """
311
367
        # this can be called in two different ways: it may be that the
312
 
        # test started running, and then raised (through addError)
 
368
        # test started running, and then raised (through requireFeature)
313
369
        # UnavailableFeature.  Alternatively this method can be called
314
 
        # while probing for features before running the tests; in that
315
 
        # case we will see startTest and stopTest, but the test will never
316
 
        # actually run.
 
370
        # while probing for features before running the test code proper; in
 
371
        # that case we will see startTest and stopTest, but the test will
 
372
        # never actually run.
317
373
        self.unsupported.setdefault(str(feature), 0)
318
374
        self.unsupported[str(feature)] += 1
319
375
        self.report_unsupported(test, feature)
323
379
        self.skip_count += 1
324
380
        self.report_skip(test, reason)
325
381
 
326
 
    def _addNotApplicable(self, test, skip_excinfo):
327
 
        if isinstance(skip_excinfo[1], TestNotApplicable):
328
 
            self.not_applicable_count += 1
329
 
            self.report_not_applicable(test, skip_excinfo)
330
 
        try:
331
 
            test.tearDown()
332
 
        except KeyboardInterrupt:
333
 
            raise
334
 
        except:
335
 
            self.addError(test, test.exc_info())
 
382
    def addNotApplicable(self, test, reason):
 
383
        self.not_applicable_count += 1
 
384
        self.report_not_applicable(test, reason)
 
385
 
 
386
    def _post_mortem(self):
 
387
        """Start a PDB post mortem session."""
 
388
        if os.environ.get('BZR_TEST_PDB', None):
 
389
            import pdb;pdb.post_mortem()
 
390
 
 
391
    def progress(self, offset, whence):
 
392
        """The test is adjusting the count of tests to run."""
 
393
        if whence == SUBUNIT_SEEK_SET:
 
394
            self.num_tests = offset
 
395
        elif whence == SUBUNIT_SEEK_CUR:
 
396
            self.num_tests += offset
336
397
        else:
337
 
            # seems best to treat this as success from point-of-view of unittest
338
 
            # -- it actually does nothing so it barely matters :)
339
 
            unittest.TestResult.addSuccess(self, test)
340
 
            test._log_contents = ''
341
 
 
342
 
    def printErrorList(self, flavour, errors):
343
 
        for test, err in errors:
344
 
            self.stream.writeln(self.separator1)
345
 
            self.stream.write("%s: " % flavour)
346
 
            self.stream.writeln(self.getDescription(test))
347
 
            if getattr(test, '_get_log', None) is not None:
348
 
                log_contents = test._get_log()
349
 
                if log_contents:
350
 
                    self.stream.write('\n')
351
 
                    self.stream.write(
352
 
                            ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
353
 
                    self.stream.write('\n')
354
 
                    self.stream.write(log_contents)
355
 
                    self.stream.write('\n')
356
 
                    self.stream.write(
357
 
                            ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
358
 
                    self.stream.write('\n')
359
 
            self.stream.writeln(self.separator2)
360
 
            self.stream.writeln("%s" % err)
361
 
 
362
 
    def finished(self):
363
 
        pass
 
398
            raise errors.BzrError("Unknown whence %r" % whence)
364
399
 
365
400
    def report_cleaning_up(self):
366
401
        pass
367
402
 
 
403
    def startTestRun(self):
 
404
        self.startTime = time.time()
 
405
 
368
406
    def report_success(self, test):
369
407
        pass
370
408
 
379
417
 
380
418
    def __init__(self, stream, descriptions, verbosity,
381
419
                 bench_history=None,
382
 
                 num_tests=None,
383
420
                 pb=None,
384
421
                 strict=None,
385
422
                 ):
386
423
        ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
387
 
            bench_history, num_tests, strict)
388
 
        if pb is None:
389
 
            self.pb = self.ui.nested_progress_bar()
390
 
            self._supplied_pb = False
391
 
        else:
392
 
            self.pb = pb
393
 
            self._supplied_pb = True
 
424
            bench_history, strict)
 
425
        # We no longer pass them around, but just rely on the UIFactory stack
 
426
        # for state
 
427
        if pb is not None:
 
428
            warnings.warn("Passing pb to TextTestResult is deprecated")
 
429
        self.pb = self.ui.nested_progress_bar()
394
430
        self.pb.show_pct = False
395
431
        self.pb.show_spinner = False
396
432
        self.pb.show_eta = False,
397
433
        self.pb.show_count = False
398
434
        self.pb.show_bar = False
399
 
 
400
 
    def report_starting(self):
 
435
        self.pb.update_latency = 0
 
436
        self.pb.show_transport_activity = False
 
437
 
 
438
    def stopTestRun(self):
 
439
        # called when the tests that are going to run have run
 
440
        self.pb.clear()
 
441
        self.pb.finished()
 
442
        super(TextTestResult, self).stopTestRun()
 
443
 
 
444
    def startTestRun(self):
 
445
        super(TextTestResult, self).startTestRun()
401
446
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
402
447
 
 
448
    def printErrors(self):
 
449
        # clear the pb to make room for the error listing
 
450
        self.pb.clear()
 
451
        super(TextTestResult, self).printErrors()
 
452
 
403
453
    def _progress_prefix_text(self):
404
454
        # the longer this text, the less space we have to show the test
405
455
        # name...
410
460
        ##     a += ', %d skip' % self.skip_count
411
461
        ## if self.known_failure_count:
412
462
        ##     a += '+%dX' % self.known_failure_count
413
 
        if self.num_tests is not None:
 
463
        if self.num_tests:
414
464
            a +='/%d' % self.num_tests
415
465
        a += ' in '
416
466
        runtime = time.time() - self._overall_start_time
418
468
            a += '%dm%ds' % (runtime / 60, runtime % 60)
419
469
        else:
420
470
            a += '%ds' % runtime
421
 
        if self.error_count:
422
 
            a += ', %d err' % self.error_count
423
 
        if self.failure_count:
424
 
            a += ', %d fail' % self.failure_count
425
 
        if self.unsupported:
426
 
            a += ', %d missing' % len(self.unsupported)
 
471
        total_fail_count = self.error_count + self.failure_count
 
472
        if total_fail_count:
 
473
            a += ', %d failed' % total_fail_count
 
474
        # if self.unsupported:
 
475
        #     a += ', %d missing' % len(self.unsupported)
427
476
        a += ']'
428
477
        return a
429
478
 
438
487
        return self._shortened_test_description(test)
439
488
 
440
489
    def report_error(self, test, err):
441
 
        self.pb.note('ERROR: %s\n    %s\n',
 
490
        self.stream.write('ERROR: %s\n    %s\n' % (
442
491
            self._test_description(test),
443
492
            err[1],
444
 
            )
 
493
            ))
445
494
 
446
495
    def report_failure(self, test, err):
447
 
        self.pb.note('FAIL: %s\n    %s\n',
 
496
        self.stream.write('FAIL: %s\n    %s\n' % (
448
497
            self._test_description(test),
449
498
            err[1],
450
 
            )
 
499
            ))
451
500
 
452
501
    def report_known_failure(self, test, err):
453
 
        self.pb.note('XFAIL: %s\n%s\n',
454
 
            self._test_description(test), err[1])
 
502
        pass
455
503
 
456
504
    def report_skip(self, test, reason):
457
505
        pass
458
506
 
459
 
    def report_not_applicable(self, test, skip_excinfo):
 
507
    def report_not_applicable(self, test, reason):
460
508
        pass
461
509
 
462
510
    def report_unsupported(self, test, feature):
465
513
    def report_cleaning_up(self):
466
514
        self.pb.update('Cleaning up')
467
515
 
468
 
    def finished(self):
469
 
        if not self._supplied_pb:
470
 
            self.pb.finished()
471
 
 
472
516
 
473
517
class VerboseTestResult(ExtendedTestResult):
474
518
    """Produce long output, with one line per test run plus times"""
481
525
            result = a_string
482
526
        return result.ljust(final_width)
483
527
 
484
 
    def report_starting(self):
 
528
    def startTestRun(self):
 
529
        super(VerboseTestResult, self).startTestRun()
485
530
        self.stream.write('running %d tests...\n' % self.num_tests)
486
531
 
487
532
    def report_test_start(self, test):
488
533
        self.count += 1
489
534
        name = self._shortened_test_description(test)
490
 
        # width needs space for 6 char status, plus 1 for slash, plus an
491
 
        # 11-char time string, plus a trailing blank
492
 
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
493
 
        self.stream.write(self._ellipsize_to_right(name,
494
 
                          osutils.terminal_width()-18))
 
535
        width = osutils.terminal_width()
 
536
        if width is not None:
 
537
            # width needs space for 6 char status, plus 1 for slash, plus an
 
538
            # 11-char time string, plus a trailing blank
 
539
            # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on
 
540
            # space
 
541
            self.stream.write(self._ellipsize_to_right(name, width-18))
 
542
        else:
 
543
            self.stream.write(name)
495
544
        self.stream.flush()
496
545
 
497
546
    def _error_summary(self, err):
499
548
        return '%s%s' % (indent, err[1])
500
549
 
501
550
    def report_error(self, test, err):
502
 
        self.stream.writeln('ERROR %s\n%s'
 
551
        self.stream.write('ERROR %s\n%s\n'
503
552
                % (self._testTimeString(test),
504
553
                   self._error_summary(err)))
505
554
 
506
555
    def report_failure(self, test, err):
507
 
        self.stream.writeln(' FAIL %s\n%s'
 
556
        self.stream.write(' FAIL %s\n%s\n'
508
557
                % (self._testTimeString(test),
509
558
                   self._error_summary(err)))
510
559
 
511
560
    def report_known_failure(self, test, err):
512
 
        self.stream.writeln('XFAIL %s\n%s'
 
561
        self.stream.write('XFAIL %s\n%s\n'
513
562
                % (self._testTimeString(test),
514
563
                   self._error_summary(err)))
515
564
 
516
565
    def report_success(self, test):
517
 
        self.stream.writeln('   OK %s' % self._testTimeString(test))
 
566
        self.stream.write('   OK %s\n' % self._testTimeString(test))
518
567
        for bench_called, stats in getattr(test, '_benchcalls', []):
519
 
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
568
            self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
520
569
            stats.pprint(file=self.stream)
521
570
        # flush the stream so that we get smooth output. This verbose mode is
522
571
        # used to show the output in PQM.
523
572
        self.stream.flush()
524
573
 
525
574
    def report_skip(self, test, reason):
526
 
        self.stream.writeln(' SKIP %s\n%s'
 
575
        self.stream.write(' SKIP %s\n%s\n'
527
576
                % (self._testTimeString(test), reason))
528
577
 
529
 
    def report_not_applicable(self, test, skip_excinfo):
530
 
        self.stream.writeln('  N/A %s\n%s'
531
 
                % (self._testTimeString(test),
532
 
                   self._error_summary(skip_excinfo)))
 
578
    def report_not_applicable(self, test, reason):
 
579
        self.stream.write('  N/A %s\n    %s\n'
 
580
                % (self._testTimeString(test), reason))
533
581
 
534
582
    def report_unsupported(self, test, feature):
535
583
        """test cannot be run because feature is missing."""
536
 
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
 
584
        self.stream.write("NODEP %s\n    The feature '%s' is not available.\n"
537
585
                %(self._testTimeString(test), feature))
538
586
 
539
587
 
545
593
                 descriptions=0,
546
594
                 verbosity=1,
547
595
                 bench_history=None,
548
 
                 list_only=False,
549
596
                 strict=False,
 
597
                 result_decorators=None,
550
598
                 ):
551
 
        self.stream = unittest._WritelnDecorator(stream)
 
599
        """Create a TextTestRunner.
 
600
 
 
601
        :param result_decorators: An optional list of decorators to apply
 
602
            to the result object being used by the runner. Decorators are
 
603
            applied left to right - the first element in the list is the 
 
604
            innermost decorator.
 
605
        """
 
606
        # stream may know claim to know to write unicode strings, but in older
 
607
        # pythons this goes sufficiently wrong that it is a bad idea. (
 
608
        # specifically a built in file with encoding 'UTF-8' will still try
 
609
        # to encode using ascii.
 
610
        new_encoding = osutils.get_terminal_encoding()
 
611
        codec = codecs.lookup(new_encoding)
 
612
        if type(codec) is tuple:
 
613
            # Python 2.4
 
614
            encode = codec[0]
 
615
        else:
 
616
            encode = codec.encode
 
617
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream)
 
618
        stream.encoding = new_encoding
 
619
        self.stream = stream
552
620
        self.descriptions = descriptions
553
621
        self.verbosity = verbosity
554
622
        self._bench_history = bench_history
555
 
        self.list_only = list_only
556
623
        self._strict = strict
 
624
        self._result_decorators = result_decorators or []
557
625
 
558
626
    def run(self, test):
559
627
        "Run the given test case or test suite."
560
 
        startTime = time.time()
561
628
        if self.verbosity == 1:
562
629
            result_class = TextTestResult
563
630
        elif self.verbosity >= 2:
564
631
            result_class = VerboseTestResult
565
 
        result = result_class(self.stream,
 
632
        original_result = result_class(self.stream,
566
633
                              self.descriptions,
567
634
                              self.verbosity,
568
635
                              bench_history=self._bench_history,
569
 
                              num_tests=test.countTestCases(),
570
636
                              strict=self._strict,
571
637
                              )
572
 
        result.stop_early = self.stop_on_failure
573
 
        result.report_starting()
574
 
        if self.list_only:
575
 
            if self.verbosity >= 2:
576
 
                self.stream.writeln("Listing tests only ...\n")
577
 
            run = 0
578
 
            for t in iter_suite_tests(test):
579
 
                self.stream.writeln("%s" % (t.id()))
580
 
                run += 1
581
 
            return None
582
 
        else:
583
 
            try:
584
 
                import testtools
585
 
            except ImportError:
586
 
                test.run(result)
587
 
            else:
588
 
                if isinstance(test, testtools.ConcurrentTestSuite):
589
 
                    # We need to catch bzr specific behaviors
590
 
                    test.run(BZRTransformingResult(result))
591
 
                else:
592
 
                    test.run(result)
593
 
            run = result.testsRun
594
 
            actionTaken = "Ran"
595
 
        stopTime = time.time()
596
 
        timeTaken = stopTime - startTime
597
 
        result.printErrors()
598
 
        self.stream.writeln(result.separator2)
599
 
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
600
 
                            run, run != 1 and "s" or "", timeTaken))
601
 
        self.stream.writeln()
602
 
        if not result.wasSuccessful():
603
 
            self.stream.write("FAILED (")
604
 
            failed, errored = map(len, (result.failures, result.errors))
605
 
            if failed:
606
 
                self.stream.write("failures=%d" % failed)
607
 
            if errored:
608
 
                if failed: self.stream.write(", ")
609
 
                self.stream.write("errors=%d" % errored)
610
 
            if result.known_failure_count:
611
 
                if failed or errored: self.stream.write(", ")
612
 
                self.stream.write("known_failure_count=%d" %
613
 
                    result.known_failure_count)
614
 
            self.stream.writeln(")")
615
 
        else:
616
 
            if result.known_failure_count:
617
 
                self.stream.writeln("OK (known_failures=%d)" %
618
 
                    result.known_failure_count)
619
 
            else:
620
 
                self.stream.writeln("OK")
621
 
        if result.skip_count > 0:
622
 
            skipped = result.skip_count
623
 
            self.stream.writeln('%d test%s skipped' %
624
 
                                (skipped, skipped != 1 and "s" or ""))
625
 
        if result.unsupported:
626
 
            for feature, count in sorted(result.unsupported.items()):
627
 
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
628
 
                    (feature, count))
629
 
        result.finished()
630
 
        return result
 
638
        # Signal to result objects that look at stop early policy to stop,
 
639
        original_result.stop_early = self.stop_on_failure
 
640
        result = original_result
 
641
        for decorator in self._result_decorators:
 
642
            result = decorator(result)
 
643
            result.stop_early = self.stop_on_failure
 
644
        result.startTestRun()
 
645
        try:
 
646
            test.run(result)
 
647
        finally:
 
648
            result.stopTestRun()
 
649
        # higher level code uses our extended protocol to determine
 
650
        # what exit code to give.
 
651
        return original_result
631
652
 
632
653
 
633
654
def iter_suite_tests(suite):
643
664
                        % (type(suite), suite))
644
665
 
645
666
 
646
 
class TestSkipped(Exception):
647
 
    """Indicates that a test was intentionally skipped, rather than failing."""
 
667
TestSkipped = testtools.testcase.TestSkipped
648
668
 
649
669
 
650
670
class TestNotApplicable(TestSkipped):
656
676
    """
657
677
 
658
678
 
659
 
class KnownFailure(AssertionError):
660
 
    """Indicates that a test failed in a precisely expected manner.
661
 
 
662
 
    Such failures dont block the whole test suite from passing because they are
663
 
    indicators of partially completed code or of future work. We have an
664
 
    explicit error for them so that we can ensure that they are always visible:
665
 
    KnownFailures are always shown in the output of bzr selftest.
666
 
    """
 
679
# traceback._some_str fails to format exceptions that have the default
 
680
# __str__ which does an implicit ascii conversion. However, repr() on those
 
681
# objects works, for all that its not quite what the doctor may have ordered.
 
682
def _clever_some_str(value):
 
683
    try:
 
684
        return str(value)
 
685
    except:
 
686
        try:
 
687
            return repr(value).replace('\\n', '\n')
 
688
        except:
 
689
            return '<unprintable %s object>' % type(value).__name__
 
690
 
 
691
traceback._some_str = _clever_some_str
 
692
 
 
693
 
 
694
# deprecated - use self.knownFailure(), or self.expectFailure.
 
695
KnownFailure = testtools.testcase._ExpectedFailure
667
696
 
668
697
 
669
698
class UnavailableFeature(Exception):
670
699
    """A feature required for this test was not available.
671
700
 
 
701
    This can be considered a specialised form of SkippedTest.
 
702
 
672
703
    The feature should be used to construct the exception.
673
704
    """
674
705
 
675
706
 
676
 
class CommandFailed(Exception):
677
 
    pass
678
 
 
679
 
 
680
707
class StringIOWrapper(object):
681
708
    """A wrapper around cStringIO which just adds an encoding attribute.
682
709
 
709
736
    Hide the progress bar but emit note()s.
710
737
    Redirect stdin.
711
738
    Allows get_password to be tested without real tty attached.
 
739
 
 
740
    See also CannedInputUIFactory which lets you provide programmatic input in
 
741
    a structured way.
712
742
    """
 
743
    # TODO: Capture progress events at the model level and allow them to be
 
744
    # observed by tests that care.
 
745
    #
 
746
    # XXX: Should probably unify more with CannedInputUIFactory or a
 
747
    # particular configuration of TextUIFactory, or otherwise have a clearer
 
748
    # idea of how they're supposed to be different.
 
749
    # See https://bugs.launchpad.net/bzr/+bug/408213
713
750
 
714
751
    def __init__(self, stdout=None, stderr=None, stdin=None):
715
752
        if stdin is not None:
720
757
            stdin = StringIOWrapper(stdin)
721
758
        super(TestUIFactory, self).__init__(stdin, stdout, stderr)
722
759
 
723
 
    def clear(self):
724
 
        """See progress.ProgressBar.clear()."""
725
 
 
726
 
    def clear_term(self):
727
 
        """See progress.ProgressBar.clear_term()."""
728
 
 
729
 
    def finished(self):
730
 
        """See progress.ProgressBar.finished()."""
731
 
 
732
 
    def note(self, fmt_string, *args):
733
 
        """See progress.ProgressBar.note()."""
734
 
        if args:
735
 
            fmt_string = fmt_string % args
736
 
        self.stdout.write(fmt_string + "\n")
737
 
 
738
 
    def progress_bar(self):
739
 
        return self
740
 
 
741
 
    def nested_progress_bar(self):
742
 
        return self
743
 
 
744
 
    def update(self, message, count=None, total=None):
745
 
        """See progress.ProgressBar.update()."""
746
 
 
747
760
    def get_non_echoed_password(self):
748
761
        """Get password from stdin without trying to handle the echo mode"""
749
762
        password = self.stdin.readline()
753
766
            password = password[:-1]
754
767
        return password
755
768
 
756
 
 
757
 
class TestCase(unittest.TestCase):
 
769
    def make_progress_view(self):
 
770
        return NullProgressView()
 
771
 
 
772
 
 
773
class TestCase(testtools.TestCase):
758
774
    """Base class for bzr unit tests.
759
775
 
760
776
    Tests that need access to disk resources should subclass
779
795
    _leaking_threads_tests = 0
780
796
    _first_thread_leaker_id = None
781
797
    _log_file_name = None
782
 
    _log_contents = ''
783
 
    _keep_log_file = False
784
798
    # record lsprof data when performing benchmark calls.
785
799
    _gather_lsprof_in_benchmarks = False
786
 
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
787
 
                     '_log_contents', '_log_file_name', '_benchtime',
788
 
                     '_TestCase__testMethodName', '_TestCase__testMethodDoc',)
789
800
 
790
801
    def __init__(self, methodName='testMethod'):
791
802
        super(TestCase, self).__init__(methodName)
792
803
        self._cleanups = []
793
 
        self._bzr_test_setUp_run = False
794
 
        self._bzr_test_tearDown_run = False
 
804
        self._directory_isolation = True
 
805
        self.exception_handlers.insert(0,
 
806
            (UnavailableFeature, self._do_unsupported_or_skip))
 
807
        self.exception_handlers.insert(0,
 
808
            (TestNotApplicable, self._do_not_applicable))
795
809
 
796
810
    def setUp(self):
797
 
        unittest.TestCase.setUp(self)
798
 
        self._bzr_test_setUp_run = True
 
811
        super(TestCase, self).setUp()
 
812
        for feature in getattr(self, '_test_needs_features', []):
 
813
            self.requireFeature(feature)
 
814
        self._log_contents = None
 
815
        self.addDetail("log", content.Content(content.ContentType("text",
 
816
            "plain", {"charset": "utf8"}),
 
817
            lambda:[self._get_log(keep_log_file=True)]))
799
818
        self._cleanEnvironment()
800
819
        self._silenceUI()
801
820
        self._startLogFile()
802
821
        self._benchcalls = []
803
822
        self._benchtime = None
804
823
        self._clear_hooks()
805
 
        # Track locks - needs to be called before _clear_debug_flags.
 
824
        self._track_transports()
806
825
        self._track_locks()
807
826
        self._clear_debug_flags()
808
827
        TestCase._active_threads = threading.activeCount()
817
836
        active = threading.activeCount()
818
837
        leaked_threads = active - TestCase._active_threads
819
838
        TestCase._active_threads = active
820
 
        if leaked_threads:
 
839
        # If some tests make the number of threads *decrease*, we'll consider
 
840
        # that they are just observing old threads dieing, not agressively kill
 
841
        # random threads. So we don't report these tests as leaking. The risk
 
842
        # is that we have false positives that way (the test see 2 threads
 
843
        # going away but leak one) but it seems less likely than the actual
 
844
        # false positives (the test see threads going away and does not leak).
 
845
        if leaked_threads > 0:
 
846
            if 'threads' in selftest_debug_flags:
 
847
                print '%s is leaking, active is now %d' % (self.id(), active)
821
848
            TestCase._leaking_threads_tests += 1
822
849
            if TestCase._first_thread_leaker_id is None:
823
850
                TestCase._first_thread_leaker_id = self.id()
828
855
        Tests that want to use debug flags can just set them in the
829
856
        debug_flags set during setup/teardown.
830
857
        """
831
 
        self._preserved_debug_flags = set(debug.debug_flags)
 
858
        # Start with a copy of the current debug flags we can safely modify.
 
859
        self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
832
860
        if 'allow_debug' not in selftest_debug_flags:
833
861
            debug.debug_flags.clear()
834
 
        self.addCleanup(self._restore_debug_flags)
 
862
        if 'disable_lock_checks' not in selftest_debug_flags:
 
863
            debug.debug_flags.add('strict_locks')
835
864
 
836
865
    def _clear_hooks(self):
837
866
        # prevent hooks affecting tests
847
876
        # this hook should always be installed
848
877
        request._install_hook()
849
878
 
 
879
    def disable_directory_isolation(self):
 
880
        """Turn off directory isolation checks."""
 
881
        self._directory_isolation = False
 
882
 
 
883
    def enable_directory_isolation(self):
 
884
        """Enable directory isolation checks."""
 
885
        self._directory_isolation = True
 
886
 
850
887
    def _silenceUI(self):
851
888
        """Turn off UI for duration of test"""
852
889
        # by default the UI is off; tests can turn it on if they want it.
853
 
        saved = ui.ui_factory
854
 
        def _restore():
855
 
            ui.ui_factory = saved
856
 
        ui.ui_factory = ui.SilentUIFactory()
857
 
        self.addCleanup(_restore)
 
890
        self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
858
891
 
859
892
    def _check_locks(self):
860
893
        """Check that all lock take/release actions have been paired."""
861
 
        # once we have fixed all the current lock problems, we can change the
862
 
        # following code to always check for mismatched locks, but only do
863
 
        # traceback showing with -Dlock (self._lock_check_thorough is True).
864
 
        # For now, because the test suite will fail, we only assert that lock
865
 
        # matching has occured with -Dlock.
 
894
        # We always check for mismatched locks. If a mismatch is found, we
 
895
        # fail unless -Edisable_lock_checks is supplied to selftest, in which
 
896
        # case we just print a warning.
866
897
        # unhook:
867
898
        acquired_locks = [lock for action, lock in self._lock_actions
868
899
                          if action == 'acquired']
887
918
    def _track_locks(self):
888
919
        """Track lock activity during tests."""
889
920
        self._lock_actions = []
890
 
        self._lock_check_thorough = 'lock' not in debug.debug_flags
 
921
        if 'disable_lock_checks' in selftest_debug_flags:
 
922
            self._lock_check_thorough = False
 
923
        else:
 
924
            self._lock_check_thorough = True
 
925
 
891
926
        self.addCleanup(self._check_locks)
892
927
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
893
928
                                                self._lock_acquired, None)
905
940
    def _lock_broken(self, result):
906
941
        self._lock_actions.append(('broken', result))
907
942
 
 
943
    def permit_dir(self, name):
 
944
        """Permit a directory to be used by this test. See permit_url."""
 
945
        name_transport = _mod_transport.get_transport(name)
 
946
        self.permit_url(name)
 
947
        self.permit_url(name_transport.base)
 
948
 
 
949
    def permit_url(self, url):
 
950
        """Declare that url is an ok url to use in this test.
 
951
        
 
952
        Do this for memory transports, temporary test directory etc.
 
953
        
 
954
        Do not do this for the current working directory, /tmp, or any other
 
955
        preexisting non isolated url.
 
956
        """
 
957
        if not url.endswith('/'):
 
958
            url += '/'
 
959
        self._bzr_selftest_roots.append(url)
 
960
 
 
961
    def permit_source_tree_branch_repo(self):
 
962
        """Permit the source tree bzr is running from to be opened.
 
963
 
 
964
        Some code such as bzrlib.version attempts to read from the bzr branch
 
965
        that bzr is executing from (if any). This method permits that directory
 
966
        to be used in the test suite.
 
967
        """
 
968
        path = self.get_source_path()
 
969
        self.record_directory_isolation()
 
970
        try:
 
971
            try:
 
972
                workingtree.WorkingTree.open(path)
 
973
            except (errors.NotBranchError, errors.NoWorkingTree):
 
974
                return
 
975
        finally:
 
976
            self.enable_directory_isolation()
 
977
 
 
978
    def _preopen_isolate_transport(self, transport):
 
979
        """Check that all transport openings are done in the test work area."""
 
980
        while isinstance(transport, pathfilter.PathFilteringTransport):
 
981
            # Unwrap pathfiltered transports
 
982
            transport = transport.server.backing_transport.clone(
 
983
                transport._filter('.'))
 
984
        url = transport.base
 
985
        # ReadonlySmartTCPServer_for_testing decorates the backing transport
 
986
        # urls it is given by prepending readonly+. This is appropriate as the
 
987
        # client shouldn't know that the server is readonly (or not readonly).
 
988
        # We could register all servers twice, with readonly+ prepending, but
 
989
        # that makes for a long list; this is about the same but easier to
 
990
        # read.
 
991
        if url.startswith('readonly+'):
 
992
            url = url[len('readonly+'):]
 
993
        self._preopen_isolate_url(url)
 
994
 
 
995
    def _preopen_isolate_url(self, url):
 
996
        if not self._directory_isolation:
 
997
            return
 
998
        if self._directory_isolation == 'record':
 
999
            self._bzr_selftest_roots.append(url)
 
1000
            return
 
1001
        # This prevents all transports, including e.g. sftp ones backed on disk
 
1002
        # from working unless they are explicitly granted permission. We then
 
1003
        # depend on the code that sets up test transports to check that they are
 
1004
        # appropriately isolated and enable their use by calling
 
1005
        # self.permit_transport()
 
1006
        if not osutils.is_inside_any(self._bzr_selftest_roots, url):
 
1007
            raise errors.BzrError("Attempt to escape test isolation: %r %r"
 
1008
                % (url, self._bzr_selftest_roots))
 
1009
 
 
1010
    def record_directory_isolation(self):
 
1011
        """Gather accessed directories to permit later access.
 
1012
        
 
1013
        This is used for tests that access the branch bzr is running from.
 
1014
        """
 
1015
        self._directory_isolation = "record"
 
1016
 
 
1017
    def start_server(self, transport_server, backing_server=None):
 
1018
        """Start transport_server for this test.
 
1019
 
 
1020
        This starts the server, registers a cleanup for it and permits the
 
1021
        server's urls to be used.
 
1022
        """
 
1023
        if backing_server is None:
 
1024
            transport_server.start_server()
 
1025
        else:
 
1026
            transport_server.start_server(backing_server)
 
1027
        self.addCleanup(transport_server.stop_server)
 
1028
        # Obtain a real transport because if the server supplies a password, it
 
1029
        # will be hidden from the base on the client side.
 
1030
        t = _mod_transport.get_transport(transport_server.get_url())
 
1031
        # Some transport servers effectively chroot the backing transport;
 
1032
        # others like SFTPServer don't - users of the transport can walk up the
 
1033
        # transport to read the entire backing transport. This wouldn't matter
 
1034
        # except that the workdir tests are given - and that they expect the
 
1035
        # server's url to point at - is one directory under the safety net. So
 
1036
        # Branch operations into the transport will attempt to walk up one
 
1037
        # directory. Chrooting all servers would avoid this but also mean that
 
1038
        # we wouldn't be testing directly against non-root urls. Alternatively
 
1039
        # getting the test framework to start the server with a backing server
 
1040
        # at the actual safety net directory would work too, but this then
 
1041
        # means that the self.get_url/self.get_transport methods would need
 
1042
        # to transform all their results. On balance its cleaner to handle it
 
1043
        # here, and permit a higher url when we have one of these transports.
 
1044
        if t.base.endswith('/work/'):
 
1045
            # we have safety net/test root/work
 
1046
            t = t.clone('../..')
 
1047
        elif isinstance(transport_server,
 
1048
                        test_server.SmartTCPServer_for_testing):
 
1049
            # The smart server adds a path similar to work, which is traversed
 
1050
            # up from by the client. But the server is chrooted - the actual
 
1051
            # backing transport is not escaped from, and VFS requests to the
 
1052
            # root will error (because they try to escape the chroot).
 
1053
            t2 = t.clone('..')
 
1054
            while t2.base != t.base:
 
1055
                t = t2
 
1056
                t2 = t.clone('..')
 
1057
        self.permit_url(t.base)
 
1058
 
 
1059
    def _track_transports(self):
 
1060
        """Install checks for transport usage."""
 
1061
        # TestCase has no safe place it can write to.
 
1062
        self._bzr_selftest_roots = []
 
1063
        # Currently the easiest way to be sure that nothing is going on is to
 
1064
        # hook into bzr dir opening. This leaves a small window of error for
 
1065
        # transport tests, but they are well known, and we can improve on this
 
1066
        # step.
 
1067
        bzrdir.BzrDir.hooks.install_named_hook("pre_open",
 
1068
            self._preopen_isolate_transport, "Check bzr directories are safe.")
 
1069
 
908
1070
    def _ndiff_strings(self, a, b):
909
1071
        """Return ndiff between two strings containing lines.
910
1072
 
932
1094
            message += '\n'
933
1095
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
934
1096
            % (message,
935
 
               pformat(a), pformat(b)))
 
1097
               pprint.pformat(a), pprint.pformat(b)))
936
1098
 
937
1099
    assertEquals = assertEqual
938
1100
 
947
1109
            return
948
1110
        if message is None:
949
1111
            message = "texts not equal:\n"
 
1112
        if a + '\n' == b:
 
1113
            message = 'first string is missing a final newline.\n'
950
1114
        if a == b + '\n':
951
 
            message = 'first string is missing a final newline.\n'
952
 
        if a + '\n' == b:
953
1115
            message = 'second string is missing a final newline.\n'
954
1116
        raise AssertionError(message +
955
1117
                             self._ndiff_strings(a, b))
966
1128
        :raises AssertionError: If the expected and actual stat values differ
967
1129
            other than by atime.
968
1130
        """
969
 
        self.assertEqual(expected.st_size, actual.st_size)
970
 
        self.assertEqual(expected.st_mtime, actual.st_mtime)
971
 
        self.assertEqual(expected.st_ctime, actual.st_ctime)
972
 
        self.assertEqual(expected.st_dev, actual.st_dev)
973
 
        self.assertEqual(expected.st_ino, actual.st_ino)
974
 
        self.assertEqual(expected.st_mode, actual.st_mode)
 
1131
        self.assertEqual(expected.st_size, actual.st_size,
 
1132
                         'st_size did not match')
 
1133
        self.assertEqual(expected.st_mtime, actual.st_mtime,
 
1134
                         'st_mtime did not match')
 
1135
        self.assertEqual(expected.st_ctime, actual.st_ctime,
 
1136
                         'st_ctime did not match')
 
1137
        if sys.platform != 'win32':
 
1138
            # On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
 
1139
            # is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
 
1140
            # odd. Regardless we shouldn't actually try to assert anything
 
1141
            # about their values
 
1142
            self.assertEqual(expected.st_dev, actual.st_dev,
 
1143
                             'st_dev did not match')
 
1144
            self.assertEqual(expected.st_ino, actual.st_ino,
 
1145
                             'st_ino did not match')
 
1146
        self.assertEqual(expected.st_mode, actual.st_mode,
 
1147
                         'st_mode did not match')
975
1148
 
976
1149
    def assertLength(self, length, obj_with_len):
977
1150
        """Assert that obj_with_len is of length length."""
979
1152
            self.fail("Incorrect length: wanted %d, got %d for %r" % (
980
1153
                length, len(obj_with_len), obj_with_len))
981
1154
 
 
1155
    def assertLogsError(self, exception_class, func, *args, **kwargs):
 
1156
        """Assert that func(*args, **kwargs) quietly logs a specific exception.
 
1157
        """
 
1158
        from bzrlib import trace
 
1159
        captured = []
 
1160
        orig_log_exception_quietly = trace.log_exception_quietly
 
1161
        try:
 
1162
            def capture():
 
1163
                orig_log_exception_quietly()
 
1164
                captured.append(sys.exc_info())
 
1165
            trace.log_exception_quietly = capture
 
1166
            func(*args, **kwargs)
 
1167
        finally:
 
1168
            trace.log_exception_quietly = orig_log_exception_quietly
 
1169
        self.assertLength(1, captured)
 
1170
        err = captured[0][1]
 
1171
        self.assertIsInstance(err, exception_class)
 
1172
        return err
 
1173
 
982
1174
    def assertPositive(self, val):
983
1175
        """Assert that val is greater than 0."""
984
1176
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
1014
1206
            raise AssertionError('pattern "%s" found in "%s"'
1015
1207
                    % (needle_re, haystack))
1016
1208
 
 
1209
    def assertContainsString(self, haystack, needle):
 
1210
        if haystack.find(needle) == -1:
 
1211
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
 
1212
 
1017
1213
    def assertSubset(self, sublist, superlist):
1018
1214
        """Assert that every entry in sublist is present in superlist."""
1019
1215
        missing = set(sublist) - set(superlist)
1106
1302
                m += ": " + msg
1107
1303
            self.fail(m)
1108
1304
 
1109
 
    def expectFailure(self, reason, assertion, *args, **kwargs):
1110
 
        """Invoke a test, expecting it to fail for the given reason.
1111
 
 
1112
 
        This is for assertions that ought to succeed, but currently fail.
1113
 
        (The failure is *expected* but not *wanted*.)  Please be very precise
1114
 
        about the failure you're expecting.  If a new bug is introduced,
1115
 
        AssertionError should be raised, not KnownFailure.
1116
 
 
1117
 
        Frequently, expectFailure should be followed by an opposite assertion.
1118
 
        See example below.
1119
 
 
1120
 
        Intended to be used with a callable that raises AssertionError as the
1121
 
        'assertion' parameter.  args and kwargs are passed to the 'assertion'.
1122
 
 
1123
 
        Raises KnownFailure if the test fails.  Raises AssertionError if the
1124
 
        test succeeds.
1125
 
 
1126
 
        example usage::
1127
 
 
1128
 
          self.expectFailure('Math is broken', self.assertNotEqual, 54,
1129
 
                             dynamic_val)
1130
 
          self.assertEqual(42, dynamic_val)
1131
 
 
1132
 
          This means that a dynamic_val of 54 will cause the test to raise
1133
 
          a KnownFailure.  Once math is fixed and the expectFailure is removed,
1134
 
          only a dynamic_val of 42 will allow the test to pass.  Anything other
1135
 
          than 54 or 42 will cause an AssertionError.
1136
 
        """
1137
 
        try:
1138
 
            assertion(*args, **kwargs)
1139
 
        except AssertionError:
1140
 
            raise KnownFailure(reason)
1141
 
        else:
1142
 
            self.fail('Unexpected success.  Should have failed: %s' % reason)
1143
 
 
1144
1305
    def assertFileEqual(self, content, path):
1145
1306
        """Fail if path does not contain 'content'."""
1146
1307
        self.failUnlessExists(path)
1151
1312
            f.close()
1152
1313
        self.assertEqualDiff(content, s)
1153
1314
 
 
1315
    def assertDocstring(self, expected_docstring, obj):
 
1316
        """Fail if obj does not have expected_docstring"""
 
1317
        if __doc__ is None:
 
1318
            # With -OO the docstring should be None instead
 
1319
            self.assertIs(obj.__doc__, None)
 
1320
        else:
 
1321
            self.assertEqual(expected_docstring, obj.__doc__)
 
1322
 
1154
1323
    def failUnlessExists(self, path):
1155
1324
        """Fail unless path or paths, which may be abs or relative, exist."""
1156
1325
        if not isinstance(path, basestring):
1296
1465
 
1297
1466
        Close the file and delete it, unless setKeepLogfile was called.
1298
1467
        """
1299
 
        if self._log_file is None:
1300
 
            return
 
1468
        if bzrlib.trace._trace_file:
 
1469
            # flush the log file, to get all content
 
1470
            bzrlib.trace._trace_file.flush()
1301
1471
        bzrlib.trace.pop_log_file(self._log_memento)
1302
 
        self._log_file.close()
1303
 
        self._log_file = None
1304
 
        if not self._keep_log_file:
1305
 
            os.remove(self._log_file_name)
1306
 
            self._log_file_name = None
1307
 
 
1308
 
    def setKeepLogfile(self):
1309
 
        """Make the logfile not be deleted when _finishLogFile is called."""
1310
 
        self._keep_log_file = True
 
1472
        # Cache the log result and delete the file on disk
 
1473
        self._get_log(False)
 
1474
 
 
1475
    def thisFailsStrictLockCheck(self):
 
1476
        """It is known that this test would fail with -Dstrict_locks.
 
1477
 
 
1478
        By default, all tests are run with strict lock checking unless
 
1479
        -Edisable_lock_checks is supplied. However there are some tests which
 
1480
        we know fail strict locks at this point that have not been fixed.
 
1481
        They should call this function to disable the strict checking.
 
1482
 
 
1483
        This should be used sparingly, it is much better to fix the locking
 
1484
        issues rather than papering over the problem by calling this function.
 
1485
        """
 
1486
        debug.debug_flags.discard('strict_locks')
1311
1487
 
1312
1488
    def addCleanup(self, callable, *args, **kwargs):
1313
1489
        """Arrange to run a callable when this case is torn down.
1317
1493
        """
1318
1494
        self._cleanups.append((callable, args, kwargs))
1319
1495
 
 
1496
    def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
 
1497
        """Overrides an object attribute restoring it after the test.
 
1498
 
 
1499
        :param obj: The object that will be mutated.
 
1500
 
 
1501
        :param attr_name: The attribute name we want to preserve/override in
 
1502
            the object.
 
1503
 
 
1504
        :param new: The optional value we want to set the attribute to.
 
1505
 
 
1506
        :returns: The actual attr value.
 
1507
        """
 
1508
        value = getattr(obj, attr_name)
 
1509
        # The actual value is captured by the call below
 
1510
        self.addCleanup(setattr, obj, attr_name, value)
 
1511
        if new is not _unitialized_attr:
 
1512
            setattr(obj, attr_name, new)
 
1513
        return value
 
1514
 
1320
1515
    def _cleanEnvironment(self):
1321
1516
        new_env = {
1322
1517
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1328
1523
            'EDITOR': None,
1329
1524
            'BZR_EMAIL': None,
1330
1525
            'BZREMAIL': None, # may still be present in the environment
1331
 
            'EMAIL': None,
 
1526
            'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
1332
1527
            'BZR_PROGRESS_BAR': None,
1333
1528
            'BZR_LOG': None,
1334
1529
            'BZR_PLUGIN_PATH': None,
 
1530
            'BZR_DISABLE_PLUGINS': None,
 
1531
            'BZR_PLUGINS_AT': None,
 
1532
            'BZR_CONCURRENCY': None,
1335
1533
            # Make sure that any text ui tests are consistent regardless of
1336
1534
            # the environment the test case is run in; you may want tests that
1337
1535
            # test other combinations.  'dumb' is a reasonable guess for tests
1339
1537
            'TERM': 'dumb',
1340
1538
            'LINES': '25',
1341
1539
            'COLUMNS': '80',
 
1540
            'BZR_COLUMNS': '80',
1342
1541
            # SSH Agent
1343
1542
            'SSH_AUTH_SOCK': None,
1344
1543
            # Proxies
1356
1555
            'ftp_proxy': None,
1357
1556
            'FTP_PROXY': None,
1358
1557
            'BZR_REMOTE_PATH': None,
 
1558
            # Generally speaking, we don't want apport reporting on crashes in
 
1559
            # the test envirnoment unless we're specifically testing apport,
 
1560
            # so that it doesn't leak into the real system environment.  We
 
1561
            # use an env var so it propagates to subprocesses.
 
1562
            'APPORT_DISABLE': '1',
1359
1563
        }
1360
 
        self.__old_env = {}
 
1564
        self._old_env = {}
1361
1565
        self.addCleanup(self._restoreEnvironment)
1362
1566
        for name, value in new_env.iteritems():
1363
1567
            self._captureVar(name, value)
1364
1568
 
1365
1569
    def _captureVar(self, name, newvalue):
1366
1570
        """Set an environment variable, and reset it when finished."""
1367
 
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1368
 
 
1369
 
    def _restore_debug_flags(self):
1370
 
        debug.debug_flags.clear()
1371
 
        debug.debug_flags.update(self._preserved_debug_flags)
 
1571
        self._old_env[name] = osutils.set_or_unset_env(name, newvalue)
1372
1572
 
1373
1573
    def _restoreEnvironment(self):
1374
 
        for name, value in self.__old_env.iteritems():
 
1574
        for name, value in self._old_env.iteritems():
1375
1575
            osutils.set_or_unset_env(name, value)
1376
1576
 
1377
1577
    def _restoreHooks(self):
1385
1585
    def _do_skip(self, result, reason):
1386
1586
        addSkip = getattr(result, 'addSkip', None)
1387
1587
        if not callable(addSkip):
1388
 
            result.addError(self, sys.exc_info())
 
1588
            result.addSuccess(result)
1389
1589
        else:
1390
1590
            addSkip(self, reason)
1391
1591
 
1392
 
    def run(self, result=None):
1393
 
        if result is None: result = self.defaultTestResult()
1394
 
        for feature in getattr(self, '_test_needs_features', []):
1395
 
            if not feature.available():
1396
 
                result.startTest(self)
1397
 
                if getattr(result, 'addNotSupported', None):
1398
 
                    result.addNotSupported(self, feature)
1399
 
                else:
1400
 
                    result.addSuccess(self)
1401
 
                result.stopTest(self)
1402
 
                return result
1403
 
        try:
1404
 
            try:
1405
 
                result.startTest(self)
1406
 
                absent_attr = object()
1407
 
                # Python 2.5
1408
 
                method_name = getattr(self, '_testMethodName', absent_attr)
1409
 
                if method_name is absent_attr:
1410
 
                    # Python 2.4
1411
 
                    method_name = getattr(self, '_TestCase__testMethodName')
1412
 
                testMethod = getattr(self, method_name)
1413
 
                try:
1414
 
                    try:
1415
 
                        self.setUp()
1416
 
                        if not self._bzr_test_setUp_run:
1417
 
                            self.fail(
1418
 
                                "test setUp did not invoke "
1419
 
                                "bzrlib.tests.TestCase's setUp")
1420
 
                    except KeyboardInterrupt:
1421
 
                        self._runCleanups()
1422
 
                        raise
1423
 
                    except TestSkipped, e:
1424
 
                        self._do_skip(result, e.args[0])
1425
 
                        self.tearDown()
1426
 
                        return result
1427
 
                    except:
1428
 
                        result.addError(self, sys.exc_info())
1429
 
                        self._runCleanups()
1430
 
                        return result
1431
 
 
1432
 
                    ok = False
1433
 
                    try:
1434
 
                        testMethod()
1435
 
                        ok = True
1436
 
                    except self.failureException:
1437
 
                        result.addFailure(self, sys.exc_info())
1438
 
                    except TestSkipped, e:
1439
 
                        if not e.args:
1440
 
                            reason = "No reason given."
1441
 
                        else:
1442
 
                            reason = e.args[0]
1443
 
                        self._do_skip(result, reason)
1444
 
                    except KeyboardInterrupt:
1445
 
                        self._runCleanups()
1446
 
                        raise
1447
 
                    except:
1448
 
                        result.addError(self, sys.exc_info())
1449
 
 
1450
 
                    try:
1451
 
                        self.tearDown()
1452
 
                        if not self._bzr_test_tearDown_run:
1453
 
                            self.fail(
1454
 
                                "test tearDown did not invoke "
1455
 
                                "bzrlib.tests.TestCase's tearDown")
1456
 
                    except KeyboardInterrupt:
1457
 
                        self._runCleanups()
1458
 
                        raise
1459
 
                    except:
1460
 
                        result.addError(self, sys.exc_info())
1461
 
                        self._runCleanups()
1462
 
                        ok = False
1463
 
                    if ok: result.addSuccess(self)
1464
 
                finally:
1465
 
                    result.stopTest(self)
1466
 
                return result
1467
 
            except TestNotApplicable:
1468
 
                # Not moved from the result [yet].
1469
 
                self._runCleanups()
1470
 
                raise
1471
 
            except KeyboardInterrupt:
1472
 
                self._runCleanups()
1473
 
                raise
1474
 
        finally:
1475
 
            saved_attrs = {}
1476
 
            for attr_name in self.attrs_to_keep:
1477
 
                if attr_name in self.__dict__:
1478
 
                    saved_attrs[attr_name] = self.__dict__[attr_name]
1479
 
            self.__dict__ = saved_attrs
1480
 
 
1481
 
    def tearDown(self):
1482
 
        self._runCleanups()
1483
 
        self._log_contents = ''
1484
 
        self._bzr_test_tearDown_run = True
1485
 
        unittest.TestCase.tearDown(self)
 
1592
    @staticmethod
 
1593
    def _do_known_failure(self, result, e):
 
1594
        err = sys.exc_info()
 
1595
        addExpectedFailure = getattr(result, 'addExpectedFailure', None)
 
1596
        if addExpectedFailure is not None:
 
1597
            addExpectedFailure(self, err)
 
1598
        else:
 
1599
            result.addSuccess(self)
 
1600
 
 
1601
    @staticmethod
 
1602
    def _do_not_applicable(self, result, e):
 
1603
        if not e.args:
 
1604
            reason = 'No reason given'
 
1605
        else:
 
1606
            reason = e.args[0]
 
1607
        addNotApplicable = getattr(result, 'addNotApplicable', None)
 
1608
        if addNotApplicable is not None:
 
1609
            result.addNotApplicable(self, reason)
 
1610
        else:
 
1611
            self._do_skip(result, reason)
 
1612
 
 
1613
    @staticmethod
 
1614
    def _do_unsupported_or_skip(self, result, e):
 
1615
        reason = e.args[0]
 
1616
        addNotSupported = getattr(result, 'addNotSupported', None)
 
1617
        if addNotSupported is not None:
 
1618
            result.addNotSupported(self, reason)
 
1619
        else:
 
1620
            self._do_skip(result, reason)
1486
1621
 
1487
1622
    def time(self, callable, *args, **kwargs):
1488
1623
        """Run callable and accrue the time it takes to the benchmark time.
1492
1627
        self._benchcalls.
1493
1628
        """
1494
1629
        if self._benchtime is None:
 
1630
            self.addDetail('benchtime', content.Content(content.ContentType(
 
1631
                "text", "plain"), lambda:[str(self._benchtime)]))
1495
1632
            self._benchtime = 0
1496
1633
        start = time.time()
1497
1634
        try:
1506
1643
        finally:
1507
1644
            self._benchtime += time.time() - start
1508
1645
 
1509
 
    def _runCleanups(self):
1510
 
        """Run registered cleanup functions.
1511
 
 
1512
 
        This should only be called from TestCase.tearDown.
1513
 
        """
1514
 
        # TODO: Perhaps this should keep running cleanups even if
1515
 
        # one of them fails?
1516
 
 
1517
 
        # Actually pop the cleanups from the list so tearDown running
1518
 
        # twice is safe (this happens for skipped tests).
1519
 
        while self._cleanups:
1520
 
            cleanup, args, kwargs = self._cleanups.pop()
1521
 
            cleanup(*args, **kwargs)
1522
 
 
1523
1646
    def log(self, *args):
1524
1647
        mutter(*args)
1525
1648
 
1526
1649
    def _get_log(self, keep_log_file=False):
1527
 
        """Get the log from bzrlib.trace calls from this test.
 
1650
        """Internal helper to get the log from bzrlib.trace for this test.
 
1651
 
 
1652
        Please use self.getDetails, or self.get_log to access this in test case
 
1653
        code.
1528
1654
 
1529
1655
        :param keep_log_file: When True, if the log is still a file on disk
1530
1656
            leave it as a file on disk. When False, if the log is still a file
1532
1658
            self._log_contents.
1533
1659
        :return: A string containing the log.
1534
1660
        """
1535
 
        # flush the log file, to get all content
 
1661
        if self._log_contents is not None:
 
1662
            try:
 
1663
                self._log_contents.decode('utf8')
 
1664
            except UnicodeDecodeError:
 
1665
                unicodestr = self._log_contents.decode('utf8', 'replace')
 
1666
                self._log_contents = unicodestr.encode('utf8')
 
1667
            return self._log_contents
1536
1668
        import bzrlib.trace
1537
1669
        if bzrlib.trace._trace_file:
 
1670
            # flush the log file, to get all content
1538
1671
            bzrlib.trace._trace_file.flush()
1539
 
        if self._log_contents:
1540
 
            # XXX: this can hardly contain the content flushed above --vila
1541
 
            # 20080128
1542
 
            return self._log_contents
1543
1672
        if self._log_file_name is not None:
1544
1673
            logfile = open(self._log_file_name)
1545
1674
            try:
1546
1675
                log_contents = logfile.read()
1547
1676
            finally:
1548
1677
                logfile.close()
 
1678
            try:
 
1679
                log_contents.decode('utf8')
 
1680
            except UnicodeDecodeError:
 
1681
                unicodestr = log_contents.decode('utf8', 'replace')
 
1682
                log_contents = unicodestr.encode('utf8')
1549
1683
            if not keep_log_file:
 
1684
                close_attempts = 0
 
1685
                max_close_attempts = 100
 
1686
                first_close_error = None
 
1687
                while close_attempts < max_close_attempts:
 
1688
                    close_attempts += 1
 
1689
                    try:
 
1690
                        self._log_file.close()
 
1691
                    except IOError, ioe:
 
1692
                        if ioe.errno is None:
 
1693
                            # No errno implies 'close() called during
 
1694
                            # concurrent operation on the same file object', so
 
1695
                            # retry.  Probably a thread is trying to write to
 
1696
                            # the log file.
 
1697
                            if first_close_error is None:
 
1698
                                first_close_error = ioe
 
1699
                            continue
 
1700
                        raise
 
1701
                    else:
 
1702
                        break
 
1703
                if close_attempts > 1:
 
1704
                    sys.stderr.write(
 
1705
                        'Unable to close log file on first attempt, '
 
1706
                        'will retry: %s\n' % (first_close_error,))
 
1707
                    if close_attempts == max_close_attempts:
 
1708
                        sys.stderr.write(
 
1709
                            'Unable to close log file after %d attempts.\n'
 
1710
                            % (max_close_attempts,))
 
1711
                self._log_file = None
 
1712
                # Permit multiple calls to get_log until we clean it up in
 
1713
                # finishLogFile
1550
1714
                self._log_contents = log_contents
1551
1715
                try:
1552
1716
                    os.remove(self._log_file_name)
1556
1720
                                             ' %r\n' % self._log_file_name))
1557
1721
                    else:
1558
1722
                        raise
 
1723
                self._log_file_name = None
1559
1724
            return log_contents
1560
1725
        else:
1561
 
            return "DELETED log file to reduce memory footprint"
 
1726
            return "No log file content and no log file name."
 
1727
 
 
1728
    def get_log(self):
 
1729
        """Get a unicode string containing the log from bzrlib.trace.
 
1730
 
 
1731
        Undecodable characters are replaced.
 
1732
        """
 
1733
        return u"".join(self.getDetails()['log'].iter_text())
1562
1734
 
1563
1735
    def requireFeature(self, feature):
1564
1736
        """This test requires a specific feature is available.
1581
1753
 
1582
1754
    def _run_bzr_core(self, args, retcode, encoding, stdin,
1583
1755
            working_dir):
 
1756
        # Clear chk_map page cache, because the contents are likely to mask
 
1757
        # locking errors.
 
1758
        chk_map.clear_cache()
1584
1759
        if encoding is None:
1585
1760
            encoding = osutils.get_user_encoding()
1586
1761
        stdout = StringIOWrapper()
1603
1778
            os.chdir(working_dir)
1604
1779
 
1605
1780
        try:
1606
 
            result = self.apply_redirected(ui.ui_factory.stdin,
1607
 
                stdout, stderr,
1608
 
                bzrlib.commands.run_bzr_catch_user_errors,
1609
 
                args)
 
1781
            try:
 
1782
                result = self.apply_redirected(ui.ui_factory.stdin,
 
1783
                    stdout, stderr,
 
1784
                    bzrlib.commands.run_bzr_catch_user_errors,
 
1785
                    args)
 
1786
            except KeyboardInterrupt:
 
1787
                # Reraise KeyboardInterrupt with contents of redirected stdout
 
1788
                # and stderr as arguments, for tests which are interested in
 
1789
                # stdout and stderr and are expecting the exception.
 
1790
                out = stdout.getvalue()
 
1791
                err = stderr.getvalue()
 
1792
                if out:
 
1793
                    self.log('output:\n%r', out)
 
1794
                if err:
 
1795
                    self.log('errors:\n%r', err)
 
1796
                raise KeyboardInterrupt(out, err)
1610
1797
        finally:
1611
1798
            logger.removeHandler(handler)
1612
1799
            ui.ui_factory = old_ui_factory
1622
1809
        if retcode is not None:
1623
1810
            self.assertEquals(retcode, result,
1624
1811
                              message='Unexpected return code')
1625
 
        return out, err
 
1812
        return result, out, err
1626
1813
 
1627
1814
    def run_bzr(self, args, retcode=0, encoding=None, stdin=None,
1628
1815
                working_dir=None, error_regexes=[], output_encoding=None):
1657
1844
        :keyword error_regexes: A list of expected error messages.  If
1658
1845
            specified they must be seen in the error output of the command.
1659
1846
        """
1660
 
        out, err = self._run_bzr_autosplit(
 
1847
        retcode, out, err = self._run_bzr_autosplit(
1661
1848
            args=args,
1662
1849
            retcode=retcode,
1663
1850
            encoding=encoding,
1798
1985
            if not allow_plugins:
1799
1986
                command.append('--no-plugins')
1800
1987
            command.extend(process_args)
1801
 
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
1988
            process = self._popen(command, stdin=subprocess.PIPE,
 
1989
                                  stdout=subprocess.PIPE,
 
1990
                                  stderr=subprocess.PIPE)
1802
1991
        finally:
1803
1992
            restore_environment()
1804
1993
            if cwd is not None:
1812
2001
        Allows tests to override this method to intercept the calls made to
1813
2002
        Popen for introspection.
1814
2003
        """
1815
 
        return Popen(*args, **kwargs)
 
2004
        return subprocess.Popen(*args, **kwargs)
 
2005
 
 
2006
    def get_source_path(self):
 
2007
        """Return the path of the directory containing bzrlib."""
 
2008
        return os.path.dirname(os.path.dirname(bzrlib.__file__))
1816
2009
 
1817
2010
    def get_bzr_path(self):
1818
2011
        """Return the path of the 'bzr' executable for this test suite."""
1819
 
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
2012
        bzr_path = os.path.join(self.get_source_path(), "bzr")
1820
2013
        if not os.path.isfile(bzr_path):
1821
2014
            # We are probably installed. Assume sys.argv is the right file
1822
2015
            bzr_path = sys.argv[0]
1908
2101
 
1909
2102
        Tests that expect to provoke LockContention errors should call this.
1910
2103
        """
1911
 
        orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
1912
 
        def resetTimeout():
1913
 
            bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
1914
 
        self.addCleanup(resetTimeout)
1915
 
        bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
 
2104
        self.overrideAttr(bzrlib.lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
1916
2105
 
1917
2106
    def make_utf8_encoded_stringio(self, encoding_type=None):
1918
2107
        """Return a StringIOWrapper instance, that will encode Unicode
1926
2115
        sio.encoding = output_encoding
1927
2116
        return sio
1928
2117
 
 
2118
    def disable_verb(self, verb):
 
2119
        """Disable a smart server verb for one test."""
 
2120
        from bzrlib.smart import request
 
2121
        request_handlers = request.request_handlers
 
2122
        orig_method = request_handlers.get(verb)
 
2123
        request_handlers.remove(verb)
 
2124
        self.addCleanup(request_handlers.register, verb, orig_method)
 
2125
 
1929
2126
 
1930
2127
class CapturedCall(object):
1931
2128
    """A helper for capturing smart server calls for easy debug analysis."""
1990
2187
 
1991
2188
        :param relpath: a path relative to the base url.
1992
2189
        """
1993
 
        t = get_transport(self.get_url(relpath))
 
2190
        t = _mod_transport.get_transport(self.get_url(relpath))
1994
2191
        self.assertFalse(t.is_readonly())
1995
2192
        return t
1996
2193
 
2002
2199
 
2003
2200
        :param relpath: a path relative to the base url.
2004
2201
        """
2005
 
        t = get_transport(self.get_readonly_url(relpath))
 
2202
        t = _mod_transport.get_transport(self.get_readonly_url(relpath))
2006
2203
        self.assertTrue(t.is_readonly())
2007
2204
        return t
2008
2205
 
2021
2218
        if self.__readonly_server is None:
2022
2219
            if self.transport_readonly_server is None:
2023
2220
                # readonly decorator requested
2024
 
                # bring up the server
2025
 
                self.__readonly_server = ReadonlyServer()
2026
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
 
2221
                self.__readonly_server = test_server.ReadonlyServer()
2027
2222
            else:
 
2223
                # explicit readonly transport.
2028
2224
                self.__readonly_server = self.create_transport_readonly_server()
2029
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
2030
 
            self.addCleanup(self.__readonly_server.tearDown)
 
2225
            self.start_server(self.__readonly_server,
 
2226
                self.get_vfs_only_server())
2031
2227
        return self.__readonly_server
2032
2228
 
2033
2229
    def get_readonly_url(self, relpath=None):
2051
2247
        is no means to override it.
2052
2248
        """
2053
2249
        if self.__vfs_server is None:
2054
 
            self.__vfs_server = MemoryServer()
2055
 
            self.__vfs_server.setUp()
2056
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2250
            self.__vfs_server = memory.MemoryServer()
 
2251
            self.start_server(self.__vfs_server)
2057
2252
        return self.__vfs_server
2058
2253
 
2059
2254
    def get_server(self):
2066
2261
        then the self.get_vfs_server is returned.
2067
2262
        """
2068
2263
        if self.__server is None:
2069
 
            if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
2070
 
                return self.get_vfs_only_server()
 
2264
            if (self.transport_server is None or self.transport_server is
 
2265
                self.vfs_transport_factory):
 
2266
                self.__server = self.get_vfs_only_server()
2071
2267
            else:
2072
2268
                # bring up a decorated means of access to the vfs only server.
2073
2269
                self.__server = self.transport_server()
2074
 
                try:
2075
 
                    self.__server.setUp(self.get_vfs_only_server())
2076
 
                except TypeError, e:
2077
 
                    # This should never happen; the try:Except here is to assist
2078
 
                    # developers having to update code rather than seeing an
2079
 
                    # uninformative TypeError.
2080
 
                    raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
2081
 
            self.addCleanup(self.__server.tearDown)
 
2270
                self.start_server(self.__server, self.get_vfs_only_server())
2082
2271
        return self.__server
2083
2272
 
2084
2273
    def _adjust_url(self, base, relpath):
2146
2335
        propagating. This method ensures than a test did not leaked.
2147
2336
        """
2148
2337
        root = TestCaseWithMemoryTransport.TEST_ROOT
 
2338
        self.permit_url(_mod_transport.get_transport(root).base)
2149
2339
        wt = workingtree.WorkingTree.open(root)
2150
2340
        last_rev = wt.last_revision()
2151
2341
        if last_rev != 'null:':
2153
2343
            # recreate a new one or all the followng tests will fail.
2154
2344
            # If you need to inspect its content uncomment the following line
2155
2345
            # import pdb; pdb.set_trace()
2156
 
            _rmtree_temp_dir(root + '/.bzr')
 
2346
            _rmtree_temp_dir(root + '/.bzr', test_id=self.id())
2157
2347
            self._create_safety_net()
2158
2348
            raise AssertionError('%s/.bzr should not be modified' % root)
2159
2349
 
2160
2350
    def _make_test_root(self):
2161
2351
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
2162
 
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
 
2352
            # Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
 
2353
            root = osutils.realpath(osutils.mkdtemp(prefix='testbzr-',
 
2354
                                                    suffix='.tmp'))
2163
2355
            TestCaseWithMemoryTransport.TEST_ROOT = root
2164
2356
 
2165
2357
            self._create_safety_net()
2168
2360
            # specifically told when all tests are finished.  This will do.
2169
2361
            atexit.register(_rmtree_temp_dir, root)
2170
2362
 
 
2363
        self.permit_dir(TestCaseWithMemoryTransport.TEST_ROOT)
2171
2364
        self.addCleanup(self._check_safety_net)
2172
2365
 
2173
2366
    def makeAndChdirToTestDir(self):
2181
2374
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2182
2375
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
2183
2376
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
 
2377
        self.permit_dir(self.test_dir)
2184
2378
 
2185
2379
    def make_branch(self, relpath, format=None):
2186
2380
        """Create a branch on the transport at relpath."""
2192
2386
            # might be a relative or absolute path
2193
2387
            maybe_a_url = self.get_url(relpath)
2194
2388
            segments = maybe_a_url.rsplit('/', 1)
2195
 
            t = get_transport(maybe_a_url)
 
2389
            t = _mod_transport.get_transport(maybe_a_url)
2196
2390
            if len(segments) > 1 and segments[-1] not in ('', '.'):
2197
2391
                t.ensure_base()
2198
2392
            if format is None:
2215
2409
        made_control = self.make_bzrdir(relpath, format=format)
2216
2410
        return made_control.create_repository(shared=shared)
2217
2411
 
2218
 
    def make_smart_server(self, path):
2219
 
        smart_server = server.SmartTCPServer_for_testing()
2220
 
        smart_server.setUp(self.get_server())
2221
 
        remote_transport = get_transport(smart_server.get_url()).clone(path)
2222
 
        self.addCleanup(smart_server.tearDown)
 
2412
    def make_smart_server(self, path, backing_server=None):
 
2413
        if backing_server is None:
 
2414
            backing_server = self.get_server()
 
2415
        smart_server = test_server.SmartTCPServer_for_testing()
 
2416
        self.start_server(smart_server, backing_server)
 
2417
        remote_transport = _mod_transport.get_transport(smart_server.get_url()
 
2418
                                                   ).clone(path)
2223
2419
        return remote_transport
2224
2420
 
2225
2421
    def make_branch_and_memory_tree(self, relpath, format=None):
2232
2428
        return branchbuilder.BranchBuilder(branch=branch)
2233
2429
 
2234
2430
    def overrideEnvironmentForTesting(self):
2235
 
        os.environ['HOME'] = self.test_home_dir
2236
 
        os.environ['BZR_HOME'] = self.test_home_dir
 
2431
        test_home_dir = self.test_home_dir
 
2432
        if isinstance(test_home_dir, unicode):
 
2433
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
 
2434
        os.environ['HOME'] = test_home_dir
 
2435
        os.environ['BZR_HOME'] = test_home_dir
2237
2436
 
2238
2437
    def setUp(self):
2239
2438
        super(TestCaseWithMemoryTransport, self).setUp()
 
2439
        # Ensure that ConnectedTransport doesn't leak sockets
 
2440
        def get_transport_with_cleanup(*args, **kwargs):
 
2441
            t = orig_get_transport(*args, **kwargs)
 
2442
            if isinstance(t, _mod_transport.ConnectedTransport):
 
2443
                self.addCleanup(t.disconnect)
 
2444
            return t
 
2445
 
 
2446
        orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
 
2447
                                               get_transport_with_cleanup)
2240
2448
        self._make_test_root()
2241
 
        _currentdir = os.getcwdu()
2242
 
        def _leaveDirectory():
2243
 
            os.chdir(_currentdir)
2244
 
        self.addCleanup(_leaveDirectory)
 
2449
        self.addCleanup(os.chdir, os.getcwdu())
2245
2450
        self.makeAndChdirToTestDir()
2246
2451
        self.overrideEnvironmentForTesting()
2247
2452
        self.__readonly_server = None
2250
2455
 
2251
2456
    def setup_smart_server_with_call_log(self):
2252
2457
        """Sets up a smart server as the transport server with a call log."""
2253
 
        self.transport_server = server.SmartTCPServer_for_testing
 
2458
        self.transport_server = test_server.SmartTCPServer_for_testing
2254
2459
        self.hpss_calls = []
2255
2460
        import traceback
2256
2461
        # Skip the current stack down to the caller of
2290
2495
 
2291
2496
    def check_file_contents(self, filename, expect):
2292
2497
        self.log("check contents of file %s" % filename)
2293
 
        contents = file(filename, 'r').read()
 
2498
        f = file(filename)
 
2499
        try:
 
2500
            contents = f.read()
 
2501
        finally:
 
2502
            f.close()
2294
2503
        if contents != expect:
2295
2504
            self.log("expected: %r" % expect)
2296
2505
            self.log("actually: %r" % contents)
2298
2507
 
2299
2508
    def _getTestDirPrefix(self):
2300
2509
        # create a directory within the top level test directory
2301
 
        if sys.platform == 'win32':
 
2510
        if sys.platform in ('win32', 'cygwin'):
2302
2511
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
2303
2512
            # windows is likely to have path-length limits so use a short name
2304
2513
            name_prefix = name_prefix[-30:]
2319
2528
            if os.path.exists(name):
2320
2529
                name = name_prefix + '_' + str(i)
2321
2530
            else:
2322
 
                os.mkdir(name)
 
2531
                # now create test and home directories within this dir
 
2532
                self.test_base_dir = name
 
2533
                self.addCleanup(self.deleteTestDir)
 
2534
                os.mkdir(self.test_base_dir)
2323
2535
                break
2324
 
        # now create test and home directories within this dir
2325
 
        self.test_base_dir = name
 
2536
        self.permit_dir(self.test_base_dir)
 
2537
        # 'sprouting' and 'init' of a branch both walk up the tree to find
 
2538
        # stacking policy to honour; create a bzr dir with an unshared
 
2539
        # repository (but not a branch - our code would be trying to escape
 
2540
        # then!) to stop them, and permit it to be read.
 
2541
        # control = bzrdir.BzrDir.create(self.test_base_dir)
 
2542
        # control.create_repository()
2326
2543
        self.test_home_dir = self.test_base_dir + '/home'
2327
2544
        os.mkdir(self.test_home_dir)
2328
2545
        self.test_dir = self.test_base_dir + '/work'
2334
2551
            f.write(self.id())
2335
2552
        finally:
2336
2553
            f.close()
2337
 
        self.addCleanup(self.deleteTestDir)
2338
2554
 
2339
2555
    def deleteTestDir(self):
2340
2556
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2341
 
        _rmtree_temp_dir(self.test_base_dir)
 
2557
        _rmtree_temp_dir(self.test_base_dir, test_id=self.id())
2342
2558
 
2343
2559
    def build_tree(self, shape, line_endings='binary', transport=None):
2344
2560
        """Build a test tree according to a pattern.
2363
2579
                "a list or a tuple. Got %r instead" % (shape,))
2364
2580
        # It's OK to just create them using forward slashes on windows.
2365
2581
        if transport is None or transport.is_readonly():
2366
 
            transport = get_transport(".")
 
2582
            transport = _mod_transport.get_transport(".")
2367
2583
        for name in shape:
2368
2584
            self.assertIsInstance(name, basestring)
2369
2585
            if name[-1] == '/':
2379
2595
                content = "contents of %s%s" % (name.encode('utf-8'), end)
2380
2596
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
2381
2597
 
2382
 
    def build_tree_contents(self, shape):
2383
 
        build_tree_contents(shape)
 
2598
    build_tree_contents = staticmethod(treeshape.build_tree_contents)
2384
2599
 
2385
2600
    def assertInWorkingTree(self, path, root_path='.', tree=None):
2386
2601
        """Assert whether path or paths are in the WorkingTree"""
2426
2641
        """
2427
2642
        if self.__vfs_server is None:
2428
2643
            self.__vfs_server = self.vfs_transport_factory()
2429
 
            self.__vfs_server.setUp()
2430
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2644
            self.start_server(self.__vfs_server)
2431
2645
        return self.__vfs_server
2432
2646
 
2433
2647
    def make_branch_and_tree(self, relpath, format=None):
2440
2654
        repository will also be accessed locally. Otherwise a lightweight
2441
2655
        checkout is created and returned.
2442
2656
 
 
2657
        We do this because we can't physically create a tree in the local
 
2658
        path, with a branch reference to the transport_factory url, and
 
2659
        a branch + repository in the vfs_transport, unless the vfs_transport
 
2660
        namespace is distinct from the local disk - the two branch objects
 
2661
        would collide. While we could construct a tree with its branch object
 
2662
        pointing at the transport_factory transport in memory, reopening it
 
2663
        would behaving unexpectedly, and has in the past caused testing bugs
 
2664
        when we tried to do it that way.
 
2665
 
2443
2666
        :param format: The BzrDirFormat.
2444
2667
        :returns: the WorkingTree.
2445
2668
        """
2454
2677
            # We can only make working trees locally at the moment.  If the
2455
2678
            # transport can't support them, then we keep the non-disk-backed
2456
2679
            # branch and create a local checkout.
2457
 
            if self.vfs_transport_factory is LocalURLServer:
 
2680
            if self.vfs_transport_factory is test_server.LocalURLServer:
2458
2681
                # the branch is colocated on disk, we cannot create a checkout.
2459
2682
                # hopefully callers will expect this.
2460
2683
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2497
2720
        super(TestCaseWithTransport, self).setUp()
2498
2721
        self.__vfs_server = None
2499
2722
 
 
2723
    def disable_missing_extensions_warning(self):
 
2724
        """Some tests expect a precise stderr content.
 
2725
 
 
2726
        There is no point in forcing them to duplicate the extension related
 
2727
        warning.
 
2728
        """
 
2729
        config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
 
2730
 
2500
2731
 
2501
2732
class ChrootedTestCase(TestCaseWithTransport):
2502
2733
    """A support class that provides readonly urls outside the local namespace.
2511
2742
    """
2512
2743
 
2513
2744
    def setUp(self):
 
2745
        from bzrlib.tests import http_server
2514
2746
        super(ChrootedTestCase, self).setUp()
2515
 
        if not self.vfs_transport_factory == MemoryServer:
2516
 
            self.transport_readonly_server = HttpServer
 
2747
        if not self.vfs_transport_factory == memory.MemoryServer:
 
2748
            self.transport_readonly_server = http_server.HttpServer
2517
2749
 
2518
2750
 
2519
2751
def condition_id_re(pattern):
2522
2754
    :param pattern: A regular expression string.
2523
2755
    :return: A callable that returns True if the re matches.
2524
2756
    """
2525
 
    filter_re = osutils.re_compile_checked(pattern, 0,
2526
 
        'test filter')
 
2757
    filter_re = re.compile(pattern, 0)
2527
2758
    def condition(test):
2528
2759
        test_id = test.id()
2529
2760
        return filter_re.search(test_id)
2716
2947
              strict=False,
2717
2948
              runner_class=None,
2718
2949
              suite_decorators=None,
2719
 
              stream=None):
 
2950
              stream=None,
 
2951
              result_decorators=None,
 
2952
              ):
2720
2953
    """Run a test suite for bzr selftest.
2721
2954
 
2722
2955
    :param runner_class: The class of runner to use. Must support the
2737
2970
                            descriptions=0,
2738
2971
                            verbosity=verbosity,
2739
2972
                            bench_history=bench_history,
2740
 
                            list_only=list_only,
2741
2973
                            strict=strict,
 
2974
                            result_decorators=result_decorators,
2742
2975
                            )
2743
2976
    runner.stop_on_failure=stop_on_failure
2744
2977
    # built in decorator factories:
2752
2985
        decorators.append(filter_tests(pattern))
2753
2986
    if suite_decorators:
2754
2987
        decorators.extend(suite_decorators)
 
2988
    # tell the result object how many tests will be running: (except if
 
2989
    # --parallel=fork is being used. Robert said he will provide a better
 
2990
    # progress design later -- vila 20090817)
 
2991
    if fork_decorator not in decorators:
 
2992
        decorators.append(CountingDecorator)
2755
2993
    for decorator in decorators:
2756
2994
        suite = decorator(suite)
 
2995
    if list_only:
 
2996
        # Done after test suite decoration to allow randomisation etc
 
2997
        # to take effect, though that is of marginal benefit.
 
2998
        if verbosity >= 2:
 
2999
            stream.write("Listing tests only ...\n")
 
3000
        for t in iter_suite_tests(suite):
 
3001
            stream.write("%s\n" % (t.id()))
 
3002
        return True
2757
3003
    result = runner.run(suite)
2758
 
    if list_only:
2759
 
        return True
2760
 
    result.done()
2761
3004
    if strict:
2762
3005
        return result.wasStrictlySuccessful()
2763
3006
    else:
2829
3072
    return suite
2830
3073
 
2831
3074
 
2832
 
class TestDecorator(TestSuite):
 
3075
class TestDecorator(TestUtil.TestSuite):
2833
3076
    """A decorator for TestCase/TestSuite objects.
2834
3077
    
2835
3078
    Usually, subclasses should override __iter__(used when flattening test
2838
3081
    """
2839
3082
 
2840
3083
    def __init__(self, suite):
2841
 
        TestSuite.__init__(self)
 
3084
        TestUtil.TestSuite.__init__(self)
2842
3085
        self.addTest(suite)
2843
3086
 
2844
3087
    def countTestCases(self):
2861
3104
        return result
2862
3105
 
2863
3106
 
 
3107
class CountingDecorator(TestDecorator):
 
3108
    """A decorator which calls result.progress(self.countTestCases)."""
 
3109
 
 
3110
    def run(self, result):
 
3111
        progress_method = getattr(result, 'progress', None)
 
3112
        if callable(progress_method):
 
3113
            progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
 
3114
        return super(CountingDecorator, self).run(result)
 
3115
 
 
3116
 
2864
3117
class ExcludeDecorator(TestDecorator):
2865
3118
    """A decorator which excludes test matching an exclude pattern."""
2866
3119
 
2910
3163
        if self.randomised:
2911
3164
            return iter(self._tests)
2912
3165
        self.randomised = True
2913
 
        self.stream.writeln("Randomizing test order using seed %s\n" %
 
3166
        self.stream.write("Randomizing test order using seed %s\n\n" %
2914
3167
            (self.actual_seed()))
2915
3168
        # Initialise the random number generator.
2916
3169
        random.seed(self.actual_seed())
2953
3206
 
2954
3207
def partition_tests(suite, count):
2955
3208
    """Partition suite into count lists of tests."""
2956
 
    result = []
2957
 
    tests = list(iter_suite_tests(suite))
2958
 
    tests_per_process = int(math.ceil(float(len(tests)) / count))
2959
 
    for block in range(count):
2960
 
        low_test = block * tests_per_process
2961
 
        high_test = low_test + tests_per_process
2962
 
        process_tests = tests[low_test:high_test]
2963
 
        result.append(process_tests)
2964
 
    return result
 
3209
    # This just assigns tests in a round-robin fashion.  On one hand this
 
3210
    # splits up blocks of related tests that might run faster if they shared
 
3211
    # resources, but on the other it avoids assigning blocks of slow tests to
 
3212
    # just one partition.  So the slowest partition shouldn't be much slower
 
3213
    # than the fastest.
 
3214
    partitions = [list() for i in range(count)]
 
3215
    tests = iter_suite_tests(suite)
 
3216
    for partition, test in itertools.izip(itertools.cycle(partitions), tests):
 
3217
        partition.append(test)
 
3218
    return partitions
 
3219
 
 
3220
 
 
3221
def workaround_zealous_crypto_random():
 
3222
    """Crypto.Random want to help us being secure, but we don't care here.
 
3223
 
 
3224
    This workaround some test failure related to the sftp server. Once paramiko
 
3225
    stop using the controversial API in Crypto.Random, we may get rid of it.
 
3226
    """
 
3227
    try:
 
3228
        from Crypto.Random import atfork
 
3229
        atfork()
 
3230
    except ImportError:
 
3231
        pass
2965
3232
 
2966
3233
 
2967
3234
def fork_for_tests(suite):
2973
3240
    concurrency = osutils.local_concurrency()
2974
3241
    result = []
2975
3242
    from subunit import TestProtocolClient, ProtocolTestCase
2976
 
    try:
2977
 
        from subunit.test_results import AutoTimingTestResultDecorator
2978
 
    except ImportError:
2979
 
        AutoTimingTestResultDecorator = lambda x:x
 
3243
    from subunit.test_results import AutoTimingTestResultDecorator
2980
3244
    class TestInOtherProcess(ProtocolTestCase):
2981
3245
        # Should be in subunit, I think. RBC.
2982
3246
        def __init__(self, stream, pid):
2987
3251
            try:
2988
3252
                ProtocolTestCase.run(self, result)
2989
3253
            finally:
2990
 
                os.waitpid(self.pid, os.WNOHANG)
 
3254
                os.waitpid(self.pid, 0)
2991
3255
 
2992
3256
    test_blocks = partition_tests(suite, concurrency)
2993
3257
    for process_tests in test_blocks:
2994
 
        process_suite = TestSuite()
 
3258
        process_suite = TestUtil.TestSuite()
2995
3259
        process_suite.addTests(process_tests)
2996
3260
        c2pread, c2pwrite = os.pipe()
2997
3261
        pid = os.fork()
2998
3262
        if pid == 0:
 
3263
            workaround_zealous_crypto_random()
2999
3264
            try:
3000
3265
                os.close(c2pread)
3001
3266
                # Leave stderr and stdout open so we can see test noise
3048
3313
        if not os.path.isfile(bzr_path):
3049
3314
            # We are probably installed. Assume sys.argv is the right file
3050
3315
            bzr_path = sys.argv[0]
 
3316
        bzr_path = [bzr_path]
 
3317
        if sys.platform == "win32":
 
3318
            # if we're on windows, we can't execute the bzr script directly
 
3319
            bzr_path = [sys.executable] + bzr_path
3051
3320
        fd, test_list_file_name = tempfile.mkstemp()
3052
3321
        test_list_file = os.fdopen(fd, 'wb', 1)
3053
3322
        for test in process_tests:
3054
3323
            test_list_file.write(test.id() + '\n')
3055
3324
        test_list_file.close()
3056
3325
        try:
3057
 
            argv = [bzr_path, 'selftest', '--load-list', test_list_file_name,
 
3326
            argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
3058
3327
                '--subunit']
3059
3328
            if '--no-plugins' in sys.argv:
3060
3329
                argv.append('--no-plugins')
3061
 
            # stderr=STDOUT would be ideal, but until we prevent noise on
3062
 
            # stderr it can interrupt the subunit protocol.
3063
 
            process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
3064
 
                bufsize=1)
 
3330
            # stderr=subprocess.STDOUT would be ideal, but until we prevent
 
3331
            # noise on stderr it can interrupt the subunit protocol.
 
3332
            process = subprocess.Popen(argv, stdin=subprocess.PIPE,
 
3333
                                      stdout=subprocess.PIPE,
 
3334
                                      stderr=subprocess.PIPE,
 
3335
                                      bufsize=1)
3065
3336
            test = TestInSubprocess(process, test_list_file_name)
3066
3337
            result.append(test)
3067
3338
        except:
3070
3341
    return result
3071
3342
 
3072
3343
 
3073
 
class BZRTransformingResult(unittest.TestResult):
 
3344
class ForwardingResult(unittest.TestResult):
3074
3345
 
3075
3346
    def __init__(self, target):
3076
3347
        unittest.TestResult.__init__(self)
3082
3353
    def stopTest(self, test):
3083
3354
        self.result.stopTest(test)
3084
3355
 
3085
 
    def addError(self, test, err):
3086
 
        feature = self._error_looks_like('UnavailableFeature: ', err)
3087
 
        if feature is not None:
3088
 
            self.result.addNotSupported(test, feature)
3089
 
        else:
3090
 
            self.result.addError(test, err)
 
3356
    def startTestRun(self):
 
3357
        self.result.startTestRun()
3091
3358
 
3092
 
    def addFailure(self, test, err):
3093
 
        known = self._error_looks_like('KnownFailure: ', err)
3094
 
        if known is not None:
3095
 
            self.result._addKnownFailure(test, [KnownFailure,
3096
 
                                                KnownFailure(known), None])
3097
 
        else:
3098
 
            self.result.addFailure(test, err)
 
3359
    def stopTestRun(self):
 
3360
        self.result.stopTestRun()
3099
3361
 
3100
3362
    def addSkip(self, test, reason):
3101
3363
        self.result.addSkip(test, reason)
3103
3365
    def addSuccess(self, test):
3104
3366
        self.result.addSuccess(test)
3105
3367
 
3106
 
    def _error_looks_like(self, prefix, err):
3107
 
        """Deserialize exception and returns the stringify value."""
3108
 
        import subunit
3109
 
        value = None
3110
 
        typ, exc, _ = err
3111
 
        if isinstance(exc, subunit.RemoteException):
3112
 
            # stringify the exception gives access to the remote traceback
3113
 
            # We search the last line for 'prefix'
3114
 
            lines = str(exc).split('\n')
3115
 
            while lines and not lines[-1]:
3116
 
                lines.pop(-1)
3117
 
            if lines:
3118
 
                if lines[-1].startswith(prefix):
3119
 
                    value = lines[-1][len(prefix):]
3120
 
        return value
 
3368
    def addError(self, test, err):
 
3369
        self.result.addError(test, err)
 
3370
 
 
3371
    def addFailure(self, test, err):
 
3372
        self.result.addFailure(test, err)
 
3373
ForwardingResult = testtools.ExtendedToOriginalDecorator
 
3374
 
 
3375
 
 
3376
class ProfileResult(ForwardingResult):
 
3377
    """Generate profiling data for all activity between start and success.
 
3378
    
 
3379
    The profile data is appended to the test's _benchcalls attribute and can
 
3380
    be accessed by the forwarded-to TestResult.
 
3381
 
 
3382
    While it might be cleaner do accumulate this in stopTest, addSuccess is
 
3383
    where our existing output support for lsprof is, and this class aims to
 
3384
    fit in with that: while it could be moved it's not necessary to accomplish
 
3385
    test profiling, nor would it be dramatically cleaner.
 
3386
    """
 
3387
 
 
3388
    def startTest(self, test):
 
3389
        self.profiler = bzrlib.lsprof.BzrProfiler()
 
3390
        # Prevent deadlocks in tests that use lsprof: those tests will
 
3391
        # unavoidably fail.
 
3392
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
 
3393
        self.profiler.start()
 
3394
        ForwardingResult.startTest(self, test)
 
3395
 
 
3396
    def addSuccess(self, test):
 
3397
        stats = self.profiler.stop()
 
3398
        try:
 
3399
            calls = test._benchcalls
 
3400
        except AttributeError:
 
3401
            test._benchcalls = []
 
3402
            calls = test._benchcalls
 
3403
        calls.append(((test.id(), "", ""), stats))
 
3404
        ForwardingResult.addSuccess(self, test)
 
3405
 
 
3406
    def stopTest(self, test):
 
3407
        ForwardingResult.stopTest(self, test)
 
3408
        self.profiler = None
3121
3409
 
3122
3410
 
3123
3411
# Controlled by "bzr selftest -E=..." option
 
3412
# Currently supported:
 
3413
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
 
3414
#                           preserves any flags supplied at the command line.
 
3415
#   -Edisable_lock_checks   Turns errors in mismatched locks into simple prints
 
3416
#                           rather than failing tests. And no longer raise
 
3417
#                           LockContention when fctnl locks are not being used
 
3418
#                           with proper exclusion rules.
 
3419
#   -Ethreads               Will display thread ident at creation/join time to
 
3420
#                           help track thread leaks
3124
3421
selftest_debug_flags = set()
3125
3422
 
3126
3423
 
3139
3436
             starting_with=None,
3140
3437
             runner_class=None,
3141
3438
             suite_decorators=None,
 
3439
             stream=None,
 
3440
             lsprof_tests=False,
3142
3441
             ):
3143
3442
    """Run the whole test suite under the enhanced runner"""
3144
3443
    # XXX: Very ugly way to do this...
3161
3460
            keep_only = None
3162
3461
        else:
3163
3462
            keep_only = load_test_id_list(load_list)
 
3463
        if starting_with:
 
3464
            starting_with = [test_prefix_alias_registry.resolve_alias(start)
 
3465
                             for start in starting_with]
3164
3466
        if test_suite_factory is None:
 
3467
            # Reduce loading time by loading modules based on the starting_with
 
3468
            # patterns.
3165
3469
            suite = test_suite(keep_only, starting_with)
3166
3470
        else:
3167
3471
            suite = test_suite_factory()
 
3472
        if starting_with:
 
3473
            # But always filter as requested.
 
3474
            suite = filter_suite_by_id_startswith(suite, starting_with)
 
3475
        result_decorators = []
 
3476
        if lsprof_tests:
 
3477
            result_decorators.append(ProfileResult)
3168
3478
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
3169
3479
                     stop_on_failure=stop_on_failure,
3170
3480
                     transport=transport,
3177
3487
                     strict=strict,
3178
3488
                     runner_class=runner_class,
3179
3489
                     suite_decorators=suite_decorators,
 
3490
                     stream=stream,
 
3491
                     result_decorators=result_decorators,
3180
3492
                     )
3181
3493
    finally:
3182
3494
        default_transport = old_transport
3330
3642
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
3331
3643
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
3332
3644
 
3333
 
# Obvious higest levels prefixes, feel free to add your own via a plugin
 
3645
# Obvious highest levels prefixes, feel free to add your own via a plugin
3334
3646
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
3335
3647
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
3336
3648
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
3338
3650
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
3339
3651
 
3340
3652
 
 
3653
def _test_suite_testmod_names():
 
3654
    """Return the standard list of test module names to test."""
 
3655
    return [
 
3656
        'bzrlib.doc',
 
3657
        'bzrlib.tests.blackbox',
 
3658
        'bzrlib.tests.commands',
 
3659
        'bzrlib.tests.doc_generate',
 
3660
        'bzrlib.tests.per_branch',
 
3661
        'bzrlib.tests.per_controldir',
 
3662
        'bzrlib.tests.per_controldir_colo',
 
3663
        'bzrlib.tests.per_foreign_vcs',
 
3664
        'bzrlib.tests.per_interrepository',
 
3665
        'bzrlib.tests.per_intertree',
 
3666
        'bzrlib.tests.per_inventory',
 
3667
        'bzrlib.tests.per_interbranch',
 
3668
        'bzrlib.tests.per_lock',
 
3669
        'bzrlib.tests.per_merger',
 
3670
        'bzrlib.tests.per_transport',
 
3671
        'bzrlib.tests.per_tree',
 
3672
        'bzrlib.tests.per_pack_repository',
 
3673
        'bzrlib.tests.per_repository',
 
3674
        'bzrlib.tests.per_repository_chk',
 
3675
        'bzrlib.tests.per_repository_reference',
 
3676
        'bzrlib.tests.per_uifactory',
 
3677
        'bzrlib.tests.per_versionedfile',
 
3678
        'bzrlib.tests.per_workingtree',
 
3679
        'bzrlib.tests.test__annotator',
 
3680
        'bzrlib.tests.test__bencode',
 
3681
        'bzrlib.tests.test__btree_serializer',
 
3682
        'bzrlib.tests.test__chk_map',
 
3683
        'bzrlib.tests.test__dirstate_helpers',
 
3684
        'bzrlib.tests.test__groupcompress',
 
3685
        'bzrlib.tests.test__known_graph',
 
3686
        'bzrlib.tests.test__rio',
 
3687
        'bzrlib.tests.test__simple_set',
 
3688
        'bzrlib.tests.test__static_tuple',
 
3689
        'bzrlib.tests.test__walkdirs_win32',
 
3690
        'bzrlib.tests.test_ancestry',
 
3691
        'bzrlib.tests.test_annotate',
 
3692
        'bzrlib.tests.test_api',
 
3693
        'bzrlib.tests.test_atomicfile',
 
3694
        'bzrlib.tests.test_bad_files',
 
3695
        'bzrlib.tests.test_bisect_multi',
 
3696
        'bzrlib.tests.test_branch',
 
3697
        'bzrlib.tests.test_branchbuilder',
 
3698
        'bzrlib.tests.test_btree_index',
 
3699
        'bzrlib.tests.test_bugtracker',
 
3700
        'bzrlib.tests.test_bundle',
 
3701
        'bzrlib.tests.test_bzrdir',
 
3702
        'bzrlib.tests.test__chunks_to_lines',
 
3703
        'bzrlib.tests.test_cache_utf8',
 
3704
        'bzrlib.tests.test_chk_map',
 
3705
        'bzrlib.tests.test_chk_serializer',
 
3706
        'bzrlib.tests.test_chunk_writer',
 
3707
        'bzrlib.tests.test_clean_tree',
 
3708
        'bzrlib.tests.test_cleanup',
 
3709
        'bzrlib.tests.test_cmdline',
 
3710
        'bzrlib.tests.test_commands',
 
3711
        'bzrlib.tests.test_commit',
 
3712
        'bzrlib.tests.test_commit_merge',
 
3713
        'bzrlib.tests.test_config',
 
3714
        'bzrlib.tests.test_conflicts',
 
3715
        'bzrlib.tests.test_counted_lock',
 
3716
        'bzrlib.tests.test_crash',
 
3717
        'bzrlib.tests.test_decorators',
 
3718
        'bzrlib.tests.test_delta',
 
3719
        'bzrlib.tests.test_debug',
 
3720
        'bzrlib.tests.test_deprecated_graph',
 
3721
        'bzrlib.tests.test_diff',
 
3722
        'bzrlib.tests.test_directory_service',
 
3723
        'bzrlib.tests.test_dirstate',
 
3724
        'bzrlib.tests.test_email_message',
 
3725
        'bzrlib.tests.test_eol_filters',
 
3726
        'bzrlib.tests.test_errors',
 
3727
        'bzrlib.tests.test_export',
 
3728
        'bzrlib.tests.test_extract',
 
3729
        'bzrlib.tests.test_fetch',
 
3730
        'bzrlib.tests.test_fixtures',
 
3731
        'bzrlib.tests.test_fifo_cache',
 
3732
        'bzrlib.tests.test_filters',
 
3733
        'bzrlib.tests.test_ftp_transport',
 
3734
        'bzrlib.tests.test_foreign',
 
3735
        'bzrlib.tests.test_generate_docs',
 
3736
        'bzrlib.tests.test_generate_ids',
 
3737
        'bzrlib.tests.test_globbing',
 
3738
        'bzrlib.tests.test_gpg',
 
3739
        'bzrlib.tests.test_graph',
 
3740
        'bzrlib.tests.test_groupcompress',
 
3741
        'bzrlib.tests.test_hashcache',
 
3742
        'bzrlib.tests.test_help',
 
3743
        'bzrlib.tests.test_hooks',
 
3744
        'bzrlib.tests.test_http',
 
3745
        'bzrlib.tests.test_http_response',
 
3746
        'bzrlib.tests.test_https_ca_bundle',
 
3747
        'bzrlib.tests.test_identitymap',
 
3748
        'bzrlib.tests.test_ignores',
 
3749
        'bzrlib.tests.test_index',
 
3750
        'bzrlib.tests.test_import_tariff',
 
3751
        'bzrlib.tests.test_info',
 
3752
        'bzrlib.tests.test_inv',
 
3753
        'bzrlib.tests.test_inventory_delta',
 
3754
        'bzrlib.tests.test_knit',
 
3755
        'bzrlib.tests.test_lazy_import',
 
3756
        'bzrlib.tests.test_lazy_regex',
 
3757
        'bzrlib.tests.test_library_state',
 
3758
        'bzrlib.tests.test_lock',
 
3759
        'bzrlib.tests.test_lockable_files',
 
3760
        'bzrlib.tests.test_lockdir',
 
3761
        'bzrlib.tests.test_log',
 
3762
        'bzrlib.tests.test_lru_cache',
 
3763
        'bzrlib.tests.test_lsprof',
 
3764
        'bzrlib.tests.test_mail_client',
 
3765
        'bzrlib.tests.test_matchers',
 
3766
        'bzrlib.tests.test_memorytree',
 
3767
        'bzrlib.tests.test_merge',
 
3768
        'bzrlib.tests.test_merge3',
 
3769
        'bzrlib.tests.test_merge_core',
 
3770
        'bzrlib.tests.test_merge_directive',
 
3771
        'bzrlib.tests.test_missing',
 
3772
        'bzrlib.tests.test_msgeditor',
 
3773
        'bzrlib.tests.test_multiparent',
 
3774
        'bzrlib.tests.test_mutabletree',
 
3775
        'bzrlib.tests.test_nonascii',
 
3776
        'bzrlib.tests.test_options',
 
3777
        'bzrlib.tests.test_osutils',
 
3778
        'bzrlib.tests.test_osutils_encodings',
 
3779
        'bzrlib.tests.test_pack',
 
3780
        'bzrlib.tests.test_patch',
 
3781
        'bzrlib.tests.test_patches',
 
3782
        'bzrlib.tests.test_permissions',
 
3783
        'bzrlib.tests.test_plugins',
 
3784
        'bzrlib.tests.test_progress',
 
3785
        'bzrlib.tests.test_read_bundle',
 
3786
        'bzrlib.tests.test_reconcile',
 
3787
        'bzrlib.tests.test_reconfigure',
 
3788
        'bzrlib.tests.test_registry',
 
3789
        'bzrlib.tests.test_remote',
 
3790
        'bzrlib.tests.test_rename_map',
 
3791
        'bzrlib.tests.test_repository',
 
3792
        'bzrlib.tests.test_revert',
 
3793
        'bzrlib.tests.test_revision',
 
3794
        'bzrlib.tests.test_revisionspec',
 
3795
        'bzrlib.tests.test_revisiontree',
 
3796
        'bzrlib.tests.test_rio',
 
3797
        'bzrlib.tests.test_rules',
 
3798
        'bzrlib.tests.test_sampler',
 
3799
        'bzrlib.tests.test_script',
 
3800
        'bzrlib.tests.test_selftest',
 
3801
        'bzrlib.tests.test_serializer',
 
3802
        'bzrlib.tests.test_setup',
 
3803
        'bzrlib.tests.test_sftp_transport',
 
3804
        'bzrlib.tests.test_shelf',
 
3805
        'bzrlib.tests.test_shelf_ui',
 
3806
        'bzrlib.tests.test_smart',
 
3807
        'bzrlib.tests.test_smart_add',
 
3808
        'bzrlib.tests.test_smart_request',
 
3809
        'bzrlib.tests.test_smart_transport',
 
3810
        'bzrlib.tests.test_smtp_connection',
 
3811
        'bzrlib.tests.test_source',
 
3812
        'bzrlib.tests.test_ssh_transport',
 
3813
        'bzrlib.tests.test_status',
 
3814
        'bzrlib.tests.test_store',
 
3815
        'bzrlib.tests.test_strace',
 
3816
        'bzrlib.tests.test_subsume',
 
3817
        'bzrlib.tests.test_switch',
 
3818
        'bzrlib.tests.test_symbol_versioning',
 
3819
        'bzrlib.tests.test_tag',
 
3820
        'bzrlib.tests.test_test_server',
 
3821
        'bzrlib.tests.test_testament',
 
3822
        'bzrlib.tests.test_textfile',
 
3823
        'bzrlib.tests.test_textmerge',
 
3824
        'bzrlib.tests.test_timestamp',
 
3825
        'bzrlib.tests.test_trace',
 
3826
        'bzrlib.tests.test_transactions',
 
3827
        'bzrlib.tests.test_transform',
 
3828
        'bzrlib.tests.test_transport',
 
3829
        'bzrlib.tests.test_transport_log',
 
3830
        'bzrlib.tests.test_tree',
 
3831
        'bzrlib.tests.test_treebuilder',
 
3832
        'bzrlib.tests.test_treeshape',
 
3833
        'bzrlib.tests.test_tsort',
 
3834
        'bzrlib.tests.test_tuned_gzip',
 
3835
        'bzrlib.tests.test_ui',
 
3836
        'bzrlib.tests.test_uncommit',
 
3837
        'bzrlib.tests.test_upgrade',
 
3838
        'bzrlib.tests.test_upgrade_stacked',
 
3839
        'bzrlib.tests.test_urlutils',
 
3840
        'bzrlib.tests.test_version',
 
3841
        'bzrlib.tests.test_version_info',
 
3842
        'bzrlib.tests.test_versionedfile',
 
3843
        'bzrlib.tests.test_weave',
 
3844
        'bzrlib.tests.test_whitebox',
 
3845
        'bzrlib.tests.test_win32utils',
 
3846
        'bzrlib.tests.test_workingtree',
 
3847
        'bzrlib.tests.test_workingtree_4',
 
3848
        'bzrlib.tests.test_wsgi',
 
3849
        'bzrlib.tests.test_xml',
 
3850
        ]
 
3851
 
 
3852
 
 
3853
def _test_suite_modules_to_doctest():
 
3854
    """Return the list of modules to doctest."""
 
3855
    if __doc__ is None:
 
3856
        # GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
 
3857
        return []
 
3858
    return [
 
3859
        'bzrlib',
 
3860
        'bzrlib.branchbuilder',
 
3861
        'bzrlib.decorators',
 
3862
        'bzrlib.export',
 
3863
        'bzrlib.inventory',
 
3864
        'bzrlib.iterablefile',
 
3865
        'bzrlib.lockdir',
 
3866
        'bzrlib.merge3',
 
3867
        'bzrlib.option',
 
3868
        'bzrlib.symbol_versioning',
 
3869
        'bzrlib.tests',
 
3870
        'bzrlib.tests.fixtures',
 
3871
        'bzrlib.timestamp',
 
3872
        'bzrlib.version_info_formats.format_custom',
 
3873
        ]
 
3874
 
 
3875
 
3341
3876
def test_suite(keep_only=None, starting_with=None):
3342
3877
    """Build and return TestSuite for the whole of bzrlib.
3343
3878
 
3349
3884
    This function can be replaced if you need to change the default test
3350
3885
    suite on a global basis, but it is not encouraged.
3351
3886
    """
3352
 
    testmod_names = [
3353
 
                   'bzrlib.doc',
3354
 
                   'bzrlib.tests.blackbox',
3355
 
                   'bzrlib.tests.commands',
3356
 
                   'bzrlib.tests.per_branch',
3357
 
                   'bzrlib.tests.per_bzrdir',
3358
 
                   'bzrlib.tests.per_interrepository',
3359
 
                   'bzrlib.tests.per_intertree',
3360
 
                   'bzrlib.tests.per_inventory',
3361
 
                   'bzrlib.tests.per_interbranch',
3362
 
                   'bzrlib.tests.per_lock',
3363
 
                   'bzrlib.tests.per_transport',
3364
 
                   'bzrlib.tests.per_tree',
3365
 
                   'bzrlib.tests.per_repository',
3366
 
                   'bzrlib.tests.per_repository_chk',
3367
 
                   'bzrlib.tests.per_repository_reference',
3368
 
                   'bzrlib.tests.per_workingtree',
3369
 
                   'bzrlib.tests.test__annotator',
3370
 
                   'bzrlib.tests.test__chk_map',
3371
 
                   'bzrlib.tests.test__dirstate_helpers',
3372
 
                   'bzrlib.tests.test__groupcompress',
3373
 
                   'bzrlib.tests.test__known_graph',
3374
 
                   'bzrlib.tests.test__rio',
3375
 
                   'bzrlib.tests.test__walkdirs_win32',
3376
 
                   'bzrlib.tests.test_ancestry',
3377
 
                   'bzrlib.tests.test_annotate',
3378
 
                   'bzrlib.tests.test_api',
3379
 
                   'bzrlib.tests.test_atomicfile',
3380
 
                   'bzrlib.tests.test_bad_files',
3381
 
                   'bzrlib.tests.test_bencode',
3382
 
                   'bzrlib.tests.test_bisect_multi',
3383
 
                   'bzrlib.tests.test_branch',
3384
 
                   'bzrlib.tests.test_branchbuilder',
3385
 
                   'bzrlib.tests.test_btree_index',
3386
 
                   'bzrlib.tests.test_bugtracker',
3387
 
                   'bzrlib.tests.test_bundle',
3388
 
                   'bzrlib.tests.test_bzrdir',
3389
 
                   'bzrlib.tests.test__chunks_to_lines',
3390
 
                   'bzrlib.tests.test_cache_utf8',
3391
 
                   'bzrlib.tests.test_chk_map',
3392
 
                   'bzrlib.tests.test_chk_serializer',
3393
 
                   'bzrlib.tests.test_chunk_writer',
3394
 
                   'bzrlib.tests.test_clean_tree',
3395
 
                   'bzrlib.tests.test_commands',
3396
 
                   'bzrlib.tests.test_commit',
3397
 
                   'bzrlib.tests.test_commit_merge',
3398
 
                   'bzrlib.tests.test_config',
3399
 
                   'bzrlib.tests.test_conflicts',
3400
 
                   'bzrlib.tests.test_counted_lock',
3401
 
                   'bzrlib.tests.test_decorators',
3402
 
                   'bzrlib.tests.test_delta',
3403
 
                   'bzrlib.tests.test_debug',
3404
 
                   'bzrlib.tests.test_deprecated_graph',
3405
 
                   'bzrlib.tests.test_diff',
3406
 
                   'bzrlib.tests.test_directory_service',
3407
 
                   'bzrlib.tests.test_dirstate',
3408
 
                   'bzrlib.tests.test_email_message',
3409
 
                   'bzrlib.tests.test_eol_filters',
3410
 
                   'bzrlib.tests.test_errors',
3411
 
                   'bzrlib.tests.test_export',
3412
 
                   'bzrlib.tests.test_extract',
3413
 
                   'bzrlib.tests.test_fetch',
3414
 
                   'bzrlib.tests.test_fifo_cache',
3415
 
                   'bzrlib.tests.test_filters',
3416
 
                   'bzrlib.tests.test_ftp_transport',
3417
 
                   'bzrlib.tests.test_foreign',
3418
 
                   'bzrlib.tests.test_generate_docs',
3419
 
                   'bzrlib.tests.test_generate_ids',
3420
 
                   'bzrlib.tests.test_globbing',
3421
 
                   'bzrlib.tests.test_gpg',
3422
 
                   'bzrlib.tests.test_graph',
3423
 
                   'bzrlib.tests.test_groupcompress',
3424
 
                   'bzrlib.tests.test_hashcache',
3425
 
                   'bzrlib.tests.test_help',
3426
 
                   'bzrlib.tests.test_hooks',
3427
 
                   'bzrlib.tests.test_http',
3428
 
                   'bzrlib.tests.test_http_response',
3429
 
                   'bzrlib.tests.test_https_ca_bundle',
3430
 
                   'bzrlib.tests.test_identitymap',
3431
 
                   'bzrlib.tests.test_ignores',
3432
 
                   'bzrlib.tests.test_index',
3433
 
                   'bzrlib.tests.test_info',
3434
 
                   'bzrlib.tests.test_inv',
3435
 
                   'bzrlib.tests.test_inventory_delta',
3436
 
                   'bzrlib.tests.test_knit',
3437
 
                   'bzrlib.tests.test_lazy_import',
3438
 
                   'bzrlib.tests.test_lazy_regex',
3439
 
                   'bzrlib.tests.test_lockable_files',
3440
 
                   'bzrlib.tests.test_lockdir',
3441
 
                   'bzrlib.tests.test_log',
3442
 
                   'bzrlib.tests.test_lru_cache',
3443
 
                   'bzrlib.tests.test_lsprof',
3444
 
                   'bzrlib.tests.test_mail_client',
3445
 
                   'bzrlib.tests.test_memorytree',
3446
 
                   'bzrlib.tests.test_merge',
3447
 
                   'bzrlib.tests.test_merge3',
3448
 
                   'bzrlib.tests.test_merge_core',
3449
 
                   'bzrlib.tests.test_merge_directive',
3450
 
                   'bzrlib.tests.test_missing',
3451
 
                   'bzrlib.tests.test_msgeditor',
3452
 
                   'bzrlib.tests.test_multiparent',
3453
 
                   'bzrlib.tests.test_mutabletree',
3454
 
                   'bzrlib.tests.test_nonascii',
3455
 
                   'bzrlib.tests.test_options',
3456
 
                   'bzrlib.tests.test_osutils',
3457
 
                   'bzrlib.tests.test_osutils_encodings',
3458
 
                   'bzrlib.tests.test_pack',
3459
 
                   'bzrlib.tests.test_pack_repository',
3460
 
                   'bzrlib.tests.test_patch',
3461
 
                   'bzrlib.tests.test_patches',
3462
 
                   'bzrlib.tests.test_permissions',
3463
 
                   'bzrlib.tests.test_plugins',
3464
 
                   'bzrlib.tests.test_progress',
3465
 
                   'bzrlib.tests.test_read_bundle',
3466
 
                   'bzrlib.tests.test_reconcile',
3467
 
                   'bzrlib.tests.test_reconfigure',
3468
 
                   'bzrlib.tests.test_registry',
3469
 
                   'bzrlib.tests.test_remote',
3470
 
                   'bzrlib.tests.test_rename_map',
3471
 
                   'bzrlib.tests.test_repository',
3472
 
                   'bzrlib.tests.test_revert',
3473
 
                   'bzrlib.tests.test_revision',
3474
 
                   'bzrlib.tests.test_revisionspec',
3475
 
                   'bzrlib.tests.test_revisiontree',
3476
 
                   'bzrlib.tests.test_rio',
3477
 
                   'bzrlib.tests.test_rules',
3478
 
                   'bzrlib.tests.test_sampler',
3479
 
                   'bzrlib.tests.test_selftest',
3480
 
                   'bzrlib.tests.test_serializer',
3481
 
                   'bzrlib.tests.test_setup',
3482
 
                   'bzrlib.tests.test_sftp_transport',
3483
 
                   'bzrlib.tests.test_shelf',
3484
 
                   'bzrlib.tests.test_shelf_ui',
3485
 
                   'bzrlib.tests.test_smart',
3486
 
                   'bzrlib.tests.test_smart_add',
3487
 
                   'bzrlib.tests.test_smart_request',
3488
 
                   'bzrlib.tests.test_smart_transport',
3489
 
                   'bzrlib.tests.test_smtp_connection',
3490
 
                   'bzrlib.tests.test_source',
3491
 
                   'bzrlib.tests.test_ssh_transport',
3492
 
                   'bzrlib.tests.test_status',
3493
 
                   'bzrlib.tests.test_store',
3494
 
                   'bzrlib.tests.test_strace',
3495
 
                   'bzrlib.tests.test_subsume',
3496
 
                   'bzrlib.tests.test_switch',
3497
 
                   'bzrlib.tests.test_symbol_versioning',
3498
 
                   'bzrlib.tests.test_tag',
3499
 
                   'bzrlib.tests.test_testament',
3500
 
                   'bzrlib.tests.test_textfile',
3501
 
                   'bzrlib.tests.test_textmerge',
3502
 
                   'bzrlib.tests.test_timestamp',
3503
 
                   'bzrlib.tests.test_trace',
3504
 
                   'bzrlib.tests.test_transactions',
3505
 
                   'bzrlib.tests.test_transform',
3506
 
                   'bzrlib.tests.test_transport',
3507
 
                   'bzrlib.tests.test_transport_log',
3508
 
                   'bzrlib.tests.test_tree',
3509
 
                   'bzrlib.tests.test_treebuilder',
3510
 
                   'bzrlib.tests.test_tsort',
3511
 
                   'bzrlib.tests.test_tuned_gzip',
3512
 
                   'bzrlib.tests.test_ui',
3513
 
                   'bzrlib.tests.test_uncommit',
3514
 
                   'bzrlib.tests.test_upgrade',
3515
 
                   'bzrlib.tests.test_upgrade_stacked',
3516
 
                   'bzrlib.tests.test_urlutils',
3517
 
                   'bzrlib.tests.test_version',
3518
 
                   'bzrlib.tests.test_version_info',
3519
 
                   'bzrlib.tests.test_versionedfile',
3520
 
                   'bzrlib.tests.test_weave',
3521
 
                   'bzrlib.tests.test_whitebox',
3522
 
                   'bzrlib.tests.test_win32utils',
3523
 
                   'bzrlib.tests.test_workingtree',
3524
 
                   'bzrlib.tests.test_workingtree_4',
3525
 
                   'bzrlib.tests.test_wsgi',
3526
 
                   'bzrlib.tests.test_xml',
3527
 
                   ]
3528
3887
 
3529
3888
    loader = TestUtil.TestLoader()
3530
3889
 
3531
3890
    if keep_only is not None:
3532
3891
        id_filter = TestIdList(keep_only)
3533
3892
    if starting_with:
3534
 
        starting_with = [test_prefix_alias_registry.resolve_alias(start)
3535
 
                         for start in starting_with]
3536
3893
        # We take precedence over keep_only because *at loading time* using
3537
3894
        # both options means we will load less tests for the same final result.
3538
3895
        def interesting_module(name):
3561
3918
    suite = loader.suiteClass()
3562
3919
 
3563
3920
    # modules building their suite with loadTestsFromModuleNames
3564
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
3565
 
 
3566
 
    modules_to_doctest = [
3567
 
        'bzrlib',
3568
 
        'bzrlib.branchbuilder',
3569
 
        'bzrlib.export',
3570
 
        'bzrlib.inventory',
3571
 
        'bzrlib.iterablefile',
3572
 
        'bzrlib.lockdir',
3573
 
        'bzrlib.merge3',
3574
 
        'bzrlib.option',
3575
 
        'bzrlib.symbol_versioning',
3576
 
        'bzrlib.tests',
3577
 
        'bzrlib.timestamp',
3578
 
        'bzrlib.version_info_formats.format_custom',
3579
 
        ]
3580
 
 
3581
 
    for mod in modules_to_doctest:
 
3921
    suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
 
3922
 
 
3923
    for mod in _test_suite_modules_to_doctest():
3582
3924
        if not interesting_module(mod):
3583
3925
            # No tests to keep here, move along
3584
3926
            continue
3613
3955
            reload(sys)
3614
3956
            sys.setdefaultencoding(default_encoding)
3615
3957
 
3616
 
    if starting_with:
3617
 
        suite = filter_suite_by_id_startswith(suite, starting_with)
3618
 
 
3619
3958
    if keep_only is not None:
3620
3959
        # Now that the referred modules have loaded their tests, keep only the
3621
3960
        # requested ones.
3675
4014
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
3676
4015
    ...     [('one', dict(param=1)),
3677
4016
    ...      ('two', dict(param=2))],
3678
 
    ...     TestSuite())
 
4017
    ...     TestUtil.TestSuite())
3679
4018
    >>> tests = list(iter_suite_tests(r))
3680
4019
    >>> len(tests)
3681
4020
    2
3728
4067
    :param new_id: The id to assign to it.
3729
4068
    :return: The new test.
3730
4069
    """
3731
 
    from copy import deepcopy
3732
 
    new_test = deepcopy(test)
 
4070
    new_test = copy.copy(test)
3733
4071
    new_test.id = lambda: new_id
3734
4072
    return new_test
3735
4073
 
3736
4074
 
3737
 
def _rmtree_temp_dir(dirname):
 
4075
def permute_tests_for_extension(standard_tests, loader, py_module_name,
 
4076
                                ext_module_name):
 
4077
    """Helper for permutating tests against an extension module.
 
4078
 
 
4079
    This is meant to be used inside a modules 'load_tests()' function. It will
 
4080
    create 2 scenarios, and cause all tests in the 'standard_tests' to be run
 
4081
    against both implementations. Setting 'test.module' to the appropriate
 
4082
    module. See bzrlib.tests.test__chk_map.load_tests as an example.
 
4083
 
 
4084
    :param standard_tests: A test suite to permute
 
4085
    :param loader: A TestLoader
 
4086
    :param py_module_name: The python path to a python module that can always
 
4087
        be loaded, and will be considered the 'python' implementation. (eg
 
4088
        'bzrlib._chk_map_py')
 
4089
    :param ext_module_name: The python path to an extension module. If the
 
4090
        module cannot be loaded, a single test will be added, which notes that
 
4091
        the module is not available. If it can be loaded, all standard_tests
 
4092
        will be run against that module.
 
4093
    :return: (suite, feature) suite is a test-suite that has all the permuted
 
4094
        tests. feature is the Feature object that can be used to determine if
 
4095
        the module is available.
 
4096
    """
 
4097
 
 
4098
    py_module = __import__(py_module_name, {}, {}, ['NO_SUCH_ATTRIB'])
 
4099
    scenarios = [
 
4100
        ('python', {'module': py_module}),
 
4101
    ]
 
4102
    suite = loader.suiteClass()
 
4103
    feature = ModuleAvailableFeature(ext_module_name)
 
4104
    if feature.available():
 
4105
        scenarios.append(('C', {'module': feature.module}))
 
4106
    else:
 
4107
        # the compiled module isn't available, so we add a failing test
 
4108
        class FailWithoutFeature(TestCase):
 
4109
            def test_fail(self):
 
4110
                self.requireFeature(feature)
 
4111
        suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
 
4112
    result = multiply_tests(standard_tests, scenarios, suite)
 
4113
    return result, feature
 
4114
 
 
4115
 
 
4116
def _rmtree_temp_dir(dirname, test_id=None):
3738
4117
    # If LANG=C we probably have created some bogus paths
3739
4118
    # which rmtree(unicode) will fail to delete
3740
4119
    # so make sure we are using rmtree(str) to delete everything
3749
4128
    try:
3750
4129
        osutils.rmtree(dirname)
3751
4130
    except OSError, e:
3752
 
        if sys.platform == 'win32' and e.errno == errno.EACCES:
3753
 
            sys.stderr.write('Permission denied: '
3754
 
                             'unable to remove testing dir '
3755
 
                             '%s\n%s'
3756
 
                             % (os.path.basename(dirname), e))
3757
 
        else:
3758
 
            raise
 
4131
        # We don't want to fail here because some useful display will be lost
 
4132
        # otherwise. Polluting the tmp dir is bad, but not giving all the
 
4133
        # possible info to the test runner is even worse.
 
4134
        if test_id != None:
 
4135
            ui.ui_factory.clear_term()
 
4136
            sys.stderr.write('\nWhile running: %s\n' % (test_id,))
 
4137
        # Ugly, but the last thing we want here is fail, so bear with it.
 
4138
        printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
 
4139
                                    ).encode('ascii', 'replace')
 
4140
        sys.stderr.write('Unable to remove testing dir %s\n%s'
 
4141
                         % (os.path.basename(dirname), printable_e))
3759
4142
 
3760
4143
 
3761
4144
class Feature(object):
3843
4226
UnicodeFilenameFeature = _UnicodeFilenameFeature()
3844
4227
 
3845
4228
 
 
4229
class _CompatabilityThunkFeature(Feature):
 
4230
    """This feature is just a thunk to another feature.
 
4231
 
 
4232
    It issues a deprecation warning if it is accessed, to let you know that you
 
4233
    should really use a different feature.
 
4234
    """
 
4235
 
 
4236
    def __init__(self, dep_version, module, name,
 
4237
                 replacement_name, replacement_module=None):
 
4238
        super(_CompatabilityThunkFeature, self).__init__()
 
4239
        self._module = module
 
4240
        if replacement_module is None:
 
4241
            replacement_module = module
 
4242
        self._replacement_module = replacement_module
 
4243
        self._name = name
 
4244
        self._replacement_name = replacement_name
 
4245
        self._dep_version = dep_version
 
4246
        self._feature = None
 
4247
 
 
4248
    def _ensure(self):
 
4249
        if self._feature is None:
 
4250
            depr_msg = self._dep_version % ('%s.%s'
 
4251
                                            % (self._module, self._name))
 
4252
            use_msg = ' Use %s.%s instead.' % (self._replacement_module,
 
4253
                                               self._replacement_name)
 
4254
            symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
 
4255
            # Import the new feature and use it as a replacement for the
 
4256
            # deprecated one.
 
4257
            mod = __import__(self._replacement_module, {}, {},
 
4258
                             [self._replacement_name])
 
4259
            self._feature = getattr(mod, self._replacement_name)
 
4260
 
 
4261
    def _probe(self):
 
4262
        self._ensure()
 
4263
        return self._feature._probe()
 
4264
 
 
4265
 
 
4266
class ModuleAvailableFeature(Feature):
 
4267
    """This is a feature than describes a module we want to be available.
 
4268
 
 
4269
    Declare the name of the module in __init__(), and then after probing, the
 
4270
    module will be available as 'self.module'.
 
4271
 
 
4272
    :ivar module: The module if it is available, else None.
 
4273
    """
 
4274
 
 
4275
    def __init__(self, module_name):
 
4276
        super(ModuleAvailableFeature, self).__init__()
 
4277
        self.module_name = module_name
 
4278
 
 
4279
    def _probe(self):
 
4280
        try:
 
4281
            self._module = __import__(self.module_name, {}, {}, [''])
 
4282
            return True
 
4283
        except ImportError:
 
4284
            return False
 
4285
 
 
4286
    @property
 
4287
    def module(self):
 
4288
        if self.available(): # Make sure the probe has been done
 
4289
            return self._module
 
4290
        return None
 
4291
 
 
4292
    def feature_name(self):
 
4293
        return self.module_name
 
4294
 
 
4295
 
 
4296
# This is kept here for compatibility, it is recommended to use
 
4297
# 'bzrlib.tests.feature.paramiko' instead
 
4298
ParamikoFeature = _CompatabilityThunkFeature(
 
4299
    deprecated_in((2,1,0)),
 
4300
    'bzrlib.tests.features', 'ParamikoFeature', 'paramiko')
 
4301
 
 
4302
 
3846
4303
def probe_unicode_in_user_encoding():
3847
4304
    """Try to encode several unicode strings to use in unicode-aware tests.
3848
4305
    Return first successfull match.
3917
4374
UnicodeFilename = _UnicodeFilename()
3918
4375
 
3919
4376
 
 
4377
class _ByteStringNamedFilesystem(Feature):
 
4378
    """Is the filesystem based on bytes?"""
 
4379
 
 
4380
    def _probe(self):
 
4381
        if os.name == "posix":
 
4382
            return True
 
4383
        return False
 
4384
 
 
4385
ByteStringNamedFilesystem = _ByteStringNamedFilesystem()
 
4386
 
 
4387
 
3920
4388
class _UTF8Filesystem(Feature):
3921
4389
    """Is the filesystem UTF-8?"""
3922
4390
 
3928
4396
UTF8Filesystem = _UTF8Filesystem()
3929
4397
 
3930
4398
 
 
4399
class _BreakinFeature(Feature):
 
4400
    """Does this platform support the breakin feature?"""
 
4401
 
 
4402
    def _probe(self):
 
4403
        from bzrlib import breakin
 
4404
        if breakin.determine_signal() is None:
 
4405
            return False
 
4406
        if sys.platform == 'win32':
 
4407
            # Windows doesn't have os.kill, and we catch the SIGBREAK signal.
 
4408
            # We trigger SIGBREAK via a Console api so we need ctypes to
 
4409
            # access the function
 
4410
            try:
 
4411
                import ctypes
 
4412
            except OSError:
 
4413
                return False
 
4414
        return True
 
4415
 
 
4416
    def feature_name(self):
 
4417
        return "SIGQUIT or SIGBREAK w/ctypes on win32"
 
4418
 
 
4419
 
 
4420
BreakinFeature = _BreakinFeature()
 
4421
 
 
4422
 
3931
4423
class _CaseInsCasePresFilenameFeature(Feature):
3932
4424
    """Is the file-system case insensitive, but case-preserving?"""
3933
4425
 
3983
4475
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
3984
4476
 
3985
4477
 
3986
 
class _SubUnitFeature(Feature):
3987
 
    """Check if subunit is available."""
 
4478
class _CaseSensitiveFilesystemFeature(Feature):
3988
4479
 
3989
4480
    def _probe(self):
3990
 
        try:
3991
 
            import subunit
 
4481
        if CaseInsCasePresFilenameFeature.available():
 
4482
            return False
 
4483
        elif CaseInsensitiveFilesystemFeature.available():
 
4484
            return False
 
4485
        else:
3992
4486
            return True
3993
 
        except ImportError:
3994
 
            return False
3995
4487
 
3996
4488
    def feature_name(self):
3997
 
        return 'subunit'
3998
 
 
3999
 
SubUnitFeature = _SubUnitFeature()
 
4489
        return 'case-sensitive filesystem'
 
4490
 
 
4491
# new coding style is for feature instances to be lowercase
 
4492
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
 
4493
 
 
4494
 
 
4495
# Kept for compatibility, use bzrlib.tests.features.subunit instead
 
4496
SubUnitFeature = _CompatabilityThunkFeature(
 
4497
    deprecated_in((2,1,0)),
 
4498
    'bzrlib.tests.features', 'SubUnitFeature', 'subunit')
4000
4499
# Only define SubUnitBzrRunner if subunit is available.
4001
4500
try:
4002
4501
    from subunit import TestProtocolClient
4003
 
    try:
4004
 
        from subunit.test_results import AutoTimingTestResultDecorator
4005
 
    except ImportError:
4006
 
        AutoTimingTestResultDecorator = lambda x:x
 
4502
    from subunit.test_results import AutoTimingTestResultDecorator
4007
4503
    class SubUnitBzrRunner(TextTestRunner):
4008
4504
        def run(self, test):
4009
4505
            result = AutoTimingTestResultDecorator(
4012
4508
            return result
4013
4509
except ImportError:
4014
4510
    pass
 
4511
 
 
4512
class _PosixPermissionsFeature(Feature):
 
4513
 
 
4514
    def _probe(self):
 
4515
        def has_perms():
 
4516
            # create temporary file and check if specified perms are maintained.
 
4517
            import tempfile
 
4518
 
 
4519
            write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
 
4520
            f = tempfile.mkstemp(prefix='bzr_perms_chk_')
 
4521
            fd, name = f
 
4522
            os.close(fd)
 
4523
            os.chmod(name, write_perms)
 
4524
 
 
4525
            read_perms = os.stat(name).st_mode & 0777
 
4526
            os.unlink(name)
 
4527
            return (write_perms == read_perms)
 
4528
 
 
4529
        return (os.name == 'posix') and has_perms()
 
4530
 
 
4531
    def feature_name(self):
 
4532
        return 'POSIX permissions support'
 
4533
 
 
4534
posix_permissions_feature = _PosixPermissionsFeature()