~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

(vila) Open 2.4.3 for bug fixes (Vincent Ladeuil)

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-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
"""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 os
37
 
from pprint import pformat
 
40
import platform
 
41
import pprint
38
42
import random
39
43
import re
40
44
import shlex
41
45
import stat
42
 
from subprocess import Popen, PIPE
 
46
import subprocess
43
47
import sys
44
48
import tempfile
45
49
import threading
46
50
import time
 
51
import traceback
47
52
import unittest
48
53
import warnings
49
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, 5):
 
59
    raise ImportError("need at least testtools 0.9.5: %s is %r"
 
60
        % (testtools.__file__, _testtools_version))
 
61
from testtools import content
50
62
 
 
63
import bzrlib
51
64
from bzrlib import (
52
65
    branchbuilder,
53
66
    bzrdir,
 
67
    chk_map,
 
68
    commands as _mod_commands,
 
69
    config,
54
70
    debug,
55
71
    errors,
56
72
    hooks,
 
73
    lock as _mod_lock,
 
74
    lockdir,
57
75
    memorytree,
58
76
    osutils,
59
 
    progress,
 
77
    plugin as _mod_plugin,
 
78
    pyutils,
60
79
    ui,
61
80
    urlutils,
62
81
    registry,
 
82
    symbol_versioning,
 
83
    trace,
 
84
    transport as _mod_transport,
63
85
    workingtree,
64
86
    )
65
 
import bzrlib.branch
66
 
import bzrlib.commands
67
 
import bzrlib.timestamp
68
 
import bzrlib.export
69
 
import bzrlib.inventory
70
 
import bzrlib.iterablefile
71
 
import bzrlib.lockdir
72
87
try:
73
88
    import bzrlib.lsprof
74
89
except ImportError:
75
90
    # lsprof not available
76
91
    pass
77
 
from bzrlib.merge import merge_inner
78
 
import bzrlib.merge3
79
 
import bzrlib.plugin
80
 
from bzrlib.smart import client, server
81
 
import bzrlib.store
82
 
from bzrlib import symbol_versioning
83
 
from bzrlib.symbol_versioning import (
84
 
    DEPRECATED_PARAMETER,
85
 
    deprecated_function,
86
 
    deprecated_method,
87
 
    deprecated_passed,
88
 
    )
89
 
import bzrlib.trace
90
 
from bzrlib.transport import get_transport
91
 
import bzrlib.transport
92
 
from bzrlib.transport.local import LocalURLServer
93
 
from bzrlib.transport.memory import MemoryServer
94
 
from bzrlib.transport.readonly import ReadonlyServer
95
 
from bzrlib.trace import mutter, note
96
 
from bzrlib.tests import TestUtil
97
 
from bzrlib.tests.http_server import HttpServer
98
 
from bzrlib.tests.TestUtil import (
99
 
                          TestSuite,
100
 
                          TestLoader,
101
 
                          )
102
 
from bzrlib.tests.treeshape import build_tree_contents
103
 
import bzrlib.version_info_formats.format_custom
104
 
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
 
92
from bzrlib.smart import client, request
 
93
from bzrlib.transport import (
 
94
    memory,
 
95
    pathfilter,
 
96
    )
 
97
from bzrlib.tests import (
 
98
    test_server,
 
99
    TestUtil,
 
100
    treeshape,
 
101
    )
 
102
from bzrlib.ui import NullProgressView
 
103
from bzrlib.ui.text import TextUIFactory
105
104
 
106
105
# Mark this python module as being part of the implementation
107
106
# of unittest: this gives us better tracebacks where the last
108
107
# shown frame is the test code, not our assertXYZ.
109
108
__unittest = 1
110
109
 
111
 
default_transport = LocalURLServer
112
 
 
113
 
 
114
 
class ExtendedTestResult(unittest._TextTestResult):
 
110
default_transport = test_server.LocalURLServer
 
111
 
 
112
 
 
113
_unitialized_attr = object()
 
114
"""A sentinel needed to act as a default value in a method signature."""
 
115
 
 
116
 
 
117
# Subunit result codes, defined here to prevent a hard dependency on subunit.
 
118
SUBUNIT_SEEK_SET = 0
 
119
SUBUNIT_SEEK_CUR = 1
 
120
 
 
121
# These are intentionally brought into this namespace. That way plugins, etc
 
122
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
 
123
TestSuite = TestUtil.TestSuite
 
124
TestLoader = TestUtil.TestLoader
 
125
 
 
126
# Tests should run in a clean and clearly defined environment. The goal is to
 
127
# keep them isolated from the running environment as mush as possible. The test
 
128
# framework ensures the variables defined below are set (or deleted if the
 
129
# value is None) before a test is run and reset to their original value after
 
130
# the test is run. Generally if some code depends on an environment variable,
 
131
# the tests should start without this variable in the environment. There are a
 
132
# few exceptions but you shouldn't violate this rule lightly.
 
133
isolated_environ = {
 
134
    'BZR_HOME': None,
 
135
    'HOME': None,
 
136
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
137
    # tests do check our impls match APPDATA
 
138
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
139
    'VISUAL': None,
 
140
    'EDITOR': None,
 
141
    'BZR_EMAIL': None,
 
142
    'BZREMAIL': None, # may still be present in the environment
 
143
    'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
 
144
    'BZR_PROGRESS_BAR': None,
 
145
    # This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
 
146
    # as a base class instead of TestCaseInTempDir. Tests inheriting from
 
147
    # TestCase should not use disk resources, BZR_LOG is one.
 
148
    'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
 
149
    'BZR_PLUGIN_PATH': None,
 
150
    'BZR_DISABLE_PLUGINS': None,
 
151
    'BZR_PLUGINS_AT': None,
 
152
    'BZR_CONCURRENCY': None,
 
153
    # Make sure that any text ui tests are consistent regardless of
 
154
    # the environment the test case is run in; you may want tests that
 
155
    # test other combinations.  'dumb' is a reasonable guess for tests
 
156
    # going to a pipe or a StringIO.
 
157
    'TERM': 'dumb',
 
158
    'LINES': '25',
 
159
    'COLUMNS': '80',
 
160
    'BZR_COLUMNS': '80',
 
161
    # Disable SSH Agent
 
162
    'SSH_AUTH_SOCK': None,
 
163
    # Proxies
 
164
    'http_proxy': None,
 
165
    'HTTP_PROXY': None,
 
166
    'https_proxy': None,
 
167
    'HTTPS_PROXY': None,
 
168
    'no_proxy': None,
 
169
    'NO_PROXY': None,
 
170
    'all_proxy': None,
 
171
    'ALL_PROXY': None,
 
172
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
173
    # least. If you do (care), please update this comment
 
174
    # -- vila 20080401
 
175
    'ftp_proxy': None,
 
176
    'FTP_PROXY': None,
 
177
    'BZR_REMOTE_PATH': None,
 
178
    # Generally speaking, we don't want apport reporting on crashes in
 
179
    # the test envirnoment unless we're specifically testing apport,
 
180
    # so that it doesn't leak into the real system environment.  We
 
181
    # use an env var so it propagates to subprocesses.
 
182
    'APPORT_DISABLE': '1',
 
183
    }
 
184
 
 
185
 
 
186
def override_os_environ(test, env=None):
 
187
    """Modify os.environ keeping a copy.
 
188
    
 
189
    :param test: A test instance
 
190
 
 
191
    :param env: A dict containing variable definitions to be installed
 
192
    """
 
193
    if env is None:
 
194
        env = isolated_environ
 
195
    test._original_os_environ = dict([(var, value)
 
196
                                      for var, value in os.environ.iteritems()])
 
197
    for var, value in env.iteritems():
 
198
        osutils.set_or_unset_env(var, value)
 
199
        if var not in test._original_os_environ:
 
200
            # The var is new, add it with a value of None, so
 
201
            # restore_os_environ will delete it
 
202
            test._original_os_environ[var] = None
 
203
 
 
204
 
 
205
def restore_os_environ(test):
 
206
    """Restore os.environ to its original state.
 
207
 
 
208
    :param test: A test instance previously passed to override_os_environ.
 
209
    """
 
210
    for var, value in test._original_os_environ.iteritems():
 
211
        # Restore the original value (or delete it if the value has been set to
 
212
        # None in override_os_environ).
 
213
        osutils.set_or_unset_env(var, value)
 
214
 
 
215
 
 
216
class ExtendedTestResult(testtools.TextTestResult):
115
217
    """Accepts, reports and accumulates the results of running tests.
116
218
 
117
219
    Compared to the unittest version this class adds support for
131
233
 
132
234
    def __init__(self, stream, descriptions, verbosity,
133
235
                 bench_history=None,
134
 
                 num_tests=None,
 
236
                 strict=False,
135
237
                 ):
136
238
        """Construct new TestResult.
137
239
 
138
240
        :param bench_history: Optionally, a writable file object to accumulate
139
241
            benchmark results.
140
242
        """
141
 
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
 
243
        testtools.TextTestResult.__init__(self, stream)
142
244
        if bench_history is not None:
143
245
            from bzrlib.version import _get_bzr_source_tree
144
246
            src_tree = _get_bzr_source_tree()
155
257
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
156
258
        self._bench_history = bench_history
157
259
        self.ui = ui.ui_factory
158
 
        self.num_tests = num_tests
 
260
        self.num_tests = 0
159
261
        self.error_count = 0
160
262
        self.failure_count = 0
161
263
        self.known_failure_count = 0
164
266
        self.unsupported = {}
165
267
        self.count = 0
166
268
        self._overall_start_time = time.time()
167
 
 
168
 
    def _extractBenchmarkTime(self, testCase):
 
269
        self._strict = strict
 
270
        self._first_thread_leaker_id = None
 
271
        self._tests_leaking_threads_count = 0
 
272
        self._traceback_from_test = None
 
273
 
 
274
    def stopTestRun(self):
 
275
        run = self.testsRun
 
276
        actionTaken = "Ran"
 
277
        stopTime = time.time()
 
278
        timeTaken = stopTime - self.startTime
 
279
        # GZ 2010-07-19: Seems testtools has no printErrors method, and though
 
280
        #                the parent class method is similar have to duplicate
 
281
        self._show_list('ERROR', self.errors)
 
282
        self._show_list('FAIL', self.failures)
 
283
        self.stream.write(self.sep2)
 
284
        self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
 
285
                            run, run != 1 and "s" or "", timeTaken))
 
286
        if not self.wasSuccessful():
 
287
            self.stream.write("FAILED (")
 
288
            failed, errored = map(len, (self.failures, self.errors))
 
289
            if failed:
 
290
                self.stream.write("failures=%d" % failed)
 
291
            if errored:
 
292
                if failed: self.stream.write(", ")
 
293
                self.stream.write("errors=%d" % errored)
 
294
            if self.known_failure_count:
 
295
                if failed or errored: self.stream.write(", ")
 
296
                self.stream.write("known_failure_count=%d" %
 
297
                    self.known_failure_count)
 
298
            self.stream.write(")\n")
 
299
        else:
 
300
            if self.known_failure_count:
 
301
                self.stream.write("OK (known_failures=%d)\n" %
 
302
                    self.known_failure_count)
 
303
            else:
 
304
                self.stream.write("OK\n")
 
305
        if self.skip_count > 0:
 
306
            skipped = self.skip_count
 
307
            self.stream.write('%d test%s skipped\n' %
 
308
                                (skipped, skipped != 1 and "s" or ""))
 
309
        if self.unsupported:
 
310
            for feature, count in sorted(self.unsupported.items()):
 
311
                self.stream.write("Missing feature '%s' skipped %d tests.\n" %
 
312
                    (feature, count))
 
313
        if self._strict:
 
314
            ok = self.wasStrictlySuccessful()
 
315
        else:
 
316
            ok = self.wasSuccessful()
 
317
        if self._first_thread_leaker_id:
 
318
            self.stream.write(
 
319
                '%s is leaking threads among %d leaking tests.\n' % (
 
320
                self._first_thread_leaker_id,
 
321
                self._tests_leaking_threads_count))
 
322
            # We don't report the main thread as an active one.
 
323
            self.stream.write(
 
324
                '%d non-main threads were left active in the end.\n'
 
325
                % (len(self._active_threads) - 1))
 
326
 
 
327
    def getDescription(self, test):
 
328
        return test.id()
 
329
 
 
330
    def _extractBenchmarkTime(self, testCase, details=None):
169
331
        """Add a benchmark time for the current test case."""
 
332
        if details and 'benchtime' in details:
 
333
            return float(''.join(details['benchtime'].iter_bytes()))
170
334
        return getattr(testCase, "_benchtime", None)
171
335
 
172
336
    def _elapsedTestTimeString(self):
173
337
        """Return a time string for the overall time the current test has taken."""
174
 
        return self._formatTime(time.time() - self._start_time)
 
338
        return self._formatTime(self._delta_to_float(
 
339
            self._now() - self._start_datetime))
175
340
 
176
341
    def _testTimeString(self, testCase):
177
342
        benchmark_time = self._extractBenchmarkTime(testCase)
178
343
        if benchmark_time is not None:
179
 
            return "%s/%s" % (
180
 
                self._formatTime(benchmark_time),
181
 
                self._elapsedTestTimeString())
 
344
            return self._formatTime(benchmark_time) + "*"
182
345
        else:
183
 
            return "           %s" % self._elapsedTestTimeString()
 
346
            return self._elapsedTestTimeString()
184
347
 
185
348
    def _formatTime(self, seconds):
186
349
        """Format seconds as milliseconds with leading spaces."""
190
353
 
191
354
    def _shortened_test_description(self, test):
192
355
        what = test.id()
193
 
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
 
356
        what = re.sub(r'^bzrlib\.tests\.', '', what)
194
357
        return what
195
358
 
 
359
    # GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
 
360
    #                multiple times in a row, because the handler is added for
 
361
    #                each test but the container list is shared between cases.
 
362
    #                See lp:498869 lp:625574 and lp:637725 for background.
 
363
    def _record_traceback_from_test(self, exc_info):
 
364
        """Store the traceback from passed exc_info tuple till"""
 
365
        self._traceback_from_test = exc_info[2]
 
366
 
196
367
    def startTest(self, test):
197
 
        unittest.TestResult.startTest(self, test)
 
368
        super(ExtendedTestResult, self).startTest(test)
 
369
        if self.count == 0:
 
370
            self.startTests()
 
371
        self.count += 1
198
372
        self.report_test_start(test)
199
373
        test.number = self.count
200
374
        self._recordTestStartTime()
 
375
        # Make testtools cases give us the real traceback on failure
 
376
        addOnException = getattr(test, "addOnException", None)
 
377
        if addOnException is not None:
 
378
            addOnException(self._record_traceback_from_test)
 
379
        # Only check for thread leaks on bzrlib derived test cases
 
380
        if isinstance(test, TestCase):
 
381
            test.addCleanup(self._check_leaked_threads, test)
 
382
 
 
383
    def stopTest(self, test):
 
384
        super(ExtendedTestResult, self).stopTest(test)
 
385
        # Manually break cycles, means touching various private things but hey
 
386
        getDetails = getattr(test, "getDetails", None)
 
387
        if getDetails is not None:
 
388
            getDetails().clear()
 
389
        # Clear _type_equality_funcs to try to stop TestCase instances
 
390
        # from wasting memory. 'clear' is not available in all Python
 
391
        # versions (bug 809048)
 
392
        type_equality_funcs = getattr(test, "_type_equality_funcs", None)
 
393
        if type_equality_funcs is not None:
 
394
            tef_clear = getattr(type_equality_funcs, "clear", None)
 
395
            if tef_clear is None:
 
396
                tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
 
397
                if tef_instance_dict is not None:
 
398
                    tef_clear = tef_instance_dict.clear
 
399
            if tef_clear is not None:
 
400
                tef_clear()
 
401
        self._traceback_from_test = None
 
402
 
 
403
    def startTests(self):
 
404
        self.report_tests_starting()
 
405
        self._active_threads = threading.enumerate()
 
406
 
 
407
    def _check_leaked_threads(self, test):
 
408
        """See if any threads have leaked since last call
 
409
 
 
410
        A sample of live threads is stored in the _active_threads attribute,
 
411
        when this method runs it compares the current live threads and any not
 
412
        in the previous sample are treated as having leaked.
 
413
        """
 
414
        now_active_threads = set(threading.enumerate())
 
415
        threads_leaked = now_active_threads.difference(self._active_threads)
 
416
        if threads_leaked:
 
417
            self._report_thread_leak(test, threads_leaked, now_active_threads)
 
418
            self._tests_leaking_threads_count += 1
 
419
            if self._first_thread_leaker_id is None:
 
420
                self._first_thread_leaker_id = test.id()
 
421
            self._active_threads = now_active_threads
201
422
 
202
423
    def _recordTestStartTime(self):
203
424
        """Record that a test has started."""
204
 
        self._start_time = time.time()
205
 
 
206
 
    def _cleanupLogFile(self, test):
207
 
        # We can only do this if we have one of our TestCases, not if
208
 
        # we have a doctest.
209
 
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
210
 
        if setKeepLogfile is not None:
211
 
            setKeepLogfile()
 
425
        self._start_datetime = self._now()
212
426
 
213
427
    def addError(self, test, err):
214
428
        """Tell result that test finished with an error.
216
430
        Called from the TestCase run() method when the test
217
431
        fails with an unexpected error.
218
432
        """
219
 
        self._testConcluded(test)
220
 
        if isinstance(err[1], TestNotApplicable):
221
 
            return self._addNotApplicable(test, err)
222
 
        elif isinstance(err[1], UnavailableFeature):
223
 
            return self.addNotSupported(test, err[1].args[0])
224
 
        else:
225
 
            unittest.TestResult.addError(self, test, err)
226
 
            self.error_count += 1
227
 
            self.report_error(test, err)
228
 
            if self.stop_early:
229
 
                self.stop()
230
 
            self._cleanupLogFile(test)
 
433
        self._post_mortem(self._traceback_from_test)
 
434
        super(ExtendedTestResult, self).addError(test, err)
 
435
        self.error_count += 1
 
436
        self.report_error(test, err)
 
437
        if self.stop_early:
 
438
            self.stop()
231
439
 
232
440
    def addFailure(self, test, err):
233
441
        """Tell result that test failed.
235
443
        Called from the TestCase run() method when the test
236
444
        fails because e.g. an assert() method failed.
237
445
        """
238
 
        self._testConcluded(test)
239
 
        if isinstance(err[1], KnownFailure):
240
 
            return self._addKnownFailure(test, err)
241
 
        else:
242
 
            unittest.TestResult.addFailure(self, test, err)
243
 
            self.failure_count += 1
244
 
            self.report_failure(test, err)
245
 
            if self.stop_early:
246
 
                self.stop()
247
 
            self._cleanupLogFile(test)
 
446
        self._post_mortem(self._traceback_from_test)
 
447
        super(ExtendedTestResult, self).addFailure(test, err)
 
448
        self.failure_count += 1
 
449
        self.report_failure(test, err)
 
450
        if self.stop_early:
 
451
            self.stop()
248
452
 
249
 
    def addSuccess(self, test):
 
453
    def addSuccess(self, test, details=None):
250
454
        """Tell result that test completed successfully.
251
455
 
252
456
        Called from the TestCase run()
253
457
        """
254
 
        self._testConcluded(test)
255
458
        if self._bench_history is not None:
256
 
            benchmark_time = self._extractBenchmarkTime(test)
 
459
            benchmark_time = self._extractBenchmarkTime(test, details)
257
460
            if benchmark_time is not None:
258
461
                self._bench_history.write("%s %s\n" % (
259
462
                    self._formatTime(benchmark_time),
260
463
                    test.id()))
261
464
        self.report_success(test)
262
 
        self._cleanupLogFile(test)
263
 
        unittest.TestResult.addSuccess(self, test)
 
465
        super(ExtendedTestResult, self).addSuccess(test)
264
466
        test._log_contents = ''
265
467
 
266
 
    def _testConcluded(self, test):
267
 
        """Common code when a test has finished.
268
 
 
269
 
        Called regardless of whether it succeded, failed, etc.
270
 
        """
271
 
        pass
272
 
 
273
 
    def _addKnownFailure(self, test, err):
 
468
    def addExpectedFailure(self, test, err):
274
469
        self.known_failure_count += 1
275
470
        self.report_known_failure(test, err)
276
471
 
 
472
    def addUnexpectedSuccess(self, test, details=None):
 
473
        """Tell result the test unexpectedly passed, counting as a failure
 
474
 
 
475
        When the minimum version of testtools required becomes 0.9.8 this
 
476
        can be updated to use the new handling there.
 
477
        """
 
478
        super(ExtendedTestResult, self).addFailure(test, details=details)
 
479
        self.failure_count += 1
 
480
        self.report_unexpected_success(test,
 
481
            "".join(details["reason"].iter_text()))
 
482
        if self.stop_early:
 
483
            self.stop()
 
484
 
277
485
    def addNotSupported(self, test, feature):
278
486
        """The test will not be run because of a missing feature.
279
487
        """
280
488
        # this can be called in two different ways: it may be that the
281
 
        # test started running, and then raised (through addError)
 
489
        # test started running, and then raised (through requireFeature)
282
490
        # UnavailableFeature.  Alternatively this method can be called
283
 
        # while probing for features before running the tests; in that
284
 
        # case we will see startTest and stopTest, but the test will never
285
 
        # actually run.
 
491
        # while probing for features before running the test code proper; in
 
492
        # that case we will see startTest and stopTest, but the test will
 
493
        # never actually run.
286
494
        self.unsupported.setdefault(str(feature), 0)
287
495
        self.unsupported[str(feature)] += 1
288
496
        self.report_unsupported(test, feature)
292
500
        self.skip_count += 1
293
501
        self.report_skip(test, reason)
294
502
 
295
 
    def _addNotApplicable(self, test, skip_excinfo):
296
 
        if isinstance(skip_excinfo[1], TestNotApplicable):
297
 
            self.not_applicable_count += 1
298
 
            self.report_not_applicable(test, skip_excinfo)
299
 
        try:
300
 
            test.tearDown()
301
 
        except KeyboardInterrupt:
302
 
            raise
303
 
        except:
304
 
            self.addError(test, test.exc_info())
305
 
        else:
306
 
            # seems best to treat this as success from point-of-view of unittest
307
 
            # -- it actually does nothing so it barely matters :)
308
 
            unittest.TestResult.addSuccess(self, test)
309
 
            test._log_contents = ''
310
 
 
311
 
    def printErrorList(self, flavour, errors):
312
 
        for test, err in errors:
313
 
            self.stream.writeln(self.separator1)
314
 
            self.stream.write("%s: " % flavour)
315
 
            self.stream.writeln(self.getDescription(test))
316
 
            if getattr(test, '_get_log', None) is not None:
317
 
                self.stream.write('\n')
