~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Launchpad Translations on behalf of bzr-core
  • Date: 2012-11-25 04:30:35 UTC
  • mto: (6581.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 6582.
  • Revision ID: launchpad_translations_on_behalf_of_bzr-core-20121125043035-9abma98g1j6p5uox
Launchpad automatic translations update.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 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
16
 
 
17
 
 
18
 
# TODO: Perhaps there should be an API to find out if bzr running under the
19
 
# test suite -- some plugins might want to avoid making intrusive changes if
20
 
# this is the case.  However, we want behaviour under to test to diverge as
21
 
# little as possible, so this should be used rarely if it's added at all.
22
 
# (Suggestion from j-a-meinel, 2005-11-24)
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Testing framework extensions"""
 
18
 
 
19
from __future__ import absolute_import
23
20
 
24
21
# NOTE: Some classes in here use camelCaseNaming() rather than
25
22
# underscore_naming().  That's for consistency with unittest; it's not the
28
25
 
29
26
import atexit
30
27
import codecs
 
28
import copy
31
29
from cStringIO import StringIO
32
30
import difflib
33
31
import doctest
34
32
import errno
 
33
import itertools
35
34
import logging
36
35
import os
37
 
from pprint import pformat
 
36
import platform
 
37
import pprint
38
38
import random
39
39
import re
40
40
import shlex
 
41
import site
41
42
import stat
42
 
from subprocess import Popen, PIPE
 
43
import subprocess
43
44
import sys
44
45
import tempfile
 
46
import threading
 
47
import time
 
48
import traceback
45
49
import unittest
46
 
import time
47
50
import warnings
48
51
 
 
52
import testtools
 
53
# nb: check this before importing anything else from within it
 
54
_testtools_version = getattr(testtools, '__version__', ())
 
55
if _testtools_version < (0, 9, 5):
 
56
    raise ImportError("need at least testtools 0.9.5: %s is %r"
 
57
        % (testtools.__file__, _testtools_version))
 
58
from testtools import content
49
59
 
 
60
import bzrlib
50
61
from bzrlib import (
51
 
    bzrdir,
 
62
    branchbuilder,
 
63
    controldir,
 
64
    chk_map,
 
65
    commands as _mod_commands,
 
66
    config,
 
67
    i18n,
52
68
    debug,
53
69
    errors,
 
70
    hooks,
 
71
    lock as _mod_lock,
 
72
    lockdir,
54
73
    memorytree,
55
74
    osutils,
56
 
    progress,
 
75
    plugin as _mod_plugin,
 
76
    pyutils,
57
77
    ui,
58
78
    urlutils,
 
79
    registry,
 
80
    symbol_versioning,
 
81
    trace,
 
82
    transport as _mod_transport,
59
83
    workingtree,
60
84
    )
61
 
import bzrlib.branch
62
 
import bzrlib.commands
63
 
import bzrlib.timestamp
64
 
import bzrlib.export
65
 
import bzrlib.inventory
66
 
import bzrlib.iterablefile
67
 
import bzrlib.lockdir
68
85
try:
69
86
    import bzrlib.lsprof
70
87
except ImportError:
71
88
    # lsprof not available
72
89
    pass
73
 
from bzrlib.merge import merge_inner
74
 
import bzrlib.merge3
75
 
import bzrlib.osutils
76
 
import bzrlib.plugin
77
 
from bzrlib.revision import common_ancestor
78
 
import bzrlib.store
79
 
from bzrlib import symbol_versioning
 
90
from bzrlib.smart import client, request
 
91
from bzrlib.transport import (
 
92
    memory,
 
93
    pathfilter,
 
94
    )
80
95
from bzrlib.symbol_versioning import (
81
 
    deprecated_method,
82
 
    zero_eighteen,
83
 
    )
84
 
import bzrlib.trace
85
 
from bzrlib.transport import get_transport
86
 
import bzrlib.transport
87
 
from bzrlib.transport.local import LocalURLServer
88
 
from bzrlib.transport.memory import MemoryServer
89
 
from bzrlib.transport.readonly import ReadonlyServer
90
 
from bzrlib.trace import mutter, note
91
 
from bzrlib.tests import TestUtil
92
 
from bzrlib.tests.HttpServer import HttpServer
93
 
from bzrlib.tests.TestUtil import (
94
 
                          TestSuite,
95
 
                          TestLoader,
96
 
                          )
97
 
from bzrlib.tests.treeshape import build_tree_contents
98
 
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
 
96
    deprecated_function,
 
97
    deprecated_in,
 
98
    )
 
99
from bzrlib.tests import (
 
100
    fixtures,
 
101
    test_server,
 
102
    TestUtil,
 
103
    treeshape,
 
104
    )
 
105
from bzrlib.ui import NullProgressView
 
106
from bzrlib.ui.text import TextUIFactory
 
107
from bzrlib.tests.features import _CompatabilityThunkFeature
99
108
 
100
109
# Mark this python module as being part of the implementation
101
110
# of unittest: this gives us better tracebacks where the last
102
111
# shown frame is the test code, not our assertXYZ.
103
112
__unittest = 1
104
113
 
105
 
default_transport = LocalURLServer
106
 
 
107
 
MODULES_TO_TEST = []
108
 
MODULES_TO_DOCTEST = [
109
 
                      bzrlib.timestamp,
110
 
                      bzrlib.errors,
111
 
                      bzrlib.export,
112
 
                      bzrlib.inventory,
113
 
                      bzrlib.iterablefile,
114
 
                      bzrlib.lockdir,
115
 
                      bzrlib.merge3,
116
 
                      bzrlib.option,
117
 
                      bzrlib.store,
118
 
                      ]
119
 
 
120
 
 
121
 
def packages_to_test():
122
 
    """Return a list of packages to test.
123
 
 
124
 
    The packages are not globally imported so that import failures are
125
 
    triggered when running selftest, not when importing the command.
126
 
    """
127
 
    import bzrlib.doc
128
 
    import bzrlib.tests.blackbox
129
 
    import bzrlib.tests.branch_implementations
130
 
    import bzrlib.tests.bzrdir_implementations
131
 
    import bzrlib.tests.interrepository_implementations
132
 
    import bzrlib.tests.interversionedfile_implementations
133
 
    import bzrlib.tests.intertree_implementations
134
 
    import bzrlib.tests.per_lock
135
 
    import bzrlib.tests.repository_implementations
136
 
    import bzrlib.tests.revisionstore_implementations
137
 
    import bzrlib.tests.tree_implementations
138
 
    import bzrlib.tests.workingtree_implementations
139
 
    return [
140
 
            bzrlib.doc,
141
 
            bzrlib.tests.blackbox,
142
 
            bzrlib.tests.branch_implementations,
143
 
            bzrlib.tests.bzrdir_implementations,
144
 
            bzrlib.tests.interrepository_implementations,
145
 
            bzrlib.tests.interversionedfile_implementations,
146
 
            bzrlib.tests.intertree_implementations,
147
 
            bzrlib.tests.per_lock,
148
 
            bzrlib.tests.repository_implementations,
149
 
            bzrlib.tests.revisionstore_implementations,
150
 
            bzrlib.tests.tree_implementations,
151
 
            bzrlib.tests.workingtree_implementations,
152
 
            ]
153
 
 
154
 
 
155
 
class ExtendedTestResult(unittest._TextTestResult):
 
114
default_transport = test_server.LocalURLServer
 
115
 
 
116
 
 
117
_unitialized_attr = object()
 
118
"""A sentinel needed to act as a default value in a method signature."""
 
119
 
 
120
 
 
121
# Subunit result codes, defined here to prevent a hard dependency on subunit.
 
122
SUBUNIT_SEEK_SET = 0
 
123
SUBUNIT_SEEK_CUR = 1
 
124
 
 
125
# These are intentionally brought into this namespace. That way plugins, etc
 
126
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
 
127
TestSuite = TestUtil.TestSuite
 
128
TestLoader = TestUtil.TestLoader
 
129
 
 
130
# Tests should run in a clean and clearly defined environment. The goal is to
 
131
# keep them isolated from the running environment as mush as possible. The test
 
132
# framework ensures the variables defined below are set (or deleted if the
 
133
# value is None) before a test is run and reset to their original value after
 
134
# the test is run. Generally if some code depends on an environment variable,
 
135
# the tests should start without this variable in the environment. There are a
 
136
# few exceptions but you shouldn't violate this rule lightly.
 
137
isolated_environ = {
 
138
    'BZR_HOME': None,
 
139
    'HOME': None,
 
140
    'XDG_CONFIG_HOME': None,
 
141
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
142
    # tests do check our impls match APPDATA
 
143
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
144
    'VISUAL': None,
 
145
    'EDITOR': None,
 
146
    'BZR_EMAIL': None,
 
147
    'BZREMAIL': None, # may still be present in the environment
 
148
    'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
 
149
    'BZR_PROGRESS_BAR': None,
 
150
    # This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
 
151
    # as a base class instead of TestCaseInTempDir. Tests inheriting from
 
152
    # TestCase should not use disk resources, BZR_LOG is one.
 
153
    'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
 
154
    'BZR_PLUGIN_PATH': None,
 
155
    'BZR_DISABLE_PLUGINS': None,
 
156
    'BZR_PLUGINS_AT': None,
 
157
    'BZR_CONCURRENCY': None,
 
158
    # Make sure that any text ui tests are consistent regardless of
 
159
    # the environment the test case is run in; you may want tests that
 
160
    # test other combinations.  'dumb' is a reasonable guess for tests
 
161
    # going to a pipe or a StringIO.
 
162
    'TERM': 'dumb',
 
163
    'LINES': '25',
 
164
    'COLUMNS': '80',
 
165
    'BZR_COLUMNS': '80',
 
166
    # Disable SSH Agent
 
167
    'SSH_AUTH_SOCK': None,
 
168
    # Proxies
 
169
    'http_proxy': None,
 
170
    'HTTP_PROXY': None,
 
171
    'https_proxy': None,
 
172
    'HTTPS_PROXY': None,
 
173
    'no_proxy': None,
 
174
    'NO_PROXY': None,
 
175
    'all_proxy': None,
 
176
    'ALL_PROXY': None,
 
177
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
178
    # least. If you do (care), please update this comment
 
179
    # -- vila 20080401
 
180
    'ftp_proxy': None,
 
181
    'FTP_PROXY': None,
 
182
    'BZR_REMOTE_PATH': None,
 
183
    # Generally speaking, we don't want apport reporting on crashes in
 
184
    # the test envirnoment unless we're specifically testing apport,
 
185
    # so that it doesn't leak into the real system environment.  We
 
186
    # use an env var so it propagates to subprocesses.
 
187
    'APPORT_DISABLE': '1',
 
188
    }
 
189
 
 
190
 
 
191
def override_os_environ(test, env=None):
 
192
    """Modify os.environ keeping a copy.
 
193
    
 
194
    :param test: A test instance
 
195
 
 
196
    :param env: A dict containing variable definitions to be installed
 
197
    """
 
198
    if env is None:
 
199
        env = isolated_environ
 
200
    test._original_os_environ = dict([(var, value)
 
201
                                      for var, value in os.environ.iteritems()])
 
202
    for var, value in env.iteritems():
 
203
        osutils.set_or_unset_env(var, value)
 
204
        if var not in test._original_os_environ:
 
205
            # The var is new, add it with a value of None, so
 
206
            # restore_os_environ will delete it
 
207
            test._original_os_environ[var] = None
 
208
 
 
209
 
 
210
def restore_os_environ(test):
 
211
    """Restore os.environ to its original state.
 
212
 
 
213
    :param test: A test instance previously passed to override_os_environ.
 
214
    """
 
215
    for var, value in test._original_os_environ.iteritems():
 
216
        # Restore the original value (or delete it if the value has been set to
 
217
        # None in override_os_environ).
 
218
        osutils.set_or_unset_env(var, value)
 
219
 
 
220
 
 
221
def _clear__type_equality_funcs(test):
 
222
    """Cleanup bound methods stored on TestCase instances
 
223
 
 
224
    Clear the dict breaking a few (mostly) harmless cycles in the affected
 
225
    unittests released with Python 2.6 and initial Python 2.7 versions.
 
226
 
 
227
    For a few revisions between Python 2.7.1 and Python 2.7.2 that annoyingly
 
228
    shipped in Oneiric, an object with no clear method was used, hence the
 
229
    extra complications, see bug 809048 for details.
 
230
    """
 
231
    type_equality_funcs = getattr(test, "_type_equality_funcs", None)
 
232
    if type_equality_funcs is not None:
 
233
        tef_clear = getattr(type_equality_funcs, "clear", None)
 
234
        if tef_clear is None:
 
235
            tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
 
236
            if tef_instance_dict is not None:
 
237
                tef_clear = tef_instance_dict.clear
 
238
        if tef_clear is not None:
 
239
            tef_clear()
 
240
 
 
241
 
 
242
class ExtendedTestResult(testtools.TextTestResult):
156
243
    """Accepts, reports and accumulates the results of running tests.
157
244
 
158
 
    Compared to this unittest version this class adds support for profiling,
159
 
    benchmarking, stopping as soon as a test fails,  and skipping tests.
160
 
    There are further-specialized subclasses for different types of display.
 
245
    Compared to the unittest version this class adds support for
 
246
    profiling, benchmarking, stopping as soon as a test fails,  and
 
247
    skipping tests.  There are further-specialized subclasses for
 
248
    different types of display.
 
249
 
 
250
    When a test finishes, in whatever way, it calls one of the addSuccess,
 
251
    addFailure or addError methods.  These in turn may redirect to a more
 
252
    specific case for the special test results supported by our extended
 
253
    tests.
 
254
 
 
255
    Note that just one of these objects is fed the results from many tests.
161
256
    """
162
257
 
163
258
    stop_early = False
164
 
    
 
259
 
165
260
    def __init__(self, stream, descriptions, verbosity,
166
261
                 bench_history=None,
167
 
                 num_tests=None,
168
 
                 use_numbered_dirs=False,
 
262
                 strict=False,
169
263
                 ):
170
264
        """Construct new TestResult.
171
265
 
172
266
        :param bench_history: Optionally, a writable file object to accumulate
173
267
            benchmark results.
174
268
        """
175
 
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
 
269
        testtools.TextTestResult.__init__(self, stream)
176
270
        if bench_history is not None:
177
271
            from bzrlib.version import _get_bzr_source_tree
178
272
            src_tree = _get_bzr_source_tree()
189
283
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
190
284
        self._bench_history = bench_history
191
285
        self.ui = ui.ui_factory
192
 
        self.num_tests = num_tests
 
286
        self.num_tests = 0
193
287
        self.error_count = 0
194
288
        self.failure_count = 0
195
289
        self.known_failure_count = 0
196
290
        self.skip_count = 0
 
291
        self.not_applicable_count = 0
197
292
        self.unsupported = {}
198
293
        self.count = 0
199
 
        self.use_numbered_dirs = use_numbered_dirs
200
294
        self._overall_start_time = time.time()
201
 
    
202
 
    def extractBenchmarkTime(self, testCase):
 
295
        self._strict = strict
 
296
        self._first_thread_leaker_id = None
 
297
        self._tests_leaking_threads_count = 0
 
298
        self._traceback_from_test = None
 
299
 
 
300
    def stopTestRun(self):
 
301
        run = self.testsRun
 
302
        actionTaken = "Ran"
 
303
        stopTime = time.time()
 
304
        timeTaken = stopTime - self.startTime
 
305
        # GZ 2010-07-19: Seems testtools has no printErrors method, and though
 
306
        #                the parent class method is similar have to duplicate
 
307
        self._show_list('ERROR', self.errors)
 
308
        self._show_list('FAIL', self.failures)
 
309
        self.stream.write(self.sep2)
 
310
        self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
 
311
                            run, run != 1 and "s" or "", timeTaken))
 
312
        if not self.wasSuccessful():
 
313
            self.stream.write("FAILED (")
 
314
            failed, errored = map(len, (self.failures, self.errors))
 
315
            if failed:
 
316
                self.stream.write("failures=%d" % failed)
 
317
            if errored:
 
318
                if failed: self.stream.write(", ")
 
319
                self.stream.write("errors=%d" % errored)
 
320
            if self.known_failure_count:
 
321
                if failed or errored: self.stream.write(", ")
 
322
                self.stream.write("known_failure_count=%d" %
 
323
                    self.known_failure_count)
 
324
            self.stream.write(")\n")
 
325
        else:
 
326
            if self.known_failure_count:
 
327
                self.stream.write("OK (known_failures=%d)\n" %
 
328
                    self.known_failure_count)
 
329
            else:
 
330
                self.stream.write("OK\n")
 
331
        if self.skip_count > 0:
 
332
            skipped = self.skip_count
 
333
            self.stream.write('%d test%s skipped\n' %
 
334
                                (skipped, skipped != 1 and "s" or ""))
 
335
        if self.unsupported:
 
336
            for feature, count in sorted(self.unsupported.items()):
 
337
                self.stream.write("Missing feature '%s' skipped %d tests.\n" %
 
338
                    (feature, count))
 
339
        if self._strict:
 
340
            ok = self.wasStrictlySuccessful()
 
341
        else:
 
342
            ok = self.wasSuccessful()
 
343
        if self._first_thread_leaker_id:
 
344
            self.stream.write(
 
345
                '%s is leaking threads among %d leaking tests.\n' % (
 
346
                self._first_thread_leaker_id,
 
347
                self._tests_leaking_threads_count))
 
348
            # We don't report the main thread as an active one.
 
349
            self.stream.write(
 
350
                '%d non-main threads were left active in the end.\n'
 
351
                % (len(self._active_threads) - 1))
 
352
 
 
353
    def getDescription(self, test):
 
354
        return test.id()
 
355
 
 
356
    def _extractBenchmarkTime(self, testCase, details=None):
203
357
        """Add a benchmark time for the current test case."""
204
 
        self._benchmarkTime = getattr(testCase, "_benchtime", None)
205
 
    
 
358
        if details and 'benchtime' in details:
 
359
            return float(''.join(details['benchtime'].iter_bytes()))
 
360
        return getattr(testCase, "_benchtime", None)
 
361
 
206
362
    def _elapsedTestTimeString(self):
207
363
        """Return a time string for the overall time the current test has taken."""
208
 
        return self._formatTime(time.time() - self._start_time)
 
364
        return self._formatTime(self._delta_to_float(
 
365
            self._now() - self._start_datetime))
209
366
 
210
 
    def _testTimeString(self):
211
 
        if self._benchmarkTime is not None:
212
 
            return "%s/%s" % (
213
 
                self._formatTime(self._benchmarkTime),
214
 
                self._elapsedTestTimeString())
 
367
    def _testTimeString(self, testCase):
 
368
        benchmark_time = self._extractBenchmarkTime(testCase)
 
369
        if benchmark_time is not None:
 
370
            return self._formatTime(benchmark_time) + "*"
215
371
        else:
216
 
            return "           %s" % self._elapsedTestTimeString()
 
372
            return self._elapsedTestTimeString()
217
373
 
218
374
    def _formatTime(self, seconds):
219
375
        """Format seconds as milliseconds with leading spaces."""
223
379
 
224
380
    def _shortened_test_description(self, test):
225
381
        what = test.id()
226
 
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
 
382
        what = re.sub(r'^bzrlib\.tests\.', '', what)
227
383
        return what
228
384
 
 
385
    # GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
 
386
    #                multiple times in a row, because the handler is added for
 
387
    #                each test but the container list is shared between cases.
 
388
    #                See lp:498869 lp:625574 and lp:637725 for background.
 
389
    def _record_traceback_from_test(self, exc_info):
 
390
        """Store the traceback from passed exc_info tuple till"""
 
391
        self._traceback_from_test = exc_info[2]
 
392
 
229
393
    def startTest(self, test):
230
 
        unittest.TestResult.startTest(self, test)
 
394
        super(ExtendedTestResult, self).startTest(test)
 
395
        if self.count == 0:
 
396
            self.startTests()
 
397
        self.count += 1
231
398
        self.report_test_start(test)
232
399
        test.number = self.count
233
400
        self._recordTestStartTime()
 
401
        # Make testtools cases give us the real traceback on failure
 
402
        addOnException = getattr(test, "addOnException", None)
 
403
        if addOnException is not None:
 
404
            addOnException(self._record_traceback_from_test)
 
405
        # Only check for thread leaks on bzrlib derived test cases
 
406
        if isinstance(test, TestCase):
 
407
            test.addCleanup(self._check_leaked_threads, test)
 
408
 
 
409
    def stopTest(self, test):
 
410
        super(ExtendedTestResult, self).stopTest(test)
 
411
        # Manually break cycles, means touching various private things but hey
 
412
        getDetails = getattr(test, "getDetails", None)
 
413
        if getDetails is not None:
 
414
            getDetails().clear()
 
415
        _clear__type_equality_funcs(test)
 
416
        self._traceback_from_test = None
 
417
 
 
418
    def startTests(self):
 
419
        self.report_tests_starting()
 
420
        self._active_threads = threading.enumerate()
 
421
 
 
422
    def _check_leaked_threads(self, test):
 
423
        """See if any threads have leaked since last call
 
424
 
 
425
        A sample of live threads is stored in the _active_threads attribute,
 
426
        when this method runs it compares the current live threads and any not
 
427
        in the previous sample are treated as having leaked.
 
428
        """
 
429
        now_active_threads = set(threading.enumerate())
 
430
        threads_leaked = now_active_threads.difference(self._active_threads)
 
431
        if threads_leaked:
 
432
            self._report_thread_leak(test, threads_leaked, now_active_threads)
 
433
            self._tests_leaking_threads_count += 1
 
434
            if self._first_thread_leaker_id is None:
 
435
                self._first_thread_leaker_id = test.id()
 
436
            self._active_threads = now_active_threads
234
437
 
235
438
    def _recordTestStartTime(self):
236
439
        """Record that a test has started."""
237
 
        self._start_time = time.time()
238
 
 
239
 
    def _cleanupLogFile(self, test):
240
 
        # We can only do this if we have one of our TestCases, not if
241
 
        # we have a doctest.
242
 
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
243
 
        if setKeepLogfile is not None:
244
 
            setKeepLogfile()
 
440
        self._start_datetime = self._now()
245
441
 
246
442
    def addError(self, test, err):
247
 
        self.extractBenchmarkTime(test)
248
 
        self._cleanupLogFile(test)
249
 
        if isinstance(err[1], TestSkipped):
250
 
            return self.addSkipped(test, err)
251
 
        elif isinstance(err[1], UnavailableFeature):
252
 
            return self.addNotSupported(test, err[1].args[0])
253
 
        unittest.TestResult.addError(self, test, err)
 
443
        """Tell result that test finished with an error.
 
444
 
 
445
        Called from the TestCase run() method when the test
 
446
        fails with an unexpected error.
 
447
        """
 
448
        self._post_mortem(self._traceback_from_test)
 
449
        super(ExtendedTestResult, self).addError(test, err)
254
450
        self.error_count += 1
255
451
        self.report_error(test, err)
256
452
        if self.stop_early:
257
453
            self.stop()
258
454
 
259
455
    def addFailure(self, test, err):
260
 
        self._cleanupLogFile(test)
261
 
        self.extractBenchmarkTime(test)
262
 
        if isinstance(err[1], KnownFailure):
263
 
            return self.addKnownFailure(test, err)
264
 
        unittest.TestResult.addFailure(self, test, err)
 
456
        """Tell result that test failed.
 
457
 
 
458
        Called from the TestCase run() method when the test
 
459
        fails because e.g. an assert() method failed.
 
460
        """
 
461
        self._post_mortem(self._traceback_from_test)
 
462
        super(ExtendedTestResult, self).addFailure(test, err)
265
463
        self.failure_count += 1
266
464
        self.report_failure(test, err)
267
465
        if self.stop_early:
268
466
            self.stop()
269
467
 
270
 
    def addKnownFailure(self, test, err):
 
468
    def addSuccess(self, test, details=None):
 
469
        """Tell result that test completed successfully.
 
470
 
 
471
        Called from the TestCase run()
 
472
        """
 
473
        if self._bench_history is not None:
 
474
            benchmark_time = self._extractBenchmarkTime(test, details)
 
475
            if benchmark_time is not None:
 
476
                self._bench_history.write("%s %s\n" % (
 
477
                    self._formatTime(benchmark_time),
 
478
                    test.id()))
 
479
        self.report_success(test)
 
480
        super(ExtendedTestResult, self).addSuccess(test)
 
481
        test._log_contents = ''
 
482
 
 
483
    def addExpectedFailure(self, test, err):
271
484
        self.known_failure_count += 1
272
485
        self.report_known_failure(test, err)
273
486
 
 
487
    def addUnexpectedSuccess(self, test, details=None):
 
488
        """Tell result the test unexpectedly passed, counting as a failure
 
489
 
 
490
        When the minimum version of testtools required becomes 0.9.8 this
 
491
        can be updated to use the new handling there.
 
492
        """
 
493
        super(ExtendedTestResult, self).addFailure(test, details=details)
 
494
        self.failure_count += 1
 
495
        self.report_unexpected_success(test,
 
496
            "".join(details["reason"].iter_text()))
 
497
        if self.stop_early:
 
498
            self.stop()
 
499
 
274
500
    def addNotSupported(self, test, feature):
 
501
        """The test will not be run because of a missing feature.
 
502
        """
 
503
        # this can be called in two different ways: it may be that the
 
504
        # test started running, and then raised (through requireFeature)
 
505
        # UnavailableFeature.  Alternatively this method can be called
 
506
        # while probing for features before running the test code proper; in
 
507
        # that case we will see startTest and stopTest, but the test will
 
508
        # never actually run.
275
509
        self.unsupported.setdefault(str(feature), 0)
276
510
        self.unsupported[str(feature)] += 1
277
511
        self.report_unsupported(test, feature)
278
512
 
279
 
    def addSuccess(self, test):
280
 
        self.extractBenchmarkTime(test)
281
 
        if self._bench_history is not None:
282
 
            if self._benchmarkTime is not None:
283
 
                self._bench_history.write("%s %s\n" % (
284
 
                    self._formatTime(self._benchmarkTime),
285
 
                    test.id()))
286
 
        self.report_success(test)
287
 
        unittest.TestResult.addSuccess(self, test)
288
 
 
289
 
    def addSkipped(self, test, skip_excinfo):
290
 
        self.report_skip(test, skip_excinfo)
291
 
        # seems best to treat this as success from point-of-view of unittest
292
 
        # -- it actually does nothing so it barely matters :)
293
 
        try:
294
 
            test.tearDown()
295
 
        except KeyboardInterrupt:
296
 
            raise
297
 
        except:
298
 
            self.addError(test, test.__exc_info())
299
 
        else:
300
 
            unittest.TestResult.addSuccess(self, test)
301
 
 
302
 
    def printErrorList(self, flavour, errors):
303
 
        for test, err in errors:
304
 
            self.stream.writeln(self.separator1)
305
 
            self.stream.write("%s: " % flavour)
306
 
            if self.use_numbered_dirs:
307
 
                self.stream.write('#%d ' % test.number)
308
 
            self.stream.writeln(self.getDescription(test))
309
 
            if getattr(test, '_get_log', None) is not None:
310
 
                print >>self.stream
311
 
                print >>self.stream, \
312
 
                        ('vvvv[log from %s]' % test.id()).ljust(78,'-')
313
 
                print >>self.stream, test._get_log()
314
 
                print >>self.stream, \
315
 
                        ('^^^^[log from %s]' % test.id()).ljust(78,'-')
316
 
            self.stream.writeln(self.separator2)
317
 
            self.stream.writeln("%s" % err)
318
 
 
319
 
    def finished(self):
320
 
        pass
321
 
 
322
 
    def report_cleaning_up(self):
323
 
        pass
 
513
    def addSkip(self, test, reason):
 
514
        """A test has not run for 'reason'."""
 
515
        self.skip_count += 1
 
516
        self.report_skip(test, reason)
 
517
 
 
518
    def addNotApplicable(self, test, reason):
 
519
        self.not_applicable_count += 1
 
520
        self.report_not_applicable(test, reason)
 
521
 
 
522
    def _count_stored_tests(self):
 
523
        """Count of tests instances kept alive due to not succeeding"""
 
524
        return self.error_count + self.failure_count + self.known_failure_count
 
525
 
 
526
    def _post_mortem(self, tb=None):
 
527
        """Start a PDB post mortem session."""
 
528
        if os.environ.get('BZR_TEST_PDB', None):
 
529
            import pdb
 
530
            pdb.post_mortem(tb)
 
531
 
 
532
    def progress(self, offset, whence):
 
533
        """The test is adjusting the count of tests to run."""
 
534
        if whence == SUBUNIT_SEEK_SET:
 
535
            self.num_tests = offset
 
536
        elif whence == SUBUNIT_SEEK_CUR:
 
537
            self.num_tests += offset
 
538
        else:
 
539
            raise errors.BzrError("Unknown whence %r" % whence)
 
540
 
 
541
    def report_tests_starting(self):
 
542
        """Display information before the test run begins"""
 
543
        if getattr(sys, 'frozen', None) is None:
 
544
            bzr_path = osutils.realpath(sys.argv[0])
 
545
        else:
 
546
            bzr_path = sys.executable
 
547
        self.stream.write(
 
548
            'bzr selftest: %s\n' % (bzr_path,))
 
549
        self.stream.write(
 
550
            '   %s\n' % (
 
551
                    bzrlib.__path__[0],))
 
552
        self.stream.write(
 
553
            '   bzr-%s python-%s %s\n' % (
 
554
                    bzrlib.version_string,
 
555
                    bzrlib._format_version_tuple(sys.version_info),
 
556
                    platform.platform(aliased=1),
 
557
                    ))
 
558
        self.stream.write('\n')
 
559
 
 
560
    def report_test_start(self, test):
 
561
        """Display information on the test just about to be run"""
 
562
 
 
563
    def _report_thread_leak(self, test, leaked_threads, active_threads):
 
564
        """Display information on a test that leaked one or more threads"""
 
565
        # GZ 2010-09-09: A leak summary reported separately from the general
 
566
        #                thread debugging would be nice. Tests under subunit
 
567
        #                need something not using stream, perhaps adding a
 
568
        #                testtools details object would be fitting.
 
569
        if 'threads' in selftest_debug_flags:
 
570
            self.stream.write('%s is leaking, active is now %d\n' %
 
571
                (test.id(), len(active_threads)))
 
572
 
 
573
    def startTestRun(self):
 
574
        self.startTime = time.time()
324
575
 
325
576
    def report_success(self, test):
326
577
        pass
327
578
 
 
579
    def wasStrictlySuccessful(self):
 
580
        if self.unsupported or self.known_failure_count:
 
581
            return False
 
582
        return self.wasSuccessful()
 
583
 
328
584
 
329
585
class TextTestResult(ExtendedTestResult):
330
586
    """Displays progress and results of tests in text form"""
331
587
 
332
588
    def __init__(self, stream, descriptions, verbosity,
333
589
                 bench_history=None,
334
 
                 num_tests=None,
335
590
                 pb=None,
336
 
                 use_numbered_dirs=False,
 
591
                 strict=None,
337
592
                 ):
338
593
        ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
339
 
            bench_history, num_tests, use_numbered_dirs)
340
 
        if pb is None:
341
 
            self.pb = self.ui.nested_progress_bar()
342
 
            self._supplied_pb = False
343
 
        else:
344
 
            self.pb = pb
345
 
            self._supplied_pb = True
 
594
            bench_history, strict)
 
595
        # We no longer pass them around, but just rely on the UIFactory stack
 
596
        # for state
 
597
        if pb is not None:
 
598
            warnings.warn("Passing pb to TextTestResult is deprecated")
 
599
        self.pb = self.ui.nested_progress_bar()
346
600
        self.pb.show_pct = False
347
601
        self.pb.show_spinner = False
348
602
        self.pb.show_eta = False,
349
603
        self.pb.show_count = False
350
604
        self.pb.show_bar = False
351
 
 
352
 
    def report_starting(self):
353
 
        self.pb.update('[test 0/%d] starting...' % (self.num_tests))
 
605
        self.pb.update_latency = 0
 
606
        self.pb.show_transport_activity = False
 
607
 
 
608
    def stopTestRun(self):
 
609
        # called when the tests that are going to run have run
 
610
        self.pb.clear()
 
611
        self.pb.finished()
 
612
        super(TextTestResult, self).stopTestRun()
 
613
 
 
614
    def report_tests_starting(self):
 
615
        super(TextTestResult, self).report_tests_starting()
 
616
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
354
617
 
355
618
    def _progress_prefix_text(self):
356
 
        a = '[%d' % self.count
357
 
        if self.num_tests is not None:
 
619
        # the longer this text, the less space we have to show the test
 
620
        # name...
 
621
        a = '[%d' % self.count              # total that have been run
 
622
        # tests skipped as known not to be relevant are not important enough
 
623
        # to show here
 
624
        ## if self.skip_count:
 
625
        ##     a += ', %d skip' % self.skip_count
 
626
        ## if self.known_failure_count:
 
627
        ##     a += '+%dX' % self.known_failure_count
 
628
        if self.num_tests:
358
629
            a +='/%d' % self.num_tests
359
 
        a += ' in %ds' % (time.time() - self._overall_start_time)
360
 
        if self.error_count:
361
 
            a += ', %d errors' % self.error_count
362
 
        if self.failure_count:
363
 
            a += ', %d failed' % self.failure_count
364
 
        if self.known_failure_count:
365
 
            a += ', %d known failures' % self.known_failure_count
366
 
        if self.skip_count:
367
 
            a += ', %d skipped' % self.skip_count
368
 
        if self.unsupported:
369
 
            a += ', %d missing features' % len(self.unsupported)
 
630
        a += ' in '
 
631
        runtime = time.time() - self._overall_start_time
 
632
        if runtime >= 60:
 
633
            a += '%dm%ds' % (runtime / 60, runtime % 60)
 
634
        else:
 
635
            a += '%ds' % runtime
 
636
        total_fail_count = self.error_count + self.failure_count
 
637
        if total_fail_count:
 
638
            a += ', %d failed' % total_fail_count
 
639
        # if self.unsupported:
 
640
        #     a += ', %d missing' % len(self.unsupported)
370
641
        a += ']'
371
642
        return a
372
643
 
373
644
    def report_test_start(self, test):
374
 
        self.count += 1
375
645
        self.pb.update(
376
646
                self._progress_prefix_text()
377
 
                + ' ' 
 
647
                + ' '
378
648
                + self._shortened_test_description(test))
379
649
 
380
650
    def _test_description(self, test):
381
 
        if self.use_numbered_dirs:
382
 
            return '#%d %s' % (self.count,
383
 
                               self._shortened_test_description(test))
384
 
        else:
385
 
            return self._shortened_test_description(test)
 
651
        return self._shortened_test_description(test)
386
652
 
387
653
    def report_error(self, test, err):
388
 
        self.pb.note('ERROR: %s\n    %s\n', 
 
654
        self.stream.write('ERROR: %s\n    %s\n' % (
389
655
            self._test_description(test),
390
656
            err[1],
391
 
            )
 
657
            ))
392
658
 
393
659
    def report_failure(self, test, err):
394
 
        self.pb.note('FAIL: %s\n    %s\n', 
 
660
        self.stream.write('FAIL: %s\n    %s\n' % (
395
661
            self._test_description(test),
396
662
            err[1],
397
 
            )
 
663
            ))
398
664
 
399
665
    def report_known_failure(self, test, err):
400
 
        self.pb.note('XFAIL: %s\n%s\n',
401
 
            self._test_description(test), err[1])
402
 
 
403
 
    def report_skip(self, test, skip_excinfo):
404
 
        self.skip_count += 1
405
 
        if False:
406
 
            # at the moment these are mostly not things we can fix
407
 
            # and so they just produce stipple; use the verbose reporter
408
 
            # to see them.
409
 
            if False:
410
 
                # show test and reason for skip
411
 
                self.pb.note('SKIP: %s\n    %s\n', 
412
 
                    self._shortened_test_description(test),
413
 
                    skip_excinfo[1])
414
 
            else:
415
 
                # since the class name was left behind in the still-visible
416
 
                # progress bar...
417
 
                self.pb.note('SKIP: %s', skip_excinfo[1])
 
666
        pass
 
667
 
 
668
    def report_unexpected_success(self, test, reason):
 
669
        self.stream.write('FAIL: %s\n    %s: %s\n' % (
 
670
            self._test_description(test),
 
671
            "Unexpected success. Should have failed",
 
672
            reason,
 
673
            ))
 
674
 
 
675
    def report_skip(self, test, reason):
 
676
        pass
 
677
 
 
678
    def report_not_applicable(self, test, reason):
 
679
        pass
418
680
 
419
681
    def report_unsupported(self, test, feature):
420
682
        """test cannot be run because feature is missing."""
421
 
                  
422
 
    def report_cleaning_up(self):
423
 
        self.pb.update('cleaning up...')
424
 
 
425
 
    def finished(self):
426
 
        if not self._supplied_pb:
427
 
            self.pb.finished()
428
683
 
429
684
 
430
685
class VerboseTestResult(ExtendedTestResult):
438
693
            result = a_string
439
694
        return result.ljust(final_width)
440
695
 
441
 
    def report_starting(self):
 
696
    def report_tests_starting(self):
442
697
        self.stream.write('running %d tests...\n' % self.num_tests)
 
698
        super(VerboseTestResult, self).report_tests_starting()
443
699
 
444
700
    def report_test_start(self, test):
445
 
        self.count += 1
446
701
        name = self._shortened_test_description(test)
447
 
        # width needs space for 6 char status, plus 1 for slash, plus 2 10-char
448
 
        # numbers, plus a trailing blank
449
 
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
450
 
        if self.use_numbered_dirs:
451
 
            self.stream.write('%5d ' % self.count)
452
 
            self.stream.write(self._ellipsize_to_right(name,
453
 
                                osutils.terminal_width()-36))
 
702
        width = osutils.terminal_width()
 
703
        if width is not None:
 
704
            # width needs space for 6 char status, plus 1 for slash, plus an
 
705
            # 11-char time string, plus a trailing blank
 
706
            # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on
 
707
            # space
 
708
            self.stream.write(self._ellipsize_to_right(name, width-18))
454
709
        else:
455
 
            self.stream.write(self._ellipsize_to_right(name,
456
 
                                osutils.terminal_width()-30))
 
710
            self.stream.write(name)
457
711
        self.stream.flush()
458
712
 
459
713
    def _error_summary(self, err):
460
714
        indent = ' ' * 4
461
 
        if self.use_numbered_dirs:
462
 
            indent += ' ' * 6
463
715
        return '%s%s' % (indent, err[1])
464
716
 
465
717
    def report_error(self, test, err):
466
 
        self.stream.writeln('ERROR %s\n%s'
467
 
                % (self._testTimeString(),
 
718
        self.stream.write('ERROR %s\n%s\n'
 
719
                % (self._testTimeString(test),
468
720
                   self._error_summary(err)))
469
721
 
470
722
    def report_failure(self, test, err):
471
 
        self.stream.writeln(' FAIL %s\n%s'
472
 
                % (self._testTimeString(),
 
723
        self.stream.write(' FAIL %s\n%s\n'
 
724
                % (self._testTimeString(test),
473
725
                   self._error_summary(err)))
474
726
 
475
727
    def report_known_failure(self, test, err):
476
 
        self.stream.writeln('XFAIL %s\n%s'
477
 
                % (self._testTimeString(),
 
728
        self.stream.write('XFAIL %s\n%s\n'
 
729
                % (self._testTimeString(test),
478
730
                   self._error_summary(err)))
479
731
 
 
732
    def report_unexpected_success(self, test, reason):
 
733
        self.stream.write(' FAIL %s\n%s: %s\n'
 
734
                % (self._testTimeString(test),
 
735
                   "Unexpected success. Should have failed",
 
736
                   reason))
 
737
 
480
738
    def report_success(self, test):
481
 
        self.stream.writeln('   OK %s' % self._testTimeString())
 
739
        self.stream.write('   OK %s\n' % self._testTimeString(test))
482
740
        for bench_called, stats in getattr(test, '_benchcalls', []):
483
 
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
 
741
            self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
484
742
            stats.pprint(file=self.stream)
485
743
        # flush the stream so that we get smooth output. This verbose mode is
486
744
        # used to show the output in PQM.
487
745
        self.stream.flush()
488
746
 
489
 
    def report_skip(self, test, skip_excinfo):
490
 
        self.skip_count += 1
491
 
        self.stream.writeln(' SKIP %s\n%s'
492
 
                % (self._testTimeString(),
493
 
                   self._error_summary(skip_excinfo)))
 
747
    def report_skip(self, test, reason):
 
748
        self.stream.write(' SKIP %s\n%s\n'
 
749
                % (self._testTimeString(test), reason))
 
750
 
 
751
    def report_not_applicable(self, test, reason):
 
752
        self.stream.write('  N/A %s\n    %s\n'
 
753
                % (self._testTimeString(test), reason))
494
754
 
495
755
    def report_unsupported(self, test, feature):
496
756
        """test cannot be run because feature is missing."""
497
 
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
498
 
                %(self._testTimeString(), feature))
499
 
                  
 
757
        self.stream.write("NODEP %s\n    The feature '%s' is not available.\n"
 
758
                %(self._testTimeString(test), feature))
500
759
 
501
760
 
502
761
class TextTestRunner(object):
507
766
                 descriptions=0,
508
767
                 verbosity=1,
509
768
                 bench_history=None,
510
 
                 use_numbered_dirs=False,
511
 
                 list_only=False
 
769
                 strict=False,
 
770
                 result_decorators=None,
512
771
                 ):
513
 
        self.stream = unittest._WritelnDecorator(stream)
 
772
        """Create a TextTestRunner.
 
773
 
 
774
        :param result_decorators: An optional list of decorators to apply
 
775
            to the result object being used by the runner. Decorators are
 
776
            applied left to right - the first element in the list is the 
 
777
            innermost decorator.
 
778
        """
 
779
        # stream may know claim to know to write unicode strings, but in older
 
780
        # pythons this goes sufficiently wrong that it is a bad idea. (
 
781
        # specifically a built in file with encoding 'UTF-8' will still try
 
782
        # to encode using ascii.
 
783
        new_encoding = osutils.get_terminal_encoding()
 
784
        codec = codecs.lookup(new_encoding)
 
785
        if type(codec) is tuple:
 
786
            # Python 2.4
 
787
            encode = codec[0]
 
788
        else:
 
789
            encode = codec.encode
 
790
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
 
791
        #                so should swap to the plain codecs.StreamWriter
 
792
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
 
793
            "backslashreplace")
 
794
        stream.encoding = new_encoding
 
795
        self.stream = stream
514
796
        self.descriptions = descriptions
515
797
        self.verbosity = verbosity
516
798
        self._bench_history = bench_history
517
 
        self.use_numbered_dirs = use_numbered_dirs
518
 
        self.list_only = list_only
 
799
        self._strict = strict
 
800
        self._result_decorators = result_decorators or []
519
801
 
520
802
    def run(self, test):
521
803
        "Run the given test case or test suite."
522
 
        startTime = time.time()
523
804
        if self.verbosity == 1:
524
805
            result_class = TextTestResult
525
806
        elif self.verbosity >= 2:
526
807
            result_class = VerboseTestResult
527
 
        result = result_class(self.stream,
 
808
        original_result = result_class(self.stream,
528
809
                              self.descriptions,
529
810
                              self.verbosity,
530
811
                              bench_history=self._bench_history,
531
 
                              num_tests=test.countTestCases(),
532
 
                              use_numbered_dirs=self.use_numbered_dirs,
 
812
                              strict=self._strict,
533
813
                              )
534
 
        result.stop_early = self.stop_on_failure
535
 
        result.report_starting()
536
 
        if self.list_only:
537
 
            if self.verbosity >= 2:
538
 
                self.stream.writeln("Listing tests only ...\n")
539
 
            run = 0
540
 
            for t in iter_suite_tests(test):
541
 
                self.stream.writeln("%s" % (t.id()))
542
 
                run += 1
543
 
            actionTaken = "Listed"
544
 
        else: 
 
814
        # Signal to result objects that look at stop early policy to stop,
 
815
        original_result.stop_early = self.stop_on_failure
 
816
        result = original_result
 
817
        for decorator in self._result_decorators:
 
818
            result = decorator(result)
 
819
            result.stop_early = self.stop_on_failure
 
820
        result.startTestRun()
 
821
        try:
545
822
            test.run(result)
546
 
            run = result.testsRun
547
 
            actionTaken = "Ran"
548
 
        stopTime = time.time()
549
 
        timeTaken = stopTime - startTime
550
 
        result.printErrors()
551
 
        self.stream.writeln(result.separator2)
552
 
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
553
 
                            run, run != 1 and "s" or "", timeTaken))
554
 
        self.stream.writeln()
555
 
        if not result.wasSuccessful():
556
 
            self.stream.write("FAILED (")
557
 
            failed, errored = map(len, (result.failures, result.errors))
558
 
            if failed:
559
 
                self.stream.write("failures=%d" % failed)
560
 
            if errored:
561
 
                if failed: self.stream.write(", ")
562
 
                self.stream.write("errors=%d" % errored)
563
 
            if result.known_failure_count:
564
 
                if failed or errored: self.stream.write(", ")
565
 
                self.stream.write("known_failure_count=%d" %
566
 
                    result.known_failure_count)
567
 
            self.stream.writeln(")")
568
 
        else:
569
 
            if result.known_failure_count:
570
 
                self.stream.writeln("OK (known_failures=%d)" %
571
 
                    result.known_failure_count)
572
 
            else:
573
 
                self.stream.writeln("OK")
574
 
        if result.skip_count > 0:
575
 
            skipped = result.skip_count
576
 
            self.stream.writeln('%d test%s skipped' %
577
 
                                (skipped, skipped != 1 and "s" or ""))
578
 
        if result.unsupported:
579
 
            for feature, count in sorted(result.unsupported.items()):
580
 
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
581
 
                    (feature, count))
582
 
        result.finished()
583
 
        return result
 
823
        finally:
 
824
            result.stopTestRun()
 
825
        # higher level code uses our extended protocol to determine
 
826
        # what exit code to give.
 
827
        return original_result
584
828
 
585
829
 
586
830
def iter_suite_tests(suite):
587
831
    """Return all tests in a suite, recursing through nested suites"""
588
 
    for item in suite._tests:
589
 
        if isinstance(item, unittest.TestCase):
590
 
            yield item
591
 
        elif isinstance(item, unittest.TestSuite):
 
832
    if isinstance(suite, unittest.TestCase):
 
833
        yield suite
 
834
    elif isinstance(suite, unittest.TestSuite):
 
835
        for item in suite:
592
836
            for r in iter_suite_tests(item):
593
837
                yield r
594
 
        else:
595
 
            raise Exception('unknown object %r inside test suite %r'
596
 
                            % (item, suite))
597
 
 
598
 
 
599
 
class TestSkipped(Exception):
600
 
    """Indicates that a test was intentionally skipped, rather than failing."""
601
 
 
602
 
 
603
 
class KnownFailure(AssertionError):
604
 
    """Indicates that a test failed in a precisely expected manner.
605
 
 
606
 
    Such failures dont block the whole test suite from passing because they are
607
 
    indicators of partially completed code or of future work. We have an
608
 
    explicit error for them so that we can ensure that they are always visible:
609
 
    KnownFailures are always shown in the output of bzr selftest.
 
838
    else:
 
839
        raise Exception('unknown type %r for object %r'
 
840
                        % (type(suite), suite))
 
841
 
 
842
 
 
843
TestSkipped = testtools.testcase.TestSkipped
 
844
 
 
845
 
 
846
class TestNotApplicable(TestSkipped):
 
847
    """A test is not applicable to the situation where it was run.
 
848
 
 
849
    This is only normally raised by parameterized tests, if they find that
 
850
    the instance they're constructed upon does not support one aspect
 
851
    of its interface.
610
852
    """
611
853
 
612
854
 
 
855
# traceback._some_str fails to format exceptions that have the default
 
856
# __str__ which does an implicit ascii conversion. However, repr() on those
 
857
# objects works, for all that its not quite what the doctor may have ordered.
 
858
def _clever_some_str(value):
 
859
    try:
 
860
        return str(value)
 
861
    except:
 
862
        try:
 
863
            return repr(value).replace('\\n', '\n')
 
864
        except:
 
865
            return '<unprintable %s object>' % type(value).__name__
 
866
 
 
867
traceback._some_str = _clever_some_str
 
868
 
 
869
 
 
870
# deprecated - use self.knownFailure(), or self.expectFailure.
 
871
KnownFailure = testtools.testcase._ExpectedFailure
 
872
 
 
873
 
613
874
class UnavailableFeature(Exception):
614
875
    """A feature required for this test was not available.
615
876
 
 
877
    This can be considered a specialised form of SkippedTest.
 
878
 
616
879
    The feature should be used to construct the exception.
617
880
    """
618
881
 
619
882
 
620
 
class CommandFailed(Exception):
621
 
    pass
622
 
 
623
 
 
624
883
class StringIOWrapper(object):
625
884
    """A wrapper around cStringIO which just adds an encoding attribute.
626
 
    
 
885
 
627
886
    Internally we can check sys.stdout to see what the output encoding
628
887
    should be. However, cStringIO has no encoding attribute that we can
629
888
    set. So we wrap it instead.
647
906
            return setattr(self._cstring, name, val)
648
907
 
649
908
 
650
 
class TestUIFactory(ui.CLIUIFactory):
 
909
class TestUIFactory(TextUIFactory):
651
910
    """A UI Factory for testing.
652
911
 
653
912
    Hide the progress bar but emit note()s.
654
913
    Redirect stdin.
655
914
    Allows get_password to be tested without real tty attached.
 
915
 
 
916
    See also CannedInputUIFactory which lets you provide programmatic input in
 
917
    a structured way.
656
918
    """
 
919
    # TODO: Capture progress events at the model level and allow them to be
 
920
    # observed by tests that care.
 
921
    #
 
922
    # XXX: Should probably unify more with CannedInputUIFactory or a
 
923
    # particular configuration of TextUIFactory, or otherwise have a clearer
 
924
    # idea of how they're supposed to be different.
 
925
    # See https://bugs.launchpad.net/bzr/+bug/408213
657
926
 
658
 
    def __init__(self,
659
 
                 stdout=None,
660
 
                 stderr=None,
661
 
                 stdin=None):
662
 
        super(TestUIFactory, self).__init__()
 
927
    def __init__(self, stdout=None, stderr=None, stdin=None):
663
928
        if stdin is not None:
664
929
            # We use a StringIOWrapper to be able to test various
665
930
            # encodings, but the user is still responsible to
666
931
            # encode the string and to set the encoding attribute
667
932
            # of StringIOWrapper.
668
 
            self.stdin = StringIOWrapper(stdin)
669
 
        if stdout is None:
670
 
            self.stdout = sys.stdout
671
 
        else:
672
 
            self.stdout = stdout
673
 
        if stderr is None:
674
 
            self.stderr = sys.stderr
675
 
        else:
676
 
            self.stderr = stderr
677
 
 
678
 
    def clear(self):
679
 
        """See progress.ProgressBar.clear()."""
680
 
 
681
 
    def clear_term(self):
682
 
        """See progress.ProgressBar.clear_term()."""
683
 
 
684
 
    def clear_term(self):
685
 
        """See progress.ProgressBar.clear_term()."""
686
 
 
687
 
    def finished(self):
688
 
        """See progress.ProgressBar.finished()."""
689
 
 
690
 
    def note(self, fmt_string, *args, **kwargs):
691
 
        """See progress.ProgressBar.note()."""
692
 
        self.stdout.write((fmt_string + "\n") % args)
693
 
 
694
 
    def progress_bar(self):
695
 
        return self
696
 
 
697
 
    def nested_progress_bar(self):
698
 
        return self
699
 
 
700
 
    def update(self, message, count=None, total=None):
701
 
        """See progress.ProgressBar.update()."""
702
 
 
703
 
    def get_non_echoed_password(self, prompt):
 
933
            stdin = StringIOWrapper(stdin)
 
934
        super(TestUIFactory, self).__init__(stdin, stdout, stderr)
 
935
 
 
936
    def get_non_echoed_password(self):
704
937
        """Get password from stdin without trying to handle the echo mode"""
705
 
        if prompt:
706
 
            self.stdout.write(prompt.encode(self.stdout.encoding, 'replace'))
707
938
        password = self.stdin.readline()
708
939
        if not password:
709
940
            raise EOFError
711
942
            password = password[:-1]
712
943
        return password
713
944
 
714
 
 
715
 
class TestCase(unittest.TestCase):
 
945
    def make_progress_view(self):
 
946
        return NullProgressView()
 
947
 
 
948
 
 
949
def isolated_doctest_setUp(test):
 
950
    override_os_environ(test)
 
951
 
 
952
 
 
953
def isolated_doctest_tearDown(test):
 
954
    restore_os_environ(test)
 
955
 
 
956
 
 
957
def IsolatedDocTestSuite(*args, **kwargs):
 
958
    """Overrides doctest.DocTestSuite to handle isolation.
 
959
 
 
960
    The method is really a factory and users are expected to use it as such.
 
961
    """
 
962
 
 
963
    kwargs['setUp'] = isolated_doctest_setUp
 
964
    kwargs['tearDown'] = isolated_doctest_tearDown
 
965
    return doctest.DocTestSuite(*args, **kwargs)
 
966
 
 
967
 
 
968
class TestCase(testtools.TestCase):
716
969
    """Base class for bzr unit tests.
717
 
    
718
 
    Tests that need access to disk resources should subclass 
 
970
 
 
971
    Tests that need access to disk resources should subclass
719
972
    TestCaseInTempDir not TestCase.
720
973
 
721
974
    Error and debug log messages are redirected from their usual
723
976
    retrieved by _get_log().  We use a real OS file, not an in-memory object,
724
977
    so that it can also capture file IO.  When the test completes this file
725
978
    is read into memory and removed from disk.
726
 
       
 
979
 
727
980
    There are also convenience functions to invoke bzr's command-line
728
981
    routine, and to build and check bzr trees.
729
 
   
 
982
 
730
983
    In addition to the usual method of overriding tearDown(), this class also
731
 
    allows subclasses to register functions into the _cleanups list, which is
 
984
    allows subclasses to register cleanup functions via addCleanup, which are
732
985
    run in order as the object is torn down.  It's less likely this will be
733
986
    accidentally overlooked.
734
987
    """
735
988
 
736
 
    _log_file_name = None
737
 
    _log_contents = ''
738
 
    _keep_log_file = False
 
989
    _log_file = None
739
990
    # record lsprof data when performing benchmark calls.
740
991
    _gather_lsprof_in_benchmarks = False
741
992
 
742
993
    def __init__(self, methodName='testMethod'):
743
994
        super(TestCase, self).__init__(methodName)
744
 
        self._cleanups = []
 
995
        self._directory_isolation = True
 
996
        self.exception_handlers.insert(0,
 
997
            (UnavailableFeature, self._do_unsupported_or_skip))
 
998
        self.exception_handlers.insert(0,
 
999
            (TestNotApplicable, self._do_not_applicable))
745
1000
 
746
1001
    def setUp(self):
747
 
        unittest.TestCase.setUp(self)
 
1002
        super(TestCase, self).setUp()
 
1003
 
 
1004
        timeout = config.GlobalStack().get('selftest.timeout')
 
1005
        if timeout:
 
1006
            timeout_fixture = fixtures.TimeoutFixture(timeout)
 
1007
            timeout_fixture.setUp()
 
1008
            self.addCleanup(timeout_fixture.cleanUp)
 
1009
 
 
1010
        for feature in getattr(self, '_test_needs_features', []):
 
1011
            self.requireFeature(feature)
748
1012
        self._cleanEnvironment()
749
 
        bzrlib.trace.disable_default_logging()
 
1013
 
 
1014
        if bzrlib.global_state is not None:
 
1015
            self.overrideAttr(bzrlib.global_state, 'cmdline_overrides',
 
1016
                              config.CommandLineStore())
 
1017
 
750
1018
        self._silenceUI()
751
1019
        self._startLogFile()
752
1020
        self._benchcalls = []
753
1021
        self._benchtime = None
754
1022
        self._clear_hooks()
 
1023
        self._track_transports()
 
1024
        self._track_locks()
755
1025
        self._clear_debug_flags()
 
1026
        # Isolate global verbosity level, to make sure it's reproducible
 
1027
        # between tests.  We should get rid of this altogether: bug 656694. --
 
1028
        # mbp 20101008
 
1029
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
 
1030
        self._log_files = set()
 
1031
        # Each key in the ``_counters`` dict holds a value for a different
 
1032
        # counter. When the test ends, addDetail() should be used to output the
 
1033
        # counter values. This happens in install_counter_hook().
 
1034
        self._counters = {}
 
1035
        if 'config_stats' in selftest_debug_flags:
 
1036
            self._install_config_stats_hooks()
 
1037
        # Do not use i18n for tests (unless the test reverses this)
 
1038
        i18n.disable_i18n()
 
1039
 
 
1040
    def debug(self):
 
1041
        # debug a frame up.
 
1042
        import pdb
 
1043
        # The sys preserved stdin/stdout should allow blackbox tests debugging
 
1044
        pdb.Pdb(stdin=sys.__stdin__, stdout=sys.__stdout__
 
1045
                ).set_trace(sys._getframe().f_back)
 
1046
 
 
1047
    def discardDetail(self, name):
 
1048
        """Extend the addDetail, getDetails api so we can remove a detail.
 
1049
 
 
1050
        eg. bzr always adds the 'log' detail at startup, but we don't want to
 
1051
        include it for skipped, xfail, etc tests.
 
1052
 
 
1053
        It is safe to call this for a detail that doesn't exist, in case this
 
1054
        gets called multiple times.
 
1055
        """
 
1056
        # We cheat. details is stored in __details which means we shouldn't
 
1057
        # touch it. but getDetails() returns the dict directly, so we can
 
1058
        # mutate it.
 
1059
        details = self.getDetails()
 
1060
        if name in details:
 
1061
            del details[name]
 
1062
 
 
1063
    def install_counter_hook(self, hooks, name, counter_name=None):
 
1064
        """Install a counting hook.
 
1065
 
 
1066
        Any hook can be counted as long as it doesn't need to return a value.
 
1067
 
 
1068
        :param hooks: Where the hook should be installed.
 
1069
 
 
1070
        :param name: The hook name that will be counted.
 
1071
 
 
1072
        :param counter_name: The counter identifier in ``_counters``, defaults
 
1073
            to ``name``.
 
1074
        """
 
1075
        _counters = self._counters # Avoid closing over self
 
1076
        if counter_name is None:
 
1077
            counter_name = name
 
1078
        if _counters.has_key(counter_name):
 
1079
            raise AssertionError('%s is already used as a counter name'
 
1080
                                  % (counter_name,))
 
1081
        _counters[counter_name] = 0
 
1082
        self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
 
1083
            lambda: ['%d' % (_counters[counter_name],)]))
 
1084
        def increment_counter(*args, **kwargs):
 
1085
            _counters[counter_name] += 1
 
1086
        label = 'count %s calls' % (counter_name,)
 
1087
        hooks.install_named_hook(name, increment_counter, label)
 
1088
        self.addCleanup(hooks.uninstall_named_hook, name, label)
 
1089
 
 
1090
    def _install_config_stats_hooks(self):
 
1091
        """Install config hooks to count hook calls.
 
1092
 
 
1093
        """
 
1094
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
 
1095
            self.install_counter_hook(config.ConfigHooks, hook_name,
 
1096
                                       'config.%s' % (hook_name,))
 
1097
 
 
1098
        # The OldConfigHooks are private and need special handling to protect
 
1099
        # against recursive tests (tests that run other tests), so we just do
 
1100
        # manually what registering them into _builtin_known_hooks will provide
 
1101
        # us.
 
1102
        self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
 
1103
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
 
1104
            self.install_counter_hook(config.OldConfigHooks, hook_name,
 
1105
                                      'old_config.%s' % (hook_name,))
756
1106
 
757
1107
    def _clear_debug_flags(self):
758
1108
        """Prevent externally set debug flags affecting tests.
759
 
        
 
1109
 
760
1110
        Tests that want to use debug flags can just set them in the
761
1111
        debug_flags set during setup/teardown.
762
1112
        """
763
 
        self._preserved_debug_flags = set(debug.debug_flags)
764
 
        debug.debug_flags.clear()
765
 
        self.addCleanup(self._restore_debug_flags)
 
1113
        # Start with a copy of the current debug flags we can safely modify.
 
1114
        self.overrideAttr(debug, 'debug_flags', set(debug.debug_flags))
 
1115
        if 'allow_debug' not in selftest_debug_flags:
 
1116
            debug.debug_flags.clear()
 
1117
        if 'disable_lock_checks' not in selftest_debug_flags:
 
1118
            debug.debug_flags.add('strict_locks')
766
1119
 
767
1120
    def _clear_hooks(self):
768
1121
        # prevent hooks affecting tests
769
 
        import bzrlib.branch
770
 
        import bzrlib.smart.server
771
 
        self._preserved_hooks = {
772
 
            bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
773
 
            bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
774
 
            }
 
1122
        known_hooks = hooks.known_hooks
 
1123
        self._preserved_hooks = {}
 
1124
        for key, (parent, name) in known_hooks.iter_parent_objects():
 
1125
            current_hooks = getattr(parent, name)
 
1126
            self._preserved_hooks[parent] = (name, current_hooks)
 
1127
        self._preserved_lazy_hooks = hooks._lazy_hooks
 
1128
        hooks._lazy_hooks = {}
775
1129
        self.addCleanup(self._restoreHooks)
776
 
        # reset all hooks to an empty instance of the appropriate type
777
 
        bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
778
 
        bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
 
1130
        for key, (parent, name) in known_hooks.iter_parent_objects():
 
1131
            factory = known_hooks.get(key)
 
1132
            setattr(parent, name, factory())
 
1133
        # this hook should always be installed
 
1134
        request._install_hook()
 
1135
 
 
1136
    def disable_directory_isolation(self):
 
1137
        """Turn off directory isolation checks."""
 
1138
        self._directory_isolation = False
 
1139
 
 
1140
    def enable_directory_isolation(self):
 
1141
        """Enable directory isolation checks."""
 
1142
        self._directory_isolation = True
779
1143
 
780
1144
    def _silenceUI(self):
781
1145
        """Turn off UI for duration of test"""
782
1146
        # by default the UI is off; tests can turn it on if they want it.
783
 
        saved = ui.ui_factory
784
 
        def _restore():
785
 
            ui.ui_factory = saved
786
 
        ui.ui_factory = ui.SilentUIFactory()
787
 
        self.addCleanup(_restore)
 
1147
        self.overrideAttr(ui, 'ui_factory', ui.SilentUIFactory())
 
1148
 
 
1149
    def _check_locks(self):
 
1150
        """Check that all lock take/release actions have been paired."""
 
1151
        # We always check for mismatched locks. If a mismatch is found, we
 
1152
        # fail unless -Edisable_lock_checks is supplied to selftest, in which
 
1153
        # case we just print a warning.
 
1154
        # unhook:
 
1155
        acquired_locks = [lock for action, lock in self._lock_actions
 
1156
                          if action == 'acquired']
 
1157
        released_locks = [lock for action, lock in self._lock_actions
 
1158
                          if action == 'released']
 
1159
        broken_locks = [lock for action, lock in self._lock_actions
 
1160
                        if action == 'broken']
 
1161
        # trivially, given the tests for lock acquistion and release, if we
 
1162
        # have as many in each list, it should be ok. Some lock tests also
 
1163
        # break some locks on purpose and should be taken into account by
 
1164
        # considering that breaking a lock is just a dirty way of releasing it.
 
1165
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
 
1166
            message = (
 
1167
                'Different number of acquired and '
 
1168
                'released or broken locks.\n'
 
1169
                'acquired=%s\n'
 
1170
                'released=%s\n'
 
1171
                'broken=%s\n' %
 
1172
                (acquired_locks, released_locks, broken_locks))
 
1173
            if not self._lock_check_thorough:
 
1174
                # Rather than fail, just warn
 
1175
                print "Broken test %s: %s" % (self, message)
 
1176
                return
 
1177
            self.fail(message)
 
1178
 
 
1179
    def _track_locks(self):
 
1180
        """Track lock activity during tests."""
 
1181
        self._lock_actions = []
 
1182
        if 'disable_lock_checks' in selftest_debug_flags:
 
1183
            self._lock_check_thorough = False
 
1184
        else:
 
1185
            self._lock_check_thorough = True
 
1186
 
 
1187
        self.addCleanup(self._check_locks)
 
1188
        _mod_lock.Lock.hooks.install_named_hook('lock_acquired',
 
1189
                                                self._lock_acquired, None)
 
1190
        _mod_lock.Lock.hooks.install_named_hook('lock_released',
 
1191
                                                self._lock_released, None)
 
1192
        _mod_lock.Lock.hooks.install_named_hook('lock_broken',
 
1193
                                                self._lock_broken, None)
 
1194
 
 
1195
    def _lock_acquired(self, result):
 
1196
        self._lock_actions.append(('acquired', result))
 
1197
 
 
1198
    def _lock_released(self, result):
 
1199
        self._lock_actions.append(('released', result))
 
1200
 
 
1201
    def _lock_broken(self, result):
 
1202
        self._lock_actions.append(('broken', result))
 
1203
 
 
1204
    def permit_dir(self, name):
 
1205
        """Permit a directory to be used by this test. See permit_url."""
 
1206
        name_transport = _mod_transport.get_transport_from_path(name)
 
1207
        self.permit_url(name)
 
1208
        self.permit_url(name_transport.base)
 
1209
 
 
1210
    def permit_url(self, url):
 
1211
        """Declare that url is an ok url to use in this test.
 
1212
        
 
1213
        Do this for memory transports, temporary test directory etc.
 
1214
        
 
1215
        Do not do this for the current working directory, /tmp, or any other
 
1216
        preexisting non isolated url.
 
1217
        """
 
1218
        if not url.endswith('/'):
 
1219
            url += '/'
 
1220
        self._bzr_selftest_roots.append(url)
 
1221
 
 
1222
    def permit_source_tree_branch_repo(self):
 
1223
        """Permit the source tree bzr is running from to be opened.
 
1224
 
 
1225
        Some code such as bzrlib.version attempts to read from the bzr branch
 
1226
        that bzr is executing from (if any). This method permits that directory
 
1227
        to be used in the test suite.
 
1228
        """
 
1229
        path = self.get_source_path()
 
1230
        self.record_directory_isolation()
 
1231
        try:
 
1232
            try:
 
1233
                workingtree.WorkingTree.open(path)
 
1234
            except (errors.NotBranchError, errors.NoWorkingTree):
 
1235
                raise TestSkipped('Needs a working tree of bzr sources')
 
1236
        finally:
 
1237
            self.enable_directory_isolation()
 
1238
 
 
1239
    def _preopen_isolate_transport(self, transport):
 
1240
        """Check that all transport openings are done in the test work area."""
 
1241
        while isinstance(transport, pathfilter.PathFilteringTransport):
 
1242
            # Unwrap pathfiltered transports
 
1243
            transport = transport.server.backing_transport.clone(
 
1244
                transport._filter('.'))
 
1245
        url = transport.base
 
1246
        # ReadonlySmartTCPServer_for_testing decorates the backing transport
 
1247
        # urls it is given by prepending readonly+. This is appropriate as the
 
1248
        # client shouldn't know that the server is readonly (or not readonly).
 
1249
        # We could register all servers twice, with readonly+ prepending, but
 
1250
        # that makes for a long list; this is about the same but easier to
 
1251
        # read.
 
1252
        if url.startswith('readonly+'):
 
1253
            url = url[len('readonly+'):]
 
1254
        self._preopen_isolate_url(url)
 
1255
 
 
1256
    def _preopen_isolate_url(self, url):
 
1257
        if not self._directory_isolation:
 
1258
            return
 
1259
        if self._directory_isolation == 'record':
 
1260
            self._bzr_selftest_roots.append(url)
 
1261
            return
 
1262
        # This prevents all transports, including e.g. sftp ones backed on disk
 
1263
        # from working unless they are explicitly granted permission. We then
 
1264
        # depend on the code that sets up test transports to check that they are
 
1265
        # appropriately isolated and enable their use by calling
 
1266
        # self.permit_transport()
 
1267
        if not osutils.is_inside_any(self._bzr_selftest_roots, url):
 
1268
            raise errors.BzrError("Attempt to escape test isolation: %r %r"
 
1269
                % (url, self._bzr_selftest_roots))
 
1270
 
 
1271
    def record_directory_isolation(self):
 
1272
        """Gather accessed directories to permit later access.
 
1273
        
 
1274
        This is used for tests that access the branch bzr is running from.
 
1275
        """
 
1276
        self._directory_isolation = "record"
 
1277
 
 
1278
    def start_server(self, transport_server, backing_server=None):
 
1279
        """Start transport_server for this test.
 
1280
 
 
1281
        This starts the server, registers a cleanup for it and permits the
 
1282
        server's urls to be used.
 
1283
        """
 
1284
        if backing_server is None:
 
1285
            transport_server.start_server()
 
1286
        else:
 
1287
            transport_server.start_server(backing_server)
 
1288
        self.addCleanup(transport_server.stop_server)
 
1289
        # Obtain a real transport because if the server supplies a password, it
 
1290
        # will be hidden from the base on the client side.
 
1291
        t = _mod_transport.get_transport_from_url(transport_server.get_url())
 
1292
        # Some transport servers effectively chroot the backing transport;
 
1293
        # others like SFTPServer don't - users of the transport can walk up the
 
1294
        # transport to read the entire backing transport. This wouldn't matter
 
1295
        # except that the workdir tests are given - and that they expect the
 
1296
        # server's url to point at - is one directory under the safety net. So
 
1297
        # Branch operations into the transport will attempt to walk up one
 
1298
        # directory. Chrooting all servers would avoid this but also mean that
 
1299
        # we wouldn't be testing directly against non-root urls. Alternatively
 
1300
        # getting the test framework to start the server with a backing server
 
1301
        # at the actual safety net directory would work too, but this then
 
1302
        # means that the self.get_url/self.get_transport methods would need
 
1303
        # to transform all their results. On balance its cleaner to handle it
 
1304
        # here, and permit a higher url when we have one of these transports.
 
1305
        if t.base.endswith('/work/'):
 
1306
            # we have safety net/test root/work
 
1307
            t = t.clone('../..')
 
1308
        elif isinstance(transport_server,
 
1309
                        test_server.SmartTCPServer_for_testing):
 
1310
            # The smart server adds a path similar to work, which is traversed
 
1311
            # up from by the client. But the server is chrooted - the actual
 
1312
            # backing transport is not escaped from, and VFS requests to the
 
1313
            # root will error (because they try to escape the chroot).
 
1314
            t2 = t.clone('..')
 
1315
            while t2.base != t.base:
 
1316
                t = t2
 
1317
                t2 = t.clone('..')
 
1318
        self.permit_url(t.base)
 
1319
 
 
1320
    def _track_transports(self):
 
1321
        """Install checks for transport usage."""
 
1322
        # TestCase has no safe place it can write to.
 
1323
        self._bzr_selftest_roots = []
 
1324
        # Currently the easiest way to be sure that nothing is going on is to
 
1325
        # hook into bzr dir opening. This leaves a small window of error for
 
1326
        # transport tests, but they are well known, and we can improve on this
 
1327
        # step.
 
1328
        controldir.ControlDir.hooks.install_named_hook("pre_open",
 
1329
            self._preopen_isolate_transport, "Check bzr directories are safe.")
788
1330
 
789
1331
    def _ndiff_strings(self, a, b):
790
1332
        """Return ndiff between two strings containing lines.
791
 
        
 
1333
 
792
1334
        A trailing newline is added if missing to make the strings
793
1335
        print properly."""
794
1336
        if b and b[-1] != '\n':
808
1350
        except UnicodeError, e:
809
1351
            # If we can't compare without getting a UnicodeError, then
810
1352
            # obviously they are different
811
 
            mutter('UnicodeError: %s', e)
 
1353
            trace.mutter('UnicodeError: %s', e)
812
1354
        if message:
813
1355
            message += '\n'
814
1356
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
815
1357
            % (message,
816
 
               pformat(a), pformat(b)))
 
1358
               pprint.pformat(a), pprint.pformat(b)))
817
1359
 
818
1360
    assertEquals = assertEqual
819
1361
 
820
1362
    def assertEqualDiff(self, a, b, message=None):
821
1363
        """Assert two texts are equal, if not raise an exception.
822
 
        
823
 
        This is intended for use with multi-line strings where it can 
 
1364
 
 
1365
        This is intended for use with multi-line strings where it can
824
1366
        be hard to find the differences by eye.
825
1367
        """
826
1368
        # TODO: perhaps override assertEquals to call this for strings?
828
1370
            return
829
1371
        if message is None:
830
1372
            message = "texts not equal:\n"
831
 
        raise AssertionError(message + 
832
 
                             self._ndiff_strings(a, b))      
833
 
        
 
1373
        if a + '\n' == b:
 
1374
            message = 'first string is missing a final newline.\n'
 
1375
        if a == b + '\n':
 
1376
            message = 'second string is missing a final newline.\n'
 
1377
        raise AssertionError(message +
 
1378
                             self._ndiff_strings(a, b))
 
1379
 
834
1380
    def assertEqualMode(self, mode, mode_test):
835
1381
        self.assertEqual(mode, mode_test,
836
1382
                         'mode mismatch %o != %o' % (mode, mode_test))
837
1383
 
 
1384
    def assertEqualStat(self, expected, actual):
 
1385
        """assert that expected and actual are the same stat result.
 
1386
 
 
1387
        :param expected: A stat result.
 
1388
        :param actual: A stat result.
 
1389
        :raises AssertionError: If the expected and actual stat values differ
 
1390
            other than by atime.
 
1391
        """
 
1392
        self.assertEqual(expected.st_size, actual.st_size,
 
1393
                         'st_size did not match')
 
1394
        self.assertEqual(expected.st_mtime, actual.st_mtime,
 
1395
                         'st_mtime did not match')
 
1396
        self.assertEqual(expected.st_ctime, actual.st_ctime,
 
1397
                         'st_ctime did not match')
 
1398
        if sys.platform == 'win32':
 
1399
            # On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
 
1400
            # is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
 
1401
            # odd. We just force it to always be 0 to avoid any problems.
 
1402
            self.assertEqual(0, expected.st_dev)
 
1403
            self.assertEqual(0, actual.st_dev)
 
1404
            self.assertEqual(0, expected.st_ino)
 
1405
            self.assertEqual(0, actual.st_ino)
 
1406
        else:
 
1407
            self.assertEqual(expected.st_dev, actual.st_dev,
 
1408
                             'st_dev did not match')
 
1409
            self.assertEqual(expected.st_ino, actual.st_ino,
 
1410
                             'st_ino did not match')
 
1411
        self.assertEqual(expected.st_mode, actual.st_mode,
 
1412
                         'st_mode did not match')
 
1413
 
 
1414
    def assertLength(self, length, obj_with_len):
 
1415
        """Assert that obj_with_len is of length length."""
 
1416
        if len(obj_with_len) != length:
 
1417
            self.fail("Incorrect length: wanted %d, got %d for %r" % (
 
1418
                length, len(obj_with_len), obj_with_len))
 
1419
 
 
1420
    def assertLogsError(self, exception_class, func, *args, **kwargs):
 
1421
        """Assert that `func(*args, **kwargs)` quietly logs a specific error.
 
1422
        """
 
1423
        captured = []
 
1424
        orig_log_exception_quietly = trace.log_exception_quietly
 
1425
        try:
 
1426
            def capture():
 
1427
                orig_log_exception_quietly()
 
1428
                captured.append(sys.exc_info()[1])
 
1429
            trace.log_exception_quietly = capture
 
1430
            func(*args, **kwargs)
 
1431
        finally:
 
1432
            trace.log_exception_quietly = orig_log_exception_quietly
 
1433
        self.assertLength(1, captured)
 
1434
        err = captured[0]
 
1435
        self.assertIsInstance(err, exception_class)
 
1436
        return err
 
1437
 
 
1438
    def assertPositive(self, val):
 
1439
        """Assert that val is greater than 0."""
 
1440
        self.assertTrue(val > 0, 'expected a positive value, but got %s' % val)
 
1441
 
 
1442
    def assertNegative(self, val):
 
1443
        """Assert that val is less than 0."""
 
1444
        self.assertTrue(val < 0, 'expected a negative value, but got %s' % val)
 
1445
 
838
1446
    def assertStartsWith(self, s, prefix):
839
1447
        if not s.startswith(prefix):
840
1448
            raise AssertionError('string %r does not start with %r' % (s, prefix))
844
1452
        if not s.endswith(suffix):
845
1453
            raise AssertionError('string %r does not end with %r' % (s, suffix))
846
1454
 
847
 
    def assertContainsRe(self, haystack, needle_re):
 
1455
    def assertContainsRe(self, haystack, needle_re, flags=0):
848
1456
        """Assert that a contains something matching a regular expression."""
849
 
        if not re.search(needle_re, haystack):
850
 
            raise AssertionError('pattern "%r" not found in "%r"'
851
 
                    % (needle_re, haystack))
 
1457
        if not re.search(needle_re, haystack, flags):
 
1458
            if '\n' in haystack or len(haystack) > 60:
 
1459
                # a long string, format it in a more readable way
 
1460
                raise AssertionError(
 
1461
                        'pattern "%s" not found in\n"""\\\n%s"""\n'
 
1462
                        % (needle_re, haystack))
 
1463
            else:
 
1464
                raise AssertionError('pattern "%s" not found in "%s"'
 
1465
                        % (needle_re, haystack))
852
1466
 
853
 
    def assertNotContainsRe(self, haystack, needle_re):
 
1467
    def assertNotContainsRe(self, haystack, needle_re, flags=0):
854
1468
        """Assert that a does not match a regular expression"""
855
 
        if re.search(needle_re, haystack):
 
1469
        if re.search(needle_re, haystack, flags):
856
1470
            raise AssertionError('pattern "%s" found in "%s"'
857
1471
                    % (needle_re, haystack))
858
1472
 
 
1473
    def assertContainsString(self, haystack, needle):
 
1474
        if haystack.find(needle) == -1:
 
1475
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
 
1476
 
 
1477
    def assertNotContainsString(self, haystack, needle):
 
1478
        if haystack.find(needle) != -1:
 
1479
            self.fail("string %r found in '''%s'''" % (needle, haystack))
 
1480
 
859
1481
    def assertSubset(self, sublist, superlist):
860
1482
        """Assert that every entry in sublist is present in superlist."""
861
 
        missing = []
862
 
        for entry in sublist:
863
 
            if entry not in superlist:
864
 
                missing.append(entry)
 
1483
        missing = set(sublist) - set(superlist)
865
1484
        if len(missing) > 0:
866
 
            raise AssertionError("value(s) %r not present in container %r" % 
 
1485
            raise AssertionError("value(s) %r not present in container %r" %
867
1486
                                 (missing, superlist))
868
1487
 
869
1488
    def assertListRaises(self, excClass, func, *args, **kwargs):
870
1489
        """Fail unless excClass is raised when the iterator from func is used.
871
 
        
 
1490
 
872
1491
        Many functions can return generators this makes sure
873
1492
        to wrap them in a list() call to make sure the whole generator
874
1493
        is run, and that the proper exception is raised.
875
1494
        """
876
1495
        try:
877
1496
            list(func(*args, **kwargs))
878
 
        except excClass:
879
 
            return
 
1497
        except excClass, e:
 
1498
            return e
880
1499
        else:
881
1500
            if getattr(excClass,'__name__', None) is not None:
882
1501
                excName = excClass.__name__
921
1540
                raise AssertionError("%r is %r." % (left, right))
922
1541
 
923
1542
    def assertTransportMode(self, transport, path, mode):
924
 
        """Fail if a path does not have mode mode.
925
 
        
 
1543
        """Fail if a path does not have mode "mode".
 
1544
 
926
1545
        If modes are not supported on this transport, the assertion is ignored.
927
1546
        """
928
1547
        if not transport._can_roundtrip_unix_modebits():
930
1549
        path_stat = transport.stat(path)
931
1550
        actual_mode = stat.S_IMODE(path_stat.st_mode)
932
1551
        self.assertEqual(mode, actual_mode,
933
 
            'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
934
 
 
935
 
    def assertIsInstance(self, obj, kls):
936
 
        """Fail if obj is not an instance of kls"""
 
1552
                         'mode of %r incorrect (%s != %s)'
 
1553
                         % (path, oct(mode), oct(actual_mode)))
 
1554
 
 
1555
    def assertIsSameRealPath(self, path1, path2):
 
1556
        """Fail if path1 and path2 points to different files"""
 
1557
        self.assertEqual(osutils.realpath(path1),
 
1558
                         osutils.realpath(path2),
 
1559
                         "apparent paths:\na = %s\nb = %s\n," % (path1, path2))
 
1560
 
 
1561
    def assertIsInstance(self, obj, kls, msg=None):
 
1562
        """Fail if obj is not an instance of kls
 
1563
        
 
1564
        :param msg: Supplementary message to show if the assertion fails.
 
1565
        """
937
1566
        if not isinstance(obj, kls):
938
 
            self.fail("%r is an instance of %s rather than %s" % (
939
 
                obj, obj.__class__, kls))
940
 
 
941
 
    def expectFailure(self, reason, assertion, *args, **kwargs):
942
 
        """Invoke a test, expecting it to fail for the given reason.
943
 
 
944
 
        This is for assertions that ought to succeed, but currently fail.
945
 
        (The failure is *expected* but not *wanted*.)  Please be very precise
946
 
        about the failure you're expecting.  If a new bug is introduced,
947
 
        AssertionError should be raised, not KnownFailure.
948
 
 
949
 
        Frequently, expectFailure should be followed by an opposite assertion.
950
 
        See example below.
951
 
 
952
 
        Intended to be used with a callable that raises AssertionError as the
953
 
        'assertion' parameter.  args and kwargs are passed to the 'assertion'.
954
 
 
955
 
        Raises KnownFailure if the test fails.  Raises AssertionError if the
956
 
        test succeeds.
957
 
 
958
 
        example usage::
959
 
 
960
 
          self.expectFailure('Math is broken', self.assertNotEqual, 54,
961
 
                             dynamic_val)
962
 
          self.assertEqual(42, dynamic_val)
963
 
 
964
 
          This means that a dynamic_val of 54 will cause the test to raise
965
 
          a KnownFailure.  Once math is fixed and the expectFailure is removed,
966
 
          only a dynamic_val of 42 will allow the test to pass.  Anything other
967
 
          than 54 or 42 will cause an AssertionError.
968
 
        """
 
1567
            m = "%r is an instance of %s rather than %s" % (
 
1568
                obj, obj.__class__, kls)
 
1569
            if msg:
 
1570
                m += ": " + msg
 
1571
            self.fail(m)
 
1572
 
 
1573
    def assertFileEqual(self, content, path):
 
1574
        """Fail if path does not contain 'content'."""
 
1575
        self.assertPathExists(path)
 
1576
        f = file(path, 'rb')
969
1577
        try:
970
 
            assertion(*args, **kwargs)
971
 
        except AssertionError:
972
 
            raise KnownFailure(reason)
973
 
        else:
974
 
            self.fail('Unexpected success.  Should have failed: %s' % reason)
975
 
 
976
 
    def _capture_warnings(self, a_callable, *args, **kwargs):
 
1578
            s = f.read()
 
1579
        finally:
 
1580
            f.close()
 
1581
        self.assertEqualDiff(content, s)
 
1582
 
 
1583
    def assertDocstring(self, expected_docstring, obj):
 
1584
        """Fail if obj does not have expected_docstring"""
 
1585
        if __doc__ is None:
 
1586
            # With -OO the docstring should be None instead
 
1587
            self.assertIs(obj.__doc__, None)
 
1588
        else:
 
1589
            self.assertEqual(expected_docstring, obj.__doc__)
 
1590
 
 
1591
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
 
1592
    def failUnlessExists(self, path):
 
1593
        return self.assertPathExists(path)
 
1594
 
 
1595
    def assertPathExists(self, path):
 
1596
        """Fail unless path or paths, which may be abs or relative, exist."""
 
1597
        if not isinstance(path, basestring):
 
1598
            for p in path:
 
1599
                self.assertPathExists(p)
 
1600
        else:
 
1601
            self.assertTrue(osutils.lexists(path),
 
1602
                path + " does not exist")
 
1603
 
 
1604
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
 
1605
    def failIfExists(self, path):
 
1606
        return self.assertPathDoesNotExist(path)
 
1607
 
 
1608
    def assertPathDoesNotExist(self, path):
 
1609
        """Fail if path or paths, which may be abs or relative, exist."""
 
1610
        if not isinstance(path, basestring):
 
1611
            for p in path:
 
1612
                self.assertPathDoesNotExist(p)
 
1613
        else:
 
1614
            self.assertFalse(osutils.lexists(path),
 
1615
                path + " exists")
 
1616
 
 
1617
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
977
1618
        """A helper for callDeprecated and applyDeprecated.
978
1619
 
979
1620
        :param a_callable: A callable to call.
1002
1643
        Note that this only captures warnings raised by symbol_versioning.warn,
1003
1644
        not other callers that go direct to the warning module.
1004
1645
 
 
1646
        To test that a deprecated method raises an error, do something like
 
1647
        this (remember that both assertRaises and applyDeprecated delays *args
 
1648
        and **kwargs passing)::
 
1649
 
 
1650
            self.assertRaises(errors.ReservedId,
 
1651
                self.applyDeprecated,
 
1652
                deprecated_in((1, 5, 0)),
 
1653
                br.append_revision,
 
1654
                'current:')
 
1655
 
1005
1656
        :param deprecation_format: The deprecation format that the callable
1006
1657
            should have been deprecated with. This is the same type as the
1007
1658
            parameter to deprecated_method/deprecated_function. If the
1014
1665
        :param kwargs: The keyword arguments for the callable
1015
1666
        :return: The result of a_callable(``*args``, ``**kwargs``)
1016
1667
        """
1017
 
        call_warnings, result = self._capture_warnings(a_callable,
 
1668
        call_warnings, result = self._capture_deprecation_warnings(a_callable,
1018
1669
            *args, **kwargs)
1019
1670
        expected_first_warning = symbol_versioning.deprecation_string(
1020
1671
            a_callable, deprecation_format)
1024
1675
        self.assertEqual(expected_first_warning, call_warnings[0])
1025
1676
        return result
1026
1677
 
 
1678
    def callCatchWarnings(self, fn, *args, **kw):
 
1679
        """Call a callable that raises python warnings.
 
1680
 
 
1681
        The caller's responsible for examining the returned warnings.
 
1682
 
 
1683
        If the callable raises an exception, the exception is not
 
1684
        caught and propagates up to the caller.  In that case, the list
 
1685
        of warnings is not available.
 
1686
 
 
1687
        :returns: ([warning_object, ...], fn_result)
 
1688
        """
 
1689
        # XXX: This is not perfect, because it completely overrides the
 
1690
        # warnings filters, and some code may depend on suppressing particular
 
1691
        # warnings.  It's the easiest way to insulate ourselves from -Werror,
 
1692
        # though.  -- Andrew, 20071062
 
1693
        wlist = []
 
1694
        def _catcher(message, category, filename, lineno, file=None, line=None):
 
1695
            # despite the name, 'message' is normally(?) a Warning subclass
 
1696
            # instance
 
1697
            wlist.append(message)
 
1698
        saved_showwarning = warnings.showwarning
 
1699
        saved_filters = warnings.filters
 
1700
        try:
 
1701
            warnings.showwarning = _catcher
 
1702
            warnings.filters = []
 
1703
            result = fn(*args, **kw)
 
1704
        finally:
 
1705
            warnings.showwarning = saved_showwarning
 
1706
            warnings.filters = saved_filters
 
1707
        return wlist, result
 
1708
 
1027
1709
    def callDeprecated(self, expected, callable, *args, **kwargs):
1028
1710
        """Assert that a callable is deprecated in a particular way.
1029
1711
 
1030
 
        This is a very precise test for unusual requirements. The 
 
1712
        This is a very precise test for unusual requirements. The
1031
1713
        applyDeprecated helper function is probably more suited for most tests
1032
1714
        as it allows you to simply specify the deprecation format being used
1033
1715
        and will ensure that that is issued for the function being called.
1034
1716
 
1035
1717
        Note that this only captures warnings raised by symbol_versioning.warn,
1036
 
        not other callers that go direct to the warning module.
 
1718
        not other callers that go direct to the warning module.  To catch
 
1719
        general warnings, use callCatchWarnings.
1037
1720
 
1038
1721
        :param expected: a list of the deprecation warnings expected, in order
1039
1722
        :param callable: The callable to call
1040
1723
        :param args: The positional arguments for the callable
1041
1724
        :param kwargs: The keyword arguments for the callable
1042
1725
        """
1043
 
        call_warnings, result = self._capture_warnings(callable,
 
1726
        call_warnings, result = self._capture_deprecation_warnings(callable,
1044
1727
            *args, **kwargs)
1045
1728
        self.assertEqual(expected, call_warnings)
1046
1729
        return result
1047
1730
 
1048
1731
    def _startLogFile(self):
1049
 
        """Send bzr and test log messages to a temporary file.
1050
 
 
1051
 
        The file is removed as the test is torn down.
1052
 
        """
1053
 
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
1054
 
        self._log_file = os.fdopen(fileno, 'w+')
1055
 
        self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
1056
 
        self._log_file_name = name
 
1732
        """Setup a in-memory target for bzr and testcase log messages"""
 
1733
        pseudo_log_file = StringIO()
 
1734
        def _get_log_contents_for_weird_testtools_api():
 
1735
            return [pseudo_log_file.getvalue().decode(
 
1736
                "utf-8", "replace").encode("utf-8")]
 
1737
        self.addDetail("log", content.Content(content.ContentType("text",
 
1738
            "plain", {"charset": "utf8"}),
 
1739
            _get_log_contents_for_weird_testtools_api))
 
1740
        self._log_file = pseudo_log_file
 
1741
        self._log_memento = trace.push_log_file(self._log_file)
1057
1742
        self.addCleanup(self._finishLogFile)
1058
1743
 
1059
1744
    def _finishLogFile(self):
1060
 
        """Finished with the log file.
1061
 
 
1062
 
        Close the file and delete it, unless setKeepLogfile was called.
1063
 
        """
1064
 
        if self._log_file is None:
1065
 
            return
1066
 
        bzrlib.trace.disable_test_log(self._log_nonce)
1067
 
        self._log_file.close()
1068
 
        self._log_file = None
1069
 
        if not self._keep_log_file:
1070
 
            os.remove(self._log_file_name)
1071
 
            self._log_file_name = None
1072
 
 
1073
 
    def setKeepLogfile(self):
1074
 
        """Make the logfile not be deleted when _finishLogFile is called."""
1075
 
        self._keep_log_file = True
1076
 
 
1077
 
    def addCleanup(self, callable):
1078
 
        """Arrange to run a callable when this case is torn down.
1079
 
 
1080
 
        Callables are run in the reverse of the order they are registered, 
1081
 
        ie last-in first-out.
1082
 
        """
1083
 
        if callable in self._cleanups:
1084
 
            raise ValueError("cleanup function %r already registered on %s" 
1085
 
                    % (callable, self))
1086
 
        self._cleanups.append(callable)
 
1745
        """Flush and dereference the in-memory log for this testcase"""
 
1746
        if trace._trace_file:
 
1747
            # flush the log file, to get all content
 
1748
            trace._trace_file.flush()
 
1749
        trace.pop_log_file(self._log_memento)
 
1750
        # The logging module now tracks references for cleanup so discard ours
 
1751
        del self._log_memento
 
1752
 
 
1753
    def thisFailsStrictLockCheck(self):
 
1754
        """It is known that this test would fail with -Dstrict_locks.
 
1755
 
 
1756
        By default, all tests are run with strict lock checking unless
 
1757
        -Edisable_lock_checks is supplied. However there are some tests which
 
1758
        we know fail strict locks at this point that have not been fixed.
 
1759
        They should call this function to disable the strict checking.
 
1760
 
 
1761
        This should be used sparingly, it is much better to fix the locking
 
1762
        issues rather than papering over the problem by calling this function.
 
1763
        """
 
1764
        debug.debug_flags.discard('strict_locks')
 
1765
 
 
1766
    def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
 
1767
        """Overrides an object attribute restoring it after the test.
 
1768
 
 
1769
        :note: This should be used with discretion; you should think about
 
1770
        whether it's better to make the code testable without monkey-patching.
 
1771
 
 
1772
        :param obj: The object that will be mutated.
 
1773
 
 
1774
        :param attr_name: The attribute name we want to preserve/override in
 
1775
            the object.
 
1776
 
 
1777
        :param new: The optional value we want to set the attribute to.
 
1778
 
 
1779
        :returns: The actual attr value.
 
1780
        """
 
1781
        value = getattr(obj, attr_name)
 
1782
        # The actual value is captured by the call below
 
1783
        self.addCleanup(setattr, obj, attr_name, value)
 
1784
        if new is not _unitialized_attr:
 
1785
            setattr(obj, attr_name, new)
 
1786
        return value
 
1787
 
 
1788
    def overrideEnv(self, name, new):
 
1789
        """Set an environment variable, and reset it after the test.
 
1790
 
 
1791
        :param name: The environment variable name.
 
1792
 
 
1793
        :param new: The value to set the variable to. If None, the 
 
1794
            variable is deleted from the environment.
 
1795
 
 
1796
        :returns: The actual variable value.
 
1797
        """
 
1798
        value = osutils.set_or_unset_env(name, new)
 
1799
        self.addCleanup(osutils.set_or_unset_env, name, value)
 
1800
        return value
 
1801
 
 
1802
    def recordCalls(self, obj, attr_name):
 
1803
        """Monkeypatch in a wrapper that will record calls.
 
1804
 
 
1805
        The monkeypatch is automatically removed when the test concludes.
 
1806
 
 
1807
        :param obj: The namespace holding the reference to be replaced;
 
1808
            typically a module, class, or object.
 
1809
        :param attr_name: A string for the name of the attribute to 
 
1810
            patch.
 
1811
        :returns: A list that will be extended with one item every time the
 
1812
            function is called, with a tuple of (args, kwargs).
 
1813
        """
 
1814
        calls = []
 
1815
 
 
1816
        def decorator(*args, **kwargs):
 
1817
            calls.append((args, kwargs))
 
1818
            return orig(*args, **kwargs)
 
1819
        orig = self.overrideAttr(obj, attr_name, decorator)
 
1820
        return calls
1087
1821
 
1088
1822
    def _cleanEnvironment(self):
1089
 
        new_env = {
1090
 
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1091
 
            'HOME': os.getcwd(),
1092
 
            'APPDATA': None,  # bzr now use Win32 API and don't rely on APPDATA
1093
 
            'BZR_EMAIL': None,
1094
 
            'BZREMAIL': None, # may still be present in the environment
1095
 
            'EMAIL': None,
1096
 
            'BZR_PROGRESS_BAR': None,
1097
 
            # Proxies
1098
 
            'http_proxy': None,
1099
 
            'HTTP_PROXY': None,
1100
 
            'https_proxy': None,
1101
 
            'HTTPS_PROXY': None,
1102
 
            'no_proxy': None,
1103
 
            'NO_PROXY': None,
1104
 
            'all_proxy': None,
1105
 
            'ALL_PROXY': None,
1106
 
            # Nobody cares about these ones AFAIK. So far at
1107
 
            # least. If you do (care), please update this comment
1108
 
            # -- vila 20061212
1109
 
            'ftp_proxy': None,
1110
 
            'FTP_PROXY': None,
1111
 
            'BZR_REMOTE_PATH': None,
1112
 
        }
1113
 
        self.__old_env = {}
1114
 
        self.addCleanup(self._restoreEnvironment)
1115
 
        for name, value in new_env.iteritems():
1116
 
            self._captureVar(name, value)
1117
 
 
1118
 
    def _captureVar(self, name, newvalue):
1119
 
        """Set an environment variable, and reset it when finished."""
1120
 
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1121
 
 
1122
 
    def _restore_debug_flags(self):
1123
 
        debug.debug_flags.clear()
1124
 
        debug.debug_flags.update(self._preserved_debug_flags)
1125
 
 
1126
 
    def _restoreEnvironment(self):
1127
 
        for name, value in self.__old_env.iteritems():
1128
 
            osutils.set_or_unset_env(name, value)
 
1823
        for name, value in isolated_environ.iteritems():
 
1824
            self.overrideEnv(name, value)
1129
1825
 
1130
1826
    def _restoreHooks(self):
1131
 
        for klass, hooks in self._preserved_hooks.items():
1132
 
            setattr(klass, 'hooks', hooks)
 
1827
        for klass, (name, hooks) in self._preserved_hooks.items():
 
1828
            setattr(klass, name, hooks)
 
1829
        self._preserved_hooks.clear()
 
1830
        bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
 
1831
        self._preserved_lazy_hooks.clear()
1133
1832
 
1134
1833
    def knownFailure(self, reason):
1135
 
        """This test has failed for some known reason."""
1136
 
        raise KnownFailure(reason)
1137
 
 
1138
 
    def run(self, result=None):
1139
 
        if result is None: result = self.defaultTestResult()
1140
 
        for feature in getattr(self, '_test_needs_features', []):
1141
 
            if not feature.available():
1142
 
                result.startTest(self)
1143
 
                if getattr(result, 'addNotSupported', None):
1144
 
                    result.addNotSupported(self, feature)
1145
 
                else:
1146
 
                    result.addSuccess(self)
1147
 
                result.stopTest(self)
1148
 
                return
1149
 
        return unittest.TestCase.run(self, result)
1150
 
 
1151
 
    def tearDown(self):
1152
 
        self._runCleanups()
1153
 
        unittest.TestCase.tearDown(self)
 
1834
        """Declare that this test fails for a known reason
 
1835
 
 
1836
        Tests that are known to fail should generally be using expectedFailure
 
1837
        with an appropriate reverse assertion if a change could cause the test
 
1838
        to start passing. Conversely if the test has no immediate prospect of
 
1839
        succeeding then using skip is more suitable.
 
1840
 
 
1841
        When this method is called while an exception is being handled, that
 
1842
        traceback will be used, otherwise a new exception will be thrown to
 
1843
        provide one but won't be reported.
 
1844
        """
 
1845
        self._add_reason(reason)
 
1846
        try:
 
1847
            exc_info = sys.exc_info()
 
1848
            if exc_info != (None, None, None):
 
1849
                self._report_traceback(exc_info)
 
1850
            else:
 
1851
                try:
 
1852
                    raise self.failureException(reason)
 
1853
                except self.failureException:
 
1854
                    exc_info = sys.exc_info()
 
1855
            # GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
 
1856
            raise testtools.testcase._ExpectedFailure(exc_info)
 
1857
        finally:
 
1858
            del exc_info
 
1859
 
 
1860
    def _suppress_log(self):
 
1861
        """Remove the log info from details."""
 
1862
        self.discardDetail('log')
 
1863
 
 
1864
    def _do_skip(self, result, reason):
 
1865
        self._suppress_log()
 
1866
        addSkip = getattr(result, 'addSkip', None)
 
1867
        if not callable(addSkip):
 
1868
            result.addSuccess(result)
 
1869
        else:
 
1870
            addSkip(self, reason)
 
1871
 
 
1872
    @staticmethod
 
1873
    def _do_known_failure(self, result, e):
 
1874
        self._suppress_log()
 
1875
        err = sys.exc_info()
 
1876
        addExpectedFailure = getattr(result, 'addExpectedFailure', None)
 
1877
        if addExpectedFailure is not None:
 
1878
            addExpectedFailure(self, err)
 
1879
        else:
 
1880
            result.addSuccess(self)
 
1881
 
 
1882
    @staticmethod
 
1883
    def _do_not_applicable(self, result, e):
 
1884
        if not e.args:
 
1885
            reason = 'No reason given'
 
1886
        else:
 
1887
            reason = e.args[0]
 
1888
        self._suppress_log ()
 
1889
        addNotApplicable = getattr(result, 'addNotApplicable', None)
 
1890
        if addNotApplicable is not None:
 
1891
            result.addNotApplicable(self, reason)
 
1892
        else:
 
1893
            self._do_skip(result, reason)
 
1894
 
 
1895
    @staticmethod
 
1896
    def _report_skip(self, result, err):
 
1897
        """Override the default _report_skip.
 
1898
 
 
1899
        We want to strip the 'log' detail. If we waint until _do_skip, it has
 
1900
        already been formatted into the 'reason' string, and we can't pull it
 
1901
        out again.
 
1902
        """
 
1903
        self._suppress_log()
 
1904
        super(TestCase, self)._report_skip(self, result, err)
 
1905
 
 
1906
    @staticmethod
 
1907
    def _report_expected_failure(self, result, err):
 
1908
        """Strip the log.
 
1909
 
 
1910
        See _report_skip for motivation.
 
1911
        """
 
1912
        self._suppress_log()
 
1913
        super(TestCase, self)._report_expected_failure(self, result, err)
 
1914
 
 
1915
    @staticmethod
 
1916
    def _do_unsupported_or_skip(self, result, e):
 
1917
        reason = e.args[0]
 
1918
        self._suppress_log()
 
1919
        addNotSupported = getattr(result, 'addNotSupported', None)
 
1920
        if addNotSupported is not None:
 
1921
            result.addNotSupported(self, reason)
 
1922
        else:
 
1923
            self._do_skip(result, reason)
1154
1924
 
1155
1925
    def time(self, callable, *args, **kwargs):
1156
1926
        """Run callable and accrue the time it takes to the benchmark time.
1157
 
        
 
1927
 
1158
1928
        If lsprofiling is enabled (i.e. by --lsprof-time to bzr selftest) then
1159
1929
        this will cause lsprofile statistics to be gathered and stored in
1160
1930
        self._benchcalls.
1161
1931
        """
1162
1932
        if self._benchtime is None:
 
1933
            self.addDetail('benchtime', content.Content(content.ContentType(
 
1934
                "text", "plain"), lambda:[str(self._benchtime)]))
1163
1935
            self._benchtime = 0
1164
1936
        start = time.time()
1165
1937
        try:
1174
1946
        finally:
1175
1947
            self._benchtime += time.time() - start
1176
1948
 
1177
 
    def _runCleanups(self):
1178
 
        """Run registered cleanup functions. 
1179
 
 
1180
 
        This should only be called from TestCase.tearDown.
1181
 
        """
1182
 
        # TODO: Perhaps this should keep running cleanups even if 
1183
 
        # one of them fails?
1184
 
 
1185
 
        # Actually pop the cleanups from the list so tearDown running
1186
 
        # twice is safe (this happens for skipped tests).
1187
 
        while self._cleanups:
1188
 
            self._cleanups.pop()()
1189
 
 
1190
1949
    def log(self, *args):
1191
 
        mutter(*args)
1192
 
 
1193
 
    def _get_log(self, keep_log_file=False):
1194
 
        """Return as a string the log for this test. If the file is still
1195
 
        on disk and keep_log_file=False, delete the log file and store the
1196
 
        content in self._log_contents."""
1197
 
        # flush the log file, to get all content
1198
 
        import bzrlib.trace
1199
 
        bzrlib.trace._trace_file.flush()
1200
 
        if self._log_contents:
1201
 
            return self._log_contents
1202
 
        if self._log_file_name is not None:
1203
 
            logfile = open(self._log_file_name)
1204
 
            try:
1205
 
                log_contents = logfile.read()
1206
 
            finally:
1207
 
                logfile.close()
1208
 
            if not keep_log_file:
1209
 
                self._log_contents = log_contents
1210
 
                try:
1211
 
                    os.remove(self._log_file_name)
1212
 
                except OSError, e:
1213
 
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
1214
 
                        print >>sys.stderr, ('Unable to delete log file '
1215
 
                                             ' %r' % self._log_file_name)
1216
 
                    else:
1217
 
                        raise
1218
 
            return log_contents
1219
 
        else:
1220
 
            return "DELETED log file to reduce memory footprint"
1221
 
 
1222
 
    @deprecated_method(zero_eighteen)
1223
 
    def capture(self, cmd, retcode=0):
1224
 
        """Shortcut that splits cmd into words, runs, and returns stdout"""
1225
 
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
 
1950
        trace.mutter(*args)
 
1951
 
 
1952
    def get_log(self):
 
1953
        """Get a unicode string containing the log from bzrlib.trace.
 
1954
 
 
1955
        Undecodable characters are replaced.
 
1956
        """
 
1957
        return u"".join(self.getDetails()['log'].iter_text())
1226
1958
 
1227
1959
    def requireFeature(self, feature):
1228
1960
        """This test requires a specific feature is available.
1232
1964
        if not feature.available():
1233
1965
            raise UnavailableFeature(feature)
1234
1966
 
1235
 
    @deprecated_method(zero_eighteen)
1236
 
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
1237
 
                         working_dir=None):
1238
 
        """Invoke bzr and return (stdout, stderr).
1239
 
 
1240
 
        Don't call this method, just use run_bzr() which is equivalent.
1241
 
 
1242
 
        :param argv: Arguments to invoke bzr.  This may be either a 
1243
 
            single string, in which case it is split by shlex into words, 
1244
 
            or a list of arguments.
1245
 
        :param retcode: Expected return code, or None for don't-care.
1246
 
        :param encoding: Encoding for sys.stdout and sys.stderr
1247
 
        :param stdin: A string to be used as stdin for the command.
1248
 
        :param working_dir: Change to this directory before running
1249
 
        """
1250
 
        return self._run_bzr_autosplit(argv, retcode=retcode,
1251
 
                encoding=encoding, stdin=stdin, working_dir=working_dir,
1252
 
                )
1253
 
 
1254
1967
    def _run_bzr_autosplit(self, args, retcode, encoding, stdin,
1255
1968
            working_dir):
1256
1969
        """Run bazaar command line, splitting up a string command line."""
1257
1970
        if isinstance(args, basestring):
1258
 
            args = list(shlex.split(args))
 
1971
            # shlex don't understand unicode strings,
 
1972
            # so args should be plain string (bialix 20070906)
 
1973
            args = list(shlex.split(str(args)))
1259
1974
        return self._run_bzr_core(args, retcode=retcode,
1260
1975
                encoding=encoding, stdin=stdin, working_dir=working_dir,
1261
1976
                )
1262
1977
 
1263
1978
    def _run_bzr_core(self, args, retcode, encoding, stdin,
1264
1979
            working_dir):
 
1980
        # Clear chk_map page cache, because the contents are likely to mask
 
1981
        # locking errors.
 
1982
        chk_map.clear_cache()
1265
1983
        if encoding is None:
1266
 
            encoding = bzrlib.user_encoding
 
1984
            encoding = osutils.get_user_encoding()
1267
1985
        stdout = StringIOWrapper()
1268
1986
        stderr = StringIOWrapper()
1269
1987
        stdout.encoding = encoding
1271
1989
 
1272
1990
        self.log('run bzr: %r', args)
1273
1991
        # FIXME: don't call into logging here
1274
 
        handler = logging.StreamHandler(stderr)
1275
 
        handler.setLevel(logging.INFO)
 
1992
        handler = trace.EncodedStreamHandler(stderr, errors="replace",
 
1993
            level=logging.INFO)
1276
1994
        logger = logging.getLogger('')
1277
1995
        logger.addHandler(handler)
1278
1996
        old_ui_factory = ui.ui_factory
1284
2002
            os.chdir(working_dir)
1285
2003
 
1286
2004
        try:
1287
 
            result = self.apply_redirected(ui.ui_factory.stdin,
1288
 
                stdout, stderr,
1289
 
                bzrlib.commands.run_bzr_catch_errors,
1290
 
                args)
 
2005
            try:
 
2006
                result = self.apply_redirected(
 
2007
                    ui.ui_factory.stdin,
 
2008
                    stdout, stderr,
 
2009
                    _mod_commands.run_bzr_catch_user_errors,
 
2010
                    args)
 
2011
            except KeyboardInterrupt:
 
2012
                # Reraise KeyboardInterrupt with contents of redirected stdout
 
2013
                # and stderr as arguments, for tests which are interested in
 
2014
                # stdout and stderr and are expecting the exception.
 
2015
                out = stdout.getvalue()
 
2016
                err = stderr.getvalue()
 
2017
                if out:
 
2018
                    self.log('output:\n%r', out)
 
2019
                if err:
 
2020
                    self.log('errors:\n%r', err)
 
2021
                raise KeyboardInterrupt(out, err)
1291
2022
        finally:
1292
2023
            logger.removeHandler(handler)
1293
2024
            ui.ui_factory = old_ui_factory
1303
2034
        if retcode is not None:
1304
2035
            self.assertEquals(retcode, result,
1305
2036
                              message='Unexpected return code')
1306
 
        return out, err
 
2037
        return result, out, err
1307
2038
 
1308
 
    def run_bzr(self, *args, **kwargs):
 
2039
    def run_bzr(self, args, retcode=0, encoding=None, stdin=None,
 
2040
                working_dir=None, error_regexes=[], output_encoding=None):
1309
2041
        """Invoke bzr, as if it were run from the command line.
1310
2042
 
1311
2043
        The argument list should not include the bzr program name - the
1313
2045
        passed in three ways:
1314
2046
 
1315
2047
        1- A list of strings, eg ["commit", "a"].  This is recommended
1316
 
        when the command contains whitespace or metacharacters, or 
 
2048
        when the command contains whitespace or metacharacters, or
1317
2049
        is built up at run time.
1318
2050
 
1319
 
        2- A single string, eg "add a".  This is the most convenient 
 
2051
        2- A single string, eg "add a".  This is the most convenient
1320
2052
        for hardcoded commands.
1321
2053
 
1322
 
        3- Several varargs parameters, eg run_bzr("add", "a").  
1323
 
        This is not recommended for new code.
1324
 
 
1325
2054
        This runs bzr through the interface that catches and reports
1326
2055
        errors, and with logging set to something approximating the
1327
2056
        default, so that error reporting can be checked.
1340
2069
        :keyword error_regexes: A list of expected error messages.  If
1341
2070
            specified they must be seen in the error output of the command.
1342
2071
        """
1343
 
        retcode = kwargs.pop('retcode', 0)
1344
 
        encoding = kwargs.pop('encoding', None)
1345
 
        stdin = kwargs.pop('stdin', None)
1346
 
        working_dir = kwargs.pop('working_dir', None)
1347
 
        error_regexes = kwargs.pop('error_regexes', [])
1348
 
 
1349
 
        if len(args) == 1:
1350
 
            if isinstance(args[0], (list, basestring)):
1351
 
                args = args[0]
1352
 
        else:
1353
 
            ## symbol_versioning.warn(zero_eighteen % "passing varargs to run_bzr",
1354
 
            ##         DeprecationWarning, stacklevel=2)
1355
 
            # not done yet, because too many tests would need to  be updated -
1356
 
            # but please don't do this in new code.  -- mbp 20070626
1357
 
            pass
1358
 
 
1359
 
        out, err = self._run_bzr_autosplit(args=args,
 
2072
        retcode, out, err = self._run_bzr_autosplit(
 
2073
            args=args,
1360
2074
            retcode=retcode,
1361
 
            encoding=encoding, stdin=stdin, working_dir=working_dir,
 
2075
            encoding=encoding,
 
2076
            stdin=stdin,
 
2077
            working_dir=working_dir,
1362
2078
            )
1363
 
 
 
2079
        self.assertIsInstance(error_regexes, (list, tuple))
1364
2080
        for regex in error_regexes:
1365
2081
            self.assertContainsRe(err, regex)
1366
2082
        return out, err
1367
2083
 
1368
 
    def run_bzr_decode(self, *args, **kwargs):
1369
 
        if 'encoding' in kwargs:
1370
 
            encoding = kwargs['encoding']
1371
 
        else:
1372
 
            encoding = bzrlib.user_encoding
1373
 
        return self.run_bzr(*args, **kwargs)[0].decode(encoding)
1374
 
 
1375
2084
    def run_bzr_error(self, error_regexes, *args, **kwargs):
1376
2085
        """Run bzr, and check that stderr contains the supplied regexes
1377
2086
 
1382
2091
        :param kwargs: Keyword arguments which are interpreted by run_bzr
1383
2092
            This function changes the default value of retcode to be 3,
1384
2093
            since in most cases this is run when you expect bzr to fail.
 
2094
 
1385
2095
        :return: (out, err) The actual output of running the command (in case
1386
2096
            you want to do more inspection)
1387
2097
 
1389
2099
 
1390
2100
            # Make sure that commit is failing because there is nothing to do
1391
2101
            self.run_bzr_error(['no changes to commit'],
1392
 
                               'commit', '-m', 'my commit comment')
 
2102
                               ['commit', '-m', 'my commit comment'])
1393
2103
            # Make sure --strict is handling an unknown file, rather than
1394
2104
            # giving us the 'nothing to do' error
1395
2105
            self.build_tree(['unknown'])
1396
2106
            self.run_bzr_error(['Commit refused because there are unknown files'],
1397
 
                               'commit', '--strict', '-m', 'my commit comment')
 
2107
                               ['commit', --strict', '-m', 'my commit comment'])
1398
2108
        """
1399
2109
        kwargs.setdefault('retcode', 3)
1400
 
        out, err = self.run_bzr(error_regexes=error_regexes, *args, **kwargs)
 
2110
        kwargs['error_regexes'] = error_regexes
 
2111
        out, err = self.run_bzr(*args, **kwargs)
1401
2112
        return out, err
1402
2113
 
1403
2114
    def run_bzr_subprocess(self, *args, **kwargs):
1404
2115
        """Run bzr in a subprocess for testing.
1405
2116
 
1406
 
        This starts a new Python interpreter and runs bzr in there. 
 
2117
        This starts a new Python interpreter and runs bzr in there.
1407
2118
        This should only be used for tests that have a justifiable need for
1408
2119
        this isolation: e.g. they are testing startup time, or signal
1409
 
        handling, or early startup code, etc.  Subprocess code can't be 
 
2120
        handling, or early startup code, etc.  Subprocess code can't be
1410
2121
        profiled or debugged so easily.
1411
2122
 
1412
2123
        :keyword retcode: The status code that is expected.  Defaults to 0.  If
1424
2135
        env_changes = kwargs.get('env_changes', {})
1425
2136
        working_dir = kwargs.get('working_dir', None)
1426
2137
        allow_plugins = kwargs.get('allow_plugins', False)
 
2138
        if len(args) == 1:
 
2139
            if isinstance(args[0], list):
 
2140
                args = args[0]
 
2141
            elif isinstance(args[0], basestring):
 
2142
                args = list(shlex.split(args[0]))
 
2143
        else:
 
2144
            raise ValueError("passing varargs to run_bzr_subprocess")
1427
2145
        process = self.start_bzr_subprocess(args, env_changes=env_changes,
1428
2146
                                            working_dir=working_dir,
1429
2147
                                            allow_plugins=allow_plugins)
1436
2154
    def start_bzr_subprocess(self, process_args, env_changes=None,
1437
2155
                             skip_if_plan_to_signal=False,
1438
2156
                             working_dir=None,
1439
 
                             allow_plugins=False):
 
2157
                             allow_plugins=False, stderr=subprocess.PIPE):
1440
2158
        """Start bzr in a subprocess for testing.
1441
2159
 
1442
2160
        This starts a new Python interpreter and runs bzr in there.
1451
2169
            variables. A value of None will unset the env variable.
1452
2170
            The values must be strings. The change will only occur in the
1453
2171
            child, so you don't need to fix the environment after running.
1454
 
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
1455
 
            is not available.
 
2172
        :param skip_if_plan_to_signal: raise TestSkipped when true and system
 
2173
            doesn't support signalling subprocesses.
1456
2174
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
 
2175
        :param stderr: file to use for the subprocess's stderr.  Valid values
 
2176
            are those valid for the stderr argument of `subprocess.Popen`.
 
2177
            Default value is ``subprocess.PIPE``.
1457
2178
 
1458
2179
        :returns: Popen object for the started process.
1459
2180
        """
1460
2181
        if skip_if_plan_to_signal:
1461
 
            if not getattr(os, 'kill', None):
1462
 
                raise TestSkipped("os.kill not available.")
 
2182
            if os.name != "posix":
 
2183
                raise TestSkipped("Sending signals not supported")
1463
2184
 
1464
2185
        if env_changes is None:
1465
2186
            env_changes = {}
 
2187
        # Because $HOME is set to a tempdir for the context of a test, modules
 
2188
        # installed in the user dir will not be found unless $PYTHONUSERBASE
 
2189
        # gets set to the computed directory of this parent process.
 
2190
        if site.USER_BASE is not None:
 
2191
            env_changes["PYTHONUSERBASE"] = site.USER_BASE
1466
2192
        old_env = {}
1467
2193
 
1468
2194
        def cleanup_environment():
1485
2211
            # so we will avoid using it on all platforms, just to
1486
2212
            # make sure the code path is used, and we don't break on win32
1487
2213
            cleanup_environment()
1488
 
            command = [sys.executable, bzr_path]
 
2214
            # Include the subprocess's log file in the test details, in case
 
2215
            # the test fails due to an error in the subprocess.
 
2216
            self._add_subprocess_log(trace._get_bzr_log_filename())
 
2217
            command = [sys.executable]
 
2218
            # frozen executables don't need the path to bzr
 
2219
            if getattr(sys, "frozen", None) is None:
 
2220
                command.append(bzr_path)
1489
2221
            if not allow_plugins:
1490
2222
                command.append('--no-plugins')
1491
2223
            command.extend(process_args)
1492
 
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
 
2224
            process = self._popen(command, stdin=subprocess.PIPE,
 
2225
                                  stdout=subprocess.PIPE,
 
2226
                                  stderr=stderr)
1493
2227
        finally:
1494
2228
            restore_environment()
1495
2229
            if cwd is not None:
1497
2231
 
1498
2232
        return process
1499
2233
 
 
2234
    def _add_subprocess_log(self, log_file_path):
 
2235
        if len(self._log_files) == 0:
 
2236
            # Register an addCleanup func.  We do this on the first call to
 
2237
            # _add_subprocess_log rather than in TestCase.setUp so that this
 
2238
            # addCleanup is registered after any cleanups for tempdirs that
 
2239
            # subclasses might create, which will probably remove the log file
 
2240
            # we want to read.
 
2241
            self.addCleanup(self._subprocess_log_cleanup)
 
2242
        # self._log_files is a set, so if a log file is reused we won't grab it
 
2243
        # twice.
 
2244
        self._log_files.add(log_file_path)
 
2245
 
 
2246
    def _subprocess_log_cleanup(self):
 
2247
        for count, log_file_path in enumerate(self._log_files):
 
2248
            # We use buffer_now=True to avoid holding the file open beyond
 
2249
            # the life of this function, which might interfere with e.g.
 
2250
            # cleaning tempdirs on Windows.
 
2251
            # XXX: Testtools 0.9.5 doesn't have the content_from_file helper
 
2252
            #detail_content = content.content_from_file(
 
2253
            #    log_file_path, buffer_now=True)
 
2254
            with open(log_file_path, 'rb') as log_file:
 
2255
                log_file_bytes = log_file.read()
 
2256
            detail_content = content.Content(content.ContentType("text",
 
2257
                "plain", {"charset": "utf8"}), lambda: [log_file_bytes])
 
2258
            self.addDetail("start_bzr_subprocess-log-%d" % (count,),
 
2259
                detail_content)
 
2260
 
1500
2261
    def _popen(self, *args, **kwargs):
1501
2262
        """Place a call to Popen.
1502
2263
 
1503
2264
        Allows tests to override this method to intercept the calls made to
1504
2265
        Popen for introspection.
1505
2266
        """
1506
 
        return Popen(*args, **kwargs)
 
2267
        return subprocess.Popen(*args, **kwargs)
 
2268
 
 
2269
    def get_source_path(self):
 
2270
        """Return the path of the directory containing bzrlib."""
 
2271
        return os.path.dirname(os.path.dirname(bzrlib.__file__))
1507
2272
 
1508
2273
    def get_bzr_path(self):
1509
2274
        """Return the path of the 'bzr' executable for this test suite."""
1510
 
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
2275
        bzr_path = os.path.join(self.get_source_path(), "bzr")
1511
2276
        if not os.path.isfile(bzr_path):
1512
2277
            # We are probably installed. Assume sys.argv is the right file
1513
2278
            bzr_path = sys.argv[0]
1535
2300
        if retcode is not None and retcode != process.returncode:
1536
2301
            if process_args is None:
1537
2302
                process_args = "(unknown args)"
1538
 
            mutter('Output of bzr %s:\n%s', process_args, out)
1539
 
            mutter('Error for bzr %s:\n%s', process_args, err)
 
2303
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
 
2304
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
1540
2305
            self.fail('Command bzr %s failed with retcode %s != %s'
1541
2306
                      % (process_args, retcode, process.returncode))
1542
2307
        return [out, err]
1543
2308
 
1544
 
    def check_inventory_shape(self, inv, shape):
1545
 
        """Compare an inventory to a list of expected names.
 
2309
    def check_tree_shape(self, tree, shape):
 
2310
        """Compare a tree to a list of expected names.
1546
2311
 
1547
2312
        Fail if they are not precisely equal.
1548
2313
        """
1549
2314
        extras = []
1550
2315
        shape = list(shape)             # copy
1551
 
        for path, ie in inv.entries():
 
2316
        for path, ie in tree.iter_entries_by_dir():
1552
2317
            name = path.replace('\\', '/')
1553
2318
            if ie.kind == 'directory':
1554
2319
                name = name + '/'
1555
 
            if name in shape:
 
2320
            if name == "/":
 
2321
                pass # ignore root entry
 
2322
            elif name in shape:
1556
2323
                shape.remove(name)
1557
2324
            else:
1558
2325
                extras.append(name)
1599
2366
 
1600
2367
        Tests that expect to provoke LockContention errors should call this.
1601
2368
        """
1602
 
        orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
1603
 
        def resetTimeout():
1604
 
            bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
1605
 
        self.addCleanup(resetTimeout)
1606
 
        bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
 
2369
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
2370
 
 
2371
    def make_utf8_encoded_stringio(self, encoding_type=None):
 
2372
        """Return a StringIOWrapper instance, that will encode Unicode
 
2373
        input to UTF-8.
 
2374
        """
 
2375
        if encoding_type is None:
 
2376
            encoding_type = 'strict'
 
2377
        sio = StringIO()
 
2378
        output_encoding = 'utf-8'
 
2379
        sio = codecs.getwriter(output_encoding)(sio, errors=encoding_type)
 
2380
        sio.encoding = output_encoding
 
2381
        return sio
 
2382
 
 
2383
    def disable_verb(self, verb):
 
2384
        """Disable a smart server verb for one test."""
 
2385
        from bzrlib.smart import request
 
2386
        request_handlers = request.request_handlers
 
2387
        orig_method = request_handlers.get(verb)
 
2388
        orig_info = request_handlers.get_info(verb)
 
2389
        request_handlers.remove(verb)
 
2390
        self.addCleanup(request_handlers.register, verb, orig_method,
 
2391
            info=orig_info)
 
2392
 
 
2393
 
 
2394
class CapturedCall(object):
 
2395
    """A helper for capturing smart server calls for easy debug analysis."""
 
2396
 
 
2397
    def __init__(self, params, prefix_length):
 
2398
        """Capture the call with params and skip prefix_length stack frames."""
 
2399
        self.call = params
 
2400
        import traceback
 
2401
        # The last 5 frames are the __init__, the hook frame, and 3 smart
 
2402
        # client frames. Beyond this we could get more clever, but this is good
 
2403
        # enough for now.
 
2404
        stack = traceback.extract_stack()[prefix_length:-5]
 
2405
        self.stack = ''.join(traceback.format_list(stack))
 
2406
 
 
2407
    def __str__(self):
 
2408
        return self.call.method
 
2409
 
 
2410
    def __repr__(self):
 
2411
        return self.call.method
 
2412
 
 
2413
    def stack(self):
 
2414
        return self.stack
1607
2415
 
1608
2416
 
1609
2417
class TestCaseWithMemoryTransport(TestCase):
1610
2418
    """Common test class for tests that do not need disk resources.
1611
2419
 
1612
 
    Tests that need disk resources should derive from TestCaseWithTransport.
 
2420
    Tests that need disk resources should derive from TestCaseInTempDir
 
2421
    orTestCaseWithTransport.
1613
2422
 
1614
2423
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
1615
2424
 
1616
 
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
 
2425
    For TestCaseWithMemoryTransport the ``test_home_dir`` is set to the name of
1617
2426
    a directory which does not exist. This serves to help ensure test isolation
1618
 
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
1619
 
    must exist. However, TestCaseWithMemoryTransport does not offer local
1620
 
    file defaults for the transport in tests, nor does it obey the command line
 
2427
    is preserved. ``test_dir`` is set to the TEST_ROOT, as is cwd, because they
 
2428
    must exist. However, TestCaseWithMemoryTransport does not offer local file
 
2429
    defaults for the transport in tests, nor does it obey the command line
1621
2430
    override, so tests that accidentally write to the common directory should
1622
2431
    be rare.
1623
2432
 
1624
 
    :cvar TEST_ROOT: Directory containing all temporary directories, plus
1625
 
    a .bzr directory that stops us ascending higher into the filesystem.
 
2433
    :cvar TEST_ROOT: Directory containing all temporary directories, plus a
 
2434
        ``.bzr`` directory that stops us ascending higher into the filesystem.
1626
2435
    """
1627
2436
 
1628
2437
    TEST_ROOT = None
1629
2438
    _TEST_NAME = 'test'
1630
2439
 
1631
2440
    def __init__(self, methodName='runTest'):
1632
 
        # allow test parameterisation after test construction and before test
1633
 
        # execution. Variables that the parameteriser sets need to be 
 
2441
        # allow test parameterization after test construction and before test
 
2442
        # execution. Variables that the parameterizer sets need to be
1634
2443
        # ones that are not set by setUp, or setUp will trash them.
1635
2444
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
1636
2445
        self.vfs_transport_factory = default_transport
1638
2447
        self.transport_readonly_server = None
1639
2448
        self.__vfs_server = None
1640
2449
 
1641
 
    def get_transport(self):
1642
 
        """Return a writeable transport for the test scratch space"""
1643
 
        t = get_transport(self.get_url())
 
2450
    def get_transport(self, relpath=None):
 
2451
        """Return a writeable transport.
 
2452
 
 
2453
        This transport is for the test scratch space relative to
 
2454
        "self._test_root"
 
2455
 
 
2456
        :param relpath: a path relative to the base url.
 
2457
        """
 
2458
        t = _mod_transport.get_transport_from_url(self.get_url(relpath))
1644
2459
        self.assertFalse(t.is_readonly())
1645
2460
        return t
1646
2461
 
1647
 
    def get_readonly_transport(self):
 
2462
    def get_readonly_transport(self, relpath=None):
1648
2463
        """Return a readonly transport for the test scratch space
1649
 
        
 
2464
 
1650
2465
        This can be used to test that operations which should only need
1651
2466
        readonly access in fact do not try to write.
 
2467
 
 
2468
        :param relpath: a path relative to the base url.
1652
2469
        """
1653
 
        t = get_transport(self.get_readonly_url())
 
2470
        t = _mod_transport.get_transport_from_url(
 
2471
            self.get_readonly_url(relpath))
1654
2472
        self.assertTrue(t.is_readonly())
1655
2473
        return t
1656
2474
 
1669
2487
        if self.__readonly_server is None:
1670
2488
            if self.transport_readonly_server is None:
1671
2489
                # readonly decorator requested
1672
 
                # bring up the server
1673
 
                self.__readonly_server = ReadonlyServer()
1674
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
 
2490
                self.__readonly_server = test_server.ReadonlyServer()
1675
2491
            else:
 
2492
                # explicit readonly transport.
1676
2493
                self.__readonly_server = self.create_transport_readonly_server()
1677
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
1678
 
            self.addCleanup(self.__readonly_server.tearDown)
 
2494
            self.start_server(self.__readonly_server,
 
2495
                self.get_vfs_only_server())
1679
2496
        return self.__readonly_server
1680
2497
 
1681
2498
    def get_readonly_url(self, relpath=None):
1682
2499
        """Get a URL for the readonly transport.
1683
2500
 
1684
 
        This will either be backed by '.' or a decorator to the transport 
 
2501
        This will either be backed by '.' or a decorator to the transport
1685
2502
        used by self.get_url()
1686
2503
        relpath provides for clients to get a path relative to the base url.
1687
2504
        These should only be downwards relative, not upwards.
1688
2505
        """
1689
2506
        base = self.get_readonly_server().get_url()
1690
 
        if relpath is not None:
1691
 
            if not base.endswith('/'):
1692
 
                base = base + '/'
1693
 
            base = base + relpath
1694
 
        return base
 
2507
        return self._adjust_url(base, relpath)
1695
2508
 
1696
2509
    def get_vfs_only_server(self):
1697
2510
        """Get the vfs only read/write server instance.
1703
2516
        is no means to override it.
1704
2517
        """
1705
2518
        if self.__vfs_server is None:
1706
 
            self.__vfs_server = MemoryServer()
1707
 
            self.__vfs_server.setUp()
1708
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2519
            self.__vfs_server = memory.MemoryServer()
 
2520
            self.start_server(self.__vfs_server)
1709
2521
        return self.__vfs_server
1710
2522
 
1711
2523
    def get_server(self):
1718
2530
        then the self.get_vfs_server is returned.
1719
2531
        """
1720
2532
        if self.__server is None:
1721
 
            if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
1722
 
                return self.get_vfs_only_server()
 
2533
            if (self.transport_server is None or self.transport_server is
 
2534
                self.vfs_transport_factory):
 
2535
                self.__server = self.get_vfs_only_server()
1723
2536
            else:
1724
2537
                # bring up a decorated means of access to the vfs only server.
1725
2538
                self.__server = self.transport_server()
1726
 
                try:
1727
 
                    self.__server.setUp(self.get_vfs_only_server())
1728
 
                except TypeError, e:
1729
 
                    # This should never happen; the try:Except here is to assist
1730
 
                    # developers having to update code rather than seeing an
1731
 
                    # uninformative TypeError.
1732
 
                    raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
1733
 
            self.addCleanup(self.__server.tearDown)
 
2539
                self.start_server(self.__server, self.get_vfs_only_server())
1734
2540
        return self.__server
1735
2541
 
1736
2542
    def _adjust_url(self, base, relpath):
1782
2588
        base = self.get_vfs_only_server().get_url()
1783
2589
        return self._adjust_url(base, relpath)
1784
2590
 
 
2591
    def _create_safety_net(self):
 
2592
        """Make a fake bzr directory.
 
2593
 
 
2594
        This prevents any tests propagating up onto the TEST_ROOT directory's
 
2595
        real branch.
 
2596
        """
 
2597
        root = TestCaseWithMemoryTransport.TEST_ROOT
 
2598
        try:
 
2599
            # Make sure we get a readable and accessible home for .bzr.log
 
2600
            # and/or config files, and not fallback to weird defaults (see
 
2601
            # http://pad.lv/825027).
 
2602
            self.assertIs(None, os.environ.get('BZR_HOME', None))
 
2603
            os.environ['BZR_HOME'] = root
 
2604
            wt = controldir.ControlDir.create_standalone_workingtree(root)
 
2605
            del os.environ['BZR_HOME']
 
2606
        except Exception, e:
 
2607
            self.fail("Fail to initialize the safety net: %r\n" % (e,))
 
2608
        # Hack for speed: remember the raw bytes of the dirstate file so that
 
2609
        # we don't need to re-open the wt to check it hasn't changed.
 
2610
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
 
2611
            wt.control_transport.get_bytes('dirstate'))
 
2612
 
 
2613
    def _check_safety_net(self):
 
2614
        """Check that the safety .bzr directory have not been touched.
 
2615
 
 
2616
        _make_test_root have created a .bzr directory to prevent tests from
 
2617
        propagating. This method ensures than a test did not leaked.
 
2618
        """
 
2619
        root = TestCaseWithMemoryTransport.TEST_ROOT
 
2620
        t = _mod_transport.get_transport_from_path(root)
 
2621
        self.permit_url(t.base)
 
2622
        if (t.get_bytes('.bzr/checkout/dirstate') != 
 
2623
                TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE):
 
2624
            # The current test have modified the /bzr directory, we need to
 
2625
            # recreate a new one or all the followng tests will fail.
 
2626
            # If you need to inspect its content uncomment the following line
 
2627
            # import pdb; pdb.set_trace()
 
2628
            _rmtree_temp_dir(root + '/.bzr', test_id=self.id())
 
2629
            self._create_safety_net()
 
2630
            raise AssertionError('%s/.bzr should not be modified' % root)
 
2631
 
1785
2632
    def _make_test_root(self):
1786
 
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1787
 
            return
1788
 
        root = tempfile.mkdtemp(prefix='testbzr-', suffix='.tmp')
1789
 
        TestCaseWithMemoryTransport.TEST_ROOT = root
1790
 
        
1791
 
        # make a fake bzr directory there to prevent any tests propagating
1792
 
        # up onto the source directory's real branch
1793
 
        bzrdir.BzrDir.create_standalone_workingtree(root)
1794
 
 
1795
 
        # The same directory is used by all tests, and we're not specifically
1796
 
        # told when all tests are finished.  This will do.
1797
 
        atexit.register(_rmtree_temp_dir, root)
 
2633
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
 
2634
            # Watch out for tricky test dir (on OSX /tmp -> /private/tmp)
 
2635
            root = osutils.realpath(osutils.mkdtemp(prefix='testbzr-',
 
2636
                                                    suffix='.tmp'))
 
2637
            TestCaseWithMemoryTransport.TEST_ROOT = root
 
2638
 
 
2639
            self._create_safety_net()
 
2640
 
 
2641
            # The same directory is used by all tests, and we're not
 
2642
            # specifically told when all tests are finished.  This will do.
 
2643
            atexit.register(_rmtree_temp_dir, root)
 
2644
 
 
2645
        self.permit_dir(TestCaseWithMemoryTransport.TEST_ROOT)
 
2646
        self.addCleanup(self._check_safety_net)
1798
2647
 
1799
2648
    def makeAndChdirToTestDir(self):
1800
2649
        """Create a temporary directories for this one test.
1801
 
        
 
2650
 
1802
2651
        This must set self.test_home_dir and self.test_dir and chdir to
1803
2652
        self.test_dir.
1804
 
        
 
2653
 
1805
2654
        For TestCaseWithMemoryTransport we chdir to the TEST_ROOT for this test.
1806
2655
        """
1807
2656
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
1808
2657
        self.test_dir = TestCaseWithMemoryTransport.TEST_ROOT
1809
2658
        self.test_home_dir = self.test_dir + "/MemoryTransportMissingHomeDir"
1810
 
        
1811
 
    def make_branch(self, relpath, format=None):
 
2659
        self.permit_dir(self.test_dir)
 
2660
 
 
2661
    def make_branch(self, relpath, format=None, name=None):
1812
2662
        """Create a branch on the transport at relpath."""
1813
2663
        repo = self.make_repository(relpath, format=format)
1814
 
        return repo.bzrdir.create_branch()
 
2664
        return repo.bzrdir.create_branch(append_revisions_only=False,
 
2665
                                         name=name)
 
2666
 
 
2667
    def get_default_format(self):
 
2668
        return 'default'
 
2669
 
 
2670
    def resolve_format(self, format):
 
2671
        """Resolve an object to a ControlDir format object.
 
2672
 
 
2673
        The initial format object can either already be
 
2674
        a ControlDirFormat, None (for the default format),
 
2675
        or a string with the name of the control dir format.
 
2676
 
 
2677
        :param format: Object to resolve
 
2678
        :return A ControlDirFormat instance
 
2679
        """
 
2680
        if format is None:
 
2681
            format = self.get_default_format()
 
2682
        if isinstance(format, basestring):
 
2683
            format = controldir.format_registry.make_bzrdir(format)
 
2684
        return format
1815
2685
 
1816
2686
    def make_bzrdir(self, relpath, format=None):
1817
2687
        try:
1818
2688
            # might be a relative or absolute path
1819
2689
            maybe_a_url = self.get_url(relpath)
1820
2690
            segments = maybe_a_url.rsplit('/', 1)
1821
 
            t = get_transport(maybe_a_url)
 
2691
            t = _mod_transport.get_transport(maybe_a_url)
1822
2692
            if len(segments) > 1 and segments[-1] not in ('', '.'):
1823
2693
                t.ensure_base()
1824
 
            if format is None:
1825
 
                format = 'default'
1826
 
            if isinstance(format, basestring):
1827
 
                format = bzrdir.format_registry.make_bzrdir(format)
 
2694
            format = self.resolve_format(format)
1828
2695
            return format.initialize_on_transport(t)
1829
2696
        except errors.UninitializableFormat:
1830
2697
            raise TestSkipped("Format %s is not initializable." % format)
1831
2698
 
1832
 
    def make_repository(self, relpath, shared=False, format=None):
 
2699
    def make_repository(self, relpath, shared=None, format=None):
1833
2700
        """Create a repository on our default transport at relpath.
1834
 
        
 
2701
 
1835
2702
        Note that relpath must be a relative path, not a full url.
1836
2703
        """
1837
2704
        # FIXME: If you create a remoterepository this returns the underlying
1838
 
        # real format, which is incorrect.  Actually we should make sure that 
 
2705
        # real format, which is incorrect.  Actually we should make sure that
1839
2706
        # RemoteBzrDir returns a RemoteRepository.
1840
2707
        # maybe  mbp 20070410
1841
2708
        made_control = self.make_bzrdir(relpath, format=format)
1842
2709
        return made_control.create_repository(shared=shared)
1843
2710
 
 
2711
    def make_smart_server(self, path, backing_server=None):
 
2712
        if backing_server is None:
 
2713
            backing_server = self.get_server()
 
2714
        smart_server = test_server.SmartTCPServer_for_testing()
 
2715
        self.start_server(smart_server, backing_server)
 
2716
        remote_transport = _mod_transport.get_transport_from_url(smart_server.get_url()
 
2717
                                                   ).clone(path)
 
2718
        return remote_transport
 
2719
 
1844
2720
    def make_branch_and_memory_tree(self, relpath, format=None):
1845
2721
        """Create a branch on the default transport and a MemoryTree for it."""
1846
2722
        b = self.make_branch(relpath, format=format)
1847
2723
        return memorytree.MemoryTree.create_on_branch(b)
1848
2724
 
 
2725
    def make_branch_builder(self, relpath, format=None):
 
2726
        branch = self.make_branch(relpath, format=format)
 
2727
        return branchbuilder.BranchBuilder(branch=branch)
 
2728
 
1849
2729
    def overrideEnvironmentForTesting(self):
1850
 
        os.environ['HOME'] = self.test_home_dir
1851
 
        os.environ['BZR_HOME'] = self.test_home_dir
1852
 
        
 
2730
        test_home_dir = self.test_home_dir
 
2731
        if isinstance(test_home_dir, unicode):
 
2732
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
 
2733
        self.overrideEnv('HOME', test_home_dir)
 
2734
        self.overrideEnv('BZR_HOME', test_home_dir)
 
2735
 
1853
2736
    def setUp(self):
1854
2737
        super(TestCaseWithMemoryTransport, self).setUp()
 
2738
 
 
2739
        def _add_disconnect_cleanup(transport):
 
2740
            """Schedule disconnection of given transport at test cleanup
 
2741
 
 
2742
            This needs to happen for all connected transports or leaks occur.
 
2743
 
 
2744
            Note reconnections may mean we call disconnect multiple times per
 
2745
            transport which is suboptimal but seems harmless.
 
2746
            """
 
2747
            self.addCleanup(transport.disconnect)
 
2748
 
 
2749
        _mod_transport.Transport.hooks.install_named_hook('post_connect',
 
2750
            _add_disconnect_cleanup, None)
 
2751
 
1855
2752
        self._make_test_root()
1856
 
        _currentdir = os.getcwdu()
1857
 
        def _leaveDirectory():
1858
 
            os.chdir(_currentdir)
1859
 
        self.addCleanup(_leaveDirectory)
 
2753
        self.addCleanup(os.chdir, os.getcwdu())
1860
2754
        self.makeAndChdirToTestDir()
1861
2755
        self.overrideEnvironmentForTesting()
1862
2756
        self.__readonly_server = None
1863
2757
        self.__server = None
1864
2758
        self.reduceLockdirTimeout()
1865
2759
 
1866
 
     
 
2760
    def setup_smart_server_with_call_log(self):
 
2761
        """Sets up a smart server as the transport server with a call log."""
 
2762
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2763
        self.hpss_connections = []
 
2764
        self.hpss_calls = []
 
2765
        import traceback
 
2766
        # Skip the current stack down to the caller of
 
2767
        # setup_smart_server_with_call_log
 
2768
        prefix_length = len(traceback.extract_stack()) - 2
 
2769
        def capture_hpss_call(params):
 
2770
            self.hpss_calls.append(
 
2771
                CapturedCall(params, prefix_length))
 
2772
        def capture_connect(transport):
 
2773
            self.hpss_connections.append(transport)
 
2774
        client._SmartClient.hooks.install_named_hook(
 
2775
            'call', capture_hpss_call, None)
 
2776
        _mod_transport.Transport.hooks.install_named_hook(
 
2777
            'post_connect', capture_connect, None)
 
2778
 
 
2779
    def reset_smart_call_log(self):
 
2780
        self.hpss_calls = []
 
2781
        self.hpss_connections = []
 
2782
 
 
2783
 
1867
2784
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1868
2785
    """Derived class that runs a test within a temporary directory.
1869
2786
 
1874
2791
    All test cases create their own directory within that.  If the
1875
2792
    tests complete successfully, the directory is removed.
1876
2793
 
1877
 
    :ivar test_base_dir: The path of the top-level directory for this 
 
2794
    :ivar test_base_dir: The path of the top-level directory for this
1878
2795
    test, which contains a home directory and a work directory.
1879
2796
 
1880
2797
    :ivar test_home_dir: An initially empty directory under test_base_dir
1885
2802
    """
1886
2803
 
1887
2804
    OVERRIDE_PYTHON = 'python'
1888
 
    use_numbered_dirs = False
 
2805
 
 
2806
    def setUp(self):
 
2807
        super(TestCaseInTempDir, self).setUp()
 
2808
        # Remove the protection set in isolated_environ, we have a proper
 
2809
        # access to disk resources now.
 
2810
        self.overrideEnv('BZR_LOG', None)
1889
2811
 
1890
2812
    def check_file_contents(self, filename, expect):
1891
2813
        self.log("check contents of file %s" % filename)
1892
 
        contents = file(filename, 'r').read()
 
2814
        f = file(filename)
 
2815
        try:
 
2816
            contents = f.read()
 
2817
        finally:
 
2818
            f.close()
1893
2819
        if contents != expect:
1894
2820
            self.log("expected: %r" % expect)
1895
2821
            self.log("actually: %r" % contents)
1896
2822
            self.fail("contents of %s not as expected" % filename)
1897
2823
 
 
2824
    def _getTestDirPrefix(self):
 
2825
        # create a directory within the top level test directory
 
2826
        if sys.platform in ('win32', 'cygwin'):
 
2827
            name_prefix = re.sub('[<>*=+",:;_/\\-]', '_', self.id())
 
2828
            # windows is likely to have path-length limits so use a short name
 
2829
            name_prefix = name_prefix[-30:]
 
2830
        else:
 
2831
            name_prefix = re.sub('[/]', '_', self.id())
 
2832
        return name_prefix
 
2833
 
1898
2834
    def makeAndChdirToTestDir(self):
1899
2835
        """See TestCaseWithMemoryTransport.makeAndChdirToTestDir().
1900
 
        
 
2836
 
1901
2837
        For TestCaseInTempDir we create a temporary directory based on the test
1902
2838
        name and then create two subdirs - test and home under it.
1903
2839
        """
1904
 
        # create a directory within the top level test directory
1905
 
        candidate_dir = tempfile.mkdtemp(dir=self.TEST_ROOT)
1906
 
        # now create test and home directories within this dir
1907
 
        self.test_base_dir = candidate_dir
 
2840
        name_prefix = osutils.pathjoin(TestCaseWithMemoryTransport.TEST_ROOT,
 
2841
            self._getTestDirPrefix())
 
2842
        name = name_prefix
 
2843
        for i in range(100):
 
2844
            if os.path.exists(name):
 
2845
                name = name_prefix + '_' + str(i)
 
2846
            else:
 
2847
                # now create test and home directories within this dir
 
2848
                self.test_base_dir = name
 
2849
                self.addCleanup(self.deleteTestDir)
 
2850
                os.mkdir(self.test_base_dir)
 
2851
                break
 
2852
        self.permit_dir(self.test_base_dir)
 
2853
        # 'sprouting' and 'init' of a branch both walk up the tree to find
 
2854
        # stacking policy to honour; create a bzr dir with an unshared
 
2855
        # repository (but not a branch - our code would be trying to escape
 
2856
        # then!) to stop them, and permit it to be read.
 
2857
        # control = controldir.ControlDir.create(self.test_base_dir)
 
2858
        # control.create_repository()
1908
2859
        self.test_home_dir = self.test_base_dir + '/home'
1909
2860
        os.mkdir(self.test_home_dir)
1910
2861
        self.test_dir = self.test_base_dir + '/work'
1916
2867
            f.write(self.id())
1917
2868
        finally:
1918
2869
            f.close()
1919
 
        self.addCleanup(self.deleteTestDir)
1920
2870
 
1921
2871
    def deleteTestDir(self):
1922
 
        os.chdir(self.TEST_ROOT)
1923
 
        _rmtree_temp_dir(self.test_base_dir)
 
2872
        os.chdir(TestCaseWithMemoryTransport.TEST_ROOT)
 
2873
        _rmtree_temp_dir(self.test_base_dir, test_id=self.id())
1924
2874
 
1925
2875
    def build_tree(self, shape, line_endings='binary', transport=None):
1926
2876
        """Build a test tree according to a pattern.
1932
2882
 
1933
2883
        This doesn't add anything to a branch.
1934
2884
 
 
2885
        :type shape:    list or tuple.
1935
2886
        :param line_endings: Either 'binary' or 'native'
1936
2887
            in binary mode, exact contents are written in native mode, the
1937
2888
            line endings match the default platform endings.
1939
2890
            If the transport is readonly or None, "." is opened automatically.
1940
2891
        :return: None
1941
2892
        """
 
2893
        if type(shape) not in (list, tuple):
 
2894
            raise AssertionError("Parameter 'shape' should be "
 
2895
                "a list or a tuple. Got %r instead" % (shape,))
1942
2896
        # It's OK to just create them using forward slashes on windows.
1943
2897
        if transport is None or transport.is_readonly():
1944
 
            transport = get_transport(".")
 
2898
            transport = _mod_transport.get_transport_from_path(".")
1945
2899
        for name in shape:
1946
 
            self.assert_(isinstance(name, basestring))
 
2900
            self.assertIsInstance(name, basestring)
1947
2901
            if name[-1] == '/':
1948
2902
                transport.mkdir(urlutils.escape(name[:-1]))
1949
2903
            else:
1957
2911
                content = "contents of %s%s" % (name.encode('utf-8'), end)
1958
2912
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
1959
2913
 
1960
 
    def build_tree_contents(self, shape):
1961
 
        build_tree_contents(shape)
1962
 
 
1963
 
    def assertFileEqual(self, content, path):
1964
 
        """Fail if path does not contain 'content'."""
1965
 
        self.failUnlessExists(path)
1966
 
        f = file(path, 'rb')
1967
 
        try:
1968
 
            s = f.read()
1969
 
        finally:
1970
 
            f.close()
1971
 
        self.assertEqualDiff(content, s)
1972
 
 
1973
 
    def failUnlessExists(self, path):
1974
 
        """Fail unless path or paths, which may be abs or relative, exist."""
1975
 
        if not isinstance(path, basestring):
1976
 
            for p in path:
1977
 
                self.failUnlessExists(p)
1978
 
        else:
1979
 
            self.failUnless(osutils.lexists(path),path+" does not exist")
1980
 
 
1981
 
    def failIfExists(self, path):
1982
 
        """Fail if path or paths, which may be abs or relative, exist."""
1983
 
        if not isinstance(path, basestring):
1984
 
            for p in path:
1985
 
                self.failIfExists(p)
1986
 
        else:
1987
 
            self.failIf(osutils.lexists(path),path+" exists")
1988
 
 
1989
 
    def assertInWorkingTree(self,path,root_path='.',tree=None):
 
2914
    build_tree_contents = staticmethod(treeshape.build_tree_contents)
 
2915
 
 
2916
    def assertInWorkingTree(self, path, root_path='.', tree=None):
1990
2917
        """Assert whether path or paths are in the WorkingTree"""
1991
2918
        if tree is None:
1992
2919
            tree = workingtree.WorkingTree.open(root_path)
1993
2920
        if not isinstance(path, basestring):
1994
2921
            for p in path:
1995
 
                self.assertInWorkingTree(p,tree=tree)
 
2922
                self.assertInWorkingTree(p, tree=tree)
1996
2923
        else:
1997
2924
            self.assertIsNot(tree.path2id(path), None,
1998
2925
                path+' not in working tree.')
1999
2926
 
2000
 
    def assertNotInWorkingTree(self,path,root_path='.',tree=None):
 
2927
    def assertNotInWorkingTree(self, path, root_path='.', tree=None):
2001
2928
        """Assert whether path or paths are not in the WorkingTree"""
2002
2929
        if tree is None:
2003
2930
            tree = workingtree.WorkingTree.open(root_path)
2018
2945
    ReadonlyTransportDecorator is used instead which allows the use of non disk
2019
2946
    based read write transports.
2020
2947
 
2021
 
    If an explicit class is provided for readonly access, that server and the 
 
2948
    If an explicit class is provided for readonly access, that server and the
2022
2949
    readwrite one must both define get_url() as resolving to os.getcwd().
2023
2950
    """
2024
2951
 
2030
2957
        """
2031
2958
        if self.__vfs_server is None:
2032
2959
            self.__vfs_server = self.vfs_transport_factory()
2033
 
            self.__vfs_server.setUp()
2034
 
            self.addCleanup(self.__vfs_server.tearDown)
 
2960
            self.start_server(self.__vfs_server)
2035
2961
        return self.__vfs_server
2036
2962
 
2037
2963
    def make_branch_and_tree(self, relpath, format=None):
2044
2970
        repository will also be accessed locally. Otherwise a lightweight
2045
2971
        checkout is created and returned.
2046
2972
 
 
2973
        We do this because we can't physically create a tree in the local
 
2974
        path, with a branch reference to the transport_factory url, and
 
2975
        a branch + repository in the vfs_transport, unless the vfs_transport
 
2976
        namespace is distinct from the local disk - the two branch objects
 
2977
        would collide. While we could construct a tree with its branch object
 
2978
        pointing at the transport_factory transport in memory, reopening it
 
2979
        would behaving unexpectedly, and has in the past caused testing bugs
 
2980
        when we tried to do it that way.
 
2981
 
2047
2982
        :param format: The BzrDirFormat.
2048
2983
        :returns: the WorkingTree.
2049
2984
        """
2051
2986
        # this obviously requires a format that supports branch references
2052
2987
        # so check for that by checking bzrdir.BzrDirFormat.get_default_format()
2053
2988
        # RBC 20060208
 
2989
        format = self.resolve_format(format=format)
 
2990
        if not format.supports_workingtrees:
 
2991
            b = self.make_branch(relpath+'.branch', format=format)
 
2992
            return b.create_checkout(relpath, lightweight=True)
2054
2993
        b = self.make_branch(relpath, format=format)
2055
2994
        try:
2056
2995
            return b.bzrdir.create_workingtree()
2058
2997
            # We can only make working trees locally at the moment.  If the
2059
2998
            # transport can't support them, then we keep the non-disk-backed
2060
2999
            # branch and create a local checkout.
2061
 
            if self.vfs_transport_factory is LocalURLServer:
 
3000
            if self.vfs_transport_factory is test_server.LocalURLServer:
2062
3001
                # the branch is colocated on disk, we cannot create a checkout.
2063
3002
                # hopefully callers will expect this.
2064
 
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2065
 
                return local_controldir.create_workingtree()
 
3003
                local_controldir = controldir.ControlDir.open(
 
3004
                    self.get_vfs_only_url(relpath))
 
3005
                wt = local_controldir.create_workingtree()
 
3006
                if wt.branch._format != b._format:
 
3007
                    wt._branch = b
 
3008
                    # Make sure that assigning to wt._branch fixes wt.branch,
 
3009
                    # in case the implementation details of workingtree objects
 
3010
                    # change.
 
3011
                    self.assertIs(b, wt.branch)
 
3012
                return wt
2066
3013
            else:
2067
3014
                return b.create_checkout(relpath, lightweight=True)
2068
3015
 
2094
3041
        super(TestCaseWithTransport, self).setUp()
2095
3042
        self.__vfs_server = None
2096
3043
 
 
3044
    def disable_missing_extensions_warning(self):
 
3045
        """Some tests expect a precise stderr content.
 
3046
 
 
3047
        There is no point in forcing them to duplicate the extension related
 
3048
        warning.
 
3049
        """
 
3050
        config.GlobalConfig().set_user_option('ignore_missing_extensions', True)
 
3051
 
2097
3052
 
2098
3053
class ChrootedTestCase(TestCaseWithTransport):
2099
3054
    """A support class that provides readonly urls outside the local namespace.
2103
3058
    for readonly urls.
2104
3059
 
2105
3060
    TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
2106
 
                       be used without needed to redo it when a different 
 
3061
                       be used without needed to redo it when a different
2107
3062
                       subclass is in use ?
2108
3063
    """
2109
3064
 
2110
3065
    def setUp(self):
 
3066
        from bzrlib.tests import http_server
2111
3067
        super(ChrootedTestCase, self).setUp()
2112
 
        if not self.vfs_transport_factory == MemoryServer:
2113
 
            self.transport_readonly_server = HttpServer
2114
 
 
2115
 
 
2116
 
def filter_suite_by_re(suite, pattern, exclude_pattern=None,
2117
 
                       random_order=False):
2118
 
    """Create a test suite by filtering another one.
2119
 
    
 
3068
        if not self.vfs_transport_factory == memory.MemoryServer:
 
3069
            self.transport_readonly_server = http_server.HttpServer
 
3070
 
 
3071
 
 
3072
def condition_id_re(pattern):
 
3073
    """Create a condition filter which performs a re check on a test's id.
 
3074
 
 
3075
    :param pattern: A regular expression string.
 
3076
    :return: A callable that returns True if the re matches.
 
3077
    """
 
3078
    filter_re = re.compile(pattern, 0)
 
3079
    def condition(test):
 
3080
        test_id = test.id()
 
3081
        return filter_re.search(test_id)
 
3082
    return condition
 
3083
 
 
3084
 
 
3085
def condition_isinstance(klass_or_klass_list):
 
3086
    """Create a condition filter which returns isinstance(param, klass).
 
3087
 
 
3088
    :return: A callable which when called with one parameter obj return the
 
3089
        result of isinstance(obj, klass_or_klass_list).
 
3090
    """
 
3091
    def condition(obj):
 
3092
        return isinstance(obj, klass_or_klass_list)
 
3093
    return condition
 
3094
 
 
3095
 
 
3096
def condition_id_in_list(id_list):
 
3097
    """Create a condition filter which verify that test's id in a list.
 
3098
 
 
3099
    :param id_list: A TestIdList object.
 
3100
    :return: A callable that returns True if the test's id appears in the list.
 
3101
    """
 
3102
    def condition(test):
 
3103
        return id_list.includes(test.id())
 
3104
    return condition
 
3105
 
 
3106
 
 
3107
def condition_id_startswith(starts):
 
3108
    """Create a condition filter verifying that test's id starts with a string.
 
3109
 
 
3110
    :param starts: A list of string.
 
3111
    :return: A callable that returns True if the test's id starts with one of
 
3112
        the given strings.
 
3113
    """
 
3114
    def condition(test):
 
3115
        for start in starts:
 
3116
            if test.id().startswith(start):
 
3117
                return True
 
3118
        return False
 
3119
    return condition
 
3120
 
 
3121
 
 
3122
def exclude_tests_by_condition(suite, condition):
 
3123
    """Create a test suite which excludes some tests from suite.
 
3124
 
 
3125
    :param suite: The suite to get tests from.
 
3126
    :param condition: A callable whose result evaluates True when called with a
 
3127
        test case which should be excluded from the result.
 
3128
    :return: A suite which contains the tests found in suite that fail
 
3129
        condition.
 
3130
    """
 
3131
    result = []
 
3132
    for test in iter_suite_tests(suite):
 
3133
        if not condition(test):
 
3134
            result.append(test)
 
3135
    return TestUtil.TestSuite(result)
 
3136
 
 
3137
 
 
3138
def filter_suite_by_condition(suite, condition):
 
3139
    """Create a test suite by filtering another one.
 
3140
 
 
3141
    :param suite: The source suite.
 
3142
    :param condition: A callable whose result evaluates True when called with a
 
3143
        test case which should be included in the result.
 
3144
    :return: A suite which contains the tests found in suite that pass
 
3145
        condition.
 
3146
    """
 
3147
    result = []
 
3148
    for test in iter_suite_tests(suite):
 
3149
        if condition(test):
 
3150
            result.append(test)
 
3151
    return TestUtil.TestSuite(result)
 
3152
 
 
3153
 
 
3154
def filter_suite_by_re(suite, pattern):
 
3155
    """Create a test suite by filtering another one.
 
3156
 
2120
3157
    :param suite:           the source suite
2121
3158
    :param pattern:         pattern that names must match
2122
 
    :param exclude_pattern: pattern that names must not match, if any
2123
 
    :param random_order:    if True, tests in the new suite will be put in
2124
 
                            random order
2125
 
    :returns: the newly created suite
2126
 
    """ 
2127
 
    return sort_suite_by_re(suite, pattern, exclude_pattern,
2128
 
        random_order, False)
2129
 
 
2130
 
 
2131
 
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
2132
 
                     random_order=False, append_rest=True):
2133
 
    """Create a test suite by sorting another one.
2134
 
    
2135
 
    :param suite:           the source suite
2136
 
    :param pattern:         pattern that names must match in order to go
2137
 
                            first in the new suite
2138
 
    :param exclude_pattern: pattern that names must not match, if any
2139
 
    :param random_order:    if True, tests in the new suite will be put in
2140
 
                            random order
2141
 
    :param append_rest:     if False, pattern is a strict filter and not
2142
 
                            just an ordering directive
2143
 
    :returns: the newly created suite
2144
 
    """ 
2145
 
    first = []
2146
 
    second = []
2147
 
    filter_re = re.compile(pattern)
2148
 
    if exclude_pattern is not None:
2149
 
        exclude_re = re.compile(exclude_pattern)
 
3159
    :returns: the newly created suite
 
3160
    """
 
3161
    condition = condition_id_re(pattern)
 
3162
    result_suite = filter_suite_by_condition(suite, condition)
 
3163
    return result_suite
 
3164
 
 
3165
 
 
3166
def filter_suite_by_id_list(suite, test_id_list):
 
3167
    """Create a test suite by filtering another one.
 
3168
 
 
3169
    :param suite: The source suite.
 
3170
    :param test_id_list: A list of the test ids to keep as strings.
 
3171
    :returns: the newly created suite
 
3172
    """
 
3173
    condition = condition_id_in_list(test_id_list)
 
3174
    result_suite = filter_suite_by_condition(suite, condition)
 
3175
    return result_suite
 
3176
 
 
3177
 
 
3178
def filter_suite_by_id_startswith(suite, start):
 
3179
    """Create a test suite by filtering another one.
 
3180
 
 
3181
    :param suite: The source suite.
 
3182
    :param start: A list of string the test id must start with one of.
 
3183
    :returns: the newly created suite
 
3184
    """
 
3185
    condition = condition_id_startswith(start)
 
3186
    result_suite = filter_suite_by_condition(suite, condition)
 
3187
    return result_suite
 
3188
 
 
3189
 
 
3190
def exclude_tests_by_re(suite, pattern):
 
3191
    """Create a test suite which excludes some tests from suite.
 
3192
 
 
3193
    :param suite: The suite to get tests from.
 
3194
    :param pattern: A regular expression string. Test ids that match this
 
3195
        pattern will be excluded from the result.
 
3196
    :return: A TestSuite that contains all the tests from suite without the
 
3197
        tests that matched pattern. The order of tests is the same as it was in
 
3198
        suite.
 
3199
    """
 
3200
    return exclude_tests_by_condition(suite, condition_id_re(pattern))
 
3201
 
 
3202
 
 
3203
def preserve_input(something):
 
3204
    """A helper for performing test suite transformation chains.
 
3205
 
 
3206
    :param something: Anything you want to preserve.
 
3207
    :return: Something.
 
3208
    """
 
3209
    return something
 
3210
 
 
3211
 
 
3212
def randomize_suite(suite):
 
3213
    """Return a new TestSuite with suite's tests in random order.
 
3214
 
 
3215
    The tests in the input suite are flattened into a single suite in order to
 
3216
    accomplish this. Any nested TestSuites are removed to provide global
 
3217
    randomness.
 
3218
    """
 
3219
    tests = list(iter_suite_tests(suite))
 
3220
    random.shuffle(tests)
 
3221
    return TestUtil.TestSuite(tests)
 
3222
 
 
3223
 
 
3224
def split_suite_by_condition(suite, condition):
 
3225
    """Split a test suite into two by a condition.
 
3226
 
 
3227
    :param suite: The suite to split.
 
3228
    :param condition: The condition to match on. Tests that match this
 
3229
        condition are returned in the first test suite, ones that do not match
 
3230
        are in the second suite.
 
3231
    :return: A tuple of two test suites, where the first contains tests from
 
3232
        suite matching the condition, and the second contains the remainder
 
3233
        from suite. The order within each output suite is the same as it was in
 
3234
        suite.
 
3235
    """
 
3236
    matched = []
 
3237
    did_not_match = []
2150
3238
    for test in iter_suite_tests(suite):
2151
 
        test_id = test.id()
2152
 
        if exclude_pattern is None or not exclude_re.search(test_id):
2153
 
            if filter_re.search(test_id):
2154
 
                first.append(test)
2155
 
            elif append_rest:
2156
 
                second.append(test)
2157
 
    if random_order:
2158
 
        random.shuffle(first)
2159
 
        random.shuffle(second)
2160
 
    return TestUtil.TestSuite(first + second)
 
3239
        if condition(test):
 
3240
            matched.append(test)
 
3241
        else:
 
3242
            did_not_match.append(test)
 
3243
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
 
3244
 
 
3245
 
 
3246
def split_suite_by_re(suite, pattern):
 
3247
    """Split a test suite into two by a regular expression.
 
3248
 
 
3249
    :param suite: The suite to split.
 
3250
    :param pattern: A regular expression string. Test ids that match this
 
3251
        pattern will be in the first test suite returned, and the others in the
 
3252
        second test suite returned.
 
3253
    :return: A tuple of two test suites, where the first contains tests from
 
3254
        suite matching pattern, and the second contains the remainder from
 
3255
        suite. The order within each output suite is the same as it was in
 
3256
        suite.
 
3257
    """
 
3258
    return split_suite_by_condition(suite, condition_id_re(pattern))
2161
3259
 
2162
3260
 
2163
3261
def run_suite(suite, name='test', verbose=False, pattern=".*",
2164
3262
              stop_on_failure=False,
2165
3263
              transport=None, lsprof_timed=None, bench_history=None,
2166
3264
              matching_tests_first=None,
2167
 
              numbered_dirs=None,
2168
3265
              list_only=False,
2169
3266
              random_seed=None,
2170
3267
              exclude_pattern=None,
 
3268
              strict=False,
 
3269
              runner_class=None,
 
3270
              suite_decorators=None,
 
3271
              stream=None,
 
3272
              result_decorators=None,
2171
3273
              ):
2172
 
    use_numbered_dirs = bool(numbered_dirs)
 
3274
    """Run a test suite for bzr selftest.
2173
3275
 
 
3276
    :param runner_class: The class of runner to use. Must support the
 
3277
        constructor arguments passed by run_suite which are more than standard
 
3278
        python uses.
 
3279
    :return: A boolean indicating success.
 
3280
    """
2174
3281
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2175
 
    if numbered_dirs is not None:
2176
 
        TestCaseInTempDir.use_numbered_dirs = use_numbered_dirs
2177
3282
    if verbose:
2178
3283
        verbosity = 2
2179
3284
    else:
2180
3285
        verbosity = 1
2181
 
    runner = TextTestRunner(stream=sys.stdout,
 
3286
    if runner_class is None:
 
3287
        runner_class = TextTestRunner
 
3288
    if stream is None:
 
3289
        stream = sys.stdout
 
3290
    runner = runner_class(stream=stream,
2182
3291
                            descriptions=0,
2183
3292
                            verbosity=verbosity,
2184
3293
                            bench_history=bench_history,
2185
 
                            use_numbered_dirs=use_numbered_dirs,
2186
 
                            list_only=list_only,
 
3294
                            strict=strict,
 
3295
                            result_decorators=result_decorators,
2187
3296
                            )
2188
3297
    runner.stop_on_failure=stop_on_failure
2189
 
    # Initialise the random number generator and display the seed used.
2190
 
    # We convert the seed to a long to make it reuseable across invocations.
2191
 
    random_order = False
2192
 
    if random_seed is not None:
2193
 
        random_order = True
2194
 
        if random_seed == "now":
2195
 
            random_seed = long(time.time())
 
3298
    if isinstance(suite, unittest.TestSuite):
 
3299
        # Empty out _tests list of passed suite and populate new TestSuite
 
3300
        suite._tests[:], suite = [], TestSuite(suite)
 
3301
    # built in decorator factories:
 
3302
    decorators = [
 
3303
        random_order(random_seed, runner),
 
3304
        exclude_tests(exclude_pattern),
 
3305
        ]
 
3306
    if matching_tests_first:
 
3307
        decorators.append(tests_first(pattern))
 
3308
    else:
 
3309
        decorators.append(filter_tests(pattern))
 
3310
    if suite_decorators:
 
3311
        decorators.extend(suite_decorators)
 
3312
    # tell the result object how many tests will be running: (except if
 
3313
    # --parallel=fork is being used. Robert said he will provide a better
 
3314
    # progress design later -- vila 20090817)
 
3315
    if fork_decorator not in decorators:
 
3316
        decorators.append(CountingDecorator)
 
3317
    for decorator in decorators:
 
3318
        suite = decorator(suite)
 
3319
    if list_only:
 
3320
        # Done after test suite decoration to allow randomisation etc
 
3321
        # to take effect, though that is of marginal benefit.
 
3322
        if verbosity >= 2:
 
3323
            stream.write("Listing tests only ...\n")
 
3324
        for t in iter_suite_tests(suite):
 
3325
            stream.write("%s\n" % (t.id()))
 
3326
        return True
 
3327
    result = runner.run(suite)
 
3328
    if strict:
 
3329
        return result.wasStrictlySuccessful()
 
3330
    else:
 
3331
        return result.wasSuccessful()
 
3332
 
 
3333
 
 
3334
# A registry where get() returns a suite decorator.
 
3335
parallel_registry = registry.Registry()
 
3336
 
 
3337
 
 
3338
def fork_decorator(suite):
 
3339
    if getattr(os, "fork", None) is None:
 
3340
        raise errors.BzrCommandError("platform does not support fork,"
 
3341
            " try --parallel=subprocess instead.")
 
3342
    concurrency = osutils.local_concurrency()
 
3343
    if concurrency == 1:
 
3344
        return suite
 
3345
    from testtools import ConcurrentTestSuite
 
3346
    return ConcurrentTestSuite(suite, fork_for_tests)
 
3347
parallel_registry.register('fork', fork_decorator)
 
3348
 
 
3349
 
 
3350
def subprocess_decorator(suite):
 
3351
    concurrency = osutils.local_concurrency()
 
3352
    if concurrency == 1:
 
3353
        return suite
 
3354
    from testtools import ConcurrentTestSuite
 
3355
    return ConcurrentTestSuite(suite, reinvoke_for_tests)
 
3356
parallel_registry.register('subprocess', subprocess_decorator)
 
3357
 
 
3358
 
 
3359
def exclude_tests(exclude_pattern):
 
3360
    """Return a test suite decorator that excludes tests."""
 
3361
    if exclude_pattern is None:
 
3362
        return identity_decorator
 
3363
    def decorator(suite):
 
3364
        return ExcludeDecorator(suite, exclude_pattern)
 
3365
    return decorator
 
3366
 
 
3367
 
 
3368
def filter_tests(pattern):
 
3369
    if pattern == '.*':
 
3370
        return identity_decorator
 
3371
    def decorator(suite):
 
3372
        return FilterTestsDecorator(suite, pattern)
 
3373
    return decorator
 
3374
 
 
3375
 
 
3376
def random_order(random_seed, runner):
 
3377
    """Return a test suite decorator factory for randomising tests order.
 
3378
    
 
3379
    :param random_seed: now, a string which casts to a long, or a long.
 
3380
    :param runner: A test runner with a stream attribute to report on.
 
3381
    """
 
3382
    if random_seed is None:
 
3383
        return identity_decorator
 
3384
    def decorator(suite):
 
3385
        return RandomDecorator(suite, random_seed, runner.stream)
 
3386
    return decorator
 
3387
 
 
3388
 
 
3389
def tests_first(pattern):
 
3390
    if pattern == '.*':
 
3391
        return identity_decorator
 
3392
    def decorator(suite):
 
3393
        return TestFirstDecorator(suite, pattern)
 
3394
    return decorator
 
3395
 
 
3396
 
 
3397
def identity_decorator(suite):
 
3398
    """Return suite."""
 
3399
    return suite
 
3400
 
 
3401
 
 
3402
class TestDecorator(TestUtil.TestSuite):
 
3403
    """A decorator for TestCase/TestSuite objects.
 
3404
 
 
3405
    Contains rather than flattening suite passed on construction
 
3406
    """
 
3407
 
 
3408
    def __init__(self, suite=None):
 
3409
        super(TestDecorator, self).__init__()
 
3410
        if suite is not None:
 
3411
            self.addTest(suite)
 
3412
 
 
3413
    # Don't need subclass run method with suite emptying
 
3414
    run = unittest.TestSuite.run
 
3415
 
 
3416
 
 
3417
class CountingDecorator(TestDecorator):
 
3418
    """A decorator which calls result.progress(self.countTestCases)."""
 
3419
 
 
3420
    def run(self, result):
 
3421
        progress_method = getattr(result, 'progress', None)
 
3422
        if callable(progress_method):
 
3423
            progress_method(self.countTestCases(), SUBUNIT_SEEK_SET)
 
3424
        return super(CountingDecorator, self).run(result)
 
3425
 
 
3426
 
 
3427
class ExcludeDecorator(TestDecorator):
 
3428
    """A decorator which excludes test matching an exclude pattern."""
 
3429
 
 
3430
    def __init__(self, suite, exclude_pattern):
 
3431
        super(ExcludeDecorator, self).__init__(
 
3432
            exclude_tests_by_re(suite, exclude_pattern))
 
3433
 
 
3434
 
 
3435
class FilterTestsDecorator(TestDecorator):
 
3436
    """A decorator which filters tests to those matching a pattern."""
 
3437
 
 
3438
    def __init__(self, suite, pattern):
 
3439
        super(FilterTestsDecorator, self).__init__(
 
3440
            filter_suite_by_re(suite, pattern))
 
3441
 
 
3442
 
 
3443
class RandomDecorator(TestDecorator):
 
3444
    """A decorator which randomises the order of its tests."""
 
3445
 
 
3446
    def __init__(self, suite, random_seed, stream):
 
3447
        random_seed = self.actual_seed(random_seed)
 
3448
        stream.write("Randomizing test order using seed %s\n\n" %
 
3449
            (random_seed,))
 
3450
        # Initialise the random number generator.
 
3451
        random.seed(random_seed)
 
3452
        super(RandomDecorator, self).__init__(randomize_suite(suite))
 
3453
 
 
3454
    @staticmethod
 
3455
    def actual_seed(seed):
 
3456
        if seed == "now":
 
3457
            # We convert the seed to a long to make it reuseable across
 
3458
            # invocations (because the user can reenter it).
 
3459
            return long(time.time())
2196
3460
        else:
2197
3461
            # Convert the seed to a long if we can
2198
3462
            try:
2199
 
                random_seed = long(random_seed)
 
3463
                return long(seed)
 
3464
            except (TypeError, ValueError):
 
3465
                pass
 
3466
        return seed
 
3467
 
 
3468
 
 
3469
class TestFirstDecorator(TestDecorator):
 
3470
    """A decorator which moves named tests to the front."""
 
3471
 
 
3472
    def __init__(self, suite, pattern):
 
3473
        super(TestFirstDecorator, self).__init__()
 
3474
        self.addTests(split_suite_by_re(suite, pattern))
 
3475
 
 
3476
 
 
3477
def partition_tests(suite, count):
 
3478
    """Partition suite into count lists of tests."""
 
3479
    # This just assigns tests in a round-robin fashion.  On one hand this
 
3480
    # splits up blocks of related tests that might run faster if they shared
 
3481
    # resources, but on the other it avoids assigning blocks of slow tests to
 
3482
    # just one partition.  So the slowest partition shouldn't be much slower
 
3483
    # than the fastest.
 
3484
    partitions = [list() for i in range(count)]
 
3485
    tests = iter_suite_tests(suite)
 
3486
    for partition, test in itertools.izip(itertools.cycle(partitions), tests):
 
3487
        partition.append(test)
 
3488
    return partitions
 
3489
 
 
3490
 
 
3491
def workaround_zealous_crypto_random():
 
3492
    """Crypto.Random want to help us being secure, but we don't care here.
 
3493
 
 
3494
    This workaround some test failure related to the sftp server. Once paramiko
 
3495
    stop using the controversial API in Crypto.Random, we may get rid of it.
 
3496
    """
 
3497
    try:
 
3498
        from Crypto.Random import atfork
 
3499
        atfork()
 
3500
    except ImportError:
 
3501
        pass
 
3502
 
 
3503
 
 
3504
def fork_for_tests(suite):
 
3505
    """Take suite and start up one runner per CPU by forking()
 
3506
 
 
3507
    :return: An iterable of TestCase-like objects which can each have
 
3508
        run(result) called on them to feed tests to result.
 
3509
    """
 
3510
    concurrency = osutils.local_concurrency()
 
3511
    result = []
 
3512
    from subunit import ProtocolTestCase
 
3513
    from subunit.test_results import AutoTimingTestResultDecorator
 
3514
    class TestInOtherProcess(ProtocolTestCase):
 
3515
        # Should be in subunit, I think. RBC.
 
3516
        def __init__(self, stream, pid):
 
3517
            ProtocolTestCase.__init__(self, stream)
 
3518
            self.pid = pid
 
3519
 
 
3520
        def run(self, result):
 
3521
            try:
 
3522
                ProtocolTestCase.run(self, result)
 
3523
            finally:
 
3524
                pid, status = os.waitpid(self.pid, 0)
 
3525
            # GZ 2011-10-18: If status is nonzero, should report to the result
 
3526
            #                that something went wrong.
 
3527
 
 
3528
    test_blocks = partition_tests(suite, concurrency)
 
3529
    # Clear the tests from the original suite so it doesn't keep them alive
 
3530
    suite._tests[:] = []
 
3531
    for process_tests in test_blocks:
 
3532
        process_suite = TestUtil.TestSuite(process_tests)
 
3533
        # Also clear each split list so new suite has only reference
 
3534
        process_tests[:] = []
 
3535
        c2pread, c2pwrite = os.pipe()
 
3536
        pid = os.fork()
 
3537
        if pid == 0:
 
3538
            try:
 
3539
                stream = os.fdopen(c2pwrite, 'wb', 1)
 
3540
                workaround_zealous_crypto_random()
 
3541
                os.close(c2pread)
 
3542
                # Leave stderr and stdout open so we can see test noise
 
3543
                # Close stdin so that the child goes away if it decides to
 
3544
                # read from stdin (otherwise its a roulette to see what
 
3545
                # child actually gets keystrokes for pdb etc).
 
3546
                sys.stdin.close()
 
3547
                subunit_result = AutoTimingTestResultDecorator(
 
3548
                    SubUnitBzrProtocolClient(stream))
 
3549
                process_suite.run(subunit_result)
2200
3550
            except:
2201
 
                pass
2202
 
        runner.stream.writeln("Randomizing test order using seed %s\n" %
2203
 
            (random_seed))
2204
 
        random.seed(random_seed)
2205
 
    # Customise the list of tests if requested
2206
 
    if pattern != '.*' or exclude_pattern is not None or random_order:
2207
 
        if matching_tests_first:
2208
 
            suite = sort_suite_by_re(suite, pattern, exclude_pattern,
2209
 
                random_order)
 
3551
                # Try and report traceback on stream, but exit with error even
 
3552
                # if stream couldn't be created or something else goes wrong.
 
3553
                # The traceback is formatted to a string and written in one go
 
3554
                # to avoid interleaving lines from multiple failing children.
 
3555
                try:
 
3556
                    stream.write(traceback.format_exc())
 
3557
                finally:
 
3558
                    os._exit(1)
 
3559
            os._exit(0)
2210
3560
        else:
2211
 
            suite = filter_suite_by_re(suite, pattern, exclude_pattern,
2212
 
                random_order)
2213
 
    result = runner.run(suite)
2214
 
    return result.wasSuccessful()
 
3561
            os.close(c2pwrite)
 
3562
            stream = os.fdopen(c2pread, 'rb', 1)
 
3563
            test = TestInOtherProcess(stream, pid)
 
3564
            result.append(test)
 
3565
    return result
 
3566
 
 
3567
 
 
3568
def reinvoke_for_tests(suite):
 
3569
    """Take suite and start up one runner per CPU using subprocess().
 
3570
 
 
3571
    :return: An iterable of TestCase-like objects which can each have
 
3572
        run(result) called on them to feed tests to result.
 
3573
    """
 
3574
    concurrency = osutils.local_concurrency()
 
3575
    result = []
 
3576
    from subunit import ProtocolTestCase
 
3577
    class TestInSubprocess(ProtocolTestCase):
 
3578
        def __init__(self, process, name):
 
3579
            ProtocolTestCase.__init__(self, process.stdout)
 
3580
            self.process = process
 
3581
            self.process.stdin.close()
 
3582
            self.name = name
 
3583
 
 
3584
        def run(self, result):
 
3585
            try:
 
3586
                ProtocolTestCase.run(self, result)
 
3587
            finally:
 
3588
                self.process.wait()
 
3589
                os.unlink(self.name)
 
3590
            # print "pid %d finished" % finished_process
 
3591
    test_blocks = partition_tests(suite, concurrency)
 
3592
    for process_tests in test_blocks:
 
3593
        # ugly; currently reimplement rather than reuses TestCase methods.
 
3594
        bzr_path = os.path.dirname(os.path.dirname(bzrlib.__file__))+'/bzr'
 
3595
        if not os.path.isfile(bzr_path):
 
3596
            # We are probably installed. Assume sys.argv is the right file
 
3597
            bzr_path = sys.argv[0]
 
3598
        bzr_path = [bzr_path]
 
3599
        if sys.platform == "win32":
 
3600
            # if we're on windows, we can't execute the bzr script directly
 
3601
            bzr_path = [sys.executable] + bzr_path
 
3602
        fd, test_list_file_name = tempfile.mkstemp()
 
3603
        test_list_file = os.fdopen(fd, 'wb', 1)
 
3604
        for test in process_tests:
 
3605
            test_list_file.write(test.id() + '\n')
 
3606
        test_list_file.close()
 
3607
        try:
 
3608
            argv = bzr_path + ['selftest', '--load-list', test_list_file_name,
 
3609
                '--subunit']
 
3610
            if '--no-plugins' in sys.argv:
 
3611
                argv.append('--no-plugins')
 
3612
            # stderr=subprocess.STDOUT would be ideal, but until we prevent
 
3613
            # noise on stderr it can interrupt the subunit protocol.
 
3614
            process = subprocess.Popen(argv, stdin=subprocess.PIPE,
 
3615
                                      stdout=subprocess.PIPE,
 
3616
                                      stderr=subprocess.PIPE,
 
3617
                                      bufsize=1)
 
3618
            test = TestInSubprocess(process, test_list_file_name)
 
3619
            result.append(test)
 
3620
        except:
 
3621
            os.unlink(test_list_file_name)
 
3622
            raise
 
3623
    return result
 
3624
 
 
3625
 
 
3626
class ProfileResult(testtools.ExtendedToOriginalDecorator):
 
3627
    """Generate profiling data for all activity between start and success.
 
3628
    
 
3629
    The profile data is appended to the test's _benchcalls attribute and can
 
3630
    be accessed by the forwarded-to TestResult.
 
3631
 
 
3632
    While it might be cleaner do accumulate this in stopTest, addSuccess is
 
3633
    where our existing output support for lsprof is, and this class aims to
 
3634
    fit in with that: while it could be moved it's not necessary to accomplish
 
3635
    test profiling, nor would it be dramatically cleaner.
 
3636
    """
 
3637
 
 
3638
    def startTest(self, test):
 
3639
        self.profiler = bzrlib.lsprof.BzrProfiler()
 
3640
        # Prevent deadlocks in tests that use lsprof: those tests will
 
3641
        # unavoidably fail.
 
3642
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
 
3643
        self.profiler.start()
 
3644
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
 
3645
 
 
3646
    def addSuccess(self, test):
 
3647
        stats = self.profiler.stop()
 
3648
        try:
 
3649
            calls = test._benchcalls
 
3650
        except AttributeError:
 
3651
            test._benchcalls = []
 
3652
            calls = test._benchcalls
 
3653
        calls.append(((test.id(), "", ""), stats))
 
3654
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
 
3655
 
 
3656
    def stopTest(self, test):
 
3657
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
 
3658
        self.profiler = None
 
3659
 
 
3660
 
 
3661
# Controlled by "bzr selftest -E=..." option
 
3662
# Currently supported:
 
3663
#   -Eallow_debug           Will no longer clear debug.debug_flags() so it
 
3664
#                           preserves any flags supplied at the command line.
 
3665
#   -Edisable_lock_checks   Turns errors in mismatched locks into simple prints
 
3666
#                           rather than failing tests. And no longer raise
 
3667
#                           LockContention when fctnl locks are not being used
 
3668
#                           with proper exclusion rules.
 
3669
#   -Ethreads               Will display thread ident at creation/join time to
 
3670
#                           help track thread leaks
 
3671
#   -Euncollected_cases     Display the identity of any test cases that weren't
 
3672
#                           deallocated after being completed.
 
3673
#   -Econfig_stats          Will collect statistics using addDetail
 
3674
selftest_debug_flags = set()
2215
3675
 
2216
3676
 
2217
3677
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
2220
3680
             lsprof_timed=None,
2221
3681
             bench_history=None,
2222
3682
             matching_tests_first=None,
2223
 
             numbered_dirs=None,
2224
3683
             list_only=False,
2225
3684
             random_seed=None,
2226
 
             exclude_pattern=None):
 
3685
             exclude_pattern=None,
 
3686
             strict=False,
 
3687
             load_list=None,
 
3688
             debug_flags=None,
 
3689
             starting_with=None,
 
3690
             runner_class=None,
 
3691
             suite_decorators=None,
 
3692
             stream=None,
 
3693
             lsprof_tests=False,
 
3694
             ):
2227
3695
    """Run the whole test suite under the enhanced runner"""
2228
3696
    # XXX: Very ugly way to do this...
2229
3697
    # Disable warning about old formats because we don't want it to disturb
2236
3704
        transport = default_transport
2237
3705
    old_transport = default_transport
2238
3706
    default_transport = transport
 
3707
    global selftest_debug_flags
 
3708
    old_debug_flags = selftest_debug_flags
 
3709
    if debug_flags is not None:
 
3710
        selftest_debug_flags = set(debug_flags)
2239
3711
    try:
 
3712
        if load_list is None:
 
3713
            keep_only = None
 
3714
        else:
 
3715
            keep_only = load_test_id_list(load_list)
 
3716
        if starting_with:
 
3717
            starting_with = [test_prefix_alias_registry.resolve_alias(start)
 
3718
                             for start in starting_with]
2240
3719
        if test_suite_factory is None:
2241
 
            suite = test_suite()
 
3720
            # Reduce loading time by loading modules based on the starting_with
 
3721
            # patterns.
 
3722
            suite = test_suite(keep_only, starting_with)
2242
3723
        else:
2243
3724
            suite = test_suite_factory()
 
3725
        if starting_with:
 
3726
            # But always filter as requested.
 
3727
            suite = filter_suite_by_id_startswith(suite, starting_with)
 
3728
        result_decorators = []
 
3729
        if lsprof_tests:
 
3730
            result_decorators.append(ProfileResult)
2244
3731
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2245
3732
                     stop_on_failure=stop_on_failure,
2246
3733
                     transport=transport,
2247
3734
                     lsprof_timed=lsprof_timed,
2248
3735
                     bench_history=bench_history,
2249
3736
                     matching_tests_first=matching_tests_first,
2250
 
                     numbered_dirs=numbered_dirs,
2251
3737
                     list_only=list_only,
2252
3738
                     random_seed=random_seed,
2253
 
                     exclude_pattern=exclude_pattern)
 
