~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Andrew Bennetts
  • Date: 2008-07-03 07:56:02 UTC
  • mto: This revision was merged to the branch mainline in revision 3520.
  • Revision ID: andrew.bennetts@canonical.com-20080703075602-8n055qsfkjijcz6i
Better tests for {pre,post}_change_branch_tip hooks.

Show diffs side-by-side

added added

removed removed

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