318
 
                self.stream.write(
319
 
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-'))
320
 
                self.stream.write('\n')
321
 
                self.stream.write(test._get_log())
322
 
                self.stream.write('\n')
323
 
                self.stream.write(
324
 
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-'))
325
 
                self.stream.write('\n')
326
 
            self.stream.writeln(self.separator2)
327
 
            self.stream.writeln("%s" % err)
328
 
 
329
 
    def finished(self):
330
 
        pass
331
 
 
332
 
    def report_cleaning_up(self):
333
 
        pass
 
503
    def addNotApplicable(self, test, reason):
 
504
        self.not_applicable_count += 1
 
505
        self.report_not_applicable(test, reason)
 
506
 
 
507
    def _post_mortem(self, tb=None):
 
508
        """Start a PDB post mortem session."""
 
509
        if os.environ.get('BZR_TEST_PDB', None):
 
510
            import pdb
 
511
            pdb.post_mortem(tb)
 
512
 
 
513
    def progress(self, offset, whence):
 
514
        """The test is adjusting the count of tests to run."""
 
515
        if whence == SUBUNIT_SEEK_SET:
 
516
            self.num_tests = offset
 
517
        elif whence == SUBUNIT_SEEK_CUR:
 
518
            self.num_tests += offset
 
519
        else:
 
520
            raise errors.BzrError("Unknown whence %r" % whence)
 
521
 
 
522
    def report_tests_starting(self):
 
523
        """Display information before the test run begins"""
 
524
        if getattr(sys, 'frozen', None) is None:
 
525
            bzr_path = osutils.realpath(sys.argv[0])
 
526
        else:
 
527
            bzr_path = sys.executable
 
528
        self.stream.write(
 
529
            'bzr selftest: %s\n' % (bzr_path,))
 
530
        self.stream.write(
 
531
            '   %s\n' % (
 
532
                    bzrlib.__path__[0],))
 
533
        self.stream.write(
 
534
            '   bzr-%s python-%s %s\n' % (
 
535
                    bzrlib.version_string,
 
536
                    bzrlib._format_version_tuple(sys.version_info),
 
537
                    platform.platform(aliased=1),
 
538
                    ))
 
539
        self.stream.write('\n')
 
540
 
 
541
    def report_test_start(self, test):
 
542
        """Display information on the test just about to be run"""
 
543
 
 
544
    def _report_thread_leak(self, test, leaked_threads, active_threads):
 
545
        """Display information on a test that leaked one or more threads"""
 
546
        # GZ 2010-09-09: A leak summary reported separately from the general
 
547
        #                thread debugging would be nice. Tests under subunit
 
548
        #                need something not using stream, perhaps adding a
 
549
        #                testtools details object would be fitting.
 
550
        if 'threads' in selftest_debug_flags:
 
551
            self.stream.write('%s is leaking, active is now %d\n' %
 
552
                (test.id(), len(active_threads)))
 
553
 
 
554
    def startTestRun(self):
 
555
        self.startTime = time.time()
334
556
 
335
557
    def report_success(self, test):
336
558
        pass
346
568
 
347
569
    def __init__(self, stream, descriptions, verbosity,
348
570
                 bench_history=None,
349
 
                 num_tests=None,
350
571
                 pb=None,
 
572
                 strict=None,
351
573
                 ):
352
574
        ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
353
 
            bench_history, num_tests)
354
 
        if pb is None:
355
 
            self.pb = self.ui.nested_progress_bar()
356
 
            self._supplied_pb = False
357
 
        else:
358
 
            self.pb = pb
359
 
            self._supplied_pb = True
 
575
            bench_history, strict)
 
576
        # We no longer pass them around, but just rely on the UIFactory stack
 
577
        # for state
 
578
        if pb is not None:
 
579
            warnings.warn("Passing pb to TextTestResult is deprecated")
 
580
        self.pb = self.ui.nested_progress_bar()
360
581
        self.pb.show_pct = False
361
582
        self.pb.show_spinner = False
362
583
        self.pb.show_eta = False,
363
584
        self.pb.show_count = False
364
585
        self.pb.show_bar = False
365
 
 
366
 
    def report_starting(self):
 
586
        self.pb.update_latency = 0
 
587
        self.pb.show_transport_activity = False
 
588
 
 
589
    def stopTestRun(self):
 
590
        # called when the tests that are going to run have run
 
591
        self.pb.clear()
 
592
        self.pb.finished()
 
593
        super(TextTestResult, self).stopTestRun()
 
594
 
 
595
    def report_tests_starting(self):
 
596
        super(TextTestResult, self).report_tests_starting()
367
597
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
368
598
 
369
599
    def _progress_prefix_text(self):
376
606
        ##     a += ', %d skip' % self.skip_count
377
607
        ## if self.known_failure_count:
378
608
        ##     a += '+%dX' % self.known_failure_count
379
 
        if self.num_tests is not None:
 
609
        if self.num_tests:
380
610
            a +='/%d' % self.num_tests
381
611
        a += ' in '
382
612
        runtime = time.time() - self._overall_start_time
384
614
            a += '%dm%ds' % (runtime / 60, runtime % 60)
385
615
        else:
386
616
            a += '%ds' % runtime
387
 
        if self.error_count:
388
 
            a += ', %d err' % self.error_count
389
 
        if self.failure_count:
390
 
            a += ', %d fail' % self.failure_count
391
 
        if self.unsupported:
392
 
            a += ', %d missing' % len(self.unsupported)
 
617
        total_fail_count = self.error_count + self.failure_count
 
618
        if total_fail_count:
 
619
            a += ', %d failed' % total_fail_count
 
620
        # if self.unsupported:
 
621
        #     a += ', %d missing' % len(self.unsupported)
393
622
        a += ']'
394
623
        return a
395
624
 
396
625
    def report_test_start(self, test):
397
 
        self.count += 1
398
626
        self.pb.update(
399
627
                self._progress_prefix_text()
400
628
                + ' '
404
632
        return self._shortened_test_description(test)
405
633
 
406
634
    def report_error(self, test, err):
407
 
        self.pb.note('ERROR: %s\n    %s\n',
 
635
        self.stream.write('ERROR: %s\n    %s\n' % (
408
636
            self._test_description(test),
409
637
            err[1],
410
 
            )
 
638
            ))
411
639
 
412
640
    def report_failure(self, test, err):
413
 
        self.pb.note('FAIL: %s\n    %s\n',
 
641
        self.stream.write('FAIL: %s\n    %s\n' % (
414
642
            self._test_description(test),
415
643
            err[1],
416
 
            )
 
644
            ))
417
645
 
418
646
    def report_known_failure(self, test, err):
419
 
        self.pb.note('XFAIL: %s\n%s\n',
420
 
            self._test_description(test), err[1])
 
647
        pass
 
648
 
 
649
    def report_unexpected_success(self, test, reason):
 
650
        self.stream.write('FAIL: %s\n    %s: %s\n' % (
 
651
            self._test_description(test),
 
652
            "Unexpected success. Should have failed",
 
653
            reason,
 
654
            ))
421
655
 
422
656
    def report_skip(self, test, reason):
423
657
        pass
424
658
 
425
 
    def report_not_applicable(self, test, skip_excinfo):
 
659
    def report_not_applicable(self, test, reason):
426
660
        pass
427
661
 
428
662
    def report_unsupported(self, test, feature):
429
663
        """test cannot be run because feature is missing."""
430
664
 
431
 
    def report_cleaning_up(self):
432
 
        self.pb.update('Cleaning up')
433
 
 
434
 
    def finished(self):
435
 
        if not self._supplied_pb:
436
 
            self.pb.finished()
437
 
 
438
665
 
439
666
class VerboseTestResult(ExtendedTestResult):
440
667
    """Produce long output, with one line per test run plus times"""
447
674
            result = a_string
448
675
        return result.ljust(final_width)
449
676
 
450
 
    def report_starting(self):
 
677
    def report_tests_starting(self):
451
678
        self.stream.write('running %d tests...\n' % self.num_tests)
 
679
        super(VerboseTestResult, self).report_tests_starting()
452
680
 
453
681
    def report_test_start(self, test):
454
 
        self.count += 1
455
682
        name = self._shortened_test_description(test)
456
 
        # width needs space for 6 char status, plus 1 for slash, plus 2 10-char
457
 
        # numbers, plus a trailing blank
458
 
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
459
 
        self.stream.write(self._ellipsize_to_right(name,
460
 
                          osutils.terminal_width()-30))
 
683
        width = osutils.terminal_width()
 
684
        if width is not None:
 
685
            # width needs space for 6 char status, plus 1 for slash, plus an
 
686
            # 11-char time string, plus a trailing blank
 
687
            # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on
 
688
            # space
 
689
            self.stream.write(self._ellipsize_to_right(name, width-18))
 
690
        else:
 
691
            self.stream.write(name)
461
692
        self.stream.flush()
462
693
 
463
694
    def _error_summary(self, err):
465
696
        return '%s%s' % (indent, err[1])
466
697
 
467
698
    def report_error(self, test, err):
468
 
        self.stream.writeln('ERROR %s\n%s'
 
699
        self.stream.write('ERROR %s\n%s\n'
469
700
                % (self._testTimeString(test),
470
701
                   self._error_summary(err)))
471
702
 
472
703
    def report_failure(self, test, err):
473
 
        self.stream.writeln(' FAIL %s\n%s'
 
704
        self.stream.write(' FAIL %s\n%s\n'
474
705
                % (self._testTimeString(test),
475
706
                   self._error_summary(err)))
476
707
 
477
708
    def report_known_failure(self, test, err):
478
 
        self.stream.writeln('XFAIL %s\n%s'
 
709
        self.stream.write('XFAIL %s\n%s\n'
479
710
                % (self._testTimeString(test),
480
711
                   self._error_summary(err)))
481
712
 
 
713
    def report_unexpected_success(self, test, reason):
 
714
        self.stream.write(' FAIL %s\n%s: %s\n'
 
715
                % (self._testTimeString(test),
 
716
                   "Unexpected success. Should have failed",
 
717
                   reason))
 
718
 
482
719
    def report_success(self, test):
483
 
        self.stream.writeln('   OK %s' % self._testTimeString(test))
 
720
        self.stream.write('   OK %s\n' % self._testTimeString(test))
484
721
        for bench_called, stats in getattr(test, '_benchcalls', []):
485
 
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
722
            self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
486
723
            stats.pprint(file=self.stream)
487
724
        # flush the stream so that we get smooth output. This verbose mode is
488
725
        # used to show the output in PQM.
489
726
        self.stream.flush()
490
727
 
491
728
    def report_skip(self, test, reason):
492
 
        self.stream.writeln(' SKIP %s\n%s'
 
729
        self.stream.write(' SKIP %s\n%s\n'
493
730
                % (self._testTimeString(test), reason))
494
731
 
495
 
    def report_not_applicable(self, test, skip_excinfo):
496
 
        self.stream.writeln('  N/A %s\n%s'
497
 
                % (self._testTimeString(test),
498
 
                   self._error_summary(skip_excinfo)))
 
732
    def report_not_applicable(self, test, reason):
 
733
        self.stream.write('  N/A %s\n    %s\n'
 
734
                % (self._testTimeString(test), reason))
499
735
 
500
736
    def report_unsupported(self, test, feature):
501
737
        """test cannot be run because feature is missing."""
502
 
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
 
738
        self.stream.write("NODEP %s\n    The feature '%s' is not available.\n"
503
739
                %(self._testTimeString(test), feature))
504
740
 
505
741
 
511
747
                 descriptions=0,
512
748
                 verbosity=1,
513
749
                 bench_history=None,
514
 
                 list_only=False
 
750
                 strict=False,
 
751
                 result_decorators=None,
515
752
                 ):
516
 
        self.stream = unittest._WritelnDecorator(stream)
 
753
        """Create a TextTestRunner.
 
754
 
 
755
        :param result_decorators: An optional list of decorators to apply
 
756
            to the result object being used by the runner. Decorators are
 
757
            applied left to right - the first element in the list is the 
 
758
            innermost decorator.
 
759
        """
 
760
        # stream may know claim to know to write unicode strings, but in older
 
761
        # pythons this goes sufficiently wrong that it is a bad idea. (
 
762
        # specifically a built in file with encoding 'UTF-8' will still try
 
763
        # to encode using ascii.
 
764
        new_encoding = osutils.get_terminal_encoding()
 
765
        codec = codecs.lookup(new_encoding)
 
766
        if type(codec) is tuple:
 
767
            # Python 2.4
 
768
            encode = codec[0]
 
769
        else:
 
770
            encode = codec.encode
 
771
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
 
772
        #                so should swap to the plain codecs.StreamWriter
 
773
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
 
774
            "backslashreplace")
 
775
        stream.encoding = new_encoding
 
776
        self.stream = stream
517
777
        self.descriptions = descriptions
518
778
        self.verbosity = verbosity
519
779
        self._bench_history = bench_history
520
 
        self.list_only = list_only
 
780
        self._strict = strict
 
781
        self._result_decorators = result_decorators or []
521
782
 
522
783
    def run(self, test):
523
784
        "Run the given test case or test suite."
524
 
        startTime = time.time()
525
785
        if self.verbosity == 1:
526
786
            result_class = TextTestResult
527
787
        elif self.verbosity >= 2:
528
788
            result_class = VerboseTestResult
529
 
        result = result_class(self.stream,
 
789
        original_result = result_class(self.stream,
530
790
                              self.descriptions,
531
791
                              self.verbosity,
532
792
                              bench_history=self._bench_history,
533
 
                              num_tests=test.countTestCases(),
 
793
                              strict=self._strict,
534
794
                              )
535
 
        result.stop_early = self.stop_on_failure
536
 
        result.report_starting()
537
 
        if self.list_only:
538
 
            if self.verbosity >= 2:
539
 
                self.stream.writeln("Listing tests only ...\n")
540
 
            run = 0
541
 
            for t in iter_suite_tests(test):
542
 
                self.stream.writeln("%s" % (t.id()))
543
 
                run += 1
544
 
            actionTaken = "Listed"
545
 
        else:
 
795
        # Signal to result objects that look at stop early policy to stop,
 
796
        original_result.stop_early = self.stop_on_failure
 
797
        result = original_result
 
798
        for decorator in self._result_decorators:
 
799
            result = decorator(result)
 
800
            result.stop_early = self.stop_on_failure
 
801
        result.startTestRun()
 
802
        try:
546
803
            test.run(result)
547
 
            run = result.testsRun
548
 
            actionTaken = "Ran"
549
 
        stopTime = time.time()
550
 
        timeTaken = stopTime - startTime
551
 
        result.printErrors()
552
 
        self.stream.writeln(result.separator2)
553
 
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
554
 
                            run, run != 1 and "s" or "", timeTaken))
555
 
        self.stream.writeln()
556
 
        if not result.wasSuccessful():
557
 
            self.stream.write("FAILED (")
558
 
            failed, errored = map(len, (result.failures, result.errors))
559
 
            if failed:
560
 
                self.stream.write("failures=%d" % failed)
561
 
            if errored:
562
 
                if failed: self.stream.write(", ")
563
 
                self.stream.write("errors=%d" % errored)
564
 
            if result.known_failure_count:
565
 
                if failed or errored: self.stream.write(", ")
566
 
                self.stream.write("known_failure_count=%d" %
567
 
                    result.known_failure_count)
568
 
            self.stream.writeln(")")
569
 
        else:
570
 
            if result.known_failure_count:
571
 
                self.stream.writeln("OK (known_failures=%d)" %
572
 
                    result.known_failure_count)
573
 
            else:
574
 
                self.stream.writeln("OK")
575
 
        if result.skip_count > 0:
576
 
            skipped = result.skip_count
577
 
            self.stream.writeln('%d test%s skipped' %
578
 
                                (skipped, skipped != 1 and "s" or ""))
579
 
        if result.unsupported:
580
 
            for feature, count in sorted(result.unsupported.items()):
581
 
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
582
 
                    (feature, count))
583
 
        result.finished()
584
 
        return result
 
804
        finally:
 
805
            result.stopTestRun()
 
806
        # higher level code uses our extended protocol to determine
 
807
        # what exit code to give.
 
808
        return original_result
585
809
 
586
810
 
587
811
def iter_suite_tests(suite):
589
813
    if isinstance(suite, unittest.TestCase):
590
814
        yield suite
591
815
    elif isinstance(suite, unittest.TestSuite):
592
 
        for item in suite._tests:
 
816
        for item in suite:
593
817
            for r in iter_suite_tests(item):
594
818
                yield r
595
819
    else:
597
821
                        % (type(suite), suite))
598
822
 
599
823
 
600
 
class TestSkipped(Exception):
601
 
    """Indicates that a test was intentionally skipped, rather than failing."""
 
824
TestSkipped = testtools.testcase.TestSkipped
602
825
 
603
826
 
604
827
class TestNotApplicable(TestSkipped):
610
833
    """
611
834
 
612
835
 
613
 
class KnownFailure(AssertionError):
614
 
    """Indicates that a test failed in a precisely expected manner.
615
 
 
616
 
    Such failures dont block the whole test suite from passing because they are
617
 
    indicators of partially completed code or of future work. We have an
618
 
    explicit error for them so that we can ensure that they are always visible:
619
 
    KnownFailures are always shown in the output of bzr selftest.
620
 
    """
 
836
# traceback._some_str fails to format exceptions that have the default
 
837
# __str__ which does an implicit ascii conversion. However, repr() on those
 
838
# objects works, for all that its not quite what the doctor may have ordered.
 
839
def _clever_some_str(value):
 
840
    try:
 
841
        return str(value)
 
842
    except:
 
843
        try:
 
844
            return repr(value).replace('\\n', '\n')
 
845
        except:
 
846
            return '<unprintable %s object>' % type(value).__name__
 
847
 
 
848
traceback._some_str = _clever_some_str
 
849
 
 
850
 
 
851
# deprecated - use self.knownFailure(), or self.expectFailure.
 
852
KnownFailure = testtools.testcase._ExpectedFailure
621
853
 
622
854
 
623
855
class UnavailableFeature(Exception):
624
856
    """A feature required for this test was not available.
625
857
 
 
858
    This can be considered a specialised form of SkippedTest.
 
859
 
626
860
    The feature should be used to construct the exception.
627
861
    """
628
862
 
629
863
 
630
 
class CommandFailed(Exception):
631
 
    pass
632
 
 
633
 
 
634
864
class StringIOWrapper(object):
635
865
    """A wrapper around cStringIO which just adds an encoding attribute.
636
866
 
657
887
            return setattr(self._cstring, name, val)
658
888
 
659
889
 
660
 
class TestUIFactory(ui.CLIUIFactory):
 
890
class TestUIFactory(TextUIFactory):
661
891
    """A UI Factory for testing.
662
892
 
663
893
    Hide the progress bar but emit note()s.
664
894
    Redirect stdin.
665
895
    Allows get_password to be tested without real tty attached.
 
896
 
 
897
    See also CannedInputUIFactory which lets you provide programmatic input in
 
898
    a structured way.
666
899
    """
 
900
    # TODO: Capture progress events at the model level and allow them to be
 
901
    # observed by tests that care.
 
902
    #
 
903
    # XXX: Should probably unify more with CannedInputUIFactory or a
 
904
    # particular configuration of TextUIFactory, or otherwise have a clearer
 
905
    # idea of how they're supposed to be different.
 
906
    # See https://bugs.launchpad.net/bzr/+bug/408213
667
907
 
668
 
    def __init__(self,
669
 
                 stdout=None,
670
 
                 stderr=None,
671
 
                 stdin=None):
672
 
        super(TestUIFactory, self).__init__()
 
908
    def __init__(self, stdout=None, stderr=None, stdin=None):
673
909
        if stdin is not None:
674
910
            # We use a StringIOWrapper to be able to test various
675
911
            # encodings, but the user is still responsible to
676
912
            # encode the string and to set the encoding attribute
677
913
            # of StringIOWrapper.
678
 
            self.stdin = StringIOWrapper(stdin)
679
 
        if stdout is None:
680
 
            self.stdout = sys.stdout
681
 
        else:
682
 
            self.stdout = stdout
683
 
        if stderr is None:
684
 
            self.stderr = sys.stderr
685
 
        else:
686
 
            self.stderr = stderr
687
 
 
688
 
    def clear(self):
689
 
        """See progress.ProgressBar.clear()."""
690
 
 
691
 
    def clear_term(self):
692
 
        """See progress.ProgressBar.clear_term()."""
693
 
 
694
 
    def clear_term(self):
695
 
        """See progress.ProgressBar.clear_term()."""
696
 
 
697
 
    def finished(self):
698
 
        """See progress.ProgressBar.finished()."""
699
 
 
700
 
    def note(self, fmt_string, *args, **kwargs):
701
 
        """See progress.ProgressBar.note()."""
702
 
        self.stdout.write((fmt_string + "\n") % args)
703
 
 
704
 
    def progress_bar(self):
705
 
        return self
706
 
 
707
 
    def nested_progress_bar(self):
708
 
        return self
709
 
 
710
 
    def update(self, message, count=None, total=None):
711
 
        """See progress.ProgressBar.update()."""
712
 
 
713
 
    def get_non_echoed_password(self, prompt):
 
914
            stdin = StringIOWrapper(stdin)
 
915
        super(TestUIFactory, self).__init__(stdin, stdout, stderr)
 
916
 
 
917
    def get_non_echoed_password(self):
714
918
        """Get password from stdin without trying to handle the echo mode"""
715
 
        if prompt:
716
 
            self.stdout.write(prompt.encode(self.stdout.encoding, 'replace'))
717
919
        password = self.stdin.readline()
718
920
        if not password:
719
921
            raise EOFError
721
923
            password = password[:-1]
722
924
        return password
723
925
 
724
 
 
725
 
def _report_leaked_threads():
726
 
    bzrlib.trace.warning('%s is leaking threads among %d leaking tests',
727
 
                         TestCase._first_thread_leaker_id,
728
 
                         TestCase._leaking_threads_tests)
729
 
 
730
 
 
731
 
class TestCase(unittest.TestCase):
 
926
    def make_progress_view(self):
 
927
        return NullProgressView()
 
928
 
 
929
 
 
930
def isolated_doctest_setUp(test):
 
931
    override_os_environ(test)
 
932
 
 
933
 
 
934
def isolated_doctest_tearDown(test):
 
935
    restore_os_environ(test)
 
936
 
 
937
 
 
938
def IsolatedDocTestSuite(*args, **kwargs):
 
939
    """Overrides doctest.DocTestSuite to handle isolation.
 
940
 
 
941
    The method is really a factory and users are expected to use it as such.
 
942
    """
 
943
 
 
944
    kwargs['setUp'] = isolated_doctest_setUp
 
945
    kwargs['tearDown'] = isolated_doctest_tearDown
 
946
    return doctest.DocTestSuite(*args, **kwargs)
 