3739
                     exclude_pattern=exclude_pattern,
 
3740
                     strict=strict,
 
3741
                     runner_class=runner_class,
 
3742
                     suite_decorators=suite_decorators,
 
3743
                     stream=stream,
 
3744
                     result_decorators=result_decorators,
 
3745
                     )
2254
3746
    finally:
2255
3747
        default_transport = old_transport
2256
 
 
2257
 
 
2258
 
def test_suite():
 
3748
        selftest_debug_flags = old_debug_flags
 
3749
 
 
3750
 
 
3751
def load_test_id_list(file_name):
 
3752
    """Load a test id list from a text file.
 
3753
 
 
3754
    The format is one test id by line.  No special care is taken to impose
 
3755
    strict rules, these test ids are used to filter the test suite so a test id
 
3756
    that do not match an existing test will do no harm. This allows user to add
 
3757
    comments, leave blank lines, etc.
 
3758
    """
 
3759
    test_list = []
 
3760
    try:
 
3761
        ftest = open(file_name, 'rt')
 
3762
    except IOError, e:
 
3763
        if e.errno != errno.ENOENT:
 
3764
            raise
 
3765
        else:
 
3766
            raise errors.NoSuchFile(file_name)
 
3767
 
 
3768
    for test_name in ftest.readlines():
 
3769
        test_list.append(test_name.strip())
 
3770
    ftest.close()
 
3771
    return test_list
 
3772
 
 
3773
 
 
3774
def suite_matches_id_list(test_suite, id_list):
 
3775
    """Warns about tests not appearing or appearing more than once.
 
3776
 
 
3777
    :param test_suite: A TestSuite object.
 
3778
    :param test_id_list: The list of test ids that should be found in
 
3779
         test_suite.
 
3780
 
 
3781
    :return: (absents, duplicates) absents is a list containing the test found
 
3782
        in id_list but not in test_suite, duplicates is a list containing the
 
3783
        test found multiple times in test_suite.
 
3784
 
 
3785
    When using a prefined test id list, it may occurs that some tests do not
 
3786
    exist anymore or that some tests use the same id. This function warns the
 
3787
    tester about potential problems in his workflow (test lists are volatile)
 
3788
    or in the test suite itself (using the same id for several tests does not
 
3789
    help to localize defects).
 
3790
    """
 
3791
    # Build a dict counting id occurrences
 
3792
    tests = dict()
 
3793
    for test in iter_suite_tests(test_suite):
 
3794
        id = test.id()
 
3795
        tests[id] = tests.get(id, 0) + 1
 
3796
 
 
3797
    not_found = []
 