947
 
 
948
 
 
949
class TestCase(testtools.TestCase):
732
950
    """Base class for bzr unit tests.
733
951
 
734
952
    Tests that need access to disk resources should subclass
744
962
    routine, and to build and check bzr trees.
745
963
 
746
964
    In addition to the usual method of overriding tearDown(), this class also
747
 
    allows subclasses to register functions into the _cleanups list, which is
 
965
    allows subclasses to register cleanup functions via addCleanup, which are
748
966
    run in order as the object is torn down.  It's less likely this will be
749
967
    accidentally overlooked.
750
968
    """
751
969
 
752
 
    _active_threads = None
753
 
    _leaking_threads_tests = 0
754
 
    _first_thread_leaker_id = None
755
 
    _log_file_name = None
756
 
    _log_contents = ''
757
 
    _keep_log_file = False
 
970
    _log_file = None
758
971
    # record lsprof data when performing benchmark calls.
759
972
    _gather_lsprof_in_benchmarks = False
760
 
    attrs_to_keep = ('id', '_testMethodName', '_testMethodDoc',
761
 
                     '_log_contents', '_log_file_name', '_benchtime',
762
 
                     '_TestCase__testMethodName')
763
973
 
764
974
    def __init__(self, methodName='testMethod'):
765
975
        super(TestCase, self).__init__(methodName)
766
 
        self._cleanups = []
767
 
        self._bzr_test_setUp_run = False
768
 
        self._bzr_test_tearDown_run = False
 
976
        self._directory_isolation = True
 
977
        self.exception_handlers.insert(0,
 
978
            (UnavailableFeature, self._do_unsupported_or_skip))
 
979
        self.exception_handlers.insert(0,
 
980
            (TestNotApplicable, self._do_not_applicable))
769
981
 
770
982
    def setUp(self):
771
 
        unittest.TestCase.setUp(self)
772
 
        self._bzr_test_setUp_run = True
 
983
        super(TestCase, self).setUp()
 
984
        for feature in getattr(self, '_test_needs_features', []):
 
985
            self.requireFeature(feature)
773
986
        self._cleanEnvironment()
774
987
        self._silenceUI()
775
988
        self._startLogFile()
776
989
        self._benchcalls = []
777
990
        self._benchtime = None
778
991
        self._clear_hooks()
 
992
        self._track_transports()
 
993
        self._track_locks()
779
994
        self._clear_debug_flags()
780
 
        TestCase._active_threads = threading.activeCount()
781
 
        self.addCleanup(self._check_leaked_threads)
 
995
        # Isolate global verbosity level, to make sure it's reproducible
 
996
        # between tests.  We should get rid of this altogether: bug 656694. --
 
997
        # mbp 20101008
 
998
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
 
999
        # Isolate config option expansion until its default value for bzrlib is
 
1000
        # settled on or a the FIXME associated with _get_expand_default_value
 
1001
        # is addressed -- vila 20110219
 
1002
        self.overrideAttr(config, '_expand_default_value', None)
 
1003
        self._log_files = set()
 
1004
        # Each key in the ``_counters`` dict holds a value for a different
 
1005
        # counter. When the test ends, addDetail() should be used to output the
 
1006
        # counter values. This happens in install_counter_hook().
 
1007
        self._counters = {}
 
1008
        if 'config_stats' in selftest_debug_flags:
 
1009
            self._install_config_stats_hooks()
782
1010
 
783
1011
    def debug(self):
784
1012
        # debug a frame up.
785
1013
        import pdb
786
1014
        pdb.Pdb().set_trace(sys._getframe().f_back)
787
1015
 
788
 
    def exc_info(self):
789
 
        absent_attr = object()
790
 
        exc_info = getattr(self, '_exc_info', absent_attr)
791
 
        if exc_info is absent_attr:
792
 
            exc_info = getattr(self, '_TestCase__exc_info')
793
 
        return exc_info()
794
 
 
795
 
    def _check_leaked_threads(self):
796
 
        active = threading.activeCount()
797
 
        leaked_threads = active - TestCase._active_threads
798
 
        TestCase._active_threads = active
799
 
        if leaked_threads:
800
 
            TestCase._leaking_threads_tests += 1
801
 
            if TestCase._first_thread_leaker_id is None:
802
 
                TestCase._first_thread_leaker_id = self.id()
803
 
                # we're not specifically told when all tests are finished.
804
 
                # This will do. We use a function to avoid keeping a reference
805
 
                # to a TestCase object.
806
 
                atexit.register(_report_leaked_threads)
 
1016
    def discardDetail(self, name):
 
1017
        """Extend the addDetail, getDetails api so we can remove a detail.
 
1018
 
 
1019
        eg. bzr always adds the 'log' detail at startup, but we don't want to
 
1020
        include it for skipped, xfail, etc tests.
 
1021
 
 
1022
        It is safe to call this for a detail that doesn't exist, in case this
 
1023
        gets called multiple times.
 
1024
        """
 
1025
        # We cheat. details is stored in __details which means we shouldn't
 
1026
        # touch it. but getDetails() returns the dict directly, so we can
 
1027
        # mutate it.
 
1028
        details = self.getDetails()
 
1029
        if name in details:
 
1030
            del details[name]
 
1031
 
 
1032
    def install_counter_hook(self, hooks, name, counter_name=None):
 
1033
        """Install a counting hook.
 
1034
 
 
1035
        Any hook can be counted as long as it doesn't need to return a value.
 
1036
 
 
1037
        :param hooks: Where the hook should be installed.
 
1038
 
 
1039
        :param name: The hook name that will be counted.
 
1040
 
 
1041
        :param counter_name: The counter identifier in ``_counters``, defaults
 
1042
            to ``name``.
 
1043
        """
 
1044
        _counters = self._counters # Avoid closing over self
 
1045
        if counter_name is None:
 
1046
            counter_name = name
 
1047
        if _counters.has_key(counter_name):
 
1048
            raise AssertionError('%s is already used as a counter name'
 
1049
                                  % (counter_name,))
 
1050
        _counters[counter_name] = 0
 
1051
        self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
 
1052
            lambda: ['%d' % (_counters[counter_name],)]))
 
1053
        def increment_counter(*args, **kwargs):
 
1054
            _counters[counter_name] += 1
 
1055
        label = 'count %s calls' % (counter_name,)
 
1056
        hooks.install_named_hook(name, increment_counter, label)
 
1057
        self.addCleanup(hooks.uninstall_named_hook, name, label)
 
1058
 
 
1059
    def _install_config_stats_hooks(self):
 
1060
        """Install config hooks to count hook calls.
 
1061
 
 
1062
        """
 
1063
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
 
1064
            self.install_counter_hook(config.ConfigHooks, hook_name,
 
1065
                                       'config.%s' % (hook_name,))
 
1066
 
 
1067
        # The OldConfigHooks are private and need special handling to protect
 
1068
        # against recursive tests (tests that run other tests), so we just do
 
1069
        # manually what registering them into _builtin_known_hooks will provide
 
1070
        # us.
 
1071
        self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
 
1072
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
 
1073
            self.install_counter_hook(config.OldConfigHooks, hook_name,
 
1074
                                      'old_config.%s' % (hook_name,))
807
1075
 
808
1076
    def _clear_debug_flags(self):
809
1077
        """Prevent externally set debug flags affecting tests.
811
1079
        Tests that want to use debug flags can just set them in the
812
1080
        debug_flags set during setup/teardown.
813
1081
        """
814
 
        self._preserved_debug_flags = set(debug.debug_flags)
 
1082
        # Start with a copy of the current debug flags we can safely modify.
 
1083
        self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
815
1084
        if 'allow_debug' not in selftest_debug_flags:
816
1085
            debug.debug_flags.clear()
817
 
        self.addCleanup(self._restore_debug_flags)
 
1086
        if 'disable_lock_checks' not in selftest_debug_flags:
 
1087
            debug.debug_flags.add('strict_locks')
818
1088
 
819
1089
    def _clear_hooks(self):
820
1090
        # prevent hooks affecting tests
 
1091
        known_hooks = hooks.known_hooks
821
1092
        self._preserved_hooks = {}
822
 
        for key, factory in hooks.known_hooks.items():
823
 
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
824
 
            current_hooks = hooks.known_hooks_key_to_object(key)
 
1093
        for key, (parent, name) in known_hooks.iter_parent_objects():
 
1094
            current_hooks = getattr(parent, name)
825
1095
            self._preserved_hooks[parent] = (name, current_hooks)
 
1096
        self._preserved_lazy_hooks = hooks._lazy_hooks
 
1097
        hooks._lazy_hooks = {}
826
1098
        self.addCleanup(self._restoreHooks)
827
 
        for key, factory in hooks.known_hooks.items():
828
 
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
1099
        for key, (parent, name) in known_hooks.iter_parent_objects():
 
1100
            factory = known_hooks.get(key)
829
1101
            setattr(parent, name, factory())
 
1102
        # this hook should always be installed
 
1103
        request._install_hook()
 
1104
 
 
1105
    def disable_directory_isolation(self):
 
1106
        """Turn off directory isolation checks."""
 
1107
        self._directory_isolation = False
 
1108
 
 
1109
    def enable_directory_isolation(self):
 
1110
        """Enable directory isolation checks."""
 
1111
        self._directory_isolation = True
830
1112
 
831
1113
    def _silenceUI(self):
832
1114
        """Turn off UI for duration of test"""
833
1115
        # by default the UI is off; tests can turn it on if they want it.
834
 
        saved = ui.ui_factory
835
 
        def _restore():
836
 
            ui.ui_factory = saved
837
 
        ui.ui_factory = ui.SilentUIFactory()
838
 
        self.addCleanup(_restore)
 
1116
        self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
 
1117
 
 
1118
    def _check_locks(self):
 
1119
        """Check that all lock take/release actions have been paired."""
 
1120
        # We always check for mismatched locks. If a mismatch is found, we
 
1121
        # fail unless -Edisable_lock_checks is supplied to selftest, in which
 
1122
        # case we just print a warning.
 
1123
        # unhook:
 
1124
        acquired_locks = [lock for action, lock in self._lock_actions
 
1125
                          if action == 'acquired']
 
1126
        released_locks = [lock for action, lock in self._lock_actions
 
1127
                          if action == 'released']
 
1128
        broken_locks = [lock for action, lock in self._lock_actions
 
1129
                        if action == 'broken']
 
1130
        # trivially, given the tests for lock acquistion and release, if we
 
1131
        # have as many in each list, it should be ok. Some lock tests also
 
1132
        # break some locks on purpose and should be taken into account by
 
1133
        # considering that breaking a lock is just a dirty way of releasing it.
 
1134
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
 
1135
            message = (
 
1136
                'Different number of acquired and '
 
1137
                'released or broken locks.\n'
 
1138
                'acquired=%s\n'
 
1139
                'released=%s\n'
 
1140
                'broken=%s\n' %
 
1141
                (acquired_locks, released_locks, broken_locks))
 
1142
            if not self._lock_check_thorough:
 
1143
                # Rather than fail, just warn
 
1144
                print "Broken test %s: %s" % (self, message)
 
1145
                return
 
1146
            self.fail(message)
 
1147
 
 
1148
    def _track_locks(self):
 
1149
        """Track lock activity during tests."""
 
1150
        self._lock_actions = []
 
1151
        if 'disable_lock_checks' in selftest_debug_flags:
 
1152
            self._lock_check_thorough = False
 
1153
        else:
 
1154
            self._lock_check_thorough = True
 
1155
 
 
1156
        self.addCleanup(self._check_locks)
 
1157
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
 
1158
                                                self._lock_acquired, None)
 
1159
        _mod_lock.Lock.hooks.install_named_hook('lock_released',
 
1160
                                                self._lock_released, None)
 
1161
        _mod_lock.Lock.hooks.install_named_hook('lock_broken',
 
1162
                                                self._lock_broken, None)
 
1163
 
 
1164
    def _lock_acquired(self, result):
 
1165
        self._lock_actions.append(('acquired', result))
 
1166
 
 
1167
    def _lock_released(self, result):
 
1168
        self._lock_actions.append(('released', result))
 
1169
 
 
1170
    def _lock_broken(self, result):
 
1171
        self._lock_actions.append(('broken', result))
 
1172
 
 
1173
    def permit_dir(self, name):
 
1174
        """Permit a directory to be used by this test. See permit_url."""
 
1175
        name_transport = _mod_transport.get_transport(name)
 
1176
        self.permit_url(name)
 
1177
        self.permit_url(name_transport.base)
 
1178
 
 
1179
    def permit_url(self, url):
 
1180
        """Declare that url is an ok url to use in this test.
 
1181
        
 
1182
        Do this for memory transports, temporary test directory etc.
 
1183
        
 
1184
        Do not do this for the current working directory, /tmp, or any other
 
1185
        preexisting non isolated url.
 
1186
        """
 
1187
        if not url.endswith('/'):
 
1188
            url += '/'
 
1189
        self._bzr_selftest_roots.append(url)
 
1190
 
 
1191
    def permit_source_tree_branch_repo(self):
 
1192
        """Permit the source tree bzr is running from to be opened.
 
1193
 
 
1194
        Some code such as bzrlib.version attempts to read from the bzr branch
 
1195
        that bzr is executing from (if any). This method permits that directory
 
1196
        to be used in the test suite.
 
1197
        """
 
1198
        path = self.get_source_path()
 
1199
        self.record_directory_isolation()
 
1200
        try:
 
1201
            try:
 
1202
                workingtree.WorkingTree.open(path)
 
1203
            except (errors.NotBranchError, errors.NoWorkingTree):
 
1204
                raise TestSkipped('Needs a working tree of bzr sources')
 
1205
        finally:
 
1206
            self.enable_directory_isolation()
 
1207
 
 
1208
    def _preopen_isolate_transport(self, transport):
 
1209
        """Check that all transport openings are done in the test work area."""
 
1210
        while isinstance(transport, pathfilter.PathFilteringTransport):
 
1211
            # Unwrap pathfiltered transports
 
1212
            transport = transport.server.backing_transport.clone(
 
1213
                transport._filter('.'))
 
1214
        url = transport.base
 
1215
        # ReadonlySmartTCPServer_for_testing decorates the backing transport
 
1216
        # urls it is given by prepending readonly+. This is appropriate as the
 
1217
        # client shouldn't know that the server is readonly (or not readonly).
 
1218
        # We could register all servers twice, with readonly+ prepending, but
 
1219
        # that makes for a long list; this is about the same but easier to
 
1220
        # read.
 
1221
        if url.startswith('readonly+'):
 
1222
            url = url[len('readonly+'):]
 
1223
        self._preopen_isolate_url(url)
 
1224
 
 
1225
    def _preopen_isolate_url(self, url):
 
1226
        if not self._directory_isolation:
 
1227
            return
 
1228
        if self._directory_isolation == 'record':
 
1229
            self._bzr_selftest_roots.append(url)
 
1230
            return
 
1231
        # This prevents all transports, including e.g. sftp ones backed on disk
 
1232
        # from working unless they are explicitly granted permission. We then
 
1233
        # depend on the code that sets up test transports to check that they are
 
1234
        # appropriately isolated and enable their use by calling
 
1235
        # self.permit_transport()
 
1236
        if not osutils.is_inside_any(self._bzr_selftest_roots, url):
 
1237
            raise errors.BzrError("Attempt to escape test isolation: %r %r"
 
1238
                % (url, self._bzr_selftest_roots))
 
1239
 
 
1240
    def record_directory_isolation(self):
 
1241
        """Gather accessed directories to permit later access.
 
1242
        
 
1243
        This is used for tests that access the branch bzr is running from.
 
1244
        """
 
1245
        self._directory_isolation = "record"
 
1246
 
 
1247
    def start_server(self, transport_server, backing_server=None):
 
1248
        """Start transport_server for this test.
 
1249
 
 
1250
        This starts the server, registers a cleanup for it and permits the
 
1251
        server's urls to be used.
 
1252
        """
 
1253
        if backing_server is None:
 
1254
            transport_server.start_server()
 
1255
        else:
 
1256
            transport_server.start_server(backing_server)
 
1257
        self.addCleanup(transport_server.stop_server)
 
1258
        # Obtain a real transport because if the server supplies a password, it
 
1259
        # will be hidden from the base on the client side.
 
1260
        t = _mod_transport.get_transport(transport_server.get_url())
 
1261
        # Some transport servers effectively chroot the backing transport;
 
1262
        # others like SFTPServer don't - users of the transport can walk up the
 
1263
        # transport to read the entire backing transport. This wouldn't matter
 
1264
        # except that the workdir tests are given - and that they expect the
 
1265
        # server's url to point at - is one directory under the safety net. So
 
1266
        # Branch operations into the transport will attempt to walk up one
 
1267
        # directory. Chrooting all servers would avoid this but also mean that
 
1268
        # we wouldn't be testing directly against non-root urls. Alternatively
 
1269
        # getting the test framework to start the server with a backing server
 
1270
        # at the actual safety net directory would work too, but this then
 
1271
        # means that the self.get_url/self.get_transport methods would need
 
1272
        # to transform all their results. On balance its cleaner to handle it
 
1273
        # here, and permit a higher url when we have one of these transports.
 
1274
        if t.base.endswith('/work/'):
 
1275
            # we have safety net/test root/work
 
1276
            t = t.clone('../..')
 
1277
        elif isinstance(transport_server,
 
1278
                        test_server.SmartTCPServer_for_testing):
 
1279
            # The smart server adds a path similar to work, which is traversed
 
1280
            # up from by the client. But the server is chrooted - the actual
 
1281
            # backing transport is not escaped from, and VFS requests to the
 
1282
            # root will error (because they try to escape the chroot).
 
1283
            t2 = t.clone('..')
 
1284
            while t2.base != t.base:
 
1285
                t = t2
 
1286
                t2 = t.clone('..')
 
1287
        self.permit_url(t.base)
 
1288
 
 
1289
    def _track_transports(self):
 
1290
        """Install checks for transport usage."""
 
1291
        # TestCase has no safe place it can write to.
 
1292
        self._bzr_selftest_roots = []
 
1293
        # Currently the easiest way to be sure that nothing is going on is to
 
1294
        # hook into bzr dir opening. This leaves a small window of error for
 
1295
        # transport tests, but they are well known, and we can improve on this
 
1296
        # step.
 
1297
        bzrdir.BzrDir.hooks.install_named_hook("pre_open",
 
1298
            self._preopen_isolate_transport, "Check bzr directories are safe.")
839
1299
 
840
1300
    def _ndiff_strings(self, a, b):
841
1301
        """Return ndiff between two strings containing lines.
859
1319
        except UnicodeError, e:
860
1320
            # If we can't compare without getting a UnicodeError, then
861
1321
            # obviously they are different
862
 
            mutter('UnicodeError: %s', e)
 
1322
            trace.mutter('UnicodeError: %s', e)
863
1323
        if message:
864
1324
            message += '\n'
865
1325
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
866
1326
            % (message,
867
 
               pformat(a), pformat(b)))
 
1327
               pprint.pformat(a), pprint.pformat(b)))
868
1328
 
869
1329
    assertEquals = assertEqual
870
1330
 
879
1339
            return
880
1340
        if message is None:
881
1341
            message = "texts not equal:\n"
 
1342
        if a + '\n' == b:
 
1343
            message = 'first string is missing a final newline.\n'
882
1344
        if a == b + '\n':
883
 
            message = 'first string is missing a final newline.\n'
884
 
        if a + '\n' == b:
885
1345
            message = 'second string is missing a final newline.\n'
886
1346
        raise AssertionError(message +
887
1347
                             self._ndiff_strings(a, b))
898
1358
        :raises AssertionError: If the expected and actual stat values differ
899
1359
            other than by atime.
900
1360
        """
901
 
        self.assertEqual(expected.st_size, actual.st_size)
902
 
        self.assertEqual(expected.st_mtime, actual.st_mtime)
903
 
        self.assertEqual(expected.st_ctime, actual.st_ctime)
904
 
        self.assertEqual(expected.st_dev, actual.st_dev)
905
 
        self.assertEqual(expected.st_ino, actual.st_ino)
906
 
        self.assertEqual(expected.st_mode, actual.st_mode)
 
1361
        self.assertEqual(expected.st_size, actual.st_size,
 
1362
                         'st_size did not match')
 
1363
        self.assertEqual(expected.st_mtime, actual.st_mtime,
 
1364
                         'st_mtime did not match')
 
1365
        self.assertEqual(expected.st_ctime, actual.st_ctime,
 
1366
                         'st_ctime did not match')
 
1367
        if sys.platform == 'win32':
 
1368
            # On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
 
1369
            # is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
 
1370
            # odd. We just force it to always be 0 to avoid any problems.
 
1371
            self.assertEqual(0, expected.st_dev)
 
1372
            self.assertEqual(0, actual.st_dev)
 
1373
            self.assertEqual(0, expected.st_ino)
 
1374
            self.assertEqual(0, actual.st_ino)
 
1375
        else:
 
1376
            self.assertEqual(expected.st_dev, actual.st_dev,
 
1377
                             'st_dev did not match')
 
1378
            self.assertEqual(expected.st_ino, actual.st_ino,
 
1379
                             'st_ino did not match')
 
1380
        self.assertEqual(expected.st_mode, actual.st_mode,
 
1381
                         'st_mode did not match')
907
1382
 
908
1383
    def assertLength(self, length, obj_with_len):
909
1384
        """Assert that obj_with_len is of length length."""
911
1386
            self.fail("Incorrect length: wanted %d, got %d for %r" % (
912
1387
                length, len(obj_with_len), obj_with_len))
913
1388
 
 
1389
    def assertLogsError(self, exception_class, func, *args, **kwargs):
 
1390
        """Assert that `func(*args, **kwargs)` quietly logs a specific error.
 
1391
        """
 
1392
        captured = []
 
1393
        orig_log_exception_quietly = trace.log_exception_quietly
 
1394
        try:
 
1395
            def capture():
 
1396
                orig_log_exception_quietly()
 
1397
                captured.append(sys.exc_info()[1])
 
1398
            trace.log_exception_quietly = capture
 
1399
            func(*args, **kwargs)
 
1400
        finally:
 
1401
            trace.log_exception_quietly = orig_log_exception_quietly
 
1402
        self.assertLength(1, captured)
 
1403
        err = captured[0]
 
1404
        self.assertIsInstance(err, exception_class)
 
1405
        return err
 
1406
 
914
1407
    def assertPositive(self, val):
915
1408
        """Assert that val is greater than 0."""
916
1409
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
946
1439
            raise AssertionError('pattern "%s" found in "%s"'
947
1440
                    % (needle_re, haystack))
948
1441
 
 
1442
    def assertContainsString(self, haystack, needle):
 
1443
        if haystack.find(needle) == -1:
 
1444
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
 
1445
 
 
1446
    def assertNotContainsString(self, haystack, needle):
 
1447
        if haystack.find(needle) != -1:
 
1448
            self.fail("string %r found in '''%s'''" % (needle, haystack))
 
1449
 
949
1450
    def assertSubset(self, sublist, superlist):