3798
    duplicates = []
 
3799
    for id in id_list:
 
3800
        occurs = tests.get(id, 0)
 
3801
        if not occurs:
 
3802
            not_found.append(id)
 
3803
        elif occurs > 1:
 
3804
            duplicates.append(id)
 
3805
 
 
3806
    return not_found, duplicates
 
3807
 
 
3808
 
 
3809
class TestIdList(object):
 
3810
    """Test id list to filter a test suite.
 
3811
 
 
3812
    Relying on the assumption that test ids are built as:
 
3813
    <module>[.<class>.<method>][(<param>+)], <module> being in python dotted
 
3814
    notation, this class offers methods to :
 
3815
    - avoid building a test suite for modules not refered to in the test list,
 
3816
    - keep only the tests listed from the module test suite.
 
3817
    """
 
3818
 
 
3819
    def __init__(self, test_id_list):
 
3820
        # When a test suite needs to be filtered against us we compare test ids
 
3821
        # for equality, so a simple dict offers a quick and simple solution.
 
3822
        self.tests = dict().fromkeys(test_id_list, True)
 
3823
 
 
3824
        # While unittest.TestCase have ids like:
 
3825
        # <module>.<class>.<method>[(<param+)],
 
3826
        # doctest.DocTestCase can have ids like:
 
3827
        # <module>
 
3828
        # <module>.<class>
 
3829
        # <module>.<function>
 
3830
        # <module>.<class>.<method>
 
3831
 
 
3832
        # Since we can't predict a test class from its name only, we settle on
 
3833
        # a simple constraint: a test id always begins with its module name.
 
3834
 
 
3835
        modules = {}
 
3836
        for test_id in test_id_list:
 
3837
            parts = test_id.split('.')
 
3838
            mod_name = parts.pop(0)
 
3839
            modules[mod_name] = True
 
3840
            for part in parts:
 
3841
                mod_name += '.' + part
 
3842
                modules[mod_name] = True
 
3843
        self.modules = modules
 
3844
 
 
3845
    def refers_to(self, module_name):
 
3846
        """Is there tests for the module or one of its sub modules."""
 
3847
        return self.modules.has_key(module_name)
 
3848
 
 
3849
    def includes(self, test_id):
 
3850
        return self.tests.has_key(test_id)
 
3851
 
 
3852
 
 
3853
class TestPrefixAliasRegistry(registry.Registry):
 
3854
    """A registry for test prefix aliases.
 
3855
 
 
3856
    This helps implement shorcuts for the --starting-with selftest
 
3857
    option. Overriding existing prefixes is not allowed but not fatal (a
 
3858
    warning will be emitted).
 
3859
    """
 