950
1451
        """Assert that every entry in sublist is present in superlist."""
951
1452
        missing = set(sublist) - set(superlist)
1008
1509
                raise AssertionError("%r is %r." % (left, right))
1009
1510
 
1010
1511
    def assertTransportMode(self, transport, path, mode):
1011
 
        """Fail if a path does not have mode mode.
 
1512
        """Fail if a path does not have mode "mode".
1012
1513
 
1013
1514
        If modes are not supported on this transport, the assertion is ignored.
1014
1515
        """
1026
1527
                         osutils.realpath(path2),
1027
1528
                         "apparent paths:\na = %s\nb = %s\n," % (path1, path2))
1028
1529
 
1029
 
    def assertIsInstance(self, obj, kls):
1030
 
        """Fail if obj is not an instance of kls"""
 
1530
    def assertIsInstance(self, obj, kls, msg=None):
 
1531
        """Fail if obj is not an instance of kls
 
1532
        
 
1533
        :param msg: Supplementary message to show if the assertion fails.
 
1534
        """
1031
1535
        if not isinstance(obj, kls):
1032
 
            self.fail("%r is an instance of %s rather than %s" % (
1033
 
                obj, obj.__class__, kls))
1034
 
 
1035
 
    def expectFailure(self, reason, assertion, *args, **kwargs):
1036
 
        """Invoke a test, expecting it to fail for the given reason.
1037
 
 
1038
 
        This is for assertions that ought to succeed, but currently fail.
1039
 
        (The failure is *expected* but not *wanted*.)  Please be very precise
1040
 
        about the failure you're expecting.  If a new bug is introduced,
1041
 
        AssertionError should be raised, not KnownFailure.
1042
 
 
1043
 
        Frequently, expectFailure should be followed by an opposite assertion.
1044
 
        See example below.
1045
 
 
1046
 
        Intended to be used with a callable that raises AssertionError as the
1047
 
        'assertion' parameter.  args and kwargs are passed to the 'assertion'.
1048
 
 
1049
 
        Raises KnownFailure if the test fails.  Raises AssertionError if the
1050
 
        test succeeds.
1051
 
 
1052
 
        example usage::
1053
 
 
1054
 
          self.expectFailure('Math is broken', self.assertNotEqual, 54,
1055
 
                             dynamic_val)
1056
 
          self.assertEqual(42, dynamic_val)
1057
 
 
1058
 
          This means that a dynamic_val of 54 will cause the test to raise
1059
 
          a KnownFailure.  Once math is fixed and the expectFailure is removed,
1060
 
          only a dynamic_val of 42 will allow the test to pass.  Anything other
1061
 
          than 54 or 42 will cause an AssertionError.
1062
 
        """
1063
 
        try:
1064
 
            assertion(*args, **kwargs)
1065
 
        except AssertionError:
1066
 
            raise KnownFailure(reason)
1067
 
        else:
1068
 
            self.fail('Unexpected success.  Should have failed: %s' % reason)
 
1536
            m = "%r is an instance of %s rather than %s" % (
 
1537
                obj, obj.__class__, kls)
 
1538
            if msg:
 
1539
                m += ": " + msg
 
1540
            self.fail(m)
1069
1541
 
1070
1542
    def assertFileEqual(self, content, path):
1071
1543
        """Fail if path does not contain 'content'."""
1072
 
        self.failUnlessExists(path)
 
1544
        self.assertPathExists(path)
1073
1545
        f = file(path, 'rb')
1074
1546
        try:
1075
1547
            s = f.read()
1077
1549
            f.close()
1078
1550
        self.assertEqualDiff(content, s)
1079
1551
 
 
1552
    def assertDocstring(self, expected_docstring, obj):
 
1553
        """Fail if obj does not have expected_docstring"""
 
1554
        if __doc__ is None:
 
1555
            # With -OO the docstring should be None instead
 
1556
            self.assertIs(obj.__doc__, None)
 
1557
        else:
 
1558
            self.assertEqual(expected_docstring, obj.__doc__)
 
1559
 
 
1560
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1080
1561
    def failUnlessExists(self, path):
 
1562
        return self.assertPathExists(path)
 
1563
 
 
1564
    def assertPathExists(self, path):
1081
1565
        """Fail unless path or paths, which may be abs or relative, exist."""
1082
1566
        if not isinstance(path, basestring):
1083
1567
            for p in path:
1084
 
                self.failUnlessExists(p)
 
1568
                self.assertPathExists(p)
1085
1569
        else:
1086
 
            self.failUnless(osutils.lexists(path),path+" does not exist")
 
1570
            self.assertTrue(osutils.lexists(path),
 
1571
                path + " does not exist")
1087
1572
 
 
1573
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1088
1574
    def failIfExists(self, path):
 
1575
        return self.assertPathDoesNotExist(path)
 
1576
 
 
1577
    def assertPathDoesNotExist(self, path):
1089
1578
        """Fail if path or paths, which may be abs or relative, exist."""
1090
1579
        if not isinstance(path, basestring):
1091
1580
            for p in path:
1092
 
                self.failIfExists(p)
 
1581
                self.assertPathDoesNotExist(p)
1093
1582
        else:
1094
 
            self.failIf(osutils.lexists(path),path+" exists")
 
1583
            self.assertFalse(osutils.lexists(path),
 
1584
                path + " exists")
1095
1585
 
1096
1586
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1097
1587
        """A helper for callDeprecated and applyDeprecated.
1123
1613
        not other callers that go direct to the warning module.
1124
1614
 
1125
1615
        To test that a deprecated method raises an error, do something like
1126
 
        this::
 
1616
        this (remember that both assertRaises and applyDeprecated delays *args
 
1617
        and **kwargs passing)::
1127
1618
 