3860
 
 
3861
    def register(self, key, obj, help=None, info=None,
 
3862
                 override_existing=False):
 
3863
        """See Registry.register.
 
3864
 
 
3865
        Trying to override an existing alias causes a warning to be emitted,
 
3866
        not a fatal execption.
 
3867
        """
 
3868
        try:
 
3869
            super(TestPrefixAliasRegistry, self).register(
 
3870
                key, obj, help=help, info=info, override_existing=False)
 
3871
        except KeyError:
 
3872
            actual = self.get(key)
 
3873
            trace.note(
 
3874
                'Test prefix alias %s is already used for %s, ignoring %s'
 
3875
                % (key, actual, obj))
 
3876
 
 
3877
    def resolve_alias(self, id_start):
 
3878
        """Replace the alias by the prefix in the given string.
 
3879
 
 
3880
        Using an unknown prefix is an error to help catching typos.
 
3881
        """
 
3882
        parts = id_start.split('.')
 
3883
        try:
 
3884
            parts[0] = self.get(parts[0])
 
3885
        except KeyError:
 
3886
            raise errors.BzrCommandError(
 
3887
                '%s is not a known test prefix alias' % parts[0])
 
3888
        return '.'.join(parts)
 
3889
 
 
3890
 
 
3891
test_prefix_alias_registry = TestPrefixAliasRegistry()
 
3892
"""Registry of test prefix aliases."""
 
3893
 
 
3894
 
 
3895
# This alias allows to detect typos ('bzrlin.') by making all valid test ids
 
3896
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
 
3897
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
 
3898
 
 
3899
# Obvious highest levels prefixes, feel free to add your own via a plugin
 
3900
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
 
3901
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
 
3902
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
 
3903
test_prefix_alias_registry.register('bb', 'bzrlib.tests.blackbox')
 
3904
test_prefix_alias_registry.register('bp', 'bzrlib.plugins')
 
3905
 
 
3906
 
 
3907
def _test_suite_testmod_names():
 
3908
    """Return the standard list of test module names to test."""
 
3909
    return [
 
3910
        'bzrlib.doc',
 
3911
        'bzrlib.tests.blackbox',
 
3912
        'bzrlib.tests.commands',
 
3913
        'bzrlib.tests.per_branch',
 
3914
        'bzrlib.tests.per_bzrdir',
 
3915
        'bzrlib.tests.per_controldir',
 
3916
        'bzrlib.tests.per_controldir_colo',
 
3917
        'bzrlib.tests.per_foreign_vcs',
 
3918
        'bzrlib.tests.per_interrepository',
 
3919
        'bzrlib.tests.per_intertree',
 
3920
        'bzrlib.tests.per_inventory',
 
3921
        'bzrlib.tests.per_interbranch',
 
3922
        'bzrlib.tests.per_lock',
 
3923
        'bzrlib.tests.per_merger',
 
3924
        'bzrlib.tests.per_transport',
 
3925
        'bzrlib.tests.per_tree',
 
3926
        'bzrlib.tests.per_pack_repository',
 
3927
        'bzrlib.tests.per_repository',
 
3928
        'bzrlib.tests.per_repository_chk',
 
3929
        'bzrlib.tests.per_repository_reference',
 
3930
        'bzrlib.tests.per_repository_vf',
 
3931
        'bzrlib.tests.per_uifactory',
 
3932
        'bzrlib.tests.per_versionedfile',
 
3933
        'bzrlib.tests.per_workingtree',
 
3934
        'bzrlib.tests.test__annotator',
 
3935
        'bzrlib.tests.test__bencode',
 
3936
        'bzrlib.tests.test__btree_serializer',
 
3937
        'bzrlib.tests.test__chk_map',
 
3938
        'bzrlib.tests.test__dirstate_helpers',
 
3939
        'bzrlib.tests.test__groupcompress',
 
3940
        'bzrlib.tests.test__known_graph',
 
3941
        'bzrlib.tests.test__rio',
 
3942
        'bzrlib.tests.test__simple_set',
 
3943
        'bzrlib.tests.test__static_tuple',
 
3944
        'bzrlib.tests.test__walkdirs_win32',
 
3945
        'bzrlib.tests.test_ancestry',
 
3946
        'bzrlib.tests.test_annotate',
 
3947
        'bzrlib.tests.test_api',
 
3948
        'bzrlib.tests.test_atomicfile',
 
3949
        'bzrlib.tests.test_bad_files',
 
3950
        'bzrlib.tests.test_bisect_multi',
 
3951
        'bzrlib.tests.test_branch',
 
3952
        'bzrlib.tests.test_branchbuilder',
 
3953
        'bzrlib.tests.test_btree_index',
 
3954
        'bzrlib.tests.test_bugtracker',
 
3955
        'bzrlib.tests.test_bundle',
 
3956
        'bzrlib.tests.test_bzrdir',
 
3957
        'bzrlib.tests.test__chunks_to_lines',
 
3958
        'bzrlib.tests.test_cache_utf8',
 
3959
        'bzrlib.tests.test_chk_map',
 
3960
        'bzrlib.tests.test_chk_serializer',
 
3961
        'bzrlib.tests.test_chunk_writer',
 
3962
        'bzrlib.tests.test_clean_tree',
 
3963
        'bzrlib.tests.test_cleanup',
 
3964
        'bzrlib.tests.test_cmdline',
 
3965
        'bzrlib.tests.test_commands',
 
3966
        'bzrlib.tests.test_commit',
 
3967
        'bzrlib.tests.test_commit_merge',
 
3968
        'bzrlib.tests.test_config',
 
3969
        'bzrlib.tests.test_conflicts',
 
3970
        'bzrlib.tests.test_controldir',
 
3971
        'bzrlib.tests.test_counted_lock',
 
3972
        'bzrlib.tests.test_crash',
 
3973
        'bzrlib.tests.test_decorators',
 
3974
        'bzrlib.tests.test_delta',
 
3975
        'bzrlib.tests.test_debug',
 
3976
        'bzrlib.tests.test_diff',
 
3977
        'bzrlib.tests.test_directory_service',
 
3978
        'bzrlib.tests.test_dirstate',
 
3979
        'bzrlib.tests.test_email_message',
 
3980
        'bzrlib.tests.test_eol_filters',
 
3981
        'bzrlib.tests.test_errors',
 
3982
        'bzrlib.tests.test_estimate_compressed_size',
 
3983
        'bzrlib.tests.test_export',
 
3984
        'bzrlib.tests.test_export_pot',
 
3985
        'bzrlib.tests.test_extract',
 
3986
        'bzrlib.tests.test_features',
 
3987
        'bzrlib.tests.test_fetch',
 
3988
        'bzrlib.tests.test_fixtures',
 
3989
        'bzrlib.tests.test_fifo_cache',
 
3990
        'bzrlib.tests.test_filters',
 
3991
        'bzrlib.tests.test_filter_tree',
 
3992
        'bzrlib.tests.test_ftp_transport',
 
3993
        'bzrlib.tests.test_foreign',
 
3994
        'bzrlib.tests.test_generate_docs',
 
3995
        'bzrlib.tests.test_generate_ids',
 
3996
        'bzrlib.tests.test_globbing',
 
3997
        'bzrlib.tests.test_gpg',
 
3998
        'bzrlib.tests.test_graph',
 
3999
        'bzrlib.tests.test_groupcompress',
 
4000
        'bzrlib.tests.test_hashcache',
 
4001
        'bzrlib.tests.test_help',
 
4002
        'bzrlib.tests.test_hooks',
 
4003
        'bzrlib.tests.test_http',
 
4004
        'bzrlib.tests.test_http_response',
 
4005
        'bzrlib.tests.test_https_ca_bundle',
 
4006
        'bzrlib.tests.test_https_urllib',
 
4007
        'bzrlib.tests.test_i18n',
 
4008
        'bzrlib.tests.test_identitymap',
 
4009
        'bzrlib.tests.test_ignores',
 
4010
        'bzrlib.tests.test_index',
 
4011
        'bzrlib.tests.test_import_tariff',
 
4012
        'bzrlib.tests.test_info',
 
4013
        'bzrlib.tests.test_inv',
 
4014
        'bzrlib.tests.test_inventory_delta',
 
4015
        'bzrlib.tests.test_knit',
 
4016
        'bzrlib.tests.test_lazy_import',
 
4017
        'bzrlib.tests.test_lazy_regex',
 
4018
        'bzrlib.tests.test_library_state',
 
4019
        'bzrlib.tests.test_lock',
 
4020
        'bzrlib.tests.test_lockable_files',
 
4021
        'bzrlib.tests.test_lockdir',
 
4022
        'bzrlib.tests.test_log',
 
4023
        'bzrlib.tests.test_lru_cache',
 
4024
        'bzrlib.tests.test_lsprof',
 
4025
        'bzrlib.tests.test_mail_client',
 
4026
        'bzrlib.tests.test_matchers',
 
4027
        'bzrlib.tests.test_memorytree',
 
4028
        'bzrlib.tests.test_merge',
 
4029
        'bzrlib.tests.test_merge3',
 
4030
        'bzrlib.tests.test_merge_core',
 
4031
        'bzrlib.tests.test_merge_directive',
 
4032
        'bzrlib.tests.test_mergetools',
 
4033
        'bzrlib.tests.test_missing',
 
4034
        'bzrlib.tests.test_msgeditor',
 
4035
        'bzrlib.tests.test_multiparent',
 
4036
        'bzrlib.tests.test_mutabletree',
 
4037
        'bzrlib.tests.test_nonascii',
 
4038
        'bzrlib.tests.test_options',
 
4039
        'bzrlib.tests.test_osutils',
 
4040
        'bzrlib.tests.test_osutils_encodings',
 
4041
        'bzrlib.tests.test_pack',
 
4042
        'bzrlib.tests.test_patch',
 
4043
        'bzrlib.tests.test_patches',
 
4044
        'bzrlib.tests.test_permissions',
 
4045
        'bzrlib.tests.test_plugins',
 
4046
        'bzrlib.tests.test_progress',
 
4047
        'bzrlib.tests.test_pyutils',
 
4048
        'bzrlib.tests.test_read_bundle',
 
4049
        'bzrlib.tests.test_reconcile',
 
4050
        'bzrlib.tests.test_reconfigure',
 
4051
        'bzrlib.tests.test_registry',
 
4052
        'bzrlib.tests.test_remote',
 
4053
        'bzrlib.tests.test_rename_map',
 
4054
        'bzrlib.tests.test_repository',
 
4055
        'bzrlib.tests.test_revert',
 
4056
        'bzrlib.tests.test_revision',
 
4057
        'bzrlib.tests.test_revisionspec',
 
4058
        'bzrlib.tests.test_revisiontree',
 
4059
        'bzrlib.tests.test_rio',
 
4060
        'bzrlib.tests.test_rules',
 
4061
        'bzrlib.tests.test_url_policy_open',
 
4062
        'bzrlib.tests.test_sampler',
 
4063
        'bzrlib.tests.test_scenarios',
 
4064
        'bzrlib.tests.test_script',
 
4065
        'bzrlib.tests.test_selftest',
 
4066
        'bzrlib.tests.test_serializer',
 
4067
        'bzrlib.tests.test_setup',
 
4068
        'bzrlib.tests.test_sftp_transport',
 
4069
        'bzrlib.tests.test_shelf',
 
4070
        'bzrlib.tests.test_shelf_ui',
 
4071
        'bzrlib.tests.test_smart',
 
4072
        'bzrlib.tests.test_smart_add',
 
4073
        'bzrlib.tests.test_smart_request',
 
4074
        'bzrlib.tests.test_smart_signals',
 
4075
        'bzrlib.tests.test_smart_transport',
 
4076
        'bzrlib.tests.test_smtp_connection',
 
4077
        'bzrlib.tests.test_source',
 
4078
        'bzrlib.tests.test_ssh_transport',
 
4079
        'bzrlib.tests.test_status',
 
4080
        'bzrlib.tests.test_store',
 
4081
        'bzrlib.tests.test_strace',
 
4082
        'bzrlib.tests.test_subsume',
 
4083
        'bzrlib.tests.test_switch',
 
4084
        'bzrlib.tests.test_symbol_versioning',
 
4085
        'bzrlib.tests.test_tag',
 
4086
        'bzrlib.tests.test_test_server',
 
4087
        'bzrlib.tests.test_testament',
 
4088
        'bzrlib.tests.test_textfile',
 
4089
        'bzrlib.tests.test_textmerge',
 
4090
        'bzrlib.tests.test_cethread',
 
4091
        'bzrlib.tests.test_timestamp',
 
4092
        'bzrlib.tests.test_trace',
 
4093
        'bzrlib.tests.test_transactions',
 
4094
        'bzrlib.tests.test_transform',
 
4095
        'bzrlib.tests.test_transport',
 
4096
        'bzrlib.tests.test_transport_log',
 
4097
        'bzrlib.tests.test_tree',
 
4098
        'bzrlib.tests.test_treebuilder',
 
4099
        'bzrlib.tests.test_treeshape',
 
4100
        'bzrlib.tests.test_tsort',
 
4101
        'bzrlib.tests.test_tuned_gzip',
 
4102
        'bzrlib.tests.test_ui',
 
4103
        'bzrlib.tests.test_uncommit',
 
4104
        'bzrlib.tests.test_upgrade',
 
4105
        'bzrlib.tests.test_upgrade_stacked',
 
4106
        'bzrlib.tests.test_urlutils',
 
4107
        'bzrlib.tests.test_utextwrap',
 
4108
        'bzrlib.tests.test_version',
 
4109
        'bzrlib.tests.test_version_info',
 
4110
        'bzrlib.tests.test_versionedfile',
 
4111
        'bzrlib.tests.test_vf_search',
 
4112
        'bzrlib.tests.test_weave',
 
4113
        'bzrlib.tests.test_whitebox',
 
4114
        'bzrlib.tests.test_win32utils',
 
4115
        'bzrlib.tests.test_workingtree',
 
4116
        'bzrlib.tests.test_workingtree_4',
 
4117
        'bzrlib.tests.test_wsgi',
 
4118
        'bzrlib.tests.test_xml',
 
4119
        ]
 
4120
 
 
4121
 
 
4122
def _test_suite_modules_to_doctest():
 