1128
1619
            self.assertRaises(errors.ReservedId,
1129
1620
                self.applyDeprecated,
1211
1702
 
1212
1703
        The file is removed as the test is torn down.
1213
1704
        """
1214
 
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1215
 
        self._log_file = os.fdopen(fileno, 'w+')
1216
 
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
1217
 
        self._log_file_name = name
 
1705
        pseudo_log_file = StringIO()
 
1706
        def _get_log_contents_for_weird_testtools_api():
 
1707
            return [pseudo_log_file.getvalue().decode(
 
1708
                "utf-8", "replace").encode("utf-8")]
 
1709
        self.addDetail("log", content.Content(content.ContentType("text",
 
1710
            "plain", {"charset": "utf8"}),
 
1711
            _get_log_contents_for_weird_testtools_api))
 
1712
        self._log_file = pseudo_log_file
 
1713
        self._log_memento = trace.push_log_file(self._log_file)
1218
1714
        self.addCleanup(self._finishLogFile)
1219
1715
 
1220
1716
    def _finishLogFile(self):
1221
1717
        """Finished with the log file.
1222
1718
 
1223
 
        Close the file and delete it, unless setKeepLogfile was called.
1224
 
        """
1225
 
        if self._log_file is None:
1226
 
            return
1227
 
        bzrlib.trace.pop_log_file(self._log_memento)
1228
 
        self._log_file.close()
1229
 
        self._log_file = None
1230
 
        if not self._keep_log_file:
1231
 
            os.remove(self._log_file_name)
1232
 
            self._log_file_name = None
1233
 
 
1234
 
    def setKeepLogfile(self):
1235
 
        """Make the logfile not be deleted when _finishLogFile is called."""
1236
 
        self._keep_log_file = True
1237
 
 
1238
 
    def addCleanup(self, callable, *args, **kwargs):
1239
 
        """Arrange to run a callable when this case is torn down.
1240
 
 
1241
 
        Callables are run in the reverse of the order they are registered,
1242
 
        ie last-in first-out.
1243
 
        """
1244
 
        self._cleanups.append((callable, args, kwargs))
 
1719
        Close the file and delete it.
 
1720
        """
 
1721
        if trace._trace_file:
 
1722
            # flush the log file, to get all content
 
1723
            trace._trace_file.flush()
 
1724
        trace.pop_log_file(self._log_memento)
 
1725
 
 
1726
    def thisFailsStrictLockCheck(self):
 
1727
        """It is known that this test would fail with -Dstrict_locks.
 
1728
 
 
1729
        By default, all tests are run with strict lock checking unless
 
1730
        -Edisable_lock_checks is supplied. However there are some tests which
 
1731
        we know fail strict locks at this point that have not been fixed.
 
1732
        They should call this function to disable the strict checking.
 
1733
 
 
1734
        This should be used sparingly, it is much better to fix the locking
 
1735
        issues rather than papering over the problem by calling this function.
 
1736
        """
 
1737
        debug.debug_flags.discard('strict_locks')
 
1738
 
 
1739
    def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
 
1740
        """Overrides an object attribute restoring it after the test.
 
1741
 
 
1742
        :note: This should be used with discretion; you should think about
 
1743
        whether it's better to make the code testable without monkey-patching.
 
1744
 
 
1745
        :param obj: The object that will be mutated.
 
1746
 
 
1747
        :param attr_name: The attribute name we want to preserve/override in
 
1748
            the object.
 
1749
 
 
1750
        :param new: The optional value we want to set the attribute to.
 
1751
 
 
1752
        :returns: The actual attr value.
 
1753
        """
 
1754
        value = getattr(obj, attr_name)
 
1755
        # The actual value is captured by the call below
 
1756
        self.addCleanup(setattr, obj, attr_name, value)
 
1757
        if new is not _unitialized_attr:
 
1758
            setattr(obj, attr_name, new)
 
1759
        return value
 
1760
 
 
1761
    def overrideEnv(self, name, new):
 
1762
        """Set an environment variable, and reset it after the test.
 
1763
 
 
1764
        :param name: The environment variable name.
 
1765
 
 
1766
        :param new: The value to set the variable to. If None, the 
 
1767
            variable is deleted from the environment.
 
1768
 
 
1769
        :returns: The actual variable value.
 
1770
        """
 
1771
        value = osutils.set_or_unset_env(name, new)
 
1772
        self.addCleanup(osutils.set_or_unset_env, name, value)
 
1773
        return value
 
1774
 
 
1775
    def recordCalls(self, obj, attr_name):
 
1776
        """Monkeypatch in a wrapper that will record calls.
 
1777
 
 
1778
        The monkeypatch is automatically removed when the test concludes.
 
1779
 
 
1780
        :param obj: The namespace holding the reference to be replaced;
 
1781
            typically a module, class, or object.
 
1782
        :param attr_name: A string for the name of the attribute to 
 
1783
            patch.
 
1784
        :returns: A list that will be extended with one item every time the
 
1785
            function is called, with a tuple of (args, kwargs).
 
1786
        """
 
1787
        calls = []
 
1788
 
 
1789
        def decorator(*args, **kwargs):
 
1790
            calls.append((args, kwargs))
 
1791
            return orig(*args, **kwargs)
 
1792
        orig = self.overrideAttr(obj, attr_name, decorator)
 
1793
        return calls
1245
1794
 
1246
1795
    def _cleanEnvironment(self):
1247
 
        new_env = {
1248
 
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1249
 
            'HOME': os.getcwd(),
1250
 
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
1251
 
            # tests do check our impls match APPDATA
1252
 
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
1253
 
            'BZR_EMAIL': None,
1254
 
            'BZREMAIL': None, # may still be present in the environment
1255
 
            'EMAIL': None,
1256
 
            'BZR_PROGRESS_BAR': None,
1257
 
            'BZR_LOG': None,
1258
 
            'BZR_PLUGIN_PATH': None,
1259
 
            # SSH Agent
1260
 
            'SSH_AUTH_SOCK': None,
1261
 
            # Proxies
1262
 
            'http_proxy': None,
1263
 
            'HTTP_PROXY': None,
1264
 
            'https_proxy': None,
1265
 
            'HTTPS_PROXY': None,
1266
 
            'no_proxy': None,
1267
 
            'NO_PROXY': None,
1268
 
            'all_proxy': None,
1269
 
            'ALL_PROXY': None,
1270
 
            # Nobody cares about these ones AFAIK. So far at
1271
 
            # least. If you do (care), please update this comment
1272
 
            # -- vila 20061212
1273
 
            'ftp_proxy': None,
1274
 
            'FTP_PROXY': None,
1275
 
            'BZR_REMOTE_PATH': None,
1276
 
        }
1277
 
        self.__old_env = {}
1278
 
        self.addCleanup(self._restoreEnvironment)
1279
 
        for name, value in new_env.iteritems():
1280
 
            self._captureVar(name, value)
1281
 
 
1282
 
    def _captureVar(self, name, newvalue):
1283
 
        """Set an environment variable, and reset it when finished."""
1284
 
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1285
 
 
1286
 
    def _restore_debug_flags(self):
1287
 
        debug.debug_flags.clear()
1288
 
        debug.debug_flags.update(self._preserved_debug_flags)
1289
 
 
1290
 
    def _restoreEnvironment(self):
1291
 
        for name, value in self.__old_env.iteritems():
1292
 
            osutils.set_or_unset_env(name, value)
 
1796
        for name, value in isolated_environ.iteritems():
 
1797
            self.overrideEnv(name, value)
1293
1798
 
1294
1799
    def _restoreHooks(self):
1295
1800
        for klass, (name, hooks) in self._preserved_hooks.items():
1296
1801
            setattr(klass, name, hooks)
 
1802
        self._preserved_hooks.clear()
 
1803
        bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
 
1804
        self._preserved_lazy_hooks.clear()
1297
1805
 
1298
1806
    def knownFailure(self, reason):
1299
1807
        """This test has failed for some known reason."""
1300
1808
        raise KnownFailure(reason)
1301
1809
 
 
1810
    def _suppress_log(self):
 
1811
        """Remove the log info from details."""
 
1812
        self.discardDetail('log')
 
1813
 
1302
1814
    def _do_skip(self, result, reason):
 
1815
        self._suppress_log()
1303
1816
        addSkip = getattr(result, 'addSkip', None)
1304
1817
        if not callable(addSkip):
1305
 
            result.addError(self, self.exc_info())
 
1818
            result.addSuccess(result)
1306
1819
        else:
1307
1820
            addSkip(self, reason)
1308
1821
 
1309
 
    def run(self, result=None):
1310
 
        if result is None: result = self.defaultTestResult()
1311
 
        for feature in getattr(self, '_test_needs_features', []):
1312
 
            if not feature.available():
1313
 
                result.startTest(self)
1314
 
                if getattr(result, 'addNotSupported', None):
1315
 
                    result.addNotSupported(self, feature)
1316
 
                else:
1317
 
                    result.addSuccess(self)
1318
 
                result.stopTest(self)
1319
 
                return
1320
 
        try:
1321
 
            try:
1322
 
                result.startTest(self)
1323
 
                absent_attr = object()
1324
 
                # Python 2.5
1325
 
                method_name = getattr(self, '_testMethodName', absent_attr)
1326
 
                if method_name is absent_attr:
1327
 
                    # Python 2.4
1328
 
                    method_name = getattr(self, '_TestCase__testMethodName')
1329
 
                testMethod = getattr(self, method_name)
1330
 
                try:
1331
 
                    try:
1332
 
                        self.setUp()
1333
 
                        if not self._bzr_test_setUp_run:
1334
 
                            self.fail(
1335
 
                                "test setUp did not invoke "
1336
 
                                "bzrlib.tests.TestCase's setUp")
1337
 
                    except KeyboardInterrupt:
1338
 
                        raise
1339
 
                    except TestSkipped, e:
1340
 
                        self._do_skip(result, e.args[0])
1341
 
                        self.tearDown()
1342
 
                        return
1343
 
                    except:
1344
 
                        result.addError(self, self.exc_info())
1345
 
                        return
1346
 
 
1347
 
                    ok = False
1348
 
                    try:
1349
 
                        testMethod()
1350
 
                        ok = True
1351
 
                    except self.failureException:
1352
 
                        result.addFailure(self, self.exc_info())
1353
 
                    except TestSkipped, e:
1354
 
                        if not e.args:
1355
 
                            reason = "No reason given."
1356
 
                        else:
1357
 
                            reason = e.args[0]
1358
 
                        self._do_skip(result, reason)
1359
 
                    except KeyboardInterrupt:
1360
 
                        raise
1361
 
                    except:
1362
 
                        result.addError(self, self.exc_info())
1363
 
 
1364
 
                    try:
1365
 
                        self.tearDown()
1366
 
                        if not self._bzr_test_tearDown_run:
1367
 
                            self.fail(
1368
 
                                "test tearDown did not invoke "
1369
 
                                "bzrlib.tests.TestCase's tearDown")
1370
 
                    except KeyboardInterrupt:
1371
 
                        raise
1372
 
                    except:
1373
 
                        result.addError(self, self.exc_info())
1374
 
                        ok = False
1375
 
                    if ok: result.addSuccess(self)
1376
 
                finally:
1377
 
                    result.stopTest(self)
1378
 
                return
1379
 
            except TestNotApplicable:
1380
 
                # Not moved from the result [yet].
1381
 
                raise
1382
 
            except KeyboardInterrupt:
1383
 
                raise
1384
 
        finally:
1385
 
            saved_attrs = {}
1386
 
            absent_attr = object()
1387
 
            for attr_name in self.attrs_to_keep:
1388
 
                attr = getattr(self, attr_name, absent_attr)
1389
 
                if attr is not absent_attr:
1390
 
                    saved_attrs[attr_name] = attr
1391
 
            self.__dict__ = saved_attrs
1392
 
 
1393
 
    def tearDown(self):
1394
 
        self._bzr_test_tearDown_run = True
1395
 
        self._runCleanups()
1396
 
        self._log_contents = ''
1397
 
        unittest.TestCase.tearDown(self)
 
1822
    @staticmethod
 
1823
    def _do_known_failure(self, result, e):
 
1824
        self._suppress_log()
 
1825
        err = sys.exc_info()
 
1826
        addExpectedFailure = getattr(result, 'addExpectedFailure', None)
 
1827
        if addExpectedFailure is not None:
 
1828
            addExpectedFailure(self, err)
 
1829
        else:
 
1830
            result.addSuccess(self)
 
1831
 
 
1832
    @staticmethod
 
1833
    def _do_not_applicable(self, result, e):
 
1834
        if not e.args:
 
1835
            reason = 'No reason given'
 
1836
        else:
 
1837
            reason = e.args[0]
 
1838
        self._suppress_log ()
 
1839
        addNotApplicable = getattr(result, 'addNotApplicable', None)
 
1840
        if addNotApplicable is not None:
 
1841
            result.addNotApplicable(self, reason)
 
1842
        else:
 
1843
            self._do_skip(result, reason)
 
1844
 
 
1845
    @staticmethod
 
1846
    def _report_skip(self, result, err):
 
1847
        """Override the default _report_skip.
 
1848
 
 
1849
        We want to strip the 'log' detail. If we waint until _do_skip, it has
 
1850
        already been formatted into the 'reason' string, and we can't pull it
 
1851
        out again.
 
1852
        """
 
1853
        self._suppress_log()
 
1854
        super(TestCase, self)._report_skip(self, result, err)
 
1855
 
 
1856
    @staticmethod
 
1857
    def _report_expected_failure(self, result, err):
 
1858
        """Strip the log.
 
1859
 
 
1860
        See _report_skip for motivation.
 
1861
        """
 
1862
        self._suppress_log()
 
1863
        super(TestCase, self)._report_expected_failure(self, result, err)
 
1864
 
 
1865
    @staticmethod
 
1866
    def _do_unsupported_or_skip(self, result, e):
 
1867
        reason = e.args[0]
 
1868
        self._suppress_log()
 
1869
        addNotSupported = getattr(result, 'addNotSupported', None)
 
1870
        if addNotSupported is not None:
 
1871
            result.addNotSupported(self, reason)
 
1872
        else:
 
1873
            self._do_skip(result, reason)
1398
1874
 
1399
1875
    def time(self, callable, *args, **kwargs):
1400
1876
        """Run callable and accrue the time it takes to the benchmark time.
1404
1880
        self._benchcalls.
1405
1881
        """
1406
1882
        if self._benchtime is None:
 
1883
            self.addDetail('benchtime', content.Content(content.ContentType(
 
1884
                "text", "plain"), lambda:[str(self._benchtime)]))
1407
1885
            self._benchtime = 0
1408
1886
        start = time.time()
1409
1887
        try:
1418
1896
        finally:
1419
1897
            self._benchtime += time.time() - start
1420
1898
 
1421
 
    def _runCleanups(self):
1422
 
        """Run registered cleanup functions.
1423
 
 
1424
 
        This should only be called from TestCase.tearDown.
1425
 
        """
1426
 
        # TODO: Perhaps this should keep running cleanups even if
1427
 
        # one of them fails?
1428
 
 
1429
 
        # Actually pop the cleanups from the list so tearDown running
1430
 
        # twice is safe (this happens for skipped tests).
1431
 
        while self._cleanups:
1432
 
            cleanup, args, kwargs = self._cleanups.pop()
1433
 
            cleanup(*args, **kwargs)
1434
 
 
1435
1899
    def log(self, *args):
1436
 
        mutter(*args)
1437
 
 
1438
 
    def _get_log(self, keep_log_file=False):
1439
 
        """Get the log from bzrlib.trace calls from this test.
1440
 
 
1441
 
        :param keep_log_file: When True, if the log is still a file on disk
1442
 
            leave it as a file on disk. When False, if the log is still a file
1443
 
            on disk, the log file is deleted and the log preserved as
1444
 
            self._log_contents.
1445
 
        :return: A string containing the log.
 
1900
        trace.mutter(*args)
 
1901
 
 
1902
    def get_log(self):
 
1903
        """Get a unicode string containing the log from bzrlib.trace.
 
1904
 
 
1905
        Undecodable characters are replaced.
1446
1906
        """
1447
 
        # flush the log file, to get all content
1448
 
        import bzrlib.trace
1449
 
        if bzrlib.trace._trace_file:
1450
 
            bzrlib.trace._trace_file.flush()
1451
 
        if self._log_contents:
1452
 
            # XXX: this can hardly contain the content flushed above --vila
1453
 
            # 20080128
1454
 
            return self._log_contents
1455
 
        if self._log_file_name is not None:
1456
 
            logfile = open(self._log_file_name)
1457
 
            try:
1458
 
                log_contents = logfile.read()
1459
 
            finally:
1460
 
                logfile.close()
1461
 
            if not keep_log_file:
1462
 
                self._log_contents = log_contents
1463
 
                try:
1464
 
                    os.remove(self._log_file_name)
1465
 
                except OSError, e:
1466
 
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
1467
 
                        sys.stderr.write(('Unable to delete log file '
1468
 
                                             ' %r\n' % self._log_file_name))
1469
 
                    else:
1470
 
                        raise
1471
 
            return log_contents
1472
 
        else:
1473
 
            return "DELETED log file to reduce memory footprint"
 
1907
        return u"".join(self.getDetails()['log'].iter_text())
1474
1908
 
1475
1909
    def requireFeature(self, feature):
1476
1910
        """This test requires a specific feature is available.
1493
1927
 
1494
1928
    def _run_bzr_core(self, args, retcode, encoding, stdin,
1495
1929
            working_dir):
 
1930
        # Clear chk_map page cache, because the contents are likely to mask
 
1931
        # locking errors.
 
1932
        chk_map.clear_cache()
1496
1933
        if encoding is None:
1497
1934
            encoding = osutils.get_user_encoding()
1498
1935
        stdout = StringIOWrapper()
1515
1952
            os.chdir(working_dir)
1516
1953
 
1517
1954
        try:
1518
 
            result = self.apply_redirected(ui.ui_factory.stdin,
1519
 
                stdout, stderr,
1520
 
                bzrlib.commands.run_bzr_catch_user_errors,
1521
 
                args)
 
1955
            try:
 
1956
                result = self.apply_redirected(
 
1957
                    ui.ui_factory.stdin,
 
1958
                    stdout, stderr,
 
1959
                    _mod_commands.run_bzr_catch_user_errors,
 
1960
                    args)
 
1961
            except KeyboardInterrupt:
 
1962
                # Reraise KeyboardInterrupt with contents of redirected stdout
 
1963
                # and stderr as arguments, for tests which are interested in
 
1964
                # stdout and stderr and are expecting the exception.
 
1965
                out = stdout.getvalue()
 
1966
                err = stderr.getvalue()
 
1967
                if out:
 
1968
                    self.log('output:\n%r', out)
 
1969
                if err:
 
1970
                    self.log('errors:\n%r', err)
 
1971
                raise KeyboardInterrupt(out, err)
1522
1972
        finally:
1523
1973
            logger.removeHandler(handler)
1524
1974
            ui.ui_factory = old_ui_factory
1534
1984
        if retcode is not None:
1535
1985
            self.assertEquals(retcode, result,
1536
1986
                              message='Unexpected return code')
1537
 
        return out, err
 
1987
        return result, out, err
1538
1988
 
1539
1989
    def run_bzr(self, args, retcode=0, encoding=None, stdin=None,
1540
1990
                working_dir=None, error_regexes=[], output_encoding=None):
1569
2019
        :keyword error_regexes: A list of expected error messages.  If
1570
2020
            specified they must be seen in the error output of the command.
1571
2021
        """
1572
 
        out, err = self._run_bzr_autosplit(
 
2022
        retcode, out, err = self._run_bzr_autosplit(
1573
2023
            args=args,
1574
2024
            retcode=retcode,
1575
2025
            encoding=encoding,
1576
2026
            stdin=stdin,
1577
2027
            working_dir=working_dir,
1578
2028
            )
 
2029
        self.assertIsInstance(error_regexes, (list, tuple))
1579
2030
        for regex in error_regexes:
1580
2031
            self.assertContainsRe(err, regex)
1581
2032
        return out, err
1653
2104
    def start_bzr_subprocess(self, process_args, env_changes=None,
1654
2105
                             skip_if_plan_to_signal=False,
1655
2106
                             working_dir=None,
1656
 
                             allow_plugins=False):
 
2107
                             allow_plugins=False, stderr=subprocess.PIPE):
1657
2108
        """Start bzr in a subprocess for testing.
1658
2109
 
1659
2110
        This starts a new Python interpreter and runs bzr in there.
1668
2119
            variables. A value of None will unset the env variable.
1669
2120
            The values must be strings. The change will only occur in the
1670
2121
            child, so you don't need to fix the environment after running.
1671
 
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
1672
 
            is not available.
 
2122
        :param skip_if_plan_to_signal: raise TestSkipped when true and system
 
2123
            doesn't support signalling subprocesses.
1673
2124
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
 
2125
        :param stderr: file to use for the subprocess's stderr.  Valid values
 
2126
            are those valid for the stderr argument of `subprocess.Popen`.
 
2127
            Default value is ``subprocess.PIPE``.
1674
2128
 
1675
2129
        :returns: Popen object for the started process.
1676
2130
        """
1677
2131
        if skip_if_plan_to_signal:
1678
 
            if not getattr(os, 'kill', None):
1679
 
                raise TestSkipped("os.kill not available.")
 
2132
            if os.name != "posix":
 
2133
                raise TestSkipped("Sending signals not supported")
1680
2134
 
1681
2135
        if env_changes is None:
1682
2136
            env_changes = {}
1702
2156
            # so we will avoid using it on all platforms, just to
1703
2157
            # make sure the code path is used, and we don't break on win32
1704
2158
            cleanup_environment()
 
2159
            # Include the subprocess's log file in the test details, in case
 
2160
            # the test fails due to an error in the subprocess.
 
2161
            self._add_subprocess_log(trace._get_bzr_log_filename())
1705
2162
            command = [sys.executable]
1706
2163
            # frozen executables don't need the path to bzr
1707
2164
            if getattr(sys, "frozen", None) is None:
1709
2166
            if not allow_plugins:
1710
2167
                command.append('--no-plugins')
1711
2168
            command.extend(process_args)
1712
 
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
2169
            process = self._popen(command, stdin=subprocess.PIPE,
 
2170
                                  stdout=subprocess.PIPE,
 
2171
                                  stderr=stderr)
1713
2172
        finally:
1714
2173
            restore_environment()
1715
2174
            if cwd is not None:
1717
2176
 
1718
2177
        return process
1719
2178
 
 
2179
    def _add_subprocess_log(self, log_file_path):
 
2180
        if len(self._log_files) == 0:
 
2181
            # Register an addCleanup func.  We do this on the first call to
 
2182
            # _add_subprocess_log rather than in TestCase.setUp so that this
 
2183
            # addCleanup is registered after any cleanups for tempdirs that
 
2184
            # subclasses might create, which will probably remove the log file
 
2185
            # we want to read.
 
2186
            self.addCleanup(self._subprocess_log_cleanup)
 
2187
        # self._log_files is a set, so if a log file is reused we won't grab it
 
2188
        # twice.
 
2189
        self._log_files.add(log_file_path)
 
2190
 
 
2191
    def _subprocess_log_cleanup(self):
 
2192
        for count, log_file_path in enumerate(self._log_files):
 
2193
            # We use buffer_now=True to avoid holding the file open beyond
 
2194
            # the life of this function, which might interfere with e.g.
 
2195
            # cleaning tempdirs on Windows.
 
2196
            # XXX: Testtools 0.9.5 doesn't have the content_from_file helper
 
2197
            #detail_content = content.content_from_file(
 
2198
            #    log_file_path, buffer_now=True)
 
2199
            with open(log_file_path, 'rb') as log_file:
 
2200
                log_file_bytes = log_file.read()
 
2201
            detail_content = content.Content(content.ContentType("text",
 
2202
                "plain", {"charset": "utf8"}), lambda: [log_file_bytes])
 
2203
            self.addDetail("start_bzr_subprocess-log-%d" % (count,),
 
2204
                detail_content)
 
2205
 
1720
2206
    def _popen(self, *args, **kwargs):
1721
2207
        """Place a call to Popen.
1722
2208
 
1723
2209
        Allows tests to override this method to intercept the calls made to
1724
2210
        Popen for introspection.
1725
2211
        """
1726
 
        return Popen(*args, **kwargs)
 
2212
        return subprocess.Popen(*args, **kwargs)
 
2213
 
 
2214
    def get_source_path(self):
 
2215
        """Return the path of the directory containing bzrlib."""
 
2216
        return os.path.dirname(os.path.dirname(bzrlib.__file__))
1727
2217
 
1728
2218
    def get_bzr_path(self):
1729
2219
        """Return the path of the 'bzr' executable for this test suite."""
1730
 
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
2220
        bzr_path = os.path.join(self.get_source_path(), "bzr")
1731
2221
        if not os.path.isfile(bzr_path):
1732
2222
            # We are probably installed. Assume sys.argv is the right file
1733
2223
            bzr_path = sys.argv[0]
1755
2245
        if retcode is not None and retcode != process.returncode:
1756
2246
            if process_args is None:
1757
2247
                process_args = "(unknown args)"
1758
 
            mutter('Output of bzr %s:\n%s', process_args, out)
1759
 
            mutter('Error for bzr %s:\n%s', process_args, err)
 
2248
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
 
2249
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
1760
2250
            self.fail('Command bzr %s failed with retcode %s != %s'
1761
2251
                      % (process_args, retcode, process.returncode))
1762
2252
        return [out, err]
1763
2253
 
1764
 
    def check_inventory_shape(self, inv, shape):
1765
 
        """Compare an inventory to a list of expected names.
 
2254
    def check_tree_shape(self, tree, shape):
 
2255
        """Compare a tree to a list of expected names.
1766
2256
 
1767
2257
        Fail if they are not precisely equal.
1768
2258
        """
1769
2259
        extras = []
1770
2260
        shape = list(shape)             # copy
1771
 
        for path, ie in inv.entries():
 
2261
        for path, ie in tree.iter_entries_by_dir():
1772
2262
            name = path.replace('\\', '/')
1773
2263
            if ie.kind == 'directory':
1774
2264
                name = name + '/'
1775
 
            if name in shape:
 
2265
            if name == "/":
 
2266
                pass # ignore root entry
 
2267
            elif name in shape:
1776
2268
                shape.remove(name)
1777
2269
            else:
1778
2270
                extras.append(name)
1819
2311
 
1820
2312
        Tests that expect to provoke LockContention errors should call this.
1821
2313
        """
1822
 
        orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
1823
 
        def resetTimeout():
1824
 
            bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
1825
 
        self.addCleanup(resetTimeout)
1826
 
        bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
 
2314
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
1827
2315
 
1828
2316
    def make_utf8_encoded_stringio(self, encoding_type=None):
1829
2317
        """Return a StringIOWrapper instance, that will encode Unicode
1837
2325
        sio.encoding = output_encoding
1838
2326
        return sio
1839
2327
 
 
2328
    def disable_verb(self, verb):
 
2329
        """Disable a smart server verb for one test."""
 
2330
        from bzrlib.smart import request
 
2331
        request_handlers = request.request_handlers
 
2332
        orig_method = request_handlers.get(verb)
 
2333
        request_handlers.remove(verb)
 
2334
        self.addCleanup(request_handlers.register, verb, orig_method)
 
2335
 
1840
2336
 
1841
2337
class CapturedCall(object):
1842
2338
    """A helper for capturing smart server calls for easy debug analysis."""
1864
2360
class TestCaseWithMemoryTransport(TestCase):
1865
2361
    """Common test class for tests that do not need disk resources.
1866
2362
 
1867
 
    Tests that need disk resources should derive from TestCaseWithTransport.
 
2363
    Tests that need disk resources should derive from TestCaseInTempDir
 
2364
    orTestCaseWithTransport.
1868
2365
 
1869
2366
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
1870
2367
 
1871
 
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
2368
    For TestCaseWithMemoryTransport the ``test_home_dir`` is set to the name of
1872
2369
    a directory which does not exist. This serves to help ensure test isolation
1873
 
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
1874
 
    must exist. However, TestCaseWithMemoryTransport does not offer local
1875
 
    file defaults for the transport in tests, nor does it obey the command line
 
2370
    is preserved. ``test_dir`` is set to the TEST_ROOT, as is cwd, because they
 
2371
    must exist. However, TestCaseWithMemoryTransport does not offer local file
 
2372
    defaults for the transport in tests, nor does it obey the command line
1876
2373
    override, so tests that accidentally write to the common directory should
1877
2374
    be rare.
1878
2375
 
1879
 
    :cvar TEST_ROOT: Directory containing all temporary directories, plus
1880
 
    a .bzr directory that stops us ascending higher into the filesystem.
 
2376
    :cvar TEST_ROOT: Directory containing all temporary directories, plus a
 
2377
        ``.bzr`` directory that stops us ascending higher into the filesystem.
1881
2378
    """
1882
2379
 
1883
2380
    TEST_ROOT = None
1901
2398
 
1902
2399
        :param relpath: a path relative to the base url.
1903
2400
        """
1904
 
        t = get_transport(self.get_url(relpath))
 
2401
        t = _mod_transport.get_transport(self.get_url(relpath))
1905
2402
        self.assertFalse(t.is_readonly())
1906
2403
        return t
1907
2404
 
1913
2410
 
1914
2411
        :param relpath: a path relative to the base url.
1915
2412
        """
1916
 
        t = get_transport(self.get_readonly_url(relpath))
 
2413
        t = _mod_transport.get_transport(self.get_readonly_url(relpath))
1917
2414
        self.assertTrue(t.is_readonly())
1918
2415
        return t
1919
2416
 
1932
2429
        if self.__readonly_server is None:
1933
2430
            if self.transport_readonly_server is None:
1934
2431
                # readonly decorator requested
1935
 
                # bring up the server
1936
 
                self.__readonly_server = ReadonlyServer()
1937
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
 
2432
                self.__readonly_server = test_server.ReadonlyServer()
1938
2433
            else:
 
2434
                # explicit readonly transport.
1939
2435
                self.__readonly_server = self.create_transport_readonly_server()
1940
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
1941
 
            self.addCleanup(self.__readonly_server.tearDown)
 
2436
            self.start_server(self.__readonly_server,
 
2437
                self.get_vfs_only_server())
1942
2438
        return self.__readonly_server
1943
2439
 
1944
2440
    def get_readonly_url(self, relpath=None):
1962
2458
        is no means to override it.
1963
2459
        """
1964
2460
        if self.__vfs_server is None:
1965
 
            self.__vfs_server = MemoryServer()
1966
 
            self.__vfs_server.setUp()
1967
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2461
            self.__vfs_server = memory.MemoryServer()
 
2462
            self.start_server(self.__vfs_server)
1968
2463
        return self.__vfs_server
1969
2464
 
1970
2465
    def get_server(self):
1977
2472
        then the self.get_vfs_server is returned.
1978
2473
        """
1979
2474
        if self.__server is None:
1980
 
            if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
1981
 
                return self.get_vfs_only_server()
 
2475
            if (self.transport_server is None or self.transport_server is
 
2476
                self.vfs_transport_factory):
 
2477
                self.__server = self.get_vfs_only_server()
1982
2478
            else:
1983
2479
                # bring up a decorated means of access to the vfs only server.
1984
2480
                self.__server = self.transport_server()
1985
 
                try:
1986
 
                    self.__server.setUp(self.get_vfs_only_server())
1987
 
                except TypeError, e:
1988
 
                    # This should never happen; the try:Except here is to assist
1989
 
                    # developers having to update code rather than seeing an
1990
 
                    # uninformative TypeError.
1991
 
                    raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
1992
 
            self.addCleanup(self.__server.tearDown)
 
2481
                self.start_server(self.__server, self.get_vfs_only_server())
1993
2482
        return self.__server
1994
2483
 
1995
2484
    def _adjust_url(self, base, relpath):
2048
2537
        real branch.
2049
2538
        """
2050
2539
        root = TestCaseWithMemoryTransport.TEST_ROOT
2051
 
        bzrdir.BzrDir.create_standalone_workingtree(root)
 
2540
        try:
 
2541
            # Make sure we get a readable and accessible home for .bzr.log
 
2542
            # and/or config files, and not fallback to weird defaults (see
 
2543
            # http://pad.lv/825027).
 
2544
            self.assertIs(None, os.environ.get('BZR_HOME', None))
 
2545
            os.environ['BZR_HOME'] = root
 
2546
            wt = bzrdir.BzrDir.create_standalone_workingtree(root)
 
2547
            del os.environ['BZR_HOME']
 
2548
        except Exception, e:
 
2549
            self.fail("Fail to initialize the safety net: %r\nExiting\n" % (e,))
 
2550
        # Hack for speed: remember the raw bytes of the dirstate file so that
 
2551
        # we don't need to re-open the wt to check it hasn't changed.
 
2552
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
 
2553
            wt.control_transport.get_bytes('dirstate'))
2052
2554
 
2053
2555
    def _check_safety_net(self):
2054
2556
        """Check that the safety .bzr directory have not been touched.
2057
2559
        propagating. This method ensures than a test did not leaked.
2058
2560
        """
2059
2561
        root = TestCaseWithMemoryTransport.TEST_ROOT
2060
 
        wt = workingtree.WorkingTree.open(root)
2061
 
        last_rev = wt.last_revision()
2062
 
        if last_rev != 'null:':
 
2562
        t = _mod_transport.get_transport(root)
 
2563
        self.permit_url(t.base)
 
2564
        if (t.get_bytes('.bzr/checkout/dirstate') != 
 
2565
                TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE):
2063
2566
            # The current test have modified the /bzr directory, we need to
2064
2567
            # recreate a new one or all the followng tests will fail.
2065
2568
            # If you need to inspect its content uncomment the following line
2066
2569
            # import pdb; pdb.set_trace()
2067
 
            _rmtree_temp_dir(root + '/.bzr')
 
2570
            _rmtree_temp_dir(root + '/.bzr', test_id=self.id())
2068
2571
            self._create_safety_net()
2069
2572
            raise AssertionError('%s/.bzr should not be modified' % root)
2070
2573
 
2071
2574
    def _make_test_root(self):
2072
2575
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
2073
 
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
 
2576
            # Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
 
2577
            root = osutils.realpath(osutils.mkdtemp(prefix='testbzr-',
 
2578
                                                    suffix='.tmp'))
2074
2579
            TestCaseWithMemoryTransport.TEST_ROOT = root
2075
2580
 
2076
2581
            self._create_safety_net()
2079
2584
            # specifically told when all tests are finished.  This will do.
2080
2585
            atexit.register(_rmtree_temp_dir, root)
2081
2586
 
 
2587
        self.permit_dir(TestCaseWithMemoryTransport.TEST_ROOT)
2082
2588
        self.addCleanup(self._check_safety_net)
2083
2589
 
2084
2590
    def makeAndChdirToTestDir(self):
2092
2598
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
2093
2599
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
2094
2600
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
 
2601
        self.permit_dir(self.test_dir)
2095
2602
 
2096
2603
    def make_branch(self, relpath, format=None):
2097
2604
        """Create a branch on the transport at relpath."""
2103
2610
            # might be a relative or absolute path
2104
2611
            maybe_a_url = self.get_url(relpath)
2105
2612
            segments = maybe_a_url.rsplit('/', 1)
2106
 
            t = get_transport(maybe_a_url)
 
2613
            t = _mod_transport.get_transport(maybe_a_url)
2107
2614
            if len(segments) > 1 and segments[-1] not in ('', '.'):
2108
2615
                t.ensure_base()
2109
2616
            if format is None:
2126
2633
        made_control = self.make_bzrdir(relpath, format=format)
2127
2634
        return made_control.create_repository(shared=shared)
2128
2635
 
2129
 
    def make_smart_server(self, path):
2130
 
        smart_server = server.SmartTCPServer_for_testing()
2131
 
        smart_server.setUp(self.get_server())
2132
 
        remote_transport = get_transport(smart_server.get_url()).clone(path)
2133
 
        self.addCleanup(smart_server.tearDown)
 
2636
    def make_smart_server(self, path, backing_server=None):
 
2637
        if backing_server is None:
 
2638
            backing_server = self.get_server()
 
2639
        smart_server = test_server.SmartTCPServer_for_testing()
 
2640
        self.start_server(smart_server, backing_server)
 
2641
        remote_transport = _mod_transport.get_transport(smart_server.get_url()
 
2642
                                                   ).clone(path)
2134
2643
        return remote_transport
2135
2644
 
2136
2645
    def make_branch_and_memory_tree(self, relpath, format=None):
2139
2648
        return memorytree.MemoryTree.create_on_branch(b)
2140
2649
 
2141
2650
    def make_branch_builder(self, relpath, format=None):
2142
 
        return branchbuilder.BranchBuilder(self.get_transport(relpath),
2143
 
            format=format)
 
2651
        branch = self.make_branch(relpath, format=format)
 
2652
        return branchbuilder.BranchBuilder(branch=branch)
2144
2653
 
2145
2654
    def overrideEnvironmentForTesting(self):
2146
 
        os.environ['HOME'] = self.test_home_dir
2147
 
        os.environ['BZR_HOME'] = self.test_home_dir
 
2655
        test_home_dir = self.test_home_dir
 
2656
        if isinstance(test_home_dir, unicode):
 
2657
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
 
2658
        self.overrideEnv('HOME', test_home_dir)
 
2659
        self.overrideEnv('BZR_HOME', test_home_dir)
2148
2660
 
2149
2661
    def setUp(self):
2150
2662
        super(TestCaseWithMemoryTransport, self).setUp()
 
2663
        # Ensure that ConnectedTransport doesn't leak sockets
 
2664
        def get_transport_with_cleanup(*args, **kwargs):
 
2665
            t = orig_get_transport(*args, **kwargs)
 
2666
            if isinstance(t, _mod_transport.ConnectedTransport):
 
2667
                self.addCleanup(t.disconnect)
 
2668
            return t
 
2669
 
 
2670
        orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
 
2671
                                               get_transport_with_cleanup)
2151
2672
        self._make_test_root()
2152
 
        _currentdir = os.getcwdu()
2153
 
        def _leaveDirectory():
2154
 
            os.chdir(_currentdir)
2155
 
        self.addCleanup(_leaveDirectory)
 
2673
        self.addCleanup(os.chdir, os.getcwdu())
2156
2674
        self.makeAndChdirToTestDir()
2157
2675
        self.overrideEnvironmentForTesting()
2158
2676
        self.__readonly_server = None
2161
2679
 
2162
2680
    def setup_smart_server_with_call_log(self):
2163
2681
        """Sets up a smart server as the transport server with a call log."""
2164
 
        self.transport_server = server.SmartTCPServer_for_testing
 
2682
        self.transport_server = test_server.SmartTCPServer_for_testing
2165
2683
        self.hpss_calls = []
2166
2684
        import traceback
2167
2685
        # Skip the current stack down to the caller of
2199
2717
 
2200
2718
    OVERRIDE_PYTHON = 'python'
2201
2719
 
 
2720
    def setUp(self):
 
2721
        super(TestCaseInTempDir, self).setUp()
 
2722
        # Remove the protection set in isolated_environ, we have a proper
 
2723
        # access to disk resources now.
 
2724
        self.overrideEnv('BZR_LOG', None)
 
2725
 
2202
2726
    def check_file_contents(self, filename, expect):
2203
2727
        self.log("check contents of file %s" % filename)
2204
 
        contents = file(filename, 'r').read()
 
2728
        f = file(filename)
 
2729
        try:
 
2730
            contents = f.read()
 
2731
        finally:
 
2732
            f.close()
2205
2733
        if contents != expect:
2206
2734
            self.log("expected: %r" % expect)
2207
2735
            self.log("actually: %r" % contents)
2209
2737
 
2210
2738
    def _getTestDirPrefix(self):
2211
2739
        # create a directory within the top level test directory
2212
 
        if sys.platform == 'win32':
 
2740
        if sys.platform in ('win32', 'cygwin'):
2213
2741
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
2214
2742
            # windows is likely to have path-length limits so use a short name
2215
2743
            name_prefix = name_prefix[-30:]
2223
2751
        For TestCaseInTempDir we create a temporary directory based on the test
2224
2752
        name and then create two subdirs - test and home under it.
2225
2753
        """
2226
 
        name_prefix = osutils.pathjoin(self.TEST_ROOT, self._getTestDirPrefix())
 
2754
        name_prefix = osutils.pathjoin(TestCaseWithMemoryTransport.TEST_ROOT,
 
2755
            self._getTestDirPrefix())
2227
2756
        name = name_prefix
2228
2757
        for i in range(100):
2229
2758
            if os.path.exists(name):
2230
2759
                name = name_prefix + '_' + str(i)
2231
2760
            else:
2232
 
                os.mkdir(name)
 
2761
                # now create test and home directories within this dir
 
2762
                self.test_base_dir = name
 
2763
                self.addCleanup(self.deleteTestDir)
 
2764
                os.mkdir(self.test_base_dir)
2233
2765
                break
2234
 
        # now create test and home directories within this dir
2235
 
        self.test_base_dir = name
 
2766
        self.permit_dir(self.test_base_dir)
 
2767
        # 'sprouting' and 'init' of a branch both walk up the tree to find
 
2768
        # stacking policy to honour; create a bzr dir with an unshared
 
2769
        # repository (but not a branch - our code would be trying to escape
 
2770
        # then!) to stop them, and permit it to be read.
 
2771
        # control = bzrdir.BzrDir.create(self.test_base_dir)
 
2772
        # control.create_repository()
2236
2773
        self.test_home_dir = self.test_base_dir + '/home'
2237
2774
        os.mkdir(self.test_home_dir)
2238
2775
        self.test_dir = self.test_base_dir + '/work'
2244
2781
            f.write(self.id())
2245
2782
        finally:
2246
2783
            f.close()
2247
 
        self.addCleanup(self.deleteTestDir)
2248
2784
 
2249
2785
    def deleteTestDir(self):
2250
 
        os.chdir(self.TEST_ROOT)
2251
 
        _rmtree_temp_dir(self.test_base_dir)
 
2786
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
2787
        _rmtree_temp_dir(self.test_base_dir, test_id=self.id())
2252
2788
 
2253
2789
    def build_tree(self, shape, line_endings='binary', transport=None):
2254
2790
        """Build a test tree according to a pattern.
2273
2809
                "a list or a tuple. Got %r instead" % (shape,))
2274
2810
        # It's OK to just create them using forward slashes on windows.
2275
2811
        if transport is None or transport.is_readonly():
2276
 
            transport = get_transport(".")
 
2812
            transport = _mod_transport.get_transport(".")
2277
2813
        for name in shape:
2278
2814
            self.assertIsInstance(name, basestring)
2279
2815
            if name[-1] == '/':
2289
2825
                content = "contents of %s%s" % (name.encode('utf-8'), end)
2290
2826
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
2291
2827
 
2292
 
    def build_tree_contents(self, shape):
2293
 
        build_tree_contents(shape)
 
2828
    build_tree_contents = staticmethod(treeshape.build_tree_contents)
2294
2829
 
2295
2830
    def assertInWorkingTree(self, path, root_path='.', tree=None):
2296
2831
        """Assert whether path or paths are in the WorkingTree"""
2336
2871
        """
2337
2872
        if self.__vfs_server is None:
2338
2873
            self.__vfs_server = self.vfs_transport_factory()
2339
 
            self.__vfs_server.setUp()
2340
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2874
            self.start_server(self.__vfs_server)
2341
2875
        return self.__vfs_server
2342
2876
 
2343
2877
    def make_branch_and_tree(self, relpath, format=None):
2350
2884
        repository will also be accessed locally. Otherwise a lightweight
2351
2885
        checkout is created and returned.
2352
2886
 
 
2887
        We do this because we can't physically create a tree in the local
 
2888
        path, with a branch reference to the transport_factory url, and
 
2889
        a branch + repository in the vfs_transport, unless the vfs_transport
 
2890
        namespace is distinct from the local disk - the two branch objects
 
2891
        would collide. While we could construct a tree with its branch object
 
2892
        pointing at the transport_factory transport in memory, reopening it
 
2893
        would behaving unexpectedly, and has in the past caused testing bugs
 
2894
        when we tried to do it that way.
 
2895
 
2353
2896
        :param format: The BzrDirFormat.
2354
2897
        :returns: the WorkingTree.
2355
2898
        """
2364
2907
            # We can only make working trees locally at the moment.  If the
2365
2908
            # transport can't support them, then we keep the non-disk-backed
2366
2909
            # branch and create a local checkout.
2367
 
            if self.vfs_transport_factory is LocalURLServer:
 
2910
            if self.vfs_transport_factory is test_server.LocalURLServer:
2368
2911
                # the branch is colocated on disk, we cannot create a checkout.
2369
2912
                # hopefully callers will expect this.
2370
2913
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2407
2950
        super(TestCaseWithTransport, self).setUp()
2408
2951
        self.__vfs_server = None
2409
2952
 
 
2953
    def disable_missing_extensions_warning(self):
 
2954
        """Some tests expect a precise stderr content.
 
2955
 
 
2956
        There is no point in forcing them to duplicate the extension related
 
2957
        warning.
 
2958
        """
 
2959
        config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
 
2960
 
2410
2961
 
2411
2962
class ChrootedTestCase(TestCaseWithTransport):
2412
2963
    """A support class that provides readonly urls outside the local namespace.
2421
2972
    """
2422
2973
 
2423
2974
    def setUp(self):
 
2975
        from bzrlib.tests import http_server
2424
2976
        super(ChrootedTestCase, self).setUp()
2425
 
        if not self.vfs_transport_factory == MemoryServer:
2426
 
            self.transport_readonly_server = HttpServer
 
2977
        if not self.vfs_transport_factory == memory.MemoryServer:
 
2978
            self.transport_readonly_server = http_server.HttpServer
2427
2979
 
2428
2980
 
2429
2981
def condition_id_re(pattern):
2432
2984
    :param pattern: A regular expression string.
2433
2985
    :return: A callable that returns True if the re matches.
2434
2986
    """
2435
 
    filter_re = re.compile(pattern)
 
2987
    filter_re = re.compile(pattern, 0)
2436
2988
    def condition(test):
2437
2989
        test_id = test.id()
2438
2990
        return filter_re.search(test_id)
2623
3175
              random_seed=None,
2624
3176
              exclude_pattern=None,
2625
3177
              strict=False,
2626
 
              runner_class=None):
 
3178
              runner_class=None,
 
3179
              suite_decorators=None,
 
3180
              stream=None,
 
3181
              result_decorators=None,
 
3182
              ):
2627
3183
    """Run a test suite for bzr selftest.
2628
3184
 
2629
3185
    :param runner_class: The class of runner to use. Must support the
2638
3194
        verbosity = 1
2639
3195
    if runner_class is None:
2640
3196
        runner_class = TextTestRunner
2641
 
    runner = runner_class(stream=sys.stdout,
 
3197
    if stream is None:
 
3198
        stream = sys.stdout
 
3199
    runner = runner_class(stream=stream,
2642
3200
                            descriptions=0,
2643
3201
                            verbosity=verbosity,
2644
3202
                            bench_history=bench_history,
2645
 
                            list_only=list_only,
 
3203
                            strict=strict,
 
3204
                            result_decorators=result_decorators,
2646
3205
                            )
2647
3206
    runner.stop_on_failure=stop_on_failure
2648
 
    # Initialise the random number generator and display the seed used.
2649
 
    # We convert the seed to a long to make it reuseable across invocations.
2650
 
    random_order = False
2651
 
    if random_seed is not None:
2652
 
        random_order = True
2653
 
        if random_seed == "now":
2654
 
            random_seed = long(time.time())
 
3207
    # built in decorator factories:
 
3208
    decorators = [
 
3209
        random_order(random_seed, runner),
 
3210
        exclude_tests(exclude_pattern),
 
3211
        ]
 
3212
    if matching_tests_first:
 
3213
        decorators.append(tests_first(pattern))
 
3214
    else:
 
3215
        decorators.append(filter_tests(pattern))
 
3216
    if suite_decorators:
 
3217
        decorators.extend(suite_decorators)
 
3218
    # tell the result object how many tests will be running: (except if
 
3219
    # --parallel=fork is being used. Robert said he will provide a better
 
3220
    # progress design later -- vila 20090817)
 
3221
    if fork_decorator not in decorators:
 
3222
        decorators.append(CountingDecorator)
 
3223
    for decorator in decorators:
 
3224
        suite = decorator(suite)
 
3225
    if list_only:
 
3226
        # Done after test suite decoration to allow randomisation etc
 
3227
        # to take effect, though that is of marginal benefit.
 
3228
        if verbosity >= 2:
 
3229
            stream.write("Listing tests only ...\n")
 
3230
        for t in iter_suite_tests(suite):
 
3231
            stream.write("%s\n" % (t.id()))
 
3232
        return True
 
3233
    result = runner.run(suite)
 
3234
    if strict:
 
3235
        return result.wasStrictlySuccessful()
 
3236
    else:
 
3237
        return result.wasSuccessful()
 
3238
 
 
3239
 
 
3240
# A registry where get() returns a suite decorator.
 
3241
parallel_registry = registry.Registry()
 
3242
 
 
3243
 
 
3244
def fork_decorator(suite):
 
3245
    if getattr(os, "fork", None) is None:
 
3246
        raise errors.BzrCommandError("platform does not support fork,"
 
3247
            " try --parallel=subprocess instead.")
 
3248
    concurrency = osutils.local_concurrency()
 
3249
    if concurrency == 1:
 
3250
        return suite
 
3251
    from testtools import ConcurrentTestSuite
 
3252
    return ConcurrentTestSuite(suite, fork_for_tests)
 
3253
parallel_registry.register('fork', fork_decorator)
 
3254
 
 
3255
 
 
3256
def subprocess_decorator(suite):
 
3257
    concurrency = osutils.local_concurrency()
 
3258
    if concurrency == 1:
 
3259
        return suite
 
3260
    from testtools import ConcurrentTestSuite
 
3261
    return ConcurrentTestSuite(suite, reinvoke_for_tests)
 
3262
parallel_registry.register('subprocess', subprocess_decorator)
 
3263
 
 
3264
 
 
3265
def exclude_tests(exclude_pattern):
 
3266
    """Return a test suite decorator that excludes tests."""
 
3267
    if exclude_pattern is None:
 
3268
        return identity_decorator
 
3269
    def decorator(suite):
 
3270
        return ExcludeDecorator(suite, exclude_pattern)
 
3271
    return decorator
 
3272
 
 
3273
 
 
3274
def filter_tests(pattern):
 
3275
    if pattern == '.*':
 
3276
        return identity_decorator
 
3277
    def decorator(suite):
 
3278
        return FilterTestsDecorator(suite, pattern)
 
3279
    return decorator
 
3280
 
 
3281
 
 
3282
def random_order(random_seed, runner):
 
3283
    """Return a test suite decorator factory for randomising tests order.
 
3284
    
 
3285
    :param random_seed: now, a string which casts to a long, or a long.
 
3286
    :param runner: A test runner with a stream attribute to report on.
 
3287
    """
 
3288
    if random_seed is None:
 
3289
        return identity_decorator
 
3290
    def decorator(suite):
 
3291
        return RandomDecorator(suite, random_seed, runner.stream)
 
3292
    return decorator
 
3293
 
 
3294
 
 
3295
def tests_first(pattern):
 
3296
    if pattern == '.*':
 
3297
        return identity_decorator
 
3298
    def decorator(suite):
 
3299
        return TestFirstDecorator(suite, pattern)
 
3300
    return decorator
 
3301
 
 
3302
 
 
3303
def identity_decorator(suite):
 
3304
    """Return suite."""
 
3305
    return suite
 
3306
 
 
3307
 
 
3308
class TestDecorator(TestUtil.TestSuite):
 
3309
    """A decorator for TestCase/TestSuite objects.
 
3310
    
 
3311
    Usually, subclasses should override __iter__(used when flattening test
 
3312
    suites), which we do to filter, reorder, parallelise and so on, run() and
 
3313
    debug().
 
3314
    """
 
3315
 
 
3316
    def __init__(self, suite):
 
3317
        TestUtil.TestSuite.__init__(self)
 
3318
        self.addTest(suite)
 
3319
 
 
3320
    def countTestCases(self):
 
3321
        cases = 0
 
3322
        for test in self:
 
3323
            cases += test.countTestCases()
 
3324
        return cases
 
3325
 
 
3326
    def debug(self):
 
3327
        for test in self:
 
3328
            test.debug()
 
3329
 
 
3330
    def run(self, result):
 
3331
        # Use iteration on self, not self._tests, to allow subclasses to hook
 
3332
        # into __iter__.
 
3333
        for test in self:
 
3334
            if result.shouldStop:
 
3335
                break
 
3336
            test.run(result)
 
3337
        return result
 
3338
 
 
3339
 
 
3340
class CountingDecorator(TestDecorator):
 
3341
    """A decorator which calls result.progress(self.countTestCases)."""
 
3342
 
 
3343
    def run(self, result):
 
3344
        progress_method = getattr(result, 'progress', None)
 
3345
        if callable(progress_method):
 
3346
            progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
 
3347
        return super(CountingDecorator, self).run(result)
 
3348
 
 
3349
 
 
3350
class ExcludeDecorator(TestDecorator):
 
3351
    """A decorator which excludes test matching an exclude pattern."""
 
3352
 
 
3353
    def __init__(self, suite, exclude_pattern):
 
3354
        TestDecorator.__init__(self, suite)
 
3355
        self.exclude_pattern = exclude_pattern
 
3356
        self.excluded = False
 
3357
 
 
3358
    def __iter__(self):
 
3359
        if self.excluded:
 
3360
            return iter(self._tests)
 
3361
        self.excluded = True
 
3362
        suite = exclude_tests_by_re(self, self.exclude_pattern)
 
3363
        del self._tests[:]
 
3364
        self.addTests(suite)
 
3365
        return iter(self._tests)
 
3366
 
 
3367
 
 
3368
class FilterTestsDecorator(TestDecorator):
 
3369
    """A decorator which filters tests to those matching a pattern."""
 
3370
 
 
3371
    def __init__(self, suite, pattern):
 
3372
        TestDecorator.__init__(self, suite)
 
3373
        self.pattern = pattern
 
3374
        self.filtered = False
 
3375
 
 
3376
    def __iter__(self):
 
3377
        if self.filtered:
 
3378
            return iter(self._tests)
 
3379
        self.filtered = True
 
3380
        suite = filter_suite_by_re(self, self.pattern)
 
3381
        del self._tests[:]
 
3382
        self.addTests(suite)
 
3383
        return iter(self._tests)
 
3384
 
 
3385
 
 
3386
class RandomDecorator(TestDecorator):
 
3387
    """A decorator which randomises the order of its tests."""
 
3388
 
 
3389
    def __init__(self, suite, random_seed, stream):
 
3390
        TestDecorator.__init__(self, suite)
 
3391
        self.random_seed = random_seed
 
3392
        self.randomised = False
 
3393
        self.stream = stream
 
3394
 
 
3395
    def __iter__(self):
 
3396
        if self.randomised:
 
3397
            return iter(self._tests)
 
3398
        self.randomised = True
 
3399
        self.stream.write("Randomizing test order using seed %s\n\n" %
 
3400
            (self.actual_seed()))
 
3401
        # Initialise the random number generator.
 
3402
        random.seed(self.actual_seed())
 
3403
        suite = randomize_suite(self)
 
3404
        del self._tests[:]
 
3405
        self.addTests(suite)
 
3406
        return iter(self._tests)
 
3407
 
 
3408
    def actual_seed(self):
 
3409
        if self.random_seed == "now":
 
3410
            # We convert the seed to a long to make it reuseable across
 
3411
            # invocations (because the user can reenter it).
 
3412
            self.random_seed = long(time.time())
2655
3413
        else:
2656
3414
            # Convert the seed to a long if we can
2657
3415
            try:
2658
 
                random_seed = long(random_seed)
 
3416
                self.random_seed = long(self.random_seed)
2659
3417
            except:
2660
3418
                pass
2661
 
        runner.stream.writeln("Randomizing test order using seed %s\n" %
2662
 
            (random_seed))
2663
 
        random.seed(random_seed)
2664
 
    # Customise the list of tests if requested
2665
 
    if exclude_pattern is not None:
2666
 
        suite = exclude_tests_by_re(suite, exclude_pattern)
2667
 
    if random_order:
2668
 
        order_changer = randomize_suite
2669
 
    else:
2670
 
        order_changer = preserve_input
2671
 
    if pattern != '.*' or random_order:
2672
 
        if matching_tests_first:
2673
 
            suites = map(order_changer, split_suite_by_re(suite, pattern))
2674
 
            suite = TestUtil.TestSuite(suites)
 
3419
        return self.random_seed
 
3420
 
 
3421
 
 
3422
class TestFirstDecorator(TestDecorator):
 
3423
    """A decorator which moves named tests to the front."""
 
3424
 
 
3425
    def __init__(self, suite, pattern):
 
3426
        TestDecorator.__init__(self, suite)
 
3427
        self.pattern = pattern
 
3428
        self.filtered = False
 
3429
 
 
3430
    def __iter__(self):
 
3431
        if self.filtered:
 
3432
            return iter(self._tests)
 
3433
        self.filtered = True
 
3434
        suites = split_suite_by_re(self, self.pattern)
 
3435
        del self._tests[:]
 
3436
        self.addTests(suites)
 
3437
        return iter(self._tests)
 
3438
 
 
3439
 
 
3440
def partition_tests(suite, count):
 
3441
    """Partition suite into count lists of tests."""
 
3442
    # This just assigns tests in a round-robin fashion.  On one hand this
 
3443
    # splits up blocks of related tests that might run faster if they shared
 
3444
    # resources, but on the other it avoids assigning blocks of slow tests to
 
3445
    # just one partition.  So the slowest partition shouldn't be much slower
 
3446
    # than the fastest.
 
3447
    partitions = [list() for i in range(count)]
 
3448
    tests = iter_suite_tests(suite)
 
3449
    for partition, test in itertools.izip(itertools.cycle(partitions), tests):
 
3450
        partition.append(test)
 
3451
    return partitions
 
3452
 
 
3453
 
 
3454
def workaround_zealous_crypto_random():
 
3455
    """Crypto.Random want to help us being secure, but we don't care here.
 
3456
 
 
3457
    This workaround some test failure related to the sftp server. Once paramiko
 
3458
    stop using the controversial API in Crypto.Random, we may get rid of it.
 
3459
    """
 
3460
    try:
 
3461
        from Crypto.Random import atfork
 
3462
        atfork()
 
3463
    except ImportError:
 
3464
        pass
 
3465
 
 
3466
 
 
3467
def fork_for_tests(suite):
 
3468
    """Take suite and start up one runner per CPU by forking()
 
3469
 
 
3470
    :return: An iterable of TestCase-like objects which can each have
 
3471
        run(result) called on them to feed tests to result.
 
3472
    """
 
3473
    concurrency = osutils.local_concurrency()
 
3474
    result = []
 
3475
    from subunit import TestProtocolClient, ProtocolTestCase
 
3476
    from subunit.test_results import AutoTimingTestResultDecorator
 
3477
    class TestInOtherProcess(ProtocolTestCase):
 
3478
        # Should be in subunit, I think. RBC.
 
3479
        def __init__(self, stream, pid):
 
3480
            ProtocolTestCase.__init__(self, stream)
 
3481
            self.pid = pid
 
3482
 
 
3483
        def run(self, result):
 
3484
            try:
 
3485
                ProtocolTestCase.run(self, result)
 
3486
            finally:
 
3487
                os.waitpid(self.pid, 0)
 
3488
 
 
3489
    test_blocks = partition_tests(suite, concurrency)
 
3490
    for process_tests in test_blocks:
 
3491
        process_suite = TestUtil.TestSuite()
 
3492
        process_suite.addTests(process_tests)
 
3493
        c2pread, c2pwrite = os.pipe()
 
3494
        pid = os.fork()
 
3495
        if pid == 0:
 
3496
            workaround_zealous_crypto_random()
 
3497
            try:
 
3498
                os.close(c2pread)
 
3499
                # Leave stderr and stdout open so we can see test noise
 
3500
                # Close stdin so that the child goes away if it decides to
 
3501
                # read from stdin (otherwise its a roulette to see what
 
3502
                # child actually gets keystrokes for pdb etc).
 
3503
                sys.stdin.close()
 
3504
                sys.stdin = None
 
3505
                stream = os.fdopen(c2pwrite, 'wb', 1)
 
3506
                subunit_result = AutoTimingTestResultDecorator(
 
3507
                    TestProtocolClient(stream))
 
3508
                process_suite.run(subunit_result)
 
3509
            finally:
 
3510
                os._exit(0)
2675
3511
        else:
2676
 
            suite = order_changer(filter_suite_by_re(suite, pattern))
2677
 
 
2678
 
    result = runner.run(suite)
2679
 
 
2680
 
    if strict:
2681
 
        return result.wasStrictlySuccessful()
2682
 
 
2683
 
    return result.wasSuccessful()
 
3512
            os.close(c2pwrite)
 
3513
            stream = os.fdopen(c2pread, 'rb', 1)
 
3514
            test = TestInOtherProcess(stream, pid)
 
3515
            result.append(test)
 
3516
    return result
 
3517
 
 
3518
 
 
3519
def reinvoke_for_tests(suite):
 
3520
    """Take suite and start up one runner per CPU using subprocess().
 
3521
 
 
3522
    :return: An iterable of TestCase-like objects which can each have
 
3523
        run(result) called on them to feed tests to result.
 