4123
    """Return the list of modules to doctest."""
 
4124
    if __doc__ is None:
 
4125
        # GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
 
4126
        return []
 
4127
    return [
 
4128
        'bzrlib',
 
4129
        'bzrlib.branchbuilder',
 
4130
        'bzrlib.decorators',
 
4131
        'bzrlib.inventory',
 
4132
        'bzrlib.iterablefile',
 
4133
        'bzrlib.lockdir',
 
4134
        'bzrlib.merge3',
 
4135
        'bzrlib.option',
 
4136
        'bzrlib.pyutils',
 
4137
        'bzrlib.symbol_versioning',
 
4138
        'bzrlib.tests',
 
4139
        'bzrlib.tests.fixtures',
 
4140
        'bzrlib.timestamp',
 
4141
        'bzrlib.transport.http',
 
4142
        'bzrlib.version_info_formats.format_custom',
 
4143
        ]
 
4144
 
 
4145
 
 
4146
def test_suite(keep_only=None, starting_with=None):
2259
4147
    """Build and return TestSuite for the whole of bzrlib.
2260
 
    
 
4148
 
 
4149
    :param keep_only: A list of test ids limiting the suite returned.
 
4150
 
 
4151
    :param starting_with: An id limiting the suite returned to the tests
 
4152
         starting with it.
 
4153
 
2261
4154
    This function can be replaced if you need to change the default test
2262
4155
    suite on a global basis, but it is not encouraged.
2263
4156
    """
2264
 
    testmod_names = [
2265
 
                   'bzrlib.tests.test_ancestry',
2266
 
                   'bzrlib.tests.test_annotate',
2267
 
                   'bzrlib.tests.test_api',
2268
 
                   'bzrlib.tests.test_atomicfile',
2269
 
                   'bzrlib.tests.test_bad_files',
2270
 
                   'bzrlib.tests.test_branch',
2271
 
                   'bzrlib.tests.test_branchbuilder',
2272
 
                   'bzrlib.tests.test_bugtracker',
2273
 
                   'bzrlib.tests.test_bundle',
2274
 
                   'bzrlib.tests.test_bzrdir',
2275
 
                   'bzrlib.tests.test_cache_utf8',
2276
 
                   'bzrlib.tests.test_commands',
2277
 
                   'bzrlib.tests.test_commit',
2278
 
                   'bzrlib.tests.test_commit_merge',
2279
 
                   'bzrlib.tests.test_config',
2280
 
                   'bzrlib.tests.test_conflicts',
2281
 
                   'bzrlib.tests.test_pack',
2282
 
                   'bzrlib.tests.test_counted_lock',
2283
 
                   'bzrlib.tests.test_decorators',
2284
 
                   'bzrlib.tests.test_delta',
2285
 
                   'bzrlib.tests.test_deprecated_graph',
2286
 
                   'bzrlib.tests.test_diff',
2287
 
                   'bzrlib.tests.test_dirstate',
2288
 
                   'bzrlib.tests.test_errors',
2289
 
                   'bzrlib.tests.test_escaped_store',
2290
 
                   'bzrlib.tests.test_extract',
2291
 
                   'bzrlib.tests.test_fetch',
2292
 
                   'bzrlib.tests.test_ftp_transport',
2293
 
                   'bzrlib.tests.test_generate_docs',
2294
 
                   'bzrlib.tests.test_generate_ids',
2295
 
                   'bzrlib.tests.test_globbing',
2296
 
                   'bzrlib.tests.test_gpg',
2297
 
                   'bzrlib.tests.test_graph',
2298
 
                   'bzrlib.tests.test_hashcache',
2299
 
                   'bzrlib.tests.test_help',
2300
 
                   'bzrlib.tests.test_hooks',
2301
 
                   'bzrlib.tests.test_http',
2302
 
                   'bzrlib.tests.test_http_response',
2303
 
                   'bzrlib.tests.test_https_ca_bundle',
2304
 
                   'bzrlib.tests.test_identitymap',
2305
 
                   'bzrlib.tests.test_ignores',
2306
 
                   'bzrlib.tests.test_info',
2307
 
                   'bzrlib.tests.test_inv',
2308
 
                   'bzrlib.tests.test_knit',
2309
 
                   'bzrlib.tests.test_lazy_import',
2310
 
                   'bzrlib.tests.test_lazy_regex',
2311
 
                   'bzrlib.tests.test_lockdir',
2312
 
                   'bzrlib.tests.test_lockable_files',
2313
 
                   'bzrlib.tests.test_log',
2314
 
                   'bzrlib.tests.test_lsprof',
2315
 
                   'bzrlib.tests.test_memorytree',
2316
 
                   'bzrlib.tests.test_merge',
2317
 
                   'bzrlib.tests.test_merge3',
2318
 
                   'bzrlib.tests.test_merge_core',
2319
 
                   'bzrlib.tests.test_merge_directive',
2320
 
                   'bzrlib.tests.test_missing',
2321
 
                   'bzrlib.tests.test_msgeditor',
2322
 
                   'bzrlib.tests.test_nonascii',
2323
 
                   'bzrlib.tests.test_options',
2324
 
                   'bzrlib.tests.test_osutils',
2325
 
                   'bzrlib.tests.test_osutils_encodings',
2326
 
                   'bzrlib.tests.test_patch',
2327
 
                   'bzrlib.tests.test_patches',
2328
 
                   'bzrlib.tests.test_permissions',
2329
 
                   'bzrlib.tests.test_plugins',
2330
 
                   'bzrlib.tests.test_progress',
2331
 
                   'bzrlib.tests.test_reconcile',
2332
 
                   'bzrlib.tests.test_registry',
2333
 
                   'bzrlib.tests.test_remote',
2334
 
                   'bzrlib.tests.test_repository',
2335
 
                   'bzrlib.tests.test_revert',
2336
 
                   'bzrlib.tests.test_revision',
2337
 
                   'bzrlib.tests.test_revisionnamespaces',
2338
 
                   'bzrlib.tests.test_revisiontree',
2339
 
                   'bzrlib.tests.test_rio',
2340
 
                   'bzrlib.tests.test_sampler',
2341
 
                   'bzrlib.tests.test_selftest',
2342
 
                   'bzrlib.tests.test_setup',
2343
 
                   'bzrlib.tests.test_sftp_transport',
2344
 
                   'bzrlib.tests.test_smart',
2345
 
                   'bzrlib.tests.test_smart_add',
2346
 
                   'bzrlib.tests.test_smart_transport',
2347
 
                   'bzrlib.tests.test_smtp_connection',
2348
 
                   'bzrlib.tests.test_source',
2349
 
                   'bzrlib.tests.test_ssh_transport',
2350
 
                   'bzrlib.tests.test_status',
2351
 
                   'bzrlib.tests.test_store',
2352
 
                   'bzrlib.tests.test_strace',
2353
 
                   'bzrlib.tests.test_subsume',
2354
 
                   'bzrlib.tests.test_symbol_versioning',
2355
 
                   'bzrlib.tests.test_tag',
2356
 
                   'bzrlib.tests.test_testament',
2357
 
                   'bzrlib.tests.test_textfile',
2358
 
                   'bzrlib.tests.test_textmerge',
2359
 
                   'bzrlib.tests.test_timestamp',
2360
 
                   'bzrlib.tests.test_trace',
2361
 
                   'bzrlib.tests.test_transactions',
2362
 
                   'bzrlib.tests.test_transform',
2363
 
                   'bzrlib.tests.test_transport',
2364
 
                   'bzrlib.tests.test_tree',
2365
 
                   'bzrlib.tests.test_treebuilder',
2366
 
                   'bzrlib.tests.test_tsort',
2367
 
                   'bzrlib.tests.test_tuned_gzip',
2368
 
                   'bzrlib.tests.test_ui',
2369
 
                   'bzrlib.tests.test_upgrade',
2370
 
                   'bzrlib.tests.test_urlutils',
2371
 
                   'bzrlib.tests.test_versionedfile',
2372
 
                   'bzrlib.tests.test_version',
2373
 
                   'bzrlib.tests.test_version_info',
2374
 
                   'bzrlib.tests.test_weave',
2375
 
                   'bzrlib.tests.test_whitebox',
2376
 
                   'bzrlib.tests.test_workingtree',
2377
 
                   'bzrlib.tests.test_workingtree_4',
2378
 
                   'bzrlib.tests.test_wsgi',
2379
 
                   'bzrlib.tests.test_xml',
2380
 
                   ]
2381
 
    test_transport_implementations = [
2382
 
        'bzrlib.tests.test_transport_implementations',
2383
 
        'bzrlib.tests.test_read_bundle',
2384
 
        ]
2385
 
    suite = TestUtil.TestSuite()
 
4157
 
2386
4158
    loader = TestUtil.TestLoader()
2387
 
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2388
 
    from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
2389
 
    adapter = TransportTestProviderAdapter()
2390
 
    adapt_modules(test_transport_implementations, adapter, loader, suite)
2391
 
    for package in packages_to_test():
2392
 
        suite.addTest(package.test_suite())
2393
 
    for m in MODULES_TO_TEST:
2394
 
        suite.addTest(loader.loadTestsFromModule(m))
2395
 
    for m in MODULES_TO_DOCTEST:
 
4159
 
 
4160
    if keep_only is not None:
 
4161
        id_filter = TestIdList(keep_only)
 
4162
    if starting_with:
 
4163
        # We take precedence over keep_only because *at loading time* using
 
4164
        # both options means we will load less tests for the same final result.
 
4165
        def interesting_module(name):
 
4166
            for start in starting_with:
 
4167
                if (
 
4168
                    # Either the module name starts with the specified string
 
4169
                    name.startswith(start)
 
4170
                    # or it may contain tests starting with the specified string
 
4171
                    or start.startswith(name)
 
4172
                    ):
 
4173
                    return True
 
4174
            return False
 
4175
        loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
 
4176
 
 
4177
    elif keep_only is not None:
 
4178
        loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
 
4179
        def interesting_module(name):
 
4180
            return id_filter.refers_to(name)
 
4181
 
 
4182
    else:
 
4183
        loader = TestUtil.TestLoader()
 
4184
        def interesting_module(name):
 
4185
            # No filtering, all modules are interesting
 
4186
            return True
 
4187
 
 
4188
    suite = loader.suiteClass()
 
4189
 
 
4190
    # modules building their suite with loadTestsFromModuleNames
 
4191
    suite.addTest(loader.loadTestsFromModuleNames(_test_suite_testmod_names()))
 
4192
 
 
4193
    for mod in _test_suite_modules_to_doctest():
 
4194
        if not interesting_module(mod):
 
4195
            # No tests to keep here, move along
 
4196
            continue
2396
4197
        try:
2397
 
            suite.addTest(doctest.DocTestSuite(m))
 
4198
            # note that this really does mean "report only" -- doctest
 
4199
            # still runs the rest of the examples
 
4200
            doc_suite = IsolatedDocTestSuite(
 
4201
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
2398
4202
        except ValueError, e:
2399
 
            print '**failed to get doctest for: %s\n%s' %(m,e)
 
4203
            print '**failed to get doctest for: %s\n%s' % (mod, e)
2400
4204
            raise
2401
 
    for name, plugin in bzrlib.plugin.all_plugins().items():
2402
 
        if getattr(plugin, 'test_suite', None) is not None:
2403
 
            default_encoding = sys.getdefaultencoding()
2404
 
            try:
2405
 
                plugin_suite = plugin.test_suite()
2406
 
            except ImportError, e:
2407
 
                bzrlib.trace.warning(
2408
 
                    'Unable to test plugin "%s": %s', name, e)
2409
 
            else:
2410
 
                suite.addTest(plugin_suite)
2411
 
            if default_encoding != sys.getdefaultencoding():
2412
 
                bzrlib.trace.warning(
2413
 
                    'Plugin "%s" tried to reset default encoding to: %s', name,
2414
 
                    sys.getdefaultencoding())
2415
 
                reload(sys)
2416
 
                sys.setdefaultencoding(default_encoding)
 
4205
        if len(doc_suite._tests) == 0:
 
4206
            raise errors.BzrError("no doctests found in %s" % (mod,))
 
4207
        suite.addTest(doc_suite)
 
4208
 
 
4209
    default_encoding = sys.getdefaultencoding()
 
4210
    for name, plugin in _mod_plugin.plugins().items():
 
4211
        if not interesting_module(plugin.module.__name__):
 
4212
            continue
 
4213
        plugin_suite = plugin.test_suite()
 
4214
        # We used to catch ImportError here and turn it into just a warning,
 
4215
        # but really if you don't have --no-plugins this should be a failure.
 
4216
        # mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
 
4217
        if plugin_suite is None:
 
4218
            plugin_suite = plugin.load_plugin_tests(loader)
 
4219
        if plugin_suite is not None:
 
4220
            suite.addTest(plugin_suite)
 
4221
        if default_encoding != sys.getdefaultencoding():
 
4222
            trace.warning(
 
4223
                'Plugin "%s" tried to reset default encoding to: %s', name,
 
4224
                sys.getdefaultencoding())
 
4225
            reload(sys)
 
4226
            sys.setdefaultencoding(default_encoding)
 
4227
 
 
4228
    if keep_only is not None:
 
4229
        # Now that the referred modules have loaded their tests, keep only the
 
4230
        # requested ones.
 
4231
        suite = filter_suite_by_id_list(suite, id_filter)
 
4232
        # Do some sanity checks on the id_list filtering
 
4233
        not_found, duplicates = suite_matches_id_list(suite, keep_only)
 
4234
        if starting_with:
 
4235
            # The tester has used both keep_only and starting_with, so he is
 
4236
            # already aware that some tests are excluded from the list, there
 
4237
            # is no need to tell him which.
 
4238
            pass
 
4239
        else:
 
4240
            # Some tests mentioned in the list are not in the test suite. The
 
4241
            # list may be out of date, report to the tester.
 
4242
            for id in not_found:
 
4243
                trace.warning('"%s" not found in the test suite', id)
 
4244
        for id in duplicates:
 
4245
            trace.warning('"%s" is used as an id by several tests', id)
 
4246
 
2417
4247
    return suite
2418
4248
 
2419
4249
 
2420
 
def adapt_modules(mods_list, adapter, loader, suite):
2421
 
    """Adapt the modules in mods_list using adapter and add to suite."""
2422
 
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
2423
 
        suite.addTests(adapter.adapt(test))
2424
 
 
2425
 
 
2426
 
def _rmtree_temp_dir(dirname):
 
4250
def multiply_scenarios(*scenarios):
 
4251
    """Multiply two or more iterables of scenarios.
 
4252
 
 
4253
    It is safe to pass scenario generators or iterators.
 
4254
 
 
4255
    :returns: A list of compound scenarios: the cross-product of all 
 
4256
        scenarios, with the names concatenated and the parameters
 
4257
        merged together.
 
4258
    """
 
4259
    return reduce(_multiply_two_scenarios, map(list, scenarios))
 
4260
 
 
4261
 
 
4262
def _multiply_two_scenarios(scenarios_left, scenarios_right):
 
4263
    """Multiply two sets of scenarios.
 
4264
 
 
4265
    :returns: the cartesian product of the two sets of scenarios, that is
 
4266
        a scenario for every possible combination of a left scenario and a
 
4267
        right scenario.
 
4268
    """
 
4269
    return [
 
4270
        ('%s,%s' % (left_name, right_name),
 
4271
         dict(left_dict.items() + right_dict.items()))
 
4272
        for left_name, left_dict in scenarios_left
 
4273
        for right_name, right_dict in scenarios_right]
 
4274
 
 
4275
 
 
4276
def multiply_tests(tests, scenarios, result):
 
4277
    """Multiply tests_list by scenarios into result.
 
4278
 
 
4279
    This is the core workhorse for test parameterisation.
 
4280
 
 
4281
    Typically the load_tests() method for a per-implementation test suite will
 
4282
    call multiply_tests and return the result.
 
4283
 
 
4284
    :param tests: The tests to parameterise.
 
4285
    :param scenarios: The scenarios to apply: pairs of (scenario_name,
 
4286
        scenario_param_dict).
 
4287
    :param result: A TestSuite to add created tests to.
 
4288
 
 
4289
    This returns the passed in result TestSuite with the cross product of all
 
4290
    the tests repeated once for each scenario.  Each test is adapted by adding
 
4291
    the scenario name at the end of its id(), and updating the test object's
 
4292
    __dict__ with the scenario_param_dict.
 
4293
 
 
4294
    >>> import bzrlib.tests.test_sampler
 
4295
    >>> r = multiply_tests(
 
4296
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
 
4297
    ...     [('one', dict(param=1)),
 
4298
    ...      ('two', dict(param=2))],
 
4299
    ...     TestUtil.TestSuite())
 
4300
    >>> tests = list(iter_suite_tests(r))
 
4301
    >>> len(tests)
 
4302
    2
 
4303
    >>> tests[0].id()
 
4304
    'bzrlib.tests.test_sampler.DemoTest.test_nothing(one)'
 
4305
    >>> tests[0].param
 
4306
    1
 
4307
    >>> tests[1].param
 
4308
    2
 
4309
    """
 
4310
    for test in iter_suite_tests(tests):
 
4311
        apply_scenarios(test, scenarios, result)
 
4312
    return result
 
4313
 
 
4314
 
 
4315
def apply_scenarios(test, scenarios, result):
 
4316
    """Apply the scenarios in scenarios to test and add to result.
 
4317
 
 
4318
    :param test: The test to apply scenarios to.
 
4319
    :param scenarios: An iterable of scenarios to apply to test.
 
4320
    :return: result
 
4321
    :seealso: apply_scenario
 
4322
    """
 
4323
    for scenario in scenarios:
 
4324
        result.addTest(apply_scenario(test, scenario))
 
4325
    return result
 
4326
 
 
4327
 
 
4328
def apply_scenario(test, scenario):
 
4329
    """Copy test and apply scenario to it.
 
4330
 
 
4331
    :param test: A test to adapt.
 
4332
    :param scenario: A tuple describing the scenarion.
 
4333
        The first element of the tuple is the new test id.
 
4334
        The second element is a dict containing attributes to set on the
 
4335
        test.
 
4336
    :return: The adapted test.
 
4337
    """
 
4338
    new_id = "%s(%s)" % (test.id(), scenario[0])
 
4339
    new_test = clone_test(test, new_id)
 
4340
    for name, value in scenario[1].items():
 
4341
        setattr(new_test, name, value)
 
4342
    return new_test
 
4343
 
 
4344
 
 
4345
def clone_test(test, new_id):
 
4346
    """Clone a test giving it a new id.
 
4347
 
 
4348
    :param test: The test to clone.
 
4349
    :param new_id: The id to assign to it.
 
4350
    :return: The new test.
 
4351
    """
 
4352
    new_test = copy.copy(test)
 
4353
    new_test.id = lambda: new_id
 
4354
    # XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
 
4355
    # causes cloned tests to share the 'details' dict.  This makes it hard to
 
4356
    # read the test output for parameterized tests, because tracebacks will be
 
4357
    # associated with irrelevant tests.
 
4358
    try:
 
4359
        details = new_test._TestCase__details
 
4360
    except AttributeError:
 
4361
        # must be a different version of testtools than expected.  Do nothing.
 
4362
        pass
 
4363
    else:
 
4364
        # Reset the '__details' dict.
 
4365
        new_test._TestCase__details = {}
 
4366
    return new_test
 
4367
 
 
4368
 
 
4369
def permute_tests_for_extension(standard_tests, loader, py_module_name,
 
4370
                                ext_module_name):
 
4371
    """Helper for permutating tests against an extension module.
 
4372
 
 
4373
    This is meant to be used inside a modules 'load_tests()' function. It will
 
4374
    create 2 scenarios, and cause all tests in the 'standard_tests' to be run
 
4375
    against both implementations. Setting 'test.module' to the appropriate
 
4376
    module. See bzrlib.tests.test__chk_map.load_tests as an example.
 
4377
 
 
4378
    :param standard_tests: A test suite to permute
 
4379
    :param loader: A TestLoader
 
4380
    :param py_module_name: The python path to a python module that can always
 
4381
        be loaded, and will be considered the 'python' implementation. (eg
 
4382
        'bzrlib._chk_map_py')
 
4383
    :param ext_module_name: The python path to an extension module. If the
 
4384
        module cannot be loaded, a single test will be added, which notes that
 
4385
        the module is not available. If it can be loaded, all standard_tests
 
4386
        will be run against that module.
 
4387
    :return: (suite, feature) suite is a test-suite that has all the permuted
 
4388
        tests. feature is the Feature object that can be used to determine if
 
4389
        the module is available.
 
4390
    """
 
4391
 
 
4392
    from bzrlib.tests.features import ModuleAvailableFeature
 
4393
    py_module = pyutils.get_named_object(py_module_name)
 
4394
    scenarios = [
 
4395
        ('python', {'module': py_module}),
 
4396
    ]
 
4397
    suite = loader.suiteClass()
 
4398
    feature = ModuleAvailableFeature(ext_module_name)
 
4399
    if feature.available():
 
4400
        scenarios.append(('C', {'module': feature.module}))
 
4401
    else:
 
4402
        # the compiled module isn't available, so we add a failing test
 
4403
        class FailWithoutFeature(TestCase):
 
4404
            def test_fail(self):
 
4405
                self.requireFeature(feature)
 
4406
        suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
 
4407
    result = multiply_tests(standard_tests, scenarios, suite)
 
4408
    return result, feature
 
4409
 
 
4410
 
 
4411
def _rmtree_temp_dir(dirname, test_id=None):
2427
4412
    # If LANG=C we probably have created some bogus paths
2428
4413
    # which rmtree(unicode) will fail to delete
2429
4414
    # so make sure we are using rmtree(str) to delete everything
2438
4423
    try:
2439
4424
        osutils.rmtree(dirname)
2440
4425
    except OSError, e:
2441
 
        if sys.platform == 'win32' and e.errno == errno.EACCES:
2442
 
            print >>sys.stderr, ('Permission denied: '
2443
 
                                 'unable to remove testing dir '
2444
 
                                 '%s' % os.path.basename(dirname))
 
4426
        # We don't want to fail here because some useful display will be lost
 
4427
        # otherwise. Polluting the tmp dir is bad, but not giving all the
 
4428
        # possible info to the test runner is even worse.
 
4429
        if test_id != None:
 
4430
            ui.ui_factory.clear_term()
 
4431
            sys.stderr.write('\nWhile running: %s\n' % (test_id,))
 
4432
        # Ugly, but the last thing we want here is fail, so bear with it.
 
4433
        printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
 
4434
                                    ).encode('ascii', 'replace')
 
4435
        sys.stderr.write('Unable to remove testing dir %s\n%s'
 
4436
                         % (os.path.basename(dirname), printable_e))
 
4437
 
 
4438
 
 
4439
def probe_unicode_in_user_encoding():
 
4440
    """Try to encode several unicode strings to use in unicode-aware tests.
 
4441
    Return first successfull match.
 
4442
 
 
4443
    :return:  (unicode value, encoded plain string value) or (None, None)
 
4444
    """
 
4445
    possible_vals = [u'm\xb5', u'\xe1', u'\u0410']
 
4446
    for uni_val in possible_vals:
 
4447
        try:
 
4448
            str_val = uni_val.encode(osutils.get_user_encoding())
 
4449
        except UnicodeEncodeError:
 
4450
            # Try a different character
 
4451
            pass
2445
4452
        else:
2446
 
            raise
2447
 
 
2448
 
 
2449
 
def clean_selftest_output(root=None, quiet=False):
2450
 
    """Remove all selftest output directories from root directory.
2451
 
 
2452
 
    :param  root:   root directory for clean
2453
 
                    (if ommitted or None then clean current directory).
2454
 
    :param  quiet:  suppress report about deleting directories
 
4453
            return uni_val, str_val
 
4454
    return None, None
 
4455
 
 
4456
 
 
4457
def probe_bad_non_ascii(encoding):
 
4458
    """Try to find [bad] character with code [128..255]
 
4459
    that cannot be decoded to unicode in some encoding.
 
4460
    Return None if all non-ascii characters is valid
 
4461
    for given encoding.
2455
4462
    """
2456
 
    import re
2457
 
    re_dir = re.compile(r'''test\d\d\d\d\.tmp''')
2458
 
    if root is None:
2459
 
        root = u'.'
2460
 
    for i in os.listdir(root):
2461
 
        if os.path.isdir(i) and re_dir.match(i):
2462
 
            if not quiet:
2463
 
                print 'delete directory:', i
2464
 
            _rmtree_temp_dir(i)
2465
 
 
2466
 
 
2467
 
class Feature(object):
2468
 
    """An operating system Feature."""
2469
 
 
2470
 
    def __init__(self):
2471
 
        self._available = None
2472
 
 
2473
 
    def available(self):
2474
 
        """Is the feature available?
2475
 
 
2476
 
        :return: True if the feature is available.
2477
 
        """
2478
 
        if self._available is None:
2479
 
            self._available = self._probe()
2480
 
        return self._available
2481
 
 
2482
 
    def _probe(self):
2483
 
        """Implement this method in concrete features.
2484
 
 
2485
 
        :return: True if the feature is available.
2486
 
        """
2487
 
        raise NotImplementedError
2488
 
 
2489
 
    def __str__(self):
2490
 
        if getattr(self, 'feature_name', None):
2491
 
            return self.feature_name()
2492
 
        return self.__class__.__name__
2493
 
 
2494
 
 
2495
 
class TestScenarioApplier(object):
2496
 
    """A tool to apply scenarios to tests."""
2497
 
 
2498
 
    def adapt(self, test):
2499
 
        """Return a TestSuite containing a copy of test for each scenario."""
2500
 
        result = unittest.TestSuite()
2501
 
        for scenario in self.scenarios:
2502
 
            result.addTest(self.adapt_test_to_scenario(test, scenario))
2503
 
        return result
2504
 
 
2505
 
    def adapt_test_to_scenario(self, test, scenario):
2506
 
        """Copy test and apply scenario to it.
2507
 
 
2508
 
        :param test: A test to adapt.
2509
 
        :param scenario: A tuple describing the scenarion.
2510
 
            The first element of the tuple is the new test id.
2511
 
            The second element is a dict containing attributes to set on the
2512
 
            test.
2513
 
        :return: The adapted test.
2514
 
        """
2515
 
        from copy import deepcopy
2516
 
        new_test = deepcopy(test)
2517
 
        for name, value in scenario[1].items():
2518
 
            setattr(new_test, name, value)
2519
 
        new_id = "%s(%s)" % (new_test.id(), scenario[0])
2520
 
        new_test.id = lambda: new_id
2521
 
        return new_test
 
4463
    for i in xrange(128, 256):
 
4464
        char = chr(i)
 
4465
        try:
 
4466
            char.decode(encoding)
 
4467
        except UnicodeDecodeError:
 
4468
            return char
 
4469
    return None
 
4470
 
 
4471
 
 
4472
# Only define SubUnitBzrRunner if subunit is available.
 
4473
try:
 
4474
    from subunit import TestProtocolClient
 
4475
    from subunit.test_results import AutoTimingTestResultDecorator
 
4476
    class SubUnitBzrProtocolClient(TestProtocolClient):
 
4477
 
 
4478
        def stopTest(self, test):
 
4479
            super(SubUnitBzrProtocolClient, self).stopTest(test)
 
4480
            _clear__type_equality_funcs(test)
 
4481
 
 
4482
        def addSuccess(self, test, details=None):
 
4483
            # The subunit client always includes the details in the subunit
 
4484
            # stream, but we don't want to include it in ours.
 
4485
            if details is not None and 'log' in details:
 
4486
                del details['log']
 
4487
            return super(SubUnitBzrProtocolClient, self).addSuccess(
 
4488
                test, details)
 
4489
 
 
4490
    class SubUnitBzrRunner(TextTestRunner):
 
4491
        def run(self, test):
 
4492
            result = AutoTimingTestResultDecorator(
 
4493
                SubUnitBzrProtocolClient(self.stream))
 
4494
            test.run(result)
 
4495
            return result
 
4496
except ImportError:
 
4497
    pass
 
4498
 
 
4499
 
 
4500
# API compatibility for old plugins; see bug 892622.
 
4501
for name in [
 
4502
    'Feature',
 
4503
    'HTTPServerFeature', 
 
4504
    'ModuleAvailableFeature',
 
4505
    'HTTPSServerFeature', 'SymlinkFeature', 'HardlinkFeature',
 
4506
    'OsFifoFeature', 'UnicodeFilenameFeature',
 
4507
    'ByteStringNamedFilesystem', 'UTF8Filesystem',
 
4508
    'BreakinFeature', 'CaseInsCasePresFilenameFeature',
 
4509
    'CaseInsensitiveFilesystemFeature', 'case_sensitive_filesystem_feature',
 
4510
    'posix_permissions_feature',
 
4511
    ]:
 
4512
    globals()[name] = _CompatabilityThunkFeature(
 
4513
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4514
        'bzrlib.tests', name,
 
4515
        name, 'bzrlib.tests.features')
 
4516
 
 
4517
 
 
4518
for (old_name, new_name) in [
 
4519
    ('UnicodeFilename', 'UnicodeFilenameFeature'),
 
4520
    ]:
 
4521
    globals()[name] = _CompatabilityThunkFeature(
 
4522
        symbol_versioning.deprecated_in((2, 5, 0)),
 
4523
        'bzrlib.tests', old_name,
 
4524
        new_name, 'bzrlib.tests.features')