3524
    """
 
3525
    concurrency = osutils.local_concurrency()
 
3526
    result = []
 
3527
    from subunit import ProtocolTestCase
 
3528
    class TestInSubprocess(ProtocolTestCase):
 
3529
        def __init__(self, process, name):
 
3530
            ProtocolTestCase.__init__(self, process.stdout)
 
3531
            self.process = process
 
3532
            self.process.stdin.close()
 
3533
            self.name = name
 
3534
 
 
3535
        def run(self, result):
 
3536
            try:
 
3537
                ProtocolTestCase.run(self, result)
 
3538
            finally:
 
3539
                self.process.wait()
 
3540
                os.unlink(self.name)
 
3541
            # print "pid %d finished" % finished_process
 
3542
    test_blocks = partition_tests(suite, concurrency)
 
3543
    for process_tests in test_blocks:
 
3544
        # ugly; currently reimplement rather than reuses TestCase methods.
 
3545
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
3546
        if not os.path.isfile(bzr_path):
 
3547
            # We are probably installed. Assume sys.argv is the right file
 
3548
            bzr_path = sys.argv[0]
 
3549
        bzr_path = [bzr_path]
 
3550
        if sys.platform == "win32":
 
3551
            # if we're on windows, we can't execute the bzr script directly
 
3552
            bzr_path = [sys.executable] + bzr_path
 
3553
        fd, test_list_file_name = tempfile.mkstemp()
 
3554
        test_list_file = os.fdopen(fd, 'wb', 1)
 
3555
        for test in process_tests:
 
3556
            test_list_file.write(test.id() + '\n')
 
3557
        test_list_file.close()
 
3558
        try:
 
3559
            argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
 
3560
                '--subunit']
 
3561
            if '--no-plugins' in sys.argv:
 
3562
                argv.append('--no-plugins')
 
3563
            # stderr=subprocess.STDOUT would be ideal, but until we prevent
 
3564
            # noise on stderr it can interrupt the subunit protocol.
 
3565
            process = subprocess.Popen(argv, stdin=subprocess.PIPE,
 
3566
                                      stdout=subprocess.PIPE,
 
3567
                                      stderr=subprocess.PIPE,
 
3568
                                      bufsize=1)
 
3569
            test = TestInSubprocess(process, test_list_file_name)
 
3570
            result.append(test)
 
3571
        except:
 
3572
            os.unlink(test_list_file_name)
 
3573
            raise
 
3574
    return result
 
3575
 
 
3576
 
 
3577
class ProfileResult(testtools.ExtendedToOriginalDecorator):
 
3578
    """Generate profiling data for all activity between start and success.
 
3579
    
 
3580
    The profile data is appended to the test's _benchcalls attribute and can
 
3581
    be accessed by the forwarded-to TestResult.
 
3582
 
 
3583
    While it might be cleaner do accumulate this in stopTest, addSuccess is
 
3584
    where our existing output support for lsprof is, and this class aims to
 
3585
    fit in with that: while it could be moved it's not necessary to accomplish
 
3586
    test profiling, nor would it be dramatically cleaner.
 
3587
    """
 
3588
 
 
3589
    def startTest(self, test):
 
3590
        self.profiler = bzrlib.lsprof.BzrProfiler()
 
3591
        # Prevent deadlocks in tests that use lsprof: those tests will
 
3592
        # unavoidably fail.
 
3593
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
 
3594
        self.profiler.start()
 
3595
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
 
3596
 
 
3597
    def addSuccess(self, test):
 
3598
        stats = self.profiler.stop()
 
3599
        try:
 
3600
            calls = test._benchcalls
 
3601
        except AttributeError:
 
3602
            test._benchcalls = []
 
3603
            calls = test._benchcalls
 
3604
        calls.append(((test.id(), "", ""), stats))
 
3605
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
 
3606
 
 
3607
    def stopTest(self, test):
 
3608
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
 
3609
        self.profiler = None
2684
3610
 
2685
3611
 
2686
3612
# Controlled by "bzr selftest -E=..." option
 
3613
# Currently supported:
 
3614
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
 
3615
#                           preserves any flags supplied at the command line.
 
3616
#   -Edisable_lock_checks   Turns errors in mismatched locks into simple prints
 
3617
#                           rather than failing tests. And no longer raise
 
3618
#                           LockContention when fctnl locks are not being used
 
3619
#                           with proper exclusion rules.
 
3620
#   -Ethreads               Will display thread ident at creation/join time to
 
3621
#                           help track thread leaks
 
3622
 
 
3623
#   -Econfig_stats          Will collect statistics using addDetail
2687
3624
selftest_debug_flags = set()
2688
3625
 
2689
3626
 
2701
3638
             debug_flags=None,
2702
3639
             starting_with=None,
2703
3640
             runner_class=None,
 
3641
             suite_decorators=None,
 
3642
             stream=None,
 
3643
             lsprof_tests=False,
2704
3644
             ):
2705
3645
    """Run the whole test suite under the enhanced runner"""
2706
3646
    # XXX: Very ugly way to do this...
2723
3663
            keep_only = None
2724
3664
        else:
2725
3665
            keep_only = load_test_id_list(load_list)
 
3666
        if starting_with:
 
3667
            starting_with = [test_prefix_alias_registry.resolve_alias(start)
 
3668
                             for start in starting_with]
2726
3669
        if test_suite_factory is None:
 
3670
            # Reduce loading time by loading modules based on the starting_with
 
3671
            # patterns.
2727
3672
            suite = test_suite(keep_only, starting_with)
2728
3673
        else:
2729
3674
            suite = test_suite_factory()
 
3675
        if starting_with:
 
3676
            # But always filter as requested.
 
3677
            suite = filter_suite_by_id_startswith(suite, starting_with)
 
3678
        result_decorators = []
 
3679
        if lsprof_tests:
 
3680
            result_decorators.append(ProfileResult)
2730
3681
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2731
3682
                     stop_on_failure=stop_on_failure,
2732
3683
                     transport=transport,
2738
3689
                     exclude_pattern=exclude_pattern,
2739
3690
                     strict=strict,
2740
3691
                     runner_class=runner_class,
 
3692
                     suite_decorators=suite_decorators,
 
3693
                     stream=stream,
 
3694
                     result_decorators=result_decorators,
2741
3695
                     )
2742
3696
    finally:
2743
3697
        default_transport = old_transport
2866
3820
                key, obj, help=help, info=info, override_existing=False)
2867
3821
        except KeyError:
2868
3822
            actual = self.get(key)
2869
 
            note('Test prefix alias %s is already used for %s, ignoring %s'
2870
 
                 % (key, actual, obj))
 
3823
            trace.note(
 
3824
                'Test prefix alias %s is already used for %s, ignoring %s'
 
3825
                % (key, actual, obj))
2871
3826
 
2872
3827
    def resolve_alias(self, id_start):
2873
3828
        """Replace the alias by the prefix in the given string.
2891
3846
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
2892
3847
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
2893
3848
 
2894
 
# Obvious higest levels prefixes, feel free to add your own via a plugin
 
3849
# Obvious highest levels prefixes, feel free to add your own via a plugin
2895
3850
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
2896
3851
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
2897
3852
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
2899
3854
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
2900
3855
 
2901
3856
 
 
3857
def _test_suite_testmod_names():
 
3858
    """Return the standard list of test module names to test."""
 
3859
    return [
 
3860
        'bzrlib.doc',
 
3861
        'bzrlib.tests.blackbox',
 
3862
        'bzrlib.tests.commands',
 
3863
        'bzrlib.tests.doc_generate',
 
3864
        'bzrlib.tests.per_branch',
 
3865
        'bzrlib.tests.per_bzrdir',
 
3866
        'bzrlib.tests.per_controldir',
 
3867
        'bzrlib.tests.per_controldir_colo',
 
3868
        'bzrlib.tests.per_foreign_vcs',
 
3869
        'bzrlib.tests.per_interrepository',
 
3870
        'bzrlib.tests.per_intertree',
 
3871
        'bzrlib.tests.per_inventory',
 
3872
        'bzrlib.tests.per_interbranch',
 
3873
        'bzrlib.tests.per_lock',
 
3874
        'bzrlib.tests.per_merger',
 
3875
        'bzrlib.tests.per_transport',
 
3876
        'bzrlib.tests.per_tree',
 
3877
        'bzrlib.tests.per_pack_repository',
 
3878
        'bzrlib.tests.per_repository',
 
3879
        'bzrlib.tests.per_repository_chk',
 
3880
        'bzrlib.tests.per_repository_reference',
 
3881
        'bzrlib.tests.per_repository_vf',
 
3882
        'bzrlib.tests.per_uifactory',
 
3883
        'bzrlib.tests.per_versionedfile',
 
3884
        'bzrlib.tests.per_workingtree',
 
3885
        'bzrlib.tests.test__annotator',
 
3886
        'bzrlib.tests.test__bencode',
 
3887
        'bzrlib.tests.test__btree_serializer',
 
3888
        'bzrlib.tests.test__chk_map',
 
3889
        'bzrlib.tests.test__dirstate_helpers',
 
3890
        'bzrlib.tests.test__groupcompress',
 
3891
        'bzrlib.tests.test__known_graph',
 
3892
        'bzrlib.tests.test__rio',
 
3893
        'bzrlib.tests.test__simple_set',
 
3894
        'bzrlib.tests.test__static_tuple',
 
3895
        'bzrlib.tests.test__walkdirs_win32',
 
3896
        'bzrlib.tests.test_ancestry',
 
3897
        'bzrlib.tests.test_annotate',
 
3898
        'bzrlib.tests.test_api',
 
3899
        'bzrlib.tests.test_atomicfile',
 
3900
        'bzrlib.tests.test_bad_files',
 
3901
        'bzrlib.tests.test_bisect_multi',
 
3902
        'bzrlib.tests.test_branch',
 
3903
        'bzrlib.tests.test_branchbuilder',
 
3904
        'bzrlib.tests.test_btree_index',
 
3905
        'bzrlib.tests.test_bugtracker',
 
3906
        'bzrlib.tests.test_bundle',
 
3907
        'bzrlib.tests.test_bzrdir',
 
3908
        'bzrlib.tests.test__chunks_to_lines',
 
3909
        'bzrlib.tests.test_cache_utf8',
 
3910
        'bzrlib.tests.test_chk_map',
 
3911
        'bzrlib.tests.test_chk_serializer',
 
3912
        'bzrlib.tests.test_chunk_writer',
 
3913
        'bzrlib.tests.test_clean_tree',
 
3914
        'bzrlib.tests.test_cleanup',
 
3915
        'bzrlib.tests.test_cmdline',
 
3916
        'bzrlib.tests.test_commands',
 
3917
        'bzrlib.tests.test_commit',
 
3918
        'bzrlib.tests.test_commit_merge',
 
3919
        'bzrlib.tests.test_config',
 
3920
        'bzrlib.tests.test_conflicts',
 
3921
        'bzrlib.tests.test_controldir',
 
3922
        'bzrlib.tests.test_counted_lock',
 
3923
        'bzrlib.tests.test_crash',
 
3924
        'bzrlib.tests.test_decorators',
 
3925
        'bzrlib.tests.test_delta',
 
3926
        'bzrlib.tests.test_debug',
 
3927
        'bzrlib.tests.test_diff',
 
3928
        'bzrlib.tests.test_directory_service',
 
3929
        'bzrlib.tests.test_dirstate',
 
3930
        'bzrlib.tests.test_email_message',
 
3931
        'bzrlib.tests.test_eol_filters',
 
3932
        'bzrlib.tests.test_errors',
 
3933
        'bzrlib.tests.test_export',
 
3934
        'bzrlib.tests.test_export_pot',
 
3935
        'bzrlib.tests.test_extract',
 
3936
        'bzrlib.tests.test_fetch',
 
3937
        'bzrlib.tests.test_fixtures',
 
3938
        'bzrlib.tests.test_fifo_cache',
 
3939
        'bzrlib.tests.test_filters',
 
3940
        'bzrlib.tests.test_ftp_transport',
 
3941
        'bzrlib.tests.test_foreign',
 
3942
        'bzrlib.tests.test_generate_docs',
 
3943
        'bzrlib.tests.test_generate_ids',
 
3944
        'bzrlib.tests.test_globbing',
 
3945
        'bzrlib.tests.test_gpg',
 
3946
        'bzrlib.tests.test_graph',
 
3947
        'bzrlib.tests.test_groupcompress',
 
3948
        'bzrlib.tests.test_hashcache',
 
3949
        'bzrlib.tests.test_help',
 
3950
        'bzrlib.tests.test_hooks',
 
3951
        'bzrlib.tests.test_http',
 
3952
        'bzrlib.tests.test_http_response',
 
3953
        'bzrlib.tests.test_https_ca_bundle',
 
3954
        'bzrlib.tests.test_i18n',
 
3955
        'bzrlib.tests.test_identitymap',
 
3956
        'bzrlib.tests.test_ignores',
 
3957
        'bzrlib.tests.test_index',
 
3958
        'bzrlib.tests.test_import_tariff',
 
3959
        'bzrlib.tests.test_info',
 
3960
        'bzrlib.tests.test_inv',
 
3961
        'bzrlib.tests.test_inventory_delta',
 
3962
        'bzrlib.tests.test_knit',
 
3963
        'bzrlib.tests.test_lazy_import',
 
3964
        'bzrlib.tests.test_lazy_regex',
 
3965
        'bzrlib.tests.test_library_state',
 
3966
        'bzrlib.tests.test_lock',
 
3967
        'bzrlib.tests.test_lockable_files',
 
3968
        'bzrlib.tests.test_lockdir',
 
3969
        'bzrlib.tests.test_log',
 
3970
        'bzrlib.tests.test_lru_cache',
 
3971
        'bzrlib.tests.test_lsprof',
 
3972
        'bzrlib.tests.test_mail_client',
 
3973
        'bzrlib.tests.test_matchers',
 
3974
        'bzrlib.tests.test_memorytree',
 
3975
        'bzrlib.tests.test_merge',
 
3976
        'bzrlib.tests.test_merge3',
 
3977
        'bzrlib.tests.test_merge_core',
 
3978
        'bzrlib.tests.test_merge_directive',
 
3979
        'bzrlib.tests.test_mergetools',
 
3980
        'bzrlib.tests.test_missing',
 
3981
        'bzrlib.tests.test_msgeditor',
 
3982
        'bzrlib.tests.test_multiparent',
 
3983
        'bzrlib.tests.test_mutabletree',
 
3984
        'bzrlib.tests.test_nonascii',
 
3985
        'bzrlib.tests.test_options',
 
3986
        'bzrlib.tests.test_osutils',
 
3987
        'bzrlib.tests.test_osutils_encodings',
 
3988
        'bzrlib.tests.test_pack',
 
3989
        'bzrlib.tests.test_patch',
 
3990
        'bzrlib.tests.test_patches',
 
3991
        'bzrlib.tests.test_permissions',
 
3992
        'bzrlib.tests.test_plugins',
 
3993
        'bzrlib.tests.test_progress',
 
3994
        'bzrlib.tests.test_pyutils',
 
3995
        'bzrlib.tests.test_read_bundle',
 
3996
        'bzrlib.tests.test_reconcile',
 
3997
        'bzrlib.tests.test_reconfigure',
 
3998
        'bzrlib.tests.test_registry',
 
3999
        'bzrlib.tests.test_remote',
 
4000
        'bzrlib.tests.test_rename_map',
 
4001
        'bzrlib.tests.test_repository',
 
4002
        'bzrlib.tests.test_revert',
 
4003
        'bzrlib.tests.test_revision',
 
4004
        'bzrlib.tests.test_revisionspec',
 
4005
        'bzrlib.tests.test_revisiontree',
 
4006
        'bzrlib.tests.test_rio',
 
4007
        'bzrlib.tests.test_rules',
 
4008
        'bzrlib.tests.test_sampler',
 
4009
        'bzrlib.tests.test_scenarios',
 
4010
        'bzrlib.tests.test_script',
 
4011
        'bzrlib.tests.test_selftest',
 
4012
        'bzrlib.tests.test_serializer',
 
4013
        'bzrlib.tests.test_setup',
 
4014
        'bzrlib.tests.test_sftp_transport',
 
4015
        'bzrlib.tests.test_shelf',
 
4016
        'bzrlib.tests.test_shelf_ui',
 
4017
        'bzrlib.tests.test_smart',
 
4018
        'bzrlib.tests.test_smart_add',
 
4019
        'bzrlib.tests.test_smart_request',
 
4020
        'bzrlib.tests.test_smart_transport',
 
4021
        'bzrlib.tests.test_smtp_connection',
 
4022
        'bzrlib.tests.test_source',
 
4023
        'bzrlib.tests.test_ssh_transport',
 
4024
        'bzrlib.tests.test_status',
 
4025
        'bzrlib.tests.test_store',
 
4026
        'bzrlib.tests.test_strace',
 
4027
        'bzrlib.tests.test_subsume',
 
4028
        'bzrlib.tests.test_switch',
 
4029
        'bzrlib.tests.test_symbol_versioning',
 
4030
        'bzrlib.tests.test_tag',
 
4031
        'bzrlib.tests.test_test_server',
 
4032
        'bzrlib.tests.test_testament',
 
4033
        'bzrlib.tests.test_textfile',
 
4034
        'bzrlib.tests.test_textmerge',
 
4035
        'bzrlib.tests.test_cethread',
 
4036
        'bzrlib.tests.test_timestamp',
 
4037
        'bzrlib.tests.test_trace',
 
4038
        'bzrlib.tests.test_transactions',
 
4039
        'bzrlib.tests.test_transform',
 
4040
        'bzrlib.tests.test_transport',
 
4041
        'bzrlib.tests.test_transport_log',
 
4042
        'bzrlib.tests.test_tree',
 
4043
        'bzrlib.tests.test_treebuilder',
 
4044
        'bzrlib.tests.test_treeshape',
 
4045
        'bzrlib.tests.test_tsort',
 
4046
        'bzrlib.tests.test_tuned_gzip',
 
4047
        'bzrlib.tests.test_ui',
 
4048
        'bzrlib.tests.test_uncommit',
 
4049
        'bzrlib.tests.test_upgrade',
 
4050
        'bzrlib.tests.test_upgrade_stacked',
 
4051
        'bzrlib.tests.test_urlutils',
 
4052
        'bzrlib.tests.test_utextwrap',
 
4053
        'bzrlib.tests.test_version',
 
4054
        'bzrlib.tests.test_version_info',
 
4055
        'bzrlib.tests.test_versionedfile',
 
4056
        'bzrlib.tests.test_weave',
 
4057
        'bzrlib.tests.test_whitebox',
 
4058
        'bzrlib.tests.test_win32utils',
 
4059
        'bzrlib.tests.test_workingtree',
 
4060
        'bzrlib.tests.test_workingtree_4',
 
4061
        'bzrlib.tests.test_wsgi',
 
4062
        'bzrlib.tests.test_xml',
 
4063
        ]
 
4064
 
 
4065
 
 
4066
def _test_suite_modules_to_doctest():
 
4067
    """Return the list of modules to doctest."""
 
4068
    if __doc__ is None:
 
4069
        # GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
 
4070
        return []
 
4071
    return [
 
4072
        'bzrlib',
 
4073
        'bzrlib.branchbuilder',
 
4074
        'bzrlib.decorators',
 
4075
        'bzrlib.inventory',
 
4076
        'bzrlib.iterablefile',
 
4077
        'bzrlib.lockdir',
 
4078
        'bzrlib.merge3',
 
4079
        'bzrlib.option',
 
4080
        'bzrlib.pyutils',
 
4081
        'bzrlib.symbol_versioning',
 
4082
        'bzrlib.tests',
 
4083
        'bzrlib.tests.fixtures',
 
4084
        'bzrlib.timestamp',
 
4085
        'bzrlib.transport.http',
 
4086
        'bzrlib.version_info_formats.format_custom',
 
4087
        ]
 
4088
 
 
4089
 
2902
4090
def test_suite(keep_only=None, starting_with=None):
2903
4091
    """Build and return TestSuite for the whole of bzrlib.
2904
4092
 
2910
4098
    This function can be replaced if you need to change the default test
2911
4099
    suite on a global basis, but it is not encouraged.
2912
4100
    """
2913
 
    testmod_names = [
2914
 
                   'bzrlib.doc',
2915
 
                   'bzrlib.tests.blackbox',
2916
 
                   'bzrlib.tests.branch_implementations',
2917
 
                   'bzrlib.tests.bzrdir_implementations',
2918
 
                   'bzrlib.tests.commands',
2919
 
                   'bzrlib.tests.interrepository_implementations',
2920
 
                   'bzrlib.tests.intertree_implementations',
2921
 
                   'bzrlib.tests.inventory_implementations',
2922
 
                   'bzrlib.tests.per_interbranch',
2923
 
                   'bzrlib.tests.per_lock',
2924
 
                   'bzrlib.tests.per_repository',
2925
 
                   'bzrlib.tests.per_repository_reference',
2926
 
                   'bzrlib.tests.test__dirstate_helpers',
2927
 
                   'bzrlib.tests.test__walkdirs_win32',
2928
 
                   'bzrlib.tests.test_ancestry',
2929
 
                   'bzrlib.tests.test_annotate',
2930
 
                   'bzrlib.tests.test_api',
2931
 
                   'bzrlib.tests.test_atomicfile',
2932
 
                   'bzrlib.tests.test_bad_files',
2933
 
                   'bzrlib.tests.test_bisect_multi',
2934
 
                   'bzrlib.tests.test_branch',
2935
 
                   'bzrlib.tests.test_branchbuilder',
2936
 
                   'bzrlib.tests.test_btree_index',
2937
 
                   'bzrlib.tests.test_bugtracker',
2938
 
                   'bzrlib.tests.test_bundle',
2939
 
                   'bzrlib.tests.test_bzrdir',
2940
 
                   'bzrlib.tests.test_cache_utf8',
2941
 
                   'bzrlib.tests.test_clean_tree',
2942
 
                   'bzrlib.tests.test_chunk_writer',
2943
 
                   'bzrlib.tests.test__chunks_to_lines',
2944
 
                   'bzrlib.tests.test_commands',
2945
 
                   'bzrlib.tests.test_commit',
2946
 
                   'bzrlib.tests.test_commit_merge',
2947
 
                   'bzrlib.tests.test_config',
2948
 
                   'bzrlib.tests.test_conflicts',
2949
 
                   'bzrlib.tests.test_counted_lock',
2950
 
                   'bzrlib.tests.test_decorators',
2951
 
                   'bzrlib.tests.test_delta',
2952
 
                   'bzrlib.tests.test_debug',
2953
 
                   'bzrlib.tests.test_deprecated_graph',
2954
 
                   'bzrlib.tests.test_diff',
2955
 
                   'bzrlib.tests.test_directory_service',
2956
 
                   'bzrlib.tests.test_dirstate',
2957
 
                   'bzrlib.tests.test_email_message',
2958
 
                   'bzrlib.tests.test_errors',
2959
 
                   'bzrlib.tests.test_export',
2960
 
                   'bzrlib.tests.test_extract',
2961
 
                   'bzrlib.tests.test_fetch',
2962
 
                   'bzrlib.tests.test_fifo_cache',
2963
 
                   'bzrlib.tests.test_ftp_transport',
2964
 
                   'bzrlib.tests.test_foreign',
2965
 
                   'bzrlib.tests.test_generate_docs',
2966
 
                   'bzrlib.tests.test_generate_ids',
2967
 
                   'bzrlib.tests.test_globbing',
2968
 
                   'bzrlib.tests.test_gpg',
2969
 
                   'bzrlib.tests.test_graph',
2970
 
                   'bzrlib.tests.test_hashcache',
2971
 
                   'bzrlib.tests.test_help',
2972
 
                   'bzrlib.tests.test_hooks',
2973
 
                   'bzrlib.tests.test_http',
2974
 
                   'bzrlib.tests.test_http_implementations',
2975
 
                   'bzrlib.tests.test_http_response',
2976
 
                   'bzrlib.tests.test_https_ca_bundle',
2977
 
                   'bzrlib.tests.test_identitymap',
2978
 
                   'bzrlib.tests.test_ignores',
2979
 
                   'bzrlib.tests.test_index',
2980
 
                   'bzrlib.tests.test_info',
2981
 
                   'bzrlib.tests.test_inv',
2982
 
                   'bzrlib.tests.test_knit',
2983
 
                   'bzrlib.tests.test_lazy_import',
2984
 
                   'bzrlib.tests.test_lazy_regex',
2985
 
                   'bzrlib.tests.test_lockable_files',
2986
 
                   'bzrlib.tests.test_lockdir',
2987
 
                   'bzrlib.tests.test_log',
2988
 
                   'bzrlib.tests.test_lru_cache',
2989
 
                   'bzrlib.tests.test_lsprof',
2990
 
                   'bzrlib.tests.test_mail_client',
2991
 
                   'bzrlib.tests.test_memorytree',
2992
 
                   'bzrlib.tests.test_merge',
2993
 
                   'bzrlib.tests.test_merge3',
2994
 
                   'bzrlib.tests.test_merge_core',
2995
 
                   'bzrlib.tests.test_merge_directive',
2996
 
                   'bzrlib.tests.test_missing',
2997
 
                   'bzrlib.tests.test_msgeditor',
2998
 
                   'bzrlib.tests.test_multiparent',
2999
 
                   'bzrlib.tests.test_mutabletree',
3000
 
                   'bzrlib.tests.test_nonascii',
3001
 
                   'bzrlib.tests.test_options',
3002
 
                   'bzrlib.tests.test_osutils',
3003
 
                   'bzrlib.tests.test_osutils_encodings',
3004
 
                   'bzrlib.tests.test_pack',
3005
 
                   'bzrlib.tests.test_pack_repository',
3006
 
                   'bzrlib.tests.test_patch',
3007
 
                   'bzrlib.tests.test_patches',
3008
 
                   'bzrlib.tests.test_permissions',
3009
 
                   'bzrlib.tests.test_plugins',
3010
 
                   'bzrlib.tests.test_progress',
3011
 
                   'bzrlib.tests.test_read_bundle',
3012
 
                   'bzrlib.tests.test_reconcile',
3013
 
                   'bzrlib.tests.test_reconfigure',
3014
 
                   'bzrlib.tests.test_registry',
3015
 
                   'bzrlib.tests.test_remote',
3016
 
                   'bzrlib.tests.test_repository',
3017
 
                   'bzrlib.tests.test_revert',
3018
 
                   'bzrlib.tests.test_revision',
3019
 
                   'bzrlib.tests.test_revisionspec',
3020
 
                   'bzrlib.tests.test_revisiontree',
3021
 
                   'bzrlib.tests.test_rio',
3022
 
                   'bzrlib.tests.test_rules',
3023
 
                   'bzrlib.tests.test_sampler',
3024
 
                   'bzrlib.tests.test_selftest',
3025
 
                   'bzrlib.tests.test_setup',
3026
 
                   'bzrlib.tests.test_sftp_transport',
3027
 
                   'bzrlib.tests.test_shelf',
3028
 
                   'bzrlib.tests.test_shelf_ui',
3029
 
                   'bzrlib.tests.test_smart',
3030
 
                   'bzrlib.tests.test_smart_add',
3031
 
                   'bzrlib.tests.test_smart_request',
3032
 
                   'bzrlib.tests.test_smart_transport',
3033
 
                   'bzrlib.tests.test_smtp_connection',
3034
 
                   'bzrlib.tests.test_source',
3035
 
                   'bzrlib.tests.test_ssh_transport',
3036
 
                   'bzrlib.tests.test_status',
3037
 
                   'bzrlib.tests.test_store',
3038
 
                   'bzrlib.tests.test_strace',
3039
 
                   'bzrlib.tests.test_subsume',
3040
 
                   'bzrlib.tests.test_switch',
3041
 
                   'bzrlib.tests.test_symbol_versioning',
3042
 
                   'bzrlib.tests.test_tag',
3043
 
                   'bzrlib.tests.test_testament',
3044
 
                   'bzrlib.tests.test_textfile',
3045
 
                   'bzrlib.tests.test_textmerge',
3046
 
                   'bzrlib.tests.test_timestamp',
3047
 
                   'bzrlib.tests.test_trace',
3048
 
                   'bzrlib.tests.test_transactions',
3049
 
                   'bzrlib.tests.test_transform',
3050
 
                   'bzrlib.tests.test_transport',
3051
 
                   'bzrlib.tests.test_transport_implementations',
3052
 
                   'bzrlib.tests.test_transport_log',
3053
 
                   'bzrlib.tests.test_tree',
3054
 
                   'bzrlib.tests.test_treebuilder',
3055
 
                   'bzrlib.tests.test_tsort',
3056
 
                   'bzrlib.tests.test_tuned_gzip',
3057
 
                   'bzrlib.tests.test_ui',
3058
 
                   'bzrlib.tests.test_uncommit',
3059
 
                   'bzrlib.tests.test_upgrade',
3060
 
                   'bzrlib.tests.test_upgrade_stacked',
3061
 
                   'bzrlib.tests.test_urlutils',
3062
 
                   'bzrlib.tests.test_version',
3063
 
                   'bzrlib.tests.test_version_info',
3064
 
                   'bzrlib.tests.test_versionedfile',
3065
 
                   'bzrlib.tests.test_weave',
3066
 
                   'bzrlib.tests.test_whitebox',
3067
 
                   'bzrlib.tests.test_win32utils',
3068
 
                   'bzrlib.tests.test_workingtree',
3069
 
                   'bzrlib.tests.test_workingtree_4',
3070
 
                   'bzrlib.tests.test_wsgi',
3071
 
                   'bzrlib.tests.test_xml',
3072
 
                   'bzrlib.tests.tree_implementations',
3073
 
                   'bzrlib.tests.workingtree_implementations',
3074
 
                   'bzrlib.util.tests.test_bencode',
3075
 
                   ]
3076
4101
 
3077
4102
    loader = TestUtil.TestLoader()
3078
4103
 
 
4104
    if keep_only is not None:
 
4105
        id_filter = TestIdList(keep_only)
3079
4106
    if starting_with:
3080
 
        starting_with = [test_prefix_alias_registry.resolve_alias(start)
3081
 
                         for start in starting_with]
3082
4107
        # We take precedence over keep_only because *at loading time* using
3083
4108
        # both options means we will load less tests for the same final result.
3084
4109
        def interesting_module(name):
3094
4119
        loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
3095
4120
 
3096
4121
    elif keep_only is not None:
3097
 
        id_filter = TestIdList(keep_only)
3098
4122
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
3099
4123
        def interesting_module(name):
3100
4124
            return id_filter.refers_to(name)
3108
4132
    suite = loader.suiteClass()
3109
4133
 
3110
4134
    # modules building their suite with loadTestsFromModuleNames
3111
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
3112
 
 
3113
 
    modules_to_doctest = [
3114
 
        'bzrlib',
3115
 
        'bzrlib.branchbuilder',
3116
 
        'bzrlib.export',
3117
 
        'bzrlib.inventory',
3118
 
        'bzrlib.iterablefile',
3119
 
        'bzrlib.lockdir',
3120
 
        'bzrlib.merge3',
3121
 
        'bzrlib.option',
3122
 
        'bzrlib.symbol_versioning',
3123
 
        'bzrlib.tests',
3124
 
        'bzrlib.timestamp',
3125
 
        'bzrlib.version_info_formats.format_custom',
3126
 
        ]
3127
 
 
3128
 
    for mod in modules_to_doctest:
 
4135
    suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
 
4136
 
 
4137
    for mod in _test_suite_modules_to_doctest():
3129
4138
        if not interesting_module(mod):
3130
4139
            # No tests to keep here, move along
3131
4140
            continue
3132
4141
        try:
3133
4142
            # note that this really does mean "report only" -- doctest
3134
4143
            # still runs the rest of the examples
3135
 
            doc_suite = doctest.DocTestSuite(mod,
3136
 
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
4144
            doc_suite = IsolatedDocTestSuite(
 
4145
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
3137
4146
        except ValueError, e:
3138
4147
            print '**failed to get doctest for: %s\n%s' % (mod, e)
3139
4148
            raise
3142
4151
        suite.addTest(doc_suite)
3143
4152
 
3144
4153
    default_encoding = sys.getdefaultencoding()
3145
 
    for name, plugin in bzrlib.plugin.plugins().items():
 
4154
    for name, plugin in _mod_plugin.plugins().items():
3146
4155
        if not interesting_module(plugin.module.__name__):
3147
4156
            continue
3148
4157
        plugin_suite = plugin.test_suite()
3154
4163
        if plugin_suite is not None:
3155
4164
            suite.addTest(plugin_suite)
3156
4165
        if default_encoding != sys.getdefaultencoding():
3157
 
            bzrlib.trace.warning(
 
4166
            trace.warning(
3158
4167
                'Plugin "%s" tried to reset default encoding to: %s', name,
3159
4168
                sys.getdefaultencoding())
3160
4169
            reload(sys)
3161
4170
            sys.setdefaultencoding(default_encoding)
3162
4171
 
3163
 
    if starting_with:
3164
 
        suite = filter_suite_by_id_startswith(suite, starting_with)
3165
 
 
3166
4172
    if keep_only is not None:
3167
4173
        # Now that the referred modules have loaded their tests, keep only the
3168
4174
        # requested ones.
3178
4184
            # Some tests mentioned in the list are not in the test suite. The
3179
4185
            # list may be out of date, report to the tester.
3180
4186
            for id in not_found:
3181
 
                bzrlib.trace.warning('"%s" not found in the test suite', id)
 
4187
                trace.warning('"%s" not found in the test suite', id)
3182
4188
        for id in duplicates:
3183
 
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
 
4189
            trace.warning('"%s" is used as an id by several tests', id)
3184
4190
 
3185
4191
    return suite
3186
4192
 
3187
4193
 
3188
 
def multiply_scenarios(scenarios_left, scenarios_right):
 
4194
def multiply_scenarios(*scenarios):
 
4195
    """Multiply two or more iterables of scenarios.
 
4196
 
 
4197
    It is safe to pass scenario generators or iterators.
 
4198
 
 
4199
    :returns: A list of compound scenarios: the cross-product of all 
 
4200
        scenarios, with the names concatenated and the parameters
 
4201
        merged together.
 
4202
    """
 
4203
    return reduce(_multiply_two_scenarios, map(list, scenarios))
 
4204
 
 
4205
 
 
4206
def _multiply_two_scenarios(scenarios_left, scenarios_right):
3189
4207
    """Multiply two sets of scenarios.
3190
4208
 
3191
4209
    :returns: the cartesian product of the two sets of scenarios, that is
3217
4235
    the scenario name at the end of its id(), and updating the test object's
3218
4236
    __dict__ with the scenario_param_dict.
3219
4237
 
 
4238
    >>> import bzrlib.tests.test_sampler
3220
4239
    >>> r = multiply_tests(
3221
4240
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
3222
4241
    ...     [('one', dict(param=1)),
3223
4242
    ...      ('two', dict(param=2))],
3224
 
    ...     TestSuite())
 
4243
    ...     TestUtil.TestSuite())
3225
4244
    >>> tests = list(iter_suite_tests(r))
3226
4245
    >>> len(tests)
3227
4246
    2
3274
4293
    :param new_id: The id to assign to it.
3275
4294
    :return: The new test.
3276
4295
    """
3277
 
    from copy import deepcopy
3278
 
    new_test = deepcopy(test)
 
4296
    new_test = copy.copy(test)
3279
4297
    new_test.id = lambda: new_id
 
4298
    # XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
 
4299
    # causes cloned tests to share the 'details' dict.  This makes it hard to
 
4300
    # read the test output for parameterized tests, because tracebacks will be
 
4301
    # associated with irrelevant tests.
 
4302
    try:
 
4303
        details = new_test._TestCase__details
 
4304
    except AttributeError:
 
4305
        # must be a different version of testtools than expected.  Do nothing.
 
4306
        pass
 
4307
    else:
 
4308
        # Reset the '__details' dict.
 
4309
        new_test._TestCase__details = {}
3280
4310
    return new_test
3281
4311
 
3282
4312
 
3283
 
def _rmtree_temp_dir(dirname):
 
4313
def permute_tests_for_extension(standard_tests, loader, py_module_name,
 
4314
                                ext_module_name):
 
4315
    """Helper for permutating tests against an extension module.
 
4316
 
 
4317
    This is meant to be used inside a modules 'load_tests()' function. It will
 
4318
    create 2 scenarios, and cause all tests in the 'standard_tests' to be run
 
4319
    against both implementations. Setting 'test.module' to the appropriate
 
4320
    module. See bzrlib.tests.test__chk_map.load_tests as an example.
 
4321
 
 
4322
    :param standard_tests: A test suite to permute
 
4323
    :param loader: A TestLoader
 
4324
    :param py_module_name: The python path to a python module that can always
 
4325
        be loaded, and will be considered the 'python' implementation. (eg
 
4326
        'bzrlib._chk_map_py')
 
4327
    :param ext_module_name: The python path to an extension module. If the
 
4328
        module cannot be loaded, a single test will be added, which notes that
 
4329
        the module is not available. If it can be loaded, all standard_tests
 
4330
        will be run against that module.
 
4331
    :return: (suite, feature) suite is a test-suite that has all the permuted
 
4332
        tests. feature is the Feature object that can be used to determine if
 
4333
        the module is available.
 
4334
    """
 
4335
 
 
4336
    py_module = pyutils.get_named_object(py_module_name)
 
4337
    scenarios = [
 
4338
        ('python', {'module': py_module}),
 
4339
    ]
 
4340
    suite = loader.suiteClass()
 
4341
    feature = ModuleAvailableFeature(ext_module_name)
 
4342
    if feature.available():
 
4343
        scenarios.append(('C', {'module': feature.module}))
 
4344
    else:
 
4345
        # the compiled module isn't available, so we add a failing test
 
4346
        class FailWithoutFeature(TestCase):
 
4347
            def test_fail(self):
 
4348
                self.requireFeature(feature)
 
4349
        suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
 
4350
    result = multiply_tests(standard_tests, scenarios, suite)
 
4351
    return result, feature
 
4352
 
 
4353
 
 
4354
def _rmtree_temp_dir(dirname, test_id=None):
3284
4355
    # If LANG=C we probably have created some bogus paths
3285
4356
    # which rmtree(unicode) will fail to delete
3286
4357
    # so make sure we are using rmtree(str) to delete everything
3295
4366
    try:
3296
4367
        osutils.rmtree(dirname)
3297
4368
    except OSError, e:
3298
 
        if sys.platform == 'win32' and e.errno == errno.EACCES:
3299
 
            sys.stderr.write(('Permission denied: '
3300
 
                                 'unable to remove testing dir '
3301
 
                                 '%s\n' % os.path.basename(dirname)))
3302
 
        else:
3303
 
            raise
 
4369
        # We don't want to fail here because some useful display will be lost
 
4370
        # otherwise. Polluting the tmp dir is bad, but not giving all the
 
4371
        # possible info to the test runner is even worse.
 
4372
        if test_id != None:
 
4373
            ui.ui_factory.clear_term()
 
4374
            sys.stderr.write('\nWhile running: %s\n' % (test_id,))
 
4375
        # Ugly, but the last thing we want here is fail, so bear with it.
 
4376
        printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
 
4377
                                    ).encode('ascii', 'replace')
 
4378
        sys.stderr.write('Unable to remove testing dir %s\n%s'
 
4379
                         % (os.path.basename(dirname), printable_e))
3304
4380
 
3305
4381
 
3306
4382
class Feature(object):
3388
4464
UnicodeFilenameFeature = _UnicodeFilenameFeature()
3389
4465
 
3390
4466
 
 
4467
class _CompatabilityThunkFeature(Feature):
 
4468
    """This feature is just a thunk to another feature.
 
4469
 
 
4470
    It issues a deprecation warning if it is accessed, to let you know that you
 
4471
    should really use a different feature.
 
4472
    """
 
4473
 
 
4474
    def __init__(self, dep_version, module, name,
 
4475
                 replacement_name, replacement_module=None):
 
4476
        super(_CompatabilityThunkFeature, self).__init__()
 
4477
        self._module = module
 
4478
        if replacement_module is None:
 
4479
            replacement_module = module
 
4480
        self._replacement_module = replacement_module
 
4481
        self._name = name
 
4482
        self._replacement_name = replacement_name
 
4483
        self._dep_version = dep_version
 
4484
        self._feature = None
 
4485
 
 
4486
    def _ensure(self):
 
4487
        if self._feature is None:
 
4488
            depr_msg = self._dep_version % ('%s.%s'
 
4489
                                            % (self._module, self._name))
 
4490
            use_msg = ' Use %s.%s instead.' % (self._replacement_module,
 
4491
                                               self._replacement_name)
 
4492
            symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
 
4493
            # Import the new feature and use it as a replacement for the
 
4494
            # deprecated one.
 
4495
            self._feature = pyutils.get_named_object(
 
4496
                self._replacement_module, self._replacement_name)
 
4497
 
 
4498
    def _probe(self):
 
4499
        self._ensure()
 
4500
        return self._feature._probe()
 
4501
 
 
4502
 
 
4503
class ModuleAvailableFeature(Feature):
 
4504
    """This is a feature than describes a module we want to be available.
 
4505
 
 
4506
    Declare the name of the module in __init__(), and then after probing, the
 
4507
    module will be available as 'self.module'.
 
4508
 
 
4509
    :ivar module: The module if it is available, else None.
 
4510
    """
 
4511
 
 
4512
    def __init__(self, module_name):
 
4513
        super(ModuleAvailableFeature, self).__init__()
 
4514
        self.module_name = module_name
 
4515
 
 
4516
    def _probe(self):
 
4517
        try:
 
4518
            self._module = __import__(self.module_name, {}, {}, [''])
 
4519
            return True
 
4520
        except ImportError:
 
4521
            return False
 
4522
 
 
4523
    @property
 
4524
    def module(self):
 
4525
        if self.available(): # Make sure the probe has been done
 
4526
            return self._module
 
4527
        return None
 
4528
 
 
4529
    def feature_name(self):
 
4530
        return self.module_name
 
4531
 
 
4532
 
3391
4533
def probe_unicode_in_user_encoding():
3392
4534
    """Try to encode several unicode strings to use in unicode-aware tests.
3393
4535
    Return first successfull match.
3462
4604
UnicodeFilename = _UnicodeFilename()
3463
4605
 
3464
4606
 
 
4607
class _ByteStringNamedFilesystem(Feature):
 
4608
    """Is the filesystem based on bytes?"""
 
4609
 
 
4610
    def _probe(self):
 
4611
        if os.name == "posix":
 
4612
            return True
 
4613
        return False
 
4614
 
 
4615
ByteStringNamedFilesystem = _ByteStringNamedFilesystem()
 
4616
 
 
4617
 
3465
4618
class _UTF8Filesystem(Feature):
3466
4619
    """Is the filesystem UTF-8?"""
3467
4620
 
3473
4626
UTF8Filesystem = _UTF8Filesystem()
3474
4627
 
3475
4628
 
 
4629
class _BreakinFeature(Feature):
 
4630
    """Does this platform support the breakin feature?"""
 
4631
 
 
4632
    def _probe(self):
 
4633
        from bzrlib import breakin
 
4634
        if breakin.determine_signal() is None:
 
4635
            return False
 
4636
        if sys.platform == 'win32':
 
4637
            # Windows doesn't have os.kill, and we catch the SIGBREAK signal.
 
4638
            # We trigger SIGBREAK via a Console api so we need ctypes to
 
4639
            # access the function
 
4640
            try:
 
4641
                import ctypes
 
4642
            except OSError:
 
4643
                return False
 
4644
        return True
 
4645
 
 
4646
    def feature_name(self):
 
4647
        return "SIGQUIT or SIGBREAK w/ctypes on win32"
 
4648
 
 
4649
 
 
4650
BreakinFeature = _BreakinFeature()
 
4651
 
 
4652
 
3476
4653
class _CaseInsCasePresFilenameFeature(Feature):
3477
4654
    """Is the file-system case insensitive, but case-preserving?"""
3478
4655
 
3526
4703
        return 'case-insensitive filesystem'
3527
4704
 
3528
4705
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
 
4706
 
 
4707
 
 
4708
class _CaseSensitiveFilesystemFeature(Feature):
 
4709
 
 
4710
    def _probe(self):
 
4711
        if CaseInsCasePresFilenameFeature.available():
 
4712
            return False
 
4713
        elif CaseInsensitiveFilesystemFeature.available():
 
4714
            return False
 
4715
        else:
 
4716
            return True
 
4717
 
 
4718
    def feature_name(self):
 
4719
        return 'case-sensitive filesystem'
 
4720
 
 
4721
# new coding style is for feature instances to be lowercase
 
4722
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
 
4723
 
 
4724
 
 
4725
# Only define SubUnitBzrRunner if subunit is available.
 
4726
try:
 
4727
    from subunit import TestProtocolClient
 
4728
    from subunit.test_results import AutoTimingTestResultDecorator
 
4729
    class SubUnitBzrProtocolClient(TestProtocolClient):
 
4730
 
 
4731
        def addSuccess(self, test, details=None):
 
4732
            # The subunit client always includes the details in the subunit
 
4733
            # stream, but we don't want to include it in ours.
 
4734
            if details is not None and 'log' in details:
 
4735
                del details['log']
 
4736
            return super(SubUnitBzrProtocolClient, self).addSuccess(
 
4737
                test, details)
 
4738
 
 
4739
    class SubUnitBzrRunner(TextTestRunner):
 
4740
        def run(self, test):
 
4741
            result = AutoTimingTestResultDecorator(
 
4742
                SubUnitBzrProtocolClient(self.stream))
 
4743
            test.run(result)
 
4744
            return result
 
4745
except ImportError:
 
4746
    pass
 
4747
 
 
4748
class _PosixPermissionsFeature(Feature):
 
4749
 
 
4750
    def _probe(self):
 
4751
        def has_perms():
 
4752
            # create temporary file and check if specified perms are maintained.
 
4753
            import tempfile
 
4754
 
 
4755
            write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
 
4756
            f = tempfile.mkstemp(prefix='bzr_perms_chk_')
 
4757
            fd, name = f
 
4758
            os.close(fd)
 
4759
            os.chmod(name, write_perms)
 
4760
 
 
4761
            read_perms = os.stat(name).st_mode & 0777
 
4762
            os.unlink(name)
 
4763
            return (write_perms == read_perms)
 
4764
 
 
4765
        return (os.name == 'posix') and has_perms()
 
4766
 
 
4767
    def feature_name(self):
 
4768
        return 'POSIX permissions support'
 
4769
 
 
4770
posix_permissions_feature = _PosixPermissionsFeature()