~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2010-02-04 16:06:36 UTC
  • mfrom: (5007 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5023.
  • Revision ID: john@arbash-meinel.com-20100204160636-xqeuwz8bwt8bbts4
Merge bzr.dev 5007, resolve conflict, update NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
"""Testing framework extensions"""
 
17
 
 
18
# TODO: Perhaps there should be an API to find out if bzr running under the
 
19
# test suite -- some plugins might want to avoid making intrusive changes if
 
20
# this is the case.  However, we want behaviour under to test to diverge as
 
21
# little as possible, so this should be used rarely if it's added at all.
 
22
# (Suggestion from j-a-meinel, 2005-11-24)
18
23
 
19
24
# NOTE: Some classes in here use camelCaseNaming() rather than
20
25
# underscore_naming().  That's for consistency with unittest; it's not the
23
28
 
24
29
import atexit
25
30
import codecs
26
 
import copy
 
31
from copy import copy
27
32
from cStringIO import StringIO
28
33
import difflib
29
34
import doctest
30
35
import errno
31
 
import itertools
32
36
import logging
 
37
import math
33
38
import os
34
 
import platform
35
 
import pprint
 
39
from pprint import pformat
36
40
import random
37
41
import re
38
42
import shlex
39
43
import stat
40
 
import subprocess
 
44
from subprocess import Popen, PIPE, STDOUT
41
45
import sys
42
46
import tempfile
43
47
import threading
49
53
import testtools
50
54
# nb: check this before importing anything else from within it
51
55
_testtools_version = getattr(testtools, '__version__', ())
52
 
if _testtools_version < (0, 9, 5):
53
 
    raise ImportError("need at least testtools 0.9.5: %s is %r"
 
56
if _testtools_version < (0, 9, 2):
 
57
    raise ImportError("need at least testtools 0.9.2: %s is %r"
54
58
        % (testtools.__file__, _testtools_version))
55
59
from testtools import content
56
60
 
57
 
import bzrlib
58
61
from bzrlib import (
59
62
    branchbuilder,
60
63
    bzrdir,
61
64
    chk_map,
62
 
    commands as _mod_commands,
63
65
    config,
64
66
    debug,
65
67
    errors,
66
68
    hooks,
67
69
    lock as _mod_lock,
68
 
    lockdir,
69
70
    memorytree,
70
71
    osutils,
71
 
    plugin as _mod_plugin,
72
 
    pyutils,
 
72
    progress,
73
73
    ui,
74
74
    urlutils,
75
75
    registry,
76
 
    symbol_versioning,
77
 
    trace,
78
 
    transport as _mod_transport,
79
76
    workingtree,
80
77
    )
 
78
import bzrlib.branch
 
79
import bzrlib.commands
 
80
import bzrlib.timestamp
 
81
import bzrlib.export
 
82
import bzrlib.inventory
 
83
import bzrlib.iterablefile
 
84
import bzrlib.lockdir
81
85
try:
82
86
    import bzrlib.lsprof
83
87
except ImportError:
84
88
    # lsprof not available
85
89
    pass
86
 
from bzrlib.smart import client, request
87
 
from bzrlib.transport import (
88
 
    memory,
89
 
    pathfilter,
90
 
    )
 
90
from bzrlib.merge import merge_inner
 
91
import bzrlib.merge3
 
92
import bzrlib.plugin
 
93
from bzrlib.smart import client, request, server
 
94
import bzrlib.store
 
95
from bzrlib import symbol_versioning
91
96
from bzrlib.symbol_versioning import (
 
97
    DEPRECATED_PARAMETER,
92
98
    deprecated_function,
93
99
    deprecated_in,
94
 
    )
95
 
from bzrlib.tests import (
96
 
    test_server,
97
 
    TestUtil,
98
 
    treeshape,
99
 
    )
 
100
    deprecated_method,
 
101
    deprecated_passed,
 
102
    )
 
103
import bzrlib.trace
 
104
from bzrlib.transport import get_transport, pathfilter
 
105
import bzrlib.transport
 
106
from bzrlib.transport.local import LocalURLServer
 
107
from bzrlib.transport.memory import MemoryServer
 
108
from bzrlib.transport.readonly import ReadonlyServer
 
109
from bzrlib.trace import mutter, note
 
110
from bzrlib.tests import TestUtil
 
111
from bzrlib.tests.http_server import HttpServer
 
112
from bzrlib.tests.TestUtil import (
 
113
                          TestSuite,
 
114
                          TestLoader,
 
115
                          )
 
116
from bzrlib.tests.treeshape import build_tree_contents
100
117
from bzrlib.ui import NullProgressView
101
118
from bzrlib.ui.text import TextUIFactory
 
119
import bzrlib.version_info_formats.format_custom
 
120
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
102
121
 
103
122
# Mark this python module as being part of the implementation
104
123
# of unittest: this gives us better tracebacks where the last
105
124
# shown frame is the test code, not our assertXYZ.
106
125
__unittest = 1
107
126
 
108
 
default_transport = test_server.LocalURLServer
 
127
default_transport = LocalURLServer
109
128
 
110
129
 
111
130
_unitialized_attr = object()
116
135
SUBUNIT_SEEK_SET = 0
117
136
SUBUNIT_SEEK_CUR = 1
118
137
 
119
 
# These are intentionally brought into this namespace. That way plugins, etc
120
 
# can just "from bzrlib.tests import TestCase, TestLoader, etc"
121
 
TestSuite = TestUtil.TestSuite
122
 
TestLoader = TestUtil.TestLoader
123
 
 
124
 
# Tests should run in a clean and clearly defined environment. The goal is to
125
 
# keep them isolated from the running environment as mush as possible. The test
126
 
# framework ensures the variables defined below are set (or deleted if the
127
 
# value is None) before a test is run and reset to their original value after
128
 
# the test is run. Generally if some code depends on an environment variable,
129
 
# the tests should start without this variable in the environment. There are a
130
 
# few exceptions but you shouldn't violate this rule lightly.
131
 
isolated_environ = {
132
 
    'BZR_HOME': None,
133
 
    'HOME': None,
134
 
    # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
135
 
    # tests do check our impls match APPDATA
136
 
    'BZR_EDITOR': None, # test_msgeditor manipulates this variable
137
 
    'VISUAL': None,
138
 
    'EDITOR': None,
139
 
    'BZR_EMAIL': None,
140
 
    'BZREMAIL': None, # may still be present in the environment
141
 
    'EMAIL': 'jrandom@example.com', # set EMAIL as bzr does not guess
142
 
    'BZR_PROGRESS_BAR': None,
143
 
    # This should trap leaks to ~/.bzr.log. This occurs when tests use TestCase
144
 
    # as a base class instead of TestCaseInTempDir. Tests inheriting from
145
 
    # TestCase should not use disk resources, BZR_LOG is one.
146
 
    'BZR_LOG': '/you-should-use-TestCaseInTempDir-if-you-need-a-log-file',
147
 
    'BZR_PLUGIN_PATH': None,
148
 
    'BZR_DISABLE_PLUGINS': None,
149
 
    'BZR_PLUGINS_AT': None,
150
 
    'BZR_CONCURRENCY': None,
151
 
    # Make sure that any text ui tests are consistent regardless of
152
 
    # the environment the test case is run in; you may want tests that
153
 
    # test other combinations.  'dumb' is a reasonable guess for tests
154
 
    # going to a pipe or a StringIO.
155
 
    'TERM': 'dumb',
156
 
    'LINES': '25',
157
 
    'COLUMNS': '80',
158
 
    'BZR_COLUMNS': '80',
159
 
    # Disable SSH Agent
160
 
    'SSH_AUTH_SOCK': None,
161
 
    # Proxies
162
 
    'http_proxy': None,
163
 
    'HTTP_PROXY': None,
164
 
    'https_proxy': None,
165
 
    'HTTPS_PROXY': None,
166
 
    'no_proxy': None,
167
 
    'NO_PROXY': None,
168
 
    'all_proxy': None,
169
 
    'ALL_PROXY': None,
170
 
    # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
171
 
    # least. If you do (care), please update this comment
172
 
    # -- vila 20080401
173
 
    'ftp_proxy': None,
174
 
    'FTP_PROXY': None,
175
 
    'BZR_REMOTE_PATH': None,
176
 
    # Generally speaking, we don't want apport reporting on crashes in
177
 
    # the test envirnoment unless we're specifically testing apport,
178
 
    # so that it doesn't leak into the real system environment.  We
179
 
    # use an env var so it propagates to subprocesses.
180
 
    'APPORT_DISABLE': '1',
181
 
    }
182
 
 
183
 
 
184
 
def override_os_environ(test, env=None):
185
 
    """Modify os.environ keeping a copy.
186
 
    
187
 
    :param test: A test instance
188
 
 
189
 
    :param env: A dict containing variable definitions to be installed
190
 
    """
191
 
    if env is None:
192
 
        env = isolated_environ
193
 
    test._original_os_environ = dict([(var, value)
194
 
                                      for var, value in os.environ.iteritems()])
195
 
    for var, value in env.iteritems():
196
 
        osutils.set_or_unset_env(var, value)
197
 
        if var not in test._original_os_environ:
198
 
            # The var is new, add it with a value of None, so
199
 
            # restore_os_environ will delete it
200
 
            test._original_os_environ[var] = None
201
 
 
202
 
 
203
 
def restore_os_environ(test):
204
 
    """Restore os.environ to its original state.
205
 
 
206
 
    :param test: A test instance previously passed to override_os_environ.
207
 
    """
208
 
    for var, value in test._original_os_environ.iteritems():
209
 
        # Restore the original value (or delete it if the value has been set to
210
 
        # None in override_os_environ).
211
 
        osutils.set_or_unset_env(var, value)
212
 
 
213
 
 
214
 
class ExtendedTestResult(testtools.TextTestResult):
 
138
 
 
139
class ExtendedTestResult(unittest._TextTestResult):
215
140
    """Accepts, reports and accumulates the results of running tests.
216
141
 
217
142
    Compared to the unittest version this class adds support for
238
163
        :param bench_history: Optionally, a writable file object to accumulate
239
164
            benchmark results.
240
165
        """
241
 
        testtools.TextTestResult.__init__(self, stream)
 
166
        unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
242
167
        if bench_history is not None:
243
168
            from bzrlib.version import _get_bzr_source_tree
244
169
            src_tree = _get_bzr_source_tree()
265
190
        self.count = 0
266
191
        self._overall_start_time = time.time()
267
192
        self._strict = strict
268
 
        self._first_thread_leaker_id = None
269
 
        self._tests_leaking_threads_count = 0
270
 
        self._traceback_from_test = None
271
193
 
272
194
    def stopTestRun(self):
273
195
        run = self.testsRun
274
196
        actionTaken = "Ran"
275
197
        stopTime = time.time()
276
198
        timeTaken = stopTime - self.startTime
277
 
        # GZ 2010-07-19: Seems testtools has no printErrors method, and though
278
 
        #                the parent class method is similar have to duplicate
279
 
        self._show_list('ERROR', self.errors)
280
 
        self._show_list('FAIL', self.failures)
281
 
        self.stream.write(self.sep2)
282
 
        self.stream.write("%s %d test%s in %.3fs\n\n" % (actionTaken,
 
199
        self.printErrors()
 
200
        self.stream.writeln(self.separator2)
 
201
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
283
202
                            run, run != 1 and "s" or "", timeTaken))
 
203
        self.stream.writeln()
284
204
        if not self.wasSuccessful():
285
205
            self.stream.write("FAILED (")
286
206
            failed, errored = map(len, (self.failures, self.errors))
293
213
                if failed or errored: self.stream.write(", ")
294
214
                self.stream.write("known_failure_count=%d" %
295
215
                    self.known_failure_count)
296
 
            self.stream.write(")\n")
 
216
            self.stream.writeln(")")
297
217
        else:
298
218
            if self.known_failure_count:
299
 
                self.stream.write("OK (known_failures=%d)\n" %
 
219
                self.stream.writeln("OK (known_failures=%d)" %
300
220
                    self.known_failure_count)
301
221
            else:
302
 
                self.stream.write("OK\n")
 
222
                self.stream.writeln("OK")
303
223
        if self.skip_count > 0:
304
224
            skipped = self.skip_count
305
 
            self.stream.write('%d test%s skipped\n' %
 
225
            self.stream.writeln('%d test%s skipped' %
306
226
                                (skipped, skipped != 1 and "s" or ""))
307
227
        if self.unsupported:
308
228
            for feature, count in sorted(self.unsupported.items()):
309
 
                self.stream.write("Missing feature '%s' skipped %d tests.\n" %
 
229
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
310
230
                    (feature, count))
311
231
        if self._strict:
312
232
            ok = self.wasStrictlySuccessful()
313
233
        else:
314
234
            ok = self.wasSuccessful()
315
 
        if self._first_thread_leaker_id:
 
235
        if TestCase._first_thread_leaker_id:
316
236
            self.stream.write(
317
237
                '%s is leaking threads among %d leaking tests.\n' % (
318
 
                self._first_thread_leaker_id,
319
 
                self._tests_leaking_threads_count))
 
238
                TestCase._first_thread_leaker_id,
 
239
                TestCase._leaking_threads_tests))
320
240
            # We don't report the main thread as an active one.
321
241
            self.stream.write(
322
242
                '%d non-main threads were left active in the end.\n'
323
 
                % (len(self._active_threads) - 1))
 
243
                % (TestCase._active_threads - 1))
324
244
 
325
245
    def getDescription(self, test):
326
246
        return test.id()
333
253
 
334
254
    def _elapsedTestTimeString(self):
335
255
        """Return a time string for the overall time the current test has taken."""
336
 
        return self._formatTime(self._delta_to_float(
337
 
            self._now() - self._start_datetime))
 
256
        return self._formatTime(time.time() - self._start_time)
338
257
 
339
258
    def _testTimeString(self, testCase):
340
259
        benchmark_time = self._extractBenchmarkTime(testCase)
351
270
 
352
271
    def _shortened_test_description(self, test):
353
272
        what = test.id()
354
 
        what = re.sub(r'^bzrlib\.tests\.', '', what)
 
273
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
355
274
        return what
356
275
 
357
 
    # GZ 2010-10-04: Cloned tests may end up harmlessly calling this method
358
 
    #                multiple times in a row, because the handler is added for
359
 
    #                each test but the container list is shared between cases.
360
 
    #                See lp:498869 lp:625574 and lp:637725 for background.
361
 
    def _record_traceback_from_test(self, exc_info):
362
 
        """Store the traceback from passed exc_info tuple till"""
363
 
        self._traceback_from_test = exc_info[2]
364
 
 
365
276
    def startTest(self, test):
366
 
        super(ExtendedTestResult, self).startTest(test)
 
277
        unittest.TestResult.startTest(self, test)
367
278
        if self.count == 0:
368
279
            self.startTests()
369
 
        self.count += 1
370
280
        self.report_test_start(test)
371
281
        test.number = self.count
372
282
        self._recordTestStartTime()
373
 
        # Make testtools cases give us the real traceback on failure
374
 
        addOnException = getattr(test, "addOnException", None)
375
 
        if addOnException is not None:
376
 
            addOnException(self._record_traceback_from_test)
377
 
        # Only check for thread leaks on bzrlib derived test cases
378
 
        if isinstance(test, TestCase):
379
 
            test.addCleanup(self._check_leaked_threads, test)
380
 
 
381
 
    def stopTest(self, test):
382
 
        super(ExtendedTestResult, self).stopTest(test)
383
 
        # Manually break cycles, means touching various private things but hey
384
 
        getDetails = getattr(test, "getDetails", None)
385
 
        if getDetails is not None:
386
 
            getDetails().clear()
387
 
        # Clear _type_equality_funcs to try to stop TestCase instances
388
 
        # from wasting memory. 'clear' is not available in all Python
389
 
        # versions (bug 809048)
390
 
        type_equality_funcs = getattr(test, "_type_equality_funcs", None)
391
 
        if type_equality_funcs is not None:
392
 
            tef_clear = getattr(type_equality_funcs, "clear", None)
393
 
            if tef_clear is None:
394
 
                tef_instance_dict = getattr(type_equality_funcs, "__dict__", None)
395
 
                if tef_instance_dict is not None:
396
 
                    tef_clear = tef_instance_dict.clear
397
 
            if tef_clear is not None:
398
 
                tef_clear()
399
 
        self._traceback_from_test = None
400
283
 
401
284
    def startTests(self):
402
 
        self.report_tests_starting()
403
 
        self._active_threads = threading.enumerate()
404
 
 
405
 
    def _check_leaked_threads(self, test):
406
 
        """See if any threads have leaked since last call
407
 
 
408
 
        A sample of live threads is stored in the _active_threads attribute,
409
 
        when this method runs it compares the current live threads and any not
410
 
        in the previous sample are treated as having leaked.
411
 
        """
412
 
        now_active_threads = set(threading.enumerate())
413
 
        threads_leaked = now_active_threads.difference(self._active_threads)
414
 
        if threads_leaked:
415
 
            self._report_thread_leak(test, threads_leaked, now_active_threads)
416
 
            self._tests_leaking_threads_count += 1
417
 
            if self._first_thread_leaker_id is None:
418
 
                self._first_thread_leaker_id = test.id()
419
 
            self._active_threads = now_active_threads
 
285
        import platform
 
286
        if getattr(sys, 'frozen', None) is None:
 
287
            bzr_path = osutils.realpath(sys.argv[0])
 
288
        else:
 
289
            bzr_path = sys.executable
 
290
        self.stream.write(
 
291
            'bzr selftest: %s\n' % (bzr_path,))
 
292
        self.stream.write(
 
293
            '   %s\n' % (
 
294
                    bzrlib.__path__[0],))
 
295
        self.stream.write(
 
296
            '   bzr-%s python-%s %s\n' % (
 
297
                    bzrlib.version_string,
 
298
                    bzrlib._format_version_tuple(sys.version_info),
 
299
                    platform.platform(aliased=1),
 
300
                    ))
 
301
        self.stream.write('\n')
420
302
 
421
303
    def _recordTestStartTime(self):
422
304
        """Record that a test has started."""
423
 
        self._start_datetime = self._now()
 
305
        self._start_time = time.time()
 
306
 
 
307
    def _cleanupLogFile(self, test):
 
308
        # We can only do this if we have one of our TestCases, not if
 
309
        # we have a doctest.
 
310
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
311
        if setKeepLogfile is not None:
 
312
            setKeepLogfile()
424
313
 
425
314
    def addError(self, test, err):
426
315
        """Tell result that test finished with an error.
428
317
        Called from the TestCase run() method when the test
429
318
        fails with an unexpected error.
430
319
        """
431
 
        self._post_mortem(self._traceback_from_test)
432
 
        super(ExtendedTestResult, self).addError(test, err)
 
320
        self._post_mortem()
 
321
        unittest.TestResult.addError(self, test, err)
433
322
        self.error_count += 1
434
323
        self.report_error(test, err)
435
324
        if self.stop_early:
436
325
            self.stop()
 
326
        self._cleanupLogFile(test)
437
327
 
438
328
    def addFailure(self, test, err):
439
329
        """Tell result that test failed.
441
331
        Called from the TestCase run() method when the test
442
332
        fails because e.g. an assert() method failed.
443
333
        """
444
 
        self._post_mortem(self._traceback_from_test)
445
 
        super(ExtendedTestResult, self).addFailure(test, err)
 
334
        self._post_mortem()
 
335
        unittest.TestResult.addFailure(self, test, err)
446
336
        self.failure_count += 1
447
337
        self.report_failure(test, err)
448
338
        if self.stop_early:
449
339
            self.stop()
 
340
        self._cleanupLogFile(test)
450
341
 
451
342
    def addSuccess(self, test, details=None):
452
343
        """Tell result that test completed successfully.
460
351
                    self._formatTime(benchmark_time),
461
352
                    test.id()))
462
353
        self.report_success(test)
463
 
        super(ExtendedTestResult, self).addSuccess(test)
 
354
        self._cleanupLogFile(test)
 
355
        unittest.TestResult.addSuccess(self, test)
464
356
        test._log_contents = ''
465
357
 
466
358
    def addExpectedFailure(self, test, err):
467
359
        self.known_failure_count += 1
468
360
        self.report_known_failure(test, err)
469
361
 
470
 
    def addUnexpectedSuccess(self, test, details=None):
471
 
        """Tell result the test unexpectedly passed, counting as a failure
472
 
 
473
 
        When the minimum version of testtools required becomes 0.9.8 this
474
 
        can be updated to use the new handling there.
475
 
        """
476
 
        super(ExtendedTestResult, self).addFailure(test, details=details)
477
 
        self.failure_count += 1
478
 
        self.report_unexpected_success(test,
479
 
            "".join(details["reason"].iter_text()))
480
 
        if self.stop_early:
481
 
            self.stop()
482
 
 
483
362
    def addNotSupported(self, test, feature):
484
363
        """The test will not be run because of a missing feature.
485
364
        """
502
381
        self.not_applicable_count += 1
503
382
        self.report_not_applicable(test, reason)
504
383
 
505
 
    def _post_mortem(self, tb=None):
 
384
    def _post_mortem(self):
506
385
        """Start a PDB post mortem session."""
507
386
        if os.environ.get('BZR_TEST_PDB', None):
508
 
            import pdb
509
 
            pdb.post_mortem(tb)
 
387
            import pdb;pdb.post_mortem()
510
388
 
511
389
    def progress(self, offset, whence):
512
390
        """The test is adjusting the count of tests to run."""
517
395
        else:
518
396
            raise errors.BzrError("Unknown whence %r" % whence)
519
397
 
520
 
    def report_tests_starting(self):
521
 
        """Display information before the test run begins"""
522
 
        if getattr(sys, 'frozen', None) is None:
523
 
            bzr_path = osutils.realpath(sys.argv[0])
524
 
        else:
525
 
            bzr_path = sys.executable
526
 
        self.stream.write(
527
 
            'bzr selftest: %s\n' % (bzr_path,))
528
 
        self.stream.write(
529
 
            '   %s\n' % (
530
 
                    bzrlib.__path__[0],))
531
 
        self.stream.write(
532
 
            '   bzr-%s python-%s %s\n' % (
533
 
                    bzrlib.version_string,
534
 
                    bzrlib._format_version_tuple(sys.version_info),
535
 
                    platform.platform(aliased=1),
536
 
                    ))
537
 
        self.stream.write('\n')
538
 
 
539
 
    def report_test_start(self, test):
540
 
        """Display information on the test just about to be run"""
541
 
 
542
 
    def _report_thread_leak(self, test, leaked_threads, active_threads):
543
 
        """Display information on a test that leaked one or more threads"""
544
 
        # GZ 2010-09-09: A leak summary reported separately from the general
545
 
        #                thread debugging would be nice. Tests under subunit
546
 
        #                need something not using stream, perhaps adding a
547
 
        #                testtools details object would be fitting.
548
 
        if 'threads' in selftest_debug_flags:
549
 
            self.stream.write('%s is leaking, active is now %d\n' %
550
 
                (test.id(), len(active_threads)))
 
398
    def report_cleaning_up(self):
 
399
        pass
551
400
 
552
401
    def startTestRun(self):
553
402
        self.startTime = time.time()
590
439
        self.pb.finished()
591
440
        super(TextTestResult, self).stopTestRun()
592
441
 
593
 
    def report_tests_starting(self):
594
 
        super(TextTestResult, self).report_tests_starting()
 
442
    def startTestRun(self):
 
443
        super(TextTestResult, self).startTestRun()
595
444
        self.pb.update('[test 0/%d] Starting' % (self.num_tests))
596
445
 
 
446
    def printErrors(self):
 
447
        # clear the pb to make room for the error listing
 
448
        self.pb.clear()
 
449
        super(TextTestResult, self).printErrors()
 
450
 
597
451
    def _progress_prefix_text(self):
598
452
        # the longer this text, the less space we have to show the test
599
453
        # name...
621
475
        return a
622
476
 
623
477
    def report_test_start(self, test):
 
478
        self.count += 1
624
479
        self.pb.update(
625
480
                self._progress_prefix_text()
626
481
                + ' '
630
485
        return self._shortened_test_description(test)
631
486
 
632
487
    def report_error(self, test, err):
633
 
        self.stream.write('ERROR: %s\n    %s\n' % (
 
488
        ui.ui_factory.note('ERROR: %s\n    %s\n' % (
634
489
            self._test_description(test),
635
490
            err[1],
636
491
            ))
637
492
 
638
493
    def report_failure(self, test, err):
639
 
        self.stream.write('FAIL: %s\n    %s\n' % (
 
494
        ui.ui_factory.note('FAIL: %s\n    %s\n' % (
640
495
            self._test_description(test),
641
496
            err[1],
642
497
            ))
644
499
    def report_known_failure(self, test, err):
645
500
        pass
646
501
 
647
 
    def report_unexpected_success(self, test, reason):
648
 
        self.stream.write('FAIL: %s\n    %s: %s\n' % (
649
 
            self._test_description(test),
650
 
            "Unexpected success. Should have failed",
651
 
            reason,
652
 
            ))
653
 
 
654
502
    def report_skip(self, test, reason):
655
503
        pass
656
504
 
660
508
    def report_unsupported(self, test, feature):
661
509
        """test cannot be run because feature is missing."""
662
510
 
 
511
    def report_cleaning_up(self):
 
512
        self.pb.update('Cleaning up')
 
513
 
663
514
 
664
515
class VerboseTestResult(ExtendedTestResult):
665
516
    """Produce long output, with one line per test run plus times"""
672
523
            result = a_string
673
524
        return result.ljust(final_width)
674
525
 
675
 
    def report_tests_starting(self):
 
526
    def startTestRun(self):
 
527
        super(VerboseTestResult, self).startTestRun()
676
528
        self.stream.write('running %d tests...\n' % self.num_tests)
677
 
        super(VerboseTestResult, self).report_tests_starting()
678
529
 
679
530
    def report_test_start(self, test):
 
531
        self.count += 1
680
532
        name = self._shortened_test_description(test)
681
533
        width = osutils.terminal_width()
682
534
        if width is not None:
694
546
        return '%s%s' % (indent, err[1])
695
547
 
696
548
    def report_error(self, test, err):
697
 
        self.stream.write('ERROR %s\n%s\n'
 
549
        self.stream.writeln('ERROR %s\n%s'
698
550
                % (self._testTimeString(test),
699
551
                   self._error_summary(err)))
700
552
 
701
553
    def report_failure(self, test, err):
702
 
        self.stream.write(' FAIL %s\n%s\n'
 
554
        self.stream.writeln(' FAIL %s\n%s'
703
555
                % (self._testTimeString(test),
704
556
                   self._error_summary(err)))
705
557
 
706
558
    def report_known_failure(self, test, err):
707
 
        self.stream.write('XFAIL %s\n%s\n'
 
559
        self.stream.writeln('XFAIL %s\n%s'
708
560
                % (self._testTimeString(test),
709
561
                   self._error_summary(err)))
710
562
 
711
 
    def report_unexpected_success(self, test, reason):
712
 
        self.stream.write(' FAIL %s\n%s: %s\n'
713
 
                % (self._testTimeString(test),
714
 
                   "Unexpected success. Should have failed",
715
 
                   reason))
716
 
 
717
563
    def report_success(self, test):
718
 
        self.stream.write('   OK %s\n' % self._testTimeString(test))
 
564
        self.stream.writeln('   OK %s' % self._testTimeString(test))
719
565
        for bench_called, stats in getattr(test, '_benchcalls', []):
720
 
            self.stream.write('LSProf output for %s(%s, %s)\n' % bench_called)
 
566
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
721
567
            stats.pprint(file=self.stream)
722
568
        # flush the stream so that we get smooth output. This verbose mode is
723
569
        # used to show the output in PQM.
724
570
        self.stream.flush()
725
571
 
726
572
    def report_skip(self, test, reason):
727
 
        self.stream.write(' SKIP %s\n%s\n'
 
573
        self.stream.writeln(' SKIP %s\n%s'
728
574
                % (self._testTimeString(test), reason))
729
575
 
730
576
    def report_not_applicable(self, test, reason):
731
 
        self.stream.write('  N/A %s\n    %s\n'
 
577
        self.stream.writeln('  N/A %s\n    %s'
732
578
                % (self._testTimeString(test), reason))
733
579
 
734
580
    def report_unsupported(self, test, feature):
735
581
        """test cannot be run because feature is missing."""
736
 
        self.stream.write("NODEP %s\n    The feature '%s' is not available.\n"
 
582
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
737
583
                %(self._testTimeString(test), feature))
738
584
 
739
585
 
766
612
            encode = codec[0]
767
613
        else:
768
614
            encode = codec.encode
769
 
        # GZ 2010-09-08: Really we don't want to be writing arbitrary bytes,
770
 
        #                so should swap to the plain codecs.StreamWriter
771
 
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream,
772
 
            "backslashreplace")
 
615
        stream = osutils.UnicodeOrBytesToBytesWriter(encode, stream)
773
616
        stream.encoding = new_encoding
774
 
        self.stream = stream
 
617
        self.stream = unittest._WritelnDecorator(stream)
775
618
        self.descriptions = descriptions
776
619
        self.verbosity = verbosity
777
620
        self._bench_history = bench_history
859
702
    """
860
703
 
861
704
 
 
705
class CommandFailed(Exception):
 
706
    pass
 
707
 
 
708
 
862
709
class StringIOWrapper(object):
863
710
    """A wrapper around cStringIO which just adds an encoding attribute.
864
711
 
901
748
    # XXX: Should probably unify more with CannedInputUIFactory or a
902
749
    # particular configuration of TextUIFactory, or otherwise have a clearer
903
750
    # idea of how they're supposed to be different.
904
 
    # See https://bugs.launchpad.net/bzr/+bug/408213
 
751
    # See https://bugs.edge.launchpad.net/bzr/+bug/408213
905
752
 
906
753
    def __init__(self, stdout=None, stderr=None, stdin=None):
907
754
        if stdin is not None:
925
772
        return NullProgressView()
926
773
 
927
774
 
928
 
def isolated_doctest_setUp(test):
929
 
    override_os_environ(test)
930
 
 
931
 
 
932
 
def isolated_doctest_tearDown(test):
933
 
    restore_os_environ(test)
934
 
 
935
 
 
936
 
def IsolatedDocTestSuite(*args, **kwargs):
937
 
    """Overrides doctest.DocTestSuite to handle isolation.
938
 
 
939
 
    The method is really a factory and users are expected to use it as such.
940
 
    """
941
 
 
942
 
    kwargs['setUp'] = isolated_doctest_setUp
943
 
    kwargs['tearDown'] = isolated_doctest_tearDown
944
 
    return doctest.DocTestSuite(*args, **kwargs)
945
 
 
946
 
 
947
775
class TestCase(testtools.TestCase):
948
776
    """Base class for bzr unit tests.
949
777
 
960
788
    routine, and to build and check bzr trees.
961
789
 
962
790
    In addition to the usual method of overriding tearDown(), this class also
963
 
    allows subclasses to register cleanup functions via addCleanup, which are
 
791
    allows subclasses to register functions into the _cleanups list, which is
964
792
    run in order as the object is torn down.  It's less likely this will be
965
793
    accidentally overlooked.
966
794
    """
967
795
 
968
 
    _log_file = None
 
796
    _active_threads = None
 
797
    _leaking_threads_tests = 0
 
798
    _first_thread_leaker_id = None
 
799
    _log_file_name = None
969
800
    # record lsprof data when performing benchmark calls.
970
801
    _gather_lsprof_in_benchmarks = False
971
802
 
972
803
    def __init__(self, methodName='testMethod'):
973
804
        super(TestCase, self).__init__(methodName)
 
805
        self._cleanups = []
974
806
        self._directory_isolation = True
975
807
        self.exception_handlers.insert(0,
976
808
            (UnavailableFeature, self._do_unsupported_or_skip))
981
813
        super(TestCase, self).setUp()
982
814
        for feature in getattr(self, '_test_needs_features', []):
983
815
            self.requireFeature(feature)
 
816
        self._log_contents = None
 
817
        self.addDetail("log", content.Content(content.ContentType("text",
 
818
            "plain", {"charset": "utf8"}),
 
819
            lambda:[self._get_log(keep_log_file=True)]))
984
820
        self._cleanEnvironment()
985
821
        self._silenceUI()
986
822
        self._startLogFile()
990
826
        self._track_transports()
991
827
        self._track_locks()
992
828
        self._clear_debug_flags()
993
 
        # Isolate global verbosity level, to make sure it's reproducible
994
 
        # between tests.  We should get rid of this altogether: bug 656694. --
995
 
        # mbp 20101008
996
 
        self.overrideAttr(bzrlib.trace, '_verbosity_level', 0)
997
 
        # Isolate config option expansion until its default value for bzrlib is
998
 
        # settled on or a the FIXME associated with _get_expand_default_value
999
 
        # is addressed -- vila 20110219
1000
 
        self.overrideAttr(config, '_expand_default_value', None)
1001
 
        self._log_files = set()
1002
 
        # Each key in the ``_counters`` dict holds a value for a different
1003
 
        # counter. When the test ends, addDetail() should be used to output the
1004
 
        # counter values. This happens in install_counter_hook().
1005
 
        self._counters = {}
1006
 
        if 'config_stats' in selftest_debug_flags:
1007
 
            self._install_config_stats_hooks()
 
829
        TestCase._active_threads = threading.activeCount()
 
830
        self.addCleanup(self._check_leaked_threads)
1008
831
 
1009
832
    def debug(self):
1010
833
        # debug a frame up.
1011
834
        import pdb
1012
835
        pdb.Pdb().set_trace(sys._getframe().f_back)
1013
836
 
1014
 
    def discardDetail(self, name):
1015
 
        """Extend the addDetail, getDetails api so we can remove a detail.
1016
 
 
1017
 
        eg. bzr always adds the 'log' detail at startup, but we don't want to
1018
 
        include it for skipped, xfail, etc tests.
1019
 
 
1020
 
        It is safe to call this for a detail that doesn't exist, in case this
1021
 
        gets called multiple times.
1022
 
        """
1023
 
        # We cheat. details is stored in __details which means we shouldn't
1024
 
        # touch it. but getDetails() returns the dict directly, so we can
1025
 
        # mutate it.
1026
 
        details = self.getDetails()
1027
 
        if name in details:
1028
 
            del details[name]
1029
 
 
1030
 
    def install_counter_hook(self, hooks, name, counter_name=None):
1031
 
        """Install a counting hook.
1032
 
 
1033
 
        Any hook can be counted as long as it doesn't need to return a value.
1034
 
 
1035
 
        :param hooks: Where the hook should be installed.
1036
 
 
1037
 
        :param name: The hook name that will be counted.
1038
 
 
1039
 
        :param counter_name: The counter identifier in ``_counters``, defaults
1040
 
            to ``name``.
1041
 
        """
1042
 
        _counters = self._counters # Avoid closing over self
1043
 
        if counter_name is None:
1044
 
            counter_name = name
1045
 
        if _counters.has_key(counter_name):
1046
 
            raise AssertionError('%s is already used as a counter name'
1047
 
                                  % (counter_name,))
1048
 
        _counters[counter_name] = 0
1049
 
        self.addDetail(counter_name, content.Content(content.UTF8_TEXT,
1050
 
            lambda: ['%d' % (_counters[counter_name],)]))
1051
 
        def increment_counter(*args, **kwargs):
1052
 
            _counters[counter_name] += 1
1053
 
        label = 'count %s calls' % (counter_name,)
1054
 
        hooks.install_named_hook(name, increment_counter, label)
1055
 
        self.addCleanup(hooks.uninstall_named_hook, name, label)
1056
 
 
1057
 
    def _install_config_stats_hooks(self):
1058
 
        """Install config hooks to count hook calls.
1059
 
 
1060
 
        """
1061
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1062
 
            self.install_counter_hook(config.ConfigHooks, hook_name,
1063
 
                                       'config.%s' % (hook_name,))
1064
 
 
1065
 
        # The OldConfigHooks are private and need special handling to protect
1066
 
        # against recursive tests (tests that run other tests), so we just do
1067
 
        # manually what registering them into _builtin_known_hooks will provide
1068
 
        # us.
1069
 
        self.overrideAttr(config, 'OldConfigHooks', config._OldConfigHooks())
1070
 
        for hook_name in ('get', 'set', 'remove', 'load', 'save'):
1071
 
            self.install_counter_hook(config.OldConfigHooks, hook_name,
1072
 
                                      'old_config.%s' % (hook_name,))
 
837
    def _check_leaked_threads(self):
 
838
        active = threading.activeCount()
 
839
        leaked_threads = active - TestCase._active_threads
 
840
        TestCase._active_threads = active
 
841
        # If some tests make the number of threads *decrease*, we'll consider
 
842
        # that they are just observing old threads dieing, not agressively kill
 
843
        # random threads. So we don't report these tests as leaking. The risk
 
844
        # is that we have false positives that way (the test see 2 threads
 
845
        # going away but leak one) but it seems less likely than the actual
 
846
        # false positives (the test see threads going away and does not leak).
 
847
        if leaked_threads > 0:
 
848
            TestCase._leaking_threads_tests += 1
 
849
            if TestCase._first_thread_leaker_id is None:
 
850
                TestCase._first_thread_leaker_id = self.id()
1073
851
 
1074
852
    def _clear_debug_flags(self):
1075
853
        """Prevent externally set debug flags affecting tests.
1086
864
 
1087
865
    def _clear_hooks(self):
1088
866
        # prevent hooks affecting tests
1089
 
        known_hooks = hooks.known_hooks
1090
867
        self._preserved_hooks = {}
1091
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1092
 
            current_hooks = getattr(parent, name)
 
868
        for key, factory in hooks.known_hooks.items():
 
869
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
 
870
            current_hooks = hooks.known_hooks_key_to_object(key)
1093
871
            self._preserved_hooks[parent] = (name, current_hooks)
1094
 
        self._preserved_lazy_hooks = hooks._lazy_hooks
1095
 
        hooks._lazy_hooks = {}
1096
872
        self.addCleanup(self._restoreHooks)
1097
 
        for key, (parent, name) in known_hooks.iter_parent_objects():
1098
 
            factory = known_hooks.get(key)
 
873
        for key, factory in hooks.known_hooks.items():
 
874
            parent, name = hooks.known_hooks_key_to_parent_and_attribute(key)
1099
875
            setattr(parent, name, factory())
1100
876
        # this hook should always be installed
1101
877
        request._install_hook()
1130
906
        # break some locks on purpose and should be taken into account by
1131
907
        # considering that breaking a lock is just a dirty way of releasing it.
1132
908
        if len(acquired_locks) != (len(released_locks) + len(broken_locks)):
1133
 
            message = (
1134
 
                'Different number of acquired and '
1135
 
                'released or broken locks.\n'
1136
 
                'acquired=%s\n'
1137
 
                'released=%s\n'
1138
 
                'broken=%s\n' %
1139
 
                (acquired_locks, released_locks, broken_locks))
 
909
            message = ('Different number of acquired and '
 
910
                       'released or broken locks. (%s, %s + %s)' %
 
911
                       (acquired_locks, released_locks, broken_locks))
1140
912
            if not self._lock_check_thorough:
1141
913
                # Rather than fail, just warn
1142
914
                print "Broken test %s: %s" % (self, message)
1170
942
 
1171
943
    def permit_dir(self, name):
1172
944
        """Permit a directory to be used by this test. See permit_url."""
1173
 
        name_transport = _mod_transport.get_transport_from_path(name)
 
945
        name_transport = get_transport(name)
1174
946
        self.permit_url(name)
1175
947
        self.permit_url(name_transport.base)
1176
948
 
1199
971
            try:
1200
972
                workingtree.WorkingTree.open(path)
1201
973
            except (errors.NotBranchError, errors.NoWorkingTree):
1202
 
                raise TestSkipped('Needs a working tree of bzr sources')
 
974
                return
1203
975
        finally:
1204
976
            self.enable_directory_isolation()
1205
977
 
1255
1027
        self.addCleanup(transport_server.stop_server)
1256
1028
        # Obtain a real transport because if the server supplies a password, it
1257
1029
        # will be hidden from the base on the client side.
1258
 
        t = _mod_transport.get_transport_from_url(transport_server.get_url())
 
1030
        t = get_transport(transport_server.get_url())
1259
1031
        # Some transport servers effectively chroot the backing transport;
1260
1032
        # others like SFTPServer don't - users of the transport can walk up the
1261
1033
        # transport to read the entire backing transport. This wouldn't matter
1272
1044
        if t.base.endswith('/work/'):
1273
1045
            # we have safety net/test root/work
1274
1046
            t = t.clone('../..')
1275
 
        elif isinstance(transport_server,
1276
 
                        test_server.SmartTCPServer_for_testing):
 
1047
        elif isinstance(transport_server, server.SmartTCPServer_for_testing):
1277
1048
            # The smart server adds a path similar to work, which is traversed
1278
1049
            # up from by the client. But the server is chrooted - the actual
1279
1050
            # backing transport is not escaped from, and VFS requests to the
1317
1088
        except UnicodeError, e:
1318
1089
            # If we can't compare without getting a UnicodeError, then
1319
1090
            # obviously they are different
1320
 
            trace.mutter('UnicodeError: %s', e)
 
1091
            mutter('UnicodeError: %s', e)
1321
1092
        if message:
1322
1093
            message += '\n'
1323
1094
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
1324
1095
            % (message,
1325
 
               pprint.pformat(a), pprint.pformat(b)))
 
1096
               pformat(a), pformat(b)))
1326
1097
 
1327
1098
    assertEquals = assertEqual
1328
1099
 
1362
1133
                         'st_mtime did not match')
1363
1134
        self.assertEqual(expected.st_ctime, actual.st_ctime,
1364
1135
                         'st_ctime did not match')
1365
 
        if sys.platform == 'win32':
 
1136
        if sys.platform != 'win32':
1366
1137
            # On Win32 both 'dev' and 'ino' cannot be trusted. In python2.4 it
1367
1138
            # is 'dev' that varies, in python 2.5 (6?) it is st_ino that is
1368
 
            # odd. We just force it to always be 0 to avoid any problems.
1369
 
            self.assertEqual(0, expected.st_dev)
1370
 
            self.assertEqual(0, actual.st_dev)
1371
 
            self.assertEqual(0, expected.st_ino)
1372
 
            self.assertEqual(0, actual.st_ino)
1373
 
        else:
 
1139
            # odd. Regardless we shouldn't actually try to assert anything
 
1140
            # about their values
1374
1141
            self.assertEqual(expected.st_dev, actual.st_dev,
1375
1142
                             'st_dev did not match')
1376
1143
            self.assertEqual(expected.st_ino, actual.st_ino,
1385
1152
                length, len(obj_with_len), obj_with_len))
1386
1153
 
1387
1154
    def assertLogsError(self, exception_class, func, *args, **kwargs):
1388
 
        """Assert that `func(*args, **kwargs)` quietly logs a specific error.
 
1155
        """Assert that func(*args, **kwargs) quietly logs a specific exception.
1389
1156
        """
 
1157
        from bzrlib import trace
1390
1158
        captured = []
1391
1159
        orig_log_exception_quietly = trace.log_exception_quietly
1392
1160
        try:
1393
1161
            def capture():
1394
1162
                orig_log_exception_quietly()
1395
 
                captured.append(sys.exc_info()[1])
 
1163
                captured.append(sys.exc_info())
1396
1164
            trace.log_exception_quietly = capture
1397
1165
            func(*args, **kwargs)
1398
1166
        finally:
1399
1167
            trace.log_exception_quietly = orig_log_exception_quietly
1400
1168
        self.assertLength(1, captured)
1401
 
        err = captured[0]
 
1169
        err = captured[0][1]
1402
1170
        self.assertIsInstance(err, exception_class)
1403
1171
        return err
1404
1172
 
1437
1205
            raise AssertionError('pattern "%s" found in "%s"'
1438
1206
                    % (needle_re, haystack))
1439
1207
 
1440
 
    def assertContainsString(self, haystack, needle):
1441
 
        if haystack.find(needle) == -1:
1442
 
            self.fail("string %r not found in '''%s'''" % (needle, haystack))
1443
 
 
1444
 
    def assertNotContainsString(self, haystack, needle):
1445
 
        if haystack.find(needle) != -1:
1446
 
            self.fail("string %r found in '''%s'''" % (needle, haystack))
1447
 
 
1448
1208
    def assertSubset(self, sublist, superlist):
1449
1209
        """Assert that every entry in sublist is present in superlist."""
1450
1210
        missing = set(sublist) - set(superlist)
1539
1299
 
1540
1300
    def assertFileEqual(self, content, path):
1541
1301
        """Fail if path does not contain 'content'."""
1542
 
        self.assertPathExists(path)
 
1302
        self.failUnlessExists(path)
1543
1303
        f = file(path, 'rb')
1544
1304
        try:
1545
1305
            s = f.read()
1547
1307
            f.close()
1548
1308
        self.assertEqualDiff(content, s)
1549
1309
 
1550
 
    def assertDocstring(self, expected_docstring, obj):
1551
 
        """Fail if obj does not have expected_docstring"""
1552
 
        if __doc__ is None:
1553
 
            # With -OO the docstring should be None instead
1554
 
            self.assertIs(obj.__doc__, None)
1555
 
        else:
1556
 
            self.assertEqual(expected_docstring, obj.__doc__)
1557
 
 
1558
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1559
1310
    def failUnlessExists(self, path):
1560
 
        return self.assertPathExists(path)
1561
 
 
1562
 
    def assertPathExists(self, path):
1563
1311
        """Fail unless path or paths, which may be abs or relative, exist."""
1564
1312
        if not isinstance(path, basestring):
1565
1313
            for p in path:
1566
 
                self.assertPathExists(p)
 
1314
                self.failUnlessExists(p)
1567
1315
        else:
1568
 
            self.assertTrue(osutils.lexists(path),
1569
 
                path + " does not exist")
 
1316
            self.failUnless(osutils.lexists(path),path+" does not exist")
1570
1317
 
1571
 
    @symbol_versioning.deprecated_method(symbol_versioning.deprecated_in((2, 4)))
1572
1318
    def failIfExists(self, path):
1573
 
        return self.assertPathDoesNotExist(path)
1574
 
 
1575
 
    def assertPathDoesNotExist(self, path):
1576
1319
        """Fail if path or paths, which may be abs or relative, exist."""
1577
1320
        if not isinstance(path, basestring):
1578
1321
            for p in path:
1579
 
                self.assertPathDoesNotExist(p)
 
1322
                self.failIfExists(p)
1580
1323
        else:
1581
 
            self.assertFalse(osutils.lexists(path),
1582
 
                path + " exists")
 
1324
            self.failIf(osutils.lexists(path),path+" exists")
1583
1325
 
1584
1326
    def _capture_deprecation_warnings(self, a_callable, *args, **kwargs):
1585
1327
        """A helper for callDeprecated and applyDeprecated.
1611
1353
        not other callers that go direct to the warning module.
1612
1354
 
1613
1355
        To test that a deprecated method raises an error, do something like
1614
 
        this (remember that both assertRaises and applyDeprecated delays *args
1615
 
        and **kwargs passing)::
 
1356
        this::
1616
1357
 
1617
1358
            self.assertRaises(errors.ReservedId,
1618
1359
                self.applyDeprecated,
1700
1441
 
1701
1442
        The file is removed as the test is torn down.
1702
1443
        """
1703
 
        pseudo_log_file = StringIO()
1704
 
        def _get_log_contents_for_weird_testtools_api():
1705
 
            return [pseudo_log_file.getvalue().decode(
1706
 
                "utf-8", "replace").encode("utf-8")]
1707
 
        self.addDetail("log", content.Content(content.ContentType("text",
1708
 
            "plain", {"charset": "utf8"}),
1709
 
            _get_log_contents_for_weird_testtools_api))
1710
 
        self._log_file = pseudo_log_file
1711
 
        self._log_memento = trace.push_log_file(self._log_file)
 
1444
        fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
 
1445
        self._log_file = os.fdopen(fileno, 'w+')
 
1446
        self._log_memento = bzrlib.trace.push_log_file(self._log_file)
 
1447
        self._log_file_name = name
1712
1448
        self.addCleanup(self._finishLogFile)
1713
1449
 
1714
1450
    def _finishLogFile(self):
1715
1451
        """Finished with the log file.
1716
1452
 
1717
 
        Close the file and delete it.
 
1453
        Close the file and delete it, unless setKeepLogfile was called.
1718
1454
        """
1719
 
        if trace._trace_file:
 
1455
        if bzrlib.trace._trace_file:
1720
1456
            # flush the log file, to get all content
1721
 
            trace._trace_file.flush()
1722
 
        trace.pop_log_file(self._log_memento)
 
1457
            bzrlib.trace._trace_file.flush()
 
1458
        bzrlib.trace.pop_log_file(self._log_memento)
 
1459
        # Cache the log result and delete the file on disk
 
1460
        self._get_log(False)
1723
1461
 
1724
1462
    def thisFailsStrictLockCheck(self):
1725
1463
        """It is known that this test would fail with -Dstrict_locks.
1734
1472
        """
1735
1473
        debug.debug_flags.discard('strict_locks')
1736
1474
 
 
1475
    def addCleanup(self, callable, *args, **kwargs):
 
1476
        """Arrange to run a callable when this case is torn down.
 
1477
 
 
1478
        Callables are run in the reverse of the order they are registered,
 
1479
        ie last-in first-out.
 
1480
        """
 
1481
        self._cleanups.append((callable, args, kwargs))
 
1482
 
1737
1483
    def overrideAttr(self, obj, attr_name, new=_unitialized_attr):
1738
1484
        """Overrides an object attribute restoring it after the test.
1739
1485
 
1740
 
        :note: This should be used with discretion; you should think about
1741
 
        whether it's better to make the code testable without monkey-patching.
1742
 
 
1743
1486
        :param obj: The object that will be mutated.
1744
1487
 
1745
1488
        :param attr_name: The attribute name we want to preserve/override in
1756
1499
            setattr(obj, attr_name, new)
1757
1500
        return value
1758
1501
 
1759
 
    def overrideEnv(self, name, new):
1760
 
        """Set an environment variable, and reset it after the test.
1761
 
 
1762
 
        :param name: The environment variable name.
1763
 
 
1764
 
        :param new: The value to set the variable to. If None, the 
1765
 
            variable is deleted from the environment.
1766
 
 
1767
 
        :returns: The actual variable value.
1768
 
        """
1769
 
        value = osutils.set_or_unset_env(name, new)
1770
 
        self.addCleanup(osutils.set_or_unset_env, name, value)
1771
 
        return value
1772
 
 
1773
 
    def recordCalls(self, obj, attr_name):
1774
 
        """Monkeypatch in a wrapper that will record calls.
1775
 
 
1776
 
        The monkeypatch is automatically removed when the test concludes.
1777
 
 
1778
 
        :param obj: The namespace holding the reference to be replaced;
1779
 
            typically a module, class, or object.
1780
 
        :param attr_name: A string for the name of the attribute to 
1781
 
            patch.
1782
 
        :returns: A list that will be extended with one item every time the
1783
 
            function is called, with a tuple of (args, kwargs).
1784
 
        """
1785
 
        calls = []
1786
 
 
1787
 
        def decorator(*args, **kwargs):
1788
 
            calls.append((args, kwargs))
1789
 
            return orig(*args, **kwargs)
1790
 
        orig = self.overrideAttr(obj, attr_name, decorator)
1791
 
        return calls
1792
 
 
1793
1502
    def _cleanEnvironment(self):
1794
 
        for name, value in isolated_environ.iteritems():
1795
 
            self.overrideEnv(name, value)
 
1503
        new_env = {
 
1504
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
 
1505
            'HOME': os.getcwd(),
 
1506
            # bzr now uses the Win32 API and doesn't rely on APPDATA, but the
 
1507
            # tests do check our impls match APPDATA
 
1508
            'BZR_EDITOR': None, # test_msgeditor manipulates this variable
 
1509
            'VISUAL': None,
 
1510
            'EDITOR': None,
 
1511
            'BZR_EMAIL': None,
 
1512
            'BZREMAIL': None, # may still be present in the environment
 
1513
            'EMAIL': None,
 
1514
            'BZR_PROGRESS_BAR': None,
 
1515
            'BZR_LOG': None,
 
1516
            'BZR_PLUGIN_PATH': None,
 
1517
            'BZR_CONCURRENCY': None,
 
1518
            # Make sure that any text ui tests are consistent regardless of
 
1519
            # the environment the test case is run in; you may want tests that
 
1520
            # test other combinations.  'dumb' is a reasonable guess for tests
 
1521
            # going to a pipe or a StringIO.
 
1522
            'TERM': 'dumb',
 
1523
            'LINES': '25',
 
1524
            'COLUMNS': '80',
 
1525
            'BZR_COLUMNS': '80',
 
1526
            # SSH Agent
 
1527
            'SSH_AUTH_SOCK': None,
 
1528
            # Proxies
 
1529
            'http_proxy': None,
 
1530
            'HTTP_PROXY': None,
 
1531
            'https_proxy': None,
 
1532
            'HTTPS_PROXY': None,
 
1533
            'no_proxy': None,
 
1534
            'NO_PROXY': None,
 
1535
            'all_proxy': None,
 
1536
            'ALL_PROXY': None,
 
1537
            # Nobody cares about ftp_proxy, FTP_PROXY AFAIK. So far at
 
1538
            # least. If you do (care), please update this comment
 
1539
            # -- vila 20080401
 
1540
            'ftp_proxy': None,
 
1541
            'FTP_PROXY': None,
 
1542
            'BZR_REMOTE_PATH': None,
 
1543
            # Generally speaking, we don't want apport reporting on crashes in
 
1544
            # the test envirnoment unless we're specifically testing apport,
 
1545
            # so that it doesn't leak into the real system environment.  We
 
1546
            # use an env var so it propagates to subprocesses.
 
1547
            'APPORT_DISABLE': '1',
 
1548
        }
 
1549
        self.__old_env = {}
 
1550
        self.addCleanup(self._restoreEnvironment)
 
1551
        for name, value in new_env.iteritems():
 
1552
            self._captureVar(name, value)
 
1553
 
 
1554
    def _captureVar(self, name, newvalue):
 
1555
        """Set an environment variable, and reset it when finished."""
 
1556
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
 
1557
 
 
1558
    def _restoreEnvironment(self):
 
1559
        for name, value in self.__old_env.iteritems():
 
1560
            osutils.set_or_unset_env(name, value)
1796
1561
 
1797
1562
    def _restoreHooks(self):
1798
1563
        for klass, (name, hooks) in self._preserved_hooks.items():
1799
1564
            setattr(klass, name, hooks)
1800
 
        self._preserved_hooks.clear()
1801
 
        bzrlib.hooks._lazy_hooks = self._preserved_lazy_hooks
1802
 
        self._preserved_lazy_hooks.clear()
1803
1565
 
1804
1566
    def knownFailure(self, reason):
1805
 
        """Declare that this test fails for a known reason
1806
 
 
1807
 
        Tests that are known to fail should generally be using expectedFailure
1808
 
        with an appropriate reverse assertion if a change could cause the test
1809
 
        to start passing. Conversely if the test has no immediate prospect of
1810
 
        succeeding then using skip is more suitable.
1811
 
 
1812
 
        When this method is called while an exception is being handled, that
1813
 
        traceback will be used, otherwise a new exception will be thrown to
1814
 
        provide one but won't be reported.
1815
 
        """
1816
 
        self._add_reason(reason)
1817
 
        try:
1818
 
            exc_info = sys.exc_info()
1819
 
            if exc_info != (None, None, None):
1820
 
                self._report_traceback(exc_info)
1821
 
            else:
1822
 
                try:
1823
 
                    raise self.failureException(reason)
1824
 
                except self.failureException:
1825
 
                    exc_info = sys.exc_info()
1826
 
            # GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
1827
 
            raise testtools.testcase._ExpectedFailure(exc_info)
1828
 
        finally:
1829
 
            del exc_info
1830
 
 
1831
 
    def _suppress_log(self):
1832
 
        """Remove the log info from details."""
1833
 
        self.discardDetail('log')
 
1567
        """This test has failed for some known reason."""
 
1568
        raise KnownFailure(reason)
1834
1569
 
1835
1570
    def _do_skip(self, result, reason):
1836
 
        self._suppress_log()
1837
1571
        addSkip = getattr(result, 'addSkip', None)
1838
1572
        if not callable(addSkip):
1839
1573
            result.addSuccess(result)
1842
1576
 
1843
1577
    @staticmethod
1844
1578
    def _do_known_failure(self, result, e):
1845
 
        self._suppress_log()
1846
1579
        err = sys.exc_info()
1847
1580
        addExpectedFailure = getattr(result, 'addExpectedFailure', None)
1848
1581
        if addExpectedFailure is not None:
1856
1589
            reason = 'No reason given'
1857
1590
        else:
1858
1591
            reason = e.args[0]
1859
 
        self._suppress_log ()
1860
1592
        addNotApplicable = getattr(result, 'addNotApplicable', None)
1861
1593
        if addNotApplicable is not None:
1862
1594
            result.addNotApplicable(self, reason)
1864
1596
            self._do_skip(result, reason)
1865
1597
 
1866
1598
    @staticmethod
1867
 
    def _report_skip(self, result, err):
1868
 
        """Override the default _report_skip.
1869
 
 
1870
 
        We want to strip the 'log' detail. If we waint until _do_skip, it has
1871
 
        already been formatted into the 'reason' string, and we can't pull it
1872
 
        out again.
1873
 
        """
1874
 
        self._suppress_log()
1875
 
        super(TestCase, self)._report_skip(self, result, err)
1876
 
 
1877
 
    @staticmethod
1878
 
    def _report_expected_failure(self, result, err):
1879
 
        """Strip the log.
1880
 
 
1881
 
        See _report_skip for motivation.
1882
 
        """
1883
 
        self._suppress_log()
1884
 
        super(TestCase, self)._report_expected_failure(self, result, err)
1885
 
 
1886
 
    @staticmethod
1887
1599
    def _do_unsupported_or_skip(self, result, e):
1888
1600
        reason = e.args[0]
1889
 
        self._suppress_log()
1890
1601
        addNotSupported = getattr(result, 'addNotSupported', None)
1891
1602
        if addNotSupported is not None:
1892
1603
            result.addNotSupported(self, reason)
1918
1629
            self._benchtime += time.time() - start
1919
1630
 
1920
1631
    def log(self, *args):
1921
 
        trace.mutter(*args)
 
1632
        mutter(*args)
 
1633
 
 
1634
    def _get_log(self, keep_log_file=False):
 
1635
        """Internal helper to get the log from bzrlib.trace for this test.
 
1636
 
 
1637
        Please use self.getDetails, or self.get_log to access this in test case
 
1638
        code.
 
1639
 
 
1640
        :param keep_log_file: When True, if the log is still a file on disk
 
1641
            leave it as a file on disk. When False, if the log is still a file
 
1642
            on disk, the log file is deleted and the log preserved as
 
1643
            self._log_contents.
 
1644
        :return: A string containing the log.
 
1645
        """
 
1646
        if self._log_contents is not None:
 
1647
            try:
 
1648
                self._log_contents.decode('utf8')
 
1649
            except UnicodeDecodeError:
 
1650
                unicodestr = self._log_contents.decode('utf8', 'replace')
 
1651
                self._log_contents = unicodestr.encode('utf8')
 
1652
            return self._log_contents
 
1653
        import bzrlib.trace
 
1654
        if bzrlib.trace._trace_file:
 
1655
            # flush the log file, to get all content
 
1656
            bzrlib.trace._trace_file.flush()
 
1657
        if self._log_file_name is not None:
 
1658
            logfile = open(self._log_file_name)
 
1659
            try:
 
1660
                log_contents = logfile.read()
 
1661
            finally:
 
1662
                logfile.close()
 
1663
            try:
 
1664
                log_contents.decode('utf8')
 
1665
            except UnicodeDecodeError:
 
1666
                unicodestr = log_contents.decode('utf8', 'replace')
 
1667
                log_contents = unicodestr.encode('utf8')
 
1668
            if not keep_log_file:
 
1669
                self._log_file.close()
 
1670
                self._log_file = None
 
1671
                # Permit multiple calls to get_log until we clean it up in
 
1672
                # finishLogFile
 
1673
                self._log_contents = log_contents
 
1674
                try:
 
1675
                    os.remove(self._log_file_name)
 
1676
                except OSError, e:
 
1677
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
 
1678
                        sys.stderr.write(('Unable to delete log file '
 
1679
                                             ' %r\n' % self._log_file_name))
 
1680
                    else:
 
1681
                        raise
 
1682
                self._log_file_name = None
 
1683
            return log_contents
 
1684
        else:
 
1685
            return "No log file content and no log file name."
1922
1686
 
1923
1687
    def get_log(self):
1924
1688
        """Get a unicode string containing the log from bzrlib.trace.
1974
1738
 
1975
1739
        try:
1976
1740
            try:
1977
 
                result = self.apply_redirected(
1978
 
                    ui.ui_factory.stdin,
 
1741
                result = self.apply_redirected(ui.ui_factory.stdin,
1979
1742
                    stdout, stderr,
1980
 
                    _mod_commands.run_bzr_catch_user_errors,
 
1743
                    bzrlib.commands.run_bzr_catch_user_errors,
1981
1744
                    args)
1982
1745
            except KeyboardInterrupt:
1983
1746
                # Reraise KeyboardInterrupt with contents of redirected stdout
2125
1888
    def start_bzr_subprocess(self, process_args, env_changes=None,
2126
1889
                             skip_if_plan_to_signal=False,
2127
1890
                             working_dir=None,
2128
 
                             allow_plugins=False, stderr=subprocess.PIPE):
 
1891
                             allow_plugins=False):
2129
1892
        """Start bzr in a subprocess for testing.
2130
1893
 
2131
1894
        This starts a new Python interpreter and runs bzr in there.
2140
1903
            variables. A value of None will unset the env variable.
2141
1904
            The values must be strings. The change will only occur in the
2142
1905
            child, so you don't need to fix the environment after running.
2143
 
        :param skip_if_plan_to_signal: raise TestSkipped when true and system
2144
 
            doesn't support signalling subprocesses.
 
1906
        :param skip_if_plan_to_signal: raise TestSkipped when true and os.kill
 
1907
            is not available.
2145
1908
        :param allow_plugins: If False (default) pass --no-plugins to bzr.
2146
 
        :param stderr: file to use for the subprocess's stderr.  Valid values
2147
 
            are those valid for the stderr argument of `subprocess.Popen`.
2148
 
            Default value is ``subprocess.PIPE``.
2149
1909
 
2150
1910
        :returns: Popen object for the started process.
2151
1911
        """
2152
1912
        if skip_if_plan_to_signal:
2153
 
            if os.name != "posix":
2154
 
                raise TestSkipped("Sending signals not supported")
 
1913
            if not getattr(os, 'kill', None):
 
1914
                raise TestSkipped("os.kill not available.")
2155
1915
 
2156
1916
        if env_changes is None:
2157
1917
            env_changes = {}
2177
1937
            # so we will avoid using it on all platforms, just to
2178
1938
            # make sure the code path is used, and we don't break on win32
2179
1939
            cleanup_environment()
2180
 
            # Include the subprocess's log file in the test details, in case
2181
 
            # the test fails due to an error in the subprocess.
2182
 
            self._add_subprocess_log(trace._get_bzr_log_filename())
2183
1940
            command = [sys.executable]
2184
1941
            # frozen executables don't need the path to bzr
2185
1942
            if getattr(sys, "frozen", None) is None:
2187
1944
            if not allow_plugins:
2188
1945
                command.append('--no-plugins')
2189
1946
            command.extend(process_args)
2190
 
            process = self._popen(command, stdin=subprocess.PIPE,
2191
 
                                  stdout=subprocess.PIPE,
2192
 
                                  stderr=stderr)
 
1947
            process = self._popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE)
2193
1948
        finally:
2194
1949
            restore_environment()
2195
1950
            if cwd is not None:
2197
1952
 
2198
1953
        return process
2199
1954
 
2200
 
    def _add_subprocess_log(self, log_file_path):
2201
 
        if len(self._log_files) == 0:
2202
 
            # Register an addCleanup func.  We do this on the first call to
2203
 
            # _add_subprocess_log rather than in TestCase.setUp so that this
2204
 
            # addCleanup is registered after any cleanups for tempdirs that
2205
 
            # subclasses might create, which will probably remove the log file
2206
 
            # we want to read.
2207
 
            self.addCleanup(self._subprocess_log_cleanup)
2208
 
        # self._log_files is a set, so if a log file is reused we won't grab it
2209
 
        # twice.
2210
 
        self._log_files.add(log_file_path)
2211
 
 
2212
 
    def _subprocess_log_cleanup(self):
2213
 
        for count, log_file_path in enumerate(self._log_files):
2214
 
            # We use buffer_now=True to avoid holding the file open beyond
2215
 
            # the life of this function, which might interfere with e.g.
2216
 
            # cleaning tempdirs on Windows.
2217
 
            # XXX: Testtools 0.9.5 doesn't have the content_from_file helper
2218
 
            #detail_content = content.content_from_file(
2219
 
            #    log_file_path, buffer_now=True)
2220
 
            with open(log_file_path, 'rb') as log_file:
2221
 
                log_file_bytes = log_file.read()
2222
 
            detail_content = content.Content(content.ContentType("text",
2223
 
                "plain", {"charset": "utf8"}), lambda: [log_file_bytes])
2224
 
            self.addDetail("start_bzr_subprocess-log-%d" % (count,),
2225
 
                detail_content)
2226
 
 
2227
1955
    def _popen(self, *args, **kwargs):
2228
1956
        """Place a call to Popen.
2229
1957
 
2230
1958
        Allows tests to override this method to intercept the calls made to
2231
1959
        Popen for introspection.
2232
1960
        """
2233
 
        return subprocess.Popen(*args, **kwargs)
 
1961
        return Popen(*args, **kwargs)
2234
1962
 
2235
1963
    def get_source_path(self):
2236
1964
        """Return the path of the directory containing bzrlib."""
2238
1966
 
2239
1967
    def get_bzr_path(self):
2240
1968
        """Return the path of the 'bzr' executable for this test suite."""
2241
 
        bzr_path = os.path.join(self.get_source_path(), "bzr")
 
1969
        bzr_path = self.get_source_path()+'/bzr'
2242
1970
        if not os.path.isfile(bzr_path):
2243
1971
            # We are probably installed. Assume sys.argv is the right file
2244
1972
            bzr_path = sys.argv[0]
2266
1994
        if retcode is not None and retcode != process.returncode:
2267
1995
            if process_args is None:
2268
1996
                process_args = "(unknown args)"
2269
 
            trace.mutter('Output of bzr %s:\n%s', process_args, out)
2270
 
            trace.mutter('Error for bzr %s:\n%s', process_args, err)
 
1997
            mutter('Output of bzr %s:\n%s', process_args, out)
 
1998
            mutter('Error for bzr %s:\n%s', process_args, err)
2271
1999
            self.fail('Command bzr %s failed with retcode %s != %s'
2272
2000
                      % (process_args, retcode, process.returncode))
2273
2001
        return [out, err]
2274
2002
 
2275
 
    def check_tree_shape(self, tree, shape):
2276
 
        """Compare a tree to a list of expected names.
 
2003
    def check_inventory_shape(self, inv, shape):
 
2004
        """Compare an inventory to a list of expected names.
2277
2005
 
2278
2006
        Fail if they are not precisely equal.
2279
2007
        """
2280
2008
        extras = []
2281
2009
        shape = list(shape)             # copy
2282
 
        for path, ie in tree.iter_entries_by_dir():
 
2010
        for path, ie in inv.entries():
2283
2011
            name = path.replace('\\', '/')
2284
2012
            if ie.kind == 'directory':
2285
2013
                name = name + '/'
2286
 
            if name == "/":
2287
 
                pass # ignore root entry
2288
 
            elif name in shape:
 
2014
            if name in shape:
2289
2015
                shape.remove(name)
2290
2016
            else:
2291
2017
                extras.append(name)
2332
2058
 
2333
2059
        Tests that expect to provoke LockContention errors should call this.
2334
2060
        """
2335
 
        self.overrideAttr(lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
 
2061
        self.overrideAttr(bzrlib.lockdir, '_DEFAULT_TIMEOUT_SECONDS', 0)
2336
2062
 
2337
2063
    def make_utf8_encoded_stringio(self, encoding_type=None):
2338
2064
        """Return a StringIOWrapper instance, that will encode Unicode
2381
2107
class TestCaseWithMemoryTransport(TestCase):
2382
2108
    """Common test class for tests that do not need disk resources.
2383
2109
 
2384
 
    Tests that need disk resources should derive from TestCaseInTempDir
2385
 
    orTestCaseWithTransport.
 
2110
    Tests that need disk resources should derive from TestCaseWithTransport.
2386
2111
 
2387
2112
    TestCaseWithMemoryTransport sets the TEST_ROOT variable for all bzr tests.
2388
2113
 
2389
 
    For TestCaseWithMemoryTransport the ``test_home_dir`` is set to the name of
 
2114
    For TestCaseWithMemoryTransport the test_home_dir is set to the name of
2390
2115
    a directory which does not exist. This serves to help ensure test isolation
2391
 
    is preserved. ``test_dir`` is set to the TEST_ROOT, as is cwd, because they
2392
 
    must exist. However, TestCaseWithMemoryTransport does not offer local file
2393
 
    defaults for the transport in tests, nor does it obey the command line
 
2116
    is preserved. test_dir is set to the TEST_ROOT, as is cwd, because they
 
2117
    must exist. However, TestCaseWithMemoryTransport does not offer local
 
2118
    file defaults for the transport in tests, nor does it obey the command line
2394
2119
    override, so tests that accidentally write to the common directory should
2395
2120
    be rare.
2396
2121
 
2397
 
    :cvar TEST_ROOT: Directory containing all temporary directories, plus a
2398
 
        ``.bzr`` directory that stops us ascending higher into the filesystem.
 
2122
    :cvar TEST_ROOT: Directory containing all temporary directories, plus
 
2123
    a .bzr directory that stops us ascending higher into the filesystem.
2399
2124
    """
2400
2125
 
2401
2126
    TEST_ROOT = None
2419
2144
 
2420
2145
        :param relpath: a path relative to the base url.
2421
2146
        """
2422
 
        t = _mod_transport.get_transport_from_url(self.get_url(relpath))
 
2147
        t = get_transport(self.get_url(relpath))
2423
2148
        self.assertFalse(t.is_readonly())
2424
2149
        return t
2425
2150
 
2431
2156
 
2432
2157
        :param relpath: a path relative to the base url.
2433
2158
        """
2434
 
        t = _mod_transport.get_transport(self.get_readonly_url(relpath))
 
2159
        t = get_transport(self.get_readonly_url(relpath))
2435
2160
        self.assertTrue(t.is_readonly())
2436
2161
        return t
2437
2162
 
2450
2175
        if self.__readonly_server is None:
2451
2176
            if self.transport_readonly_server is None:
2452
2177
                # readonly decorator requested
2453
 
                self.__readonly_server = test_server.ReadonlyServer()
 
2178
                self.__readonly_server = ReadonlyServer()
2454
2179
            else:
2455
2180
                # explicit readonly transport.
2456
2181
                self.__readonly_server = self.create_transport_readonly_server()
2479
2204
        is no means to override it.
2480
2205
        """
2481
2206
        if self.__vfs_server is None:
2482
 
            self.__vfs_server = memory.MemoryServer()
 
2207
            self.__vfs_server = MemoryServer()
2483
2208
            self.start_server(self.__vfs_server)
2484
2209
        return self.__vfs_server
2485
2210
 
2558
2283
        real branch.
2559
2284
        """
2560
2285
        root = TestCaseWithMemoryTransport.TEST_ROOT
2561
 
        wt = bzrdir.BzrDir.create_standalone_workingtree(root)
2562
 
        # Hack for speed: remember the raw bytes of the dirstate file so that
2563
 
        # we don't need to re-open the wt to check it hasn't changed.
2564
 
        TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE = (
2565
 
            wt.control_transport.get_bytes('dirstate'))
 
2286
        bzrdir.BzrDir.create_standalone_workingtree(root)
2566
2287
 
2567
2288
    def _check_safety_net(self):
2568
2289
        """Check that the safety .bzr directory have not been touched.
2571
2292
        propagating. This method ensures than a test did not leaked.
2572
2293
        """
2573
2294
        root = TestCaseWithMemoryTransport.TEST_ROOT
2574
 
        t = _mod_transport.get_transport(root)
2575
 
        self.permit_url(t.base)
2576
 
        if (t.get_bytes('.bzr/checkout/dirstate') != 
2577
 
                TestCaseWithMemoryTransport._SAFETY_NET_PRISTINE_DIRSTATE):
 
2295
        self.permit_url(get_transport(root).base)
 
2296
        wt = workingtree.WorkingTree.open(root)
 
2297
        last_rev = wt.last_revision()
 
2298
        if last_rev != 'null:':
2578
2299
            # The current test have modified the /bzr directory, we need to
2579
2300
            # recreate a new one or all the followng tests will fail.
2580
2301
            # If you need to inspect its content uncomment the following line
2622
2343
            # might be a relative or absolute path
2623
2344
            maybe_a_url = self.get_url(relpath)
2624
2345
            segments = maybe_a_url.rsplit('/', 1)
2625
 
            t = _mod_transport.get_transport(maybe_a_url)
 
2346
            t = get_transport(maybe_a_url)
2626
2347
            if len(segments) > 1 and segments[-1] not in ('', '.'):
2627
2348
                t.ensure_base()
2628
2349
            if format is None:
2645
2366
        made_control = self.make_bzrdir(relpath, format=format)
2646
2367
        return made_control.create_repository(shared=shared)
2647
2368
 
2648
 
    def make_smart_server(self, path, backing_server=None):
2649
 
        if backing_server is None:
2650
 
            backing_server = self.get_server()
2651
 
        smart_server = test_server.SmartTCPServer_for_testing()
2652
 
        self.start_server(smart_server, backing_server)
2653
 
        remote_transport = _mod_transport.get_transport_from_url(smart_server.get_url()
2654
 
                                                   ).clone(path)
 
2369
    def make_smart_server(self, path):
 
2370
        smart_server = server.SmartTCPServer_for_testing()
 
2371
        self.start_server(smart_server, self.get_server())
 
2372
        remote_transport = get_transport(smart_server.get_url()).clone(path)
2655
2373
        return remote_transport
2656
2374
 
2657
2375
    def make_branch_and_memory_tree(self, relpath, format=None):
2667
2385
        test_home_dir = self.test_home_dir
2668
2386
        if isinstance(test_home_dir, unicode):
2669
2387
            test_home_dir = test_home_dir.encode(sys.getfilesystemencoding())
2670
 
        self.overrideEnv('HOME', test_home_dir)
2671
 
        self.overrideEnv('BZR_HOME', test_home_dir)
 
2388
        os.environ['HOME'] = test_home_dir
 
2389
        os.environ['BZR_HOME'] = test_home_dir
2672
2390
 
2673
2391
    def setUp(self):
2674
2392
        super(TestCaseWithMemoryTransport, self).setUp()
2675
 
        # Ensure that ConnectedTransport doesn't leak sockets
2676
 
        def get_transport_from_url_with_cleanup(*args, **kwargs):
2677
 
            t = orig_get_transport_from_url(*args, **kwargs)
2678
 
            if isinstance(t, _mod_transport.ConnectedTransport):
2679
 
                self.addCleanup(t.disconnect)
2680
 
            return t
2681
 
 
2682
 
        orig_get_transport_from_url = self.overrideAttr(
2683
 
            _mod_transport, 'get_transport_from_url',
2684
 
            get_transport_from_url_with_cleanup)
2685
2393
        self._make_test_root()
2686
2394
        self.addCleanup(os.chdir, os.getcwdu())
2687
2395
        self.makeAndChdirToTestDir()
2692
2400
 
2693
2401
    def setup_smart_server_with_call_log(self):
2694
2402
        """Sets up a smart server as the transport server with a call log."""
2695
 
        self.transport_server = test_server.SmartTCPServer_for_testing
 
2403
        self.transport_server = server.SmartTCPServer_for_testing
2696
2404
        self.hpss_calls = []
2697
2405
        import traceback
2698
2406
        # Skip the current stack down to the caller of
2730
2438
 
2731
2439
    OVERRIDE_PYTHON = 'python'
2732
2440
 
2733
 
    def setUp(self):
2734
 
        super(TestCaseInTempDir, self).setUp()
2735
 
        # Remove the protection set in isolated_environ, we have a proper
2736
 
        # access to disk resources now.
2737
 
        self.overrideEnv('BZR_LOG', None)
2738
 
 
2739
2441
    def check_file_contents(self, filename, expect):
2740
2442
        self.log("check contents of file %s" % filename)
2741
 
        f = file(filename)
2742
 
        try:
2743
 
            contents = f.read()
2744
 
        finally:
2745
 
            f.close()
 
2443
        contents = file(filename, 'r').read()
2746
2444
        if contents != expect:
2747
2445
            self.log("expected: %r" % expect)
2748
2446
            self.log("actually: %r" % contents)
2822
2520
                "a list or a tuple. Got %r instead" % (shape,))
2823
2521
        # It's OK to just create them using forward slashes on windows.
2824
2522
        if transport is None or transport.is_readonly():
2825
 
            transport = _mod_transport.get_transport(".")
 
2523
            transport = get_transport(".")
2826
2524
        for name in shape:
2827
2525
            self.assertIsInstance(name, basestring)
2828
2526
            if name[-1] == '/':
2838
2536
                content = "contents of %s%s" % (name.encode('utf-8'), end)
2839
2537
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
2840
2538
 
2841
 
    build_tree_contents = staticmethod(treeshape.build_tree_contents)
 
2539
    def build_tree_contents(self, shape):
 
2540
        build_tree_contents(shape)
2842
2541
 
2843
2542
    def assertInWorkingTree(self, path, root_path='.', tree=None):
2844
2543
        """Assert whether path or paths are in the WorkingTree"""
2920
2619
            # We can only make working trees locally at the moment.  If the
2921
2620
            # transport can't support them, then we keep the non-disk-backed
2922
2621
            # branch and create a local checkout.
2923
 
            if self.vfs_transport_factory is test_server.LocalURLServer:
 
2622
            if self.vfs_transport_factory is LocalURLServer:
2924
2623
                # the branch is colocated on disk, we cannot create a checkout.
2925
2624
                # hopefully callers will expect this.
2926
2625
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2985
2684
    """
2986
2685
 
2987
2686
    def setUp(self):
2988
 
        from bzrlib.tests import http_server
2989
2687
        super(ChrootedTestCase, self).setUp()
2990
 
        if not self.vfs_transport_factory == memory.MemoryServer:
2991
 
            self.transport_readonly_server = http_server.HttpServer
 
2688
        if not self.vfs_transport_factory == MemoryServer:
 
2689
            self.transport_readonly_server = HttpServer
2992
2690
 
2993
2691
 
2994
2692
def condition_id_re(pattern):
2997
2695
    :param pattern: A regular expression string.
2998
2696
    :return: A callable that returns True if the re matches.
2999
2697
    """
3000
 
    filter_re = re.compile(pattern, 0)
 
2698
    filter_re = osutils.re_compile_checked(pattern, 0,
 
2699
        'test filter')
3001
2700
    def condition(test):
3002
2701
        test_id = test.id()
3003
2702
        return filter_re.search(test_id)
3255
2954
 
3256
2955
 
3257
2956
def fork_decorator(suite):
3258
 
    if getattr(os, "fork", None) is None:
3259
 
        raise errors.BzrCommandError("platform does not support fork,"
3260
 
            " try --parallel=subprocess instead.")
3261
2957
    concurrency = osutils.local_concurrency()
3262
2958
    if concurrency == 1:
3263
2959
        return suite
3318
3014
    return suite
3319
3015
 
3320
3016
 
3321
 
class TestDecorator(TestUtil.TestSuite):
 
3017
class TestDecorator(TestSuite):
3322
3018
    """A decorator for TestCase/TestSuite objects.
3323
3019
    
3324
3020
    Usually, subclasses should override __iter__(used when flattening test
3327
3023
    """
3328
3024
 
3329
3025
    def __init__(self, suite):
3330
 
        TestUtil.TestSuite.__init__(self)
 
3026
        TestSuite.__init__(self)
3331
3027
        self.addTest(suite)
3332
3028
 
3333
3029
    def countTestCases(self):
3452
3148
 
3453
3149
def partition_tests(suite, count):
3454
3150
    """Partition suite into count lists of tests."""
3455
 
    # This just assigns tests in a round-robin fashion.  On one hand this
3456
 
    # splits up blocks of related tests that might run faster if they shared
3457
 
    # resources, but on the other it avoids assigning blocks of slow tests to
3458
 
    # just one partition.  So the slowest partition shouldn't be much slower
3459
 
    # than the fastest.
3460
 
    partitions = [list() for i in range(count)]
3461
 
    tests = iter_suite_tests(suite)
3462
 
    for partition, test in itertools.izip(itertools.cycle(partitions), tests):
3463
 
        partition.append(test)
3464
 
    return partitions
3465
 
 
3466
 
 
3467
 
def workaround_zealous_crypto_random():
3468
 
    """Crypto.Random want to help us being secure, but we don't care here.
3469
 
 
3470
 
    This workaround some test failure related to the sftp server. Once paramiko
3471
 
    stop using the controversial API in Crypto.Random, we may get rid of it.
3472
 
    """
3473
 
    try:
3474
 
        from Crypto.Random import atfork
3475
 
        atfork()
3476
 
    except ImportError:
3477
 
        pass
 
3151
    result = []
 
3152
    tests = list(iter_suite_tests(suite))
 
3153
    tests_per_process = int(math.ceil(float(len(tests)) / count))
 
3154
    for block in range(count):
 
3155
        low_test = block * tests_per_process
 
3156
        high_test = low_test + tests_per_process
 
3157
        process_tests = tests[low_test:high_test]
 
3158
        result.append(process_tests)
 
3159
    return result
3478
3160
 
3479
3161
 
3480
3162
def fork_for_tests(suite):
3497
3179
            try:
3498
3180
                ProtocolTestCase.run(self, result)
3499
3181
            finally:
3500
 
                os.waitpid(self.pid, 0)
 
3182
                os.waitpid(self.pid, os.WNOHANG)
3501
3183
 
3502
3184
    test_blocks = partition_tests(suite, concurrency)
3503
3185
    for process_tests in test_blocks:
3504
 
        process_suite = TestUtil.TestSuite()
 
3186
        process_suite = TestSuite()
3505
3187
        process_suite.addTests(process_tests)
3506
3188
        c2pread, c2pwrite = os.pipe()
3507
3189
        pid = os.fork()
3508
3190
        if pid == 0:
3509
 
            workaround_zealous_crypto_random()
3510
3191
            try:
3511
3192
                os.close(c2pread)
3512
3193
                # Leave stderr and stdout open so we can see test noise
3573
3254
                '--subunit']
3574
3255
            if '--no-plugins' in sys.argv:
3575
3256
                argv.append('--no-plugins')
3576
 
            # stderr=subprocess.STDOUT would be ideal, but until we prevent
3577
 
            # noise on stderr it can interrupt the subunit protocol.
3578
 
            process = subprocess.Popen(argv, stdin=subprocess.PIPE,
3579
 
                                      stdout=subprocess.PIPE,
3580
 
                                      stderr=subprocess.PIPE,
3581
 
                                      bufsize=1)
 
3257
            # stderr=STDOUT would be ideal, but until we prevent noise on
 
3258
            # stderr it can interrupt the subunit protocol.
 
3259
            process = Popen(argv, stdin=PIPE, stdout=PIPE, stderr=PIPE,
 
3260
                bufsize=1)
3582
3261
            test = TestInSubprocess(process, test_list_file_name)
3583
3262
            result.append(test)
3584
3263
        except:
3587
3266
    return result
3588
3267
 
3589
3268
 
3590
 
class ProfileResult(testtools.ExtendedToOriginalDecorator):
 
3269
class ForwardingResult(unittest.TestResult):
 
3270
 
 
3271
    def __init__(self, target):
 
3272
        unittest.TestResult.__init__(self)
 
3273
        self.result = target
 
3274
 
 
3275
    def startTest(self, test):
 
3276
        self.result.startTest(test)
 
3277
 
 
3278
    def stopTest(self, test):
 
3279
        self.result.stopTest(test)
 
3280
 
 
3281
    def startTestRun(self):
 
3282
        self.result.startTestRun()
 
3283
 
 
3284
    def stopTestRun(self):
 
3285
        self.result.stopTestRun()
 
3286
 
 
3287
    def addSkip(self, test, reason):
 
3288
        self.result.addSkip(test, reason)
 
3289
 
 
3290
    def addSuccess(self, test):
 
3291
        self.result.addSuccess(test)
 
3292
 
 
3293
    def addError(self, test, err):
 
3294
        self.result.addError(test, err)
 
3295
 
 
3296
    def addFailure(self, test, err):
 
3297
        self.result.addFailure(test, err)
 
3298
ForwardingResult = testtools.ExtendedToOriginalDecorator
 
3299
 
 
3300
 
 
3301
class ProfileResult(ForwardingResult):
3591
3302
    """Generate profiling data for all activity between start and success.
3592
3303
    
3593
3304
    The profile data is appended to the test's _benchcalls attribute and can
3601
3312
 
3602
3313
    def startTest(self, test):
3603
3314
        self.profiler = bzrlib.lsprof.BzrProfiler()
3604
 
        # Prevent deadlocks in tests that use lsprof: those tests will
3605
 
        # unavoidably fail.
3606
 
        bzrlib.lsprof.BzrProfiler.profiler_block = 0
3607
3315
        self.profiler.start()
3608
 
        testtools.ExtendedToOriginalDecorator.startTest(self, test)
 
3316
        ForwardingResult.startTest(self, test)
3609
3317
 
3610
3318
    def addSuccess(self, test):
3611
3319
        stats = self.profiler.stop()
3615
3323
            test._benchcalls = []
3616
3324
            calls = test._benchcalls
3617
3325
        calls.append(((test.id(), "", ""), stats))
3618
 
        testtools.ExtendedToOriginalDecorator.addSuccess(self, test)
 
3326
        ForwardingResult.addSuccess(self, test)
3619
3327
 
3620
3328
    def stopTest(self, test):
3621
 
        testtools.ExtendedToOriginalDecorator.stopTest(self, test)
 
3329
        ForwardingResult.stopTest(self, test)
3622
3330
        self.profiler = None
3623
3331
 
3624
3332
 
3630
3338
#                           rather than failing tests. And no longer raise
3631
3339
#                           LockContention when fctnl locks are not being used
3632
3340
#                           with proper exclusion rules.
3633
 
#   -Ethreads               Will display thread ident at creation/join time to
3634
 
#                           help track thread leaks
3635
 
 
3636
 
#   -Econfig_stats          Will collect statistics using addDetail
3637
3341
selftest_debug_flags = set()
3638
3342
 
3639
3343
 
3833
3537
                key, obj, help=help, info=info, override_existing=False)
3834
3538
        except KeyError:
3835
3539
            actual = self.get(key)
3836
 
            trace.note(
3837
 
                'Test prefix alias %s is already used for %s, ignoring %s'
3838
 
                % (key, actual, obj))
 
3540
            note('Test prefix alias %s is already used for %s, ignoring %s'
 
3541
                 % (key, actual, obj))
3839
3542
 
3840
3543
    def resolve_alias(self, id_start):
3841
3544
        """Replace the alias by the prefix in the given string.
3859
3562
# appear prefixed ('bzrlib.' is "replaced" by 'bzrlib.').
3860
3563
test_prefix_alias_registry.register('bzrlib', 'bzrlib')
3861
3564
 
3862
 
# Obvious highest levels prefixes, feel free to add your own via a plugin
 
3565
# Obvious higest levels prefixes, feel free to add your own via a plugin
3863
3566
test_prefix_alias_registry.register('bd', 'bzrlib.doc')
3864
3567
test_prefix_alias_registry.register('bu', 'bzrlib.utils')
3865
3568
test_prefix_alias_registry.register('bt', 'bzrlib.tests')
3873
3576
        'bzrlib.doc',
3874
3577
        'bzrlib.tests.blackbox',
3875
3578
        'bzrlib.tests.commands',
3876
 
        'bzrlib.tests.doc_generate',
3877
3579
        'bzrlib.tests.per_branch',
3878
3580
        'bzrlib.tests.per_bzrdir',
3879
 
        'bzrlib.tests.per_controldir',
3880
 
        'bzrlib.tests.per_controldir_colo',
3881
3581
        'bzrlib.tests.per_foreign_vcs',
3882
3582
        'bzrlib.tests.per_interrepository',
3883
3583
        'bzrlib.tests.per_intertree',
3891
3591
        'bzrlib.tests.per_repository',
3892
3592
        'bzrlib.tests.per_repository_chk',
3893
3593
        'bzrlib.tests.per_repository_reference',
3894
 
        'bzrlib.tests.per_repository_vf',
3895
3594
        'bzrlib.tests.per_uifactory',
3896
3595
        'bzrlib.tests.per_versionedfile',
3897
3596
        'bzrlib.tests.per_workingtree',
3898
3597
        'bzrlib.tests.test__annotator',
3899
3598
        'bzrlib.tests.test__bencode',
3900
 
        'bzrlib.tests.test__btree_serializer',
3901
3599
        'bzrlib.tests.test__chk_map',
3902
3600
        'bzrlib.tests.test__dirstate_helpers',
3903
3601
        'bzrlib.tests.test__groupcompress',
3925
3623
        'bzrlib.tests.test_chunk_writer',
3926
3624
        'bzrlib.tests.test_clean_tree',
3927
3625
        'bzrlib.tests.test_cleanup',
3928
 
        'bzrlib.tests.test_cmdline',
3929
3626
        'bzrlib.tests.test_commands',
3930
3627
        'bzrlib.tests.test_commit',
3931
3628
        'bzrlib.tests.test_commit_merge',
3932
3629
        'bzrlib.tests.test_config',
3933
3630
        'bzrlib.tests.test_conflicts',
3934
 
        'bzrlib.tests.test_controldir',
3935
3631
        'bzrlib.tests.test_counted_lock',
3936
3632
        'bzrlib.tests.test_crash',
3937
3633
        'bzrlib.tests.test_decorators',
3938
3634
        'bzrlib.tests.test_delta',
3939
3635
        'bzrlib.tests.test_debug',
 
3636
        'bzrlib.tests.test_deprecated_graph',
3940
3637
        'bzrlib.tests.test_diff',
3941
3638
        'bzrlib.tests.test_directory_service',
3942
3639
        'bzrlib.tests.test_dirstate',
3944
3641
        'bzrlib.tests.test_eol_filters',
3945
3642
        'bzrlib.tests.test_errors',
3946
3643
        'bzrlib.tests.test_export',
3947
 
        'bzrlib.tests.test_export_pot',
3948
3644
        'bzrlib.tests.test_extract',
3949
 
        'bzrlib.tests.test_features',
3950
3645
        'bzrlib.tests.test_fetch',
3951
 
        'bzrlib.tests.test_fixtures',
3952
3646
        'bzrlib.tests.test_fifo_cache',
3953
3647
        'bzrlib.tests.test_filters',
3954
 
        'bzrlib.tests.test_filter_tree',
3955
3648
        'bzrlib.tests.test_ftp_transport',
3956
3649
        'bzrlib.tests.test_foreign',
3957
3650
        'bzrlib.tests.test_generate_docs',
3966
3659
        'bzrlib.tests.test_http',
3967
3660
        'bzrlib.tests.test_http_response',
3968
3661
        'bzrlib.tests.test_https_ca_bundle',
3969
 
        'bzrlib.tests.test_i18n',
3970
3662
        'bzrlib.tests.test_identitymap',
3971
3663
        'bzrlib.tests.test_ignores',
3972
3664
        'bzrlib.tests.test_index',
3973
 
        'bzrlib.tests.test_import_tariff',
3974
3665
        'bzrlib.tests.test_info',
3975
3666
        'bzrlib.tests.test_inv',
3976
3667
        'bzrlib.tests.test_inventory_delta',
3977
3668
        'bzrlib.tests.test_knit',
3978
3669
        'bzrlib.tests.test_lazy_import',
3979
3670
        'bzrlib.tests.test_lazy_regex',
3980
 
        'bzrlib.tests.test_library_state',
3981
3671
        'bzrlib.tests.test_lock',
3982
3672
        'bzrlib.tests.test_lockable_files',
3983
3673
        'bzrlib.tests.test_lockdir',
3985
3675
        'bzrlib.tests.test_lru_cache',
3986
3676
        'bzrlib.tests.test_lsprof',
3987
3677
        'bzrlib.tests.test_mail_client',
3988
 
        'bzrlib.tests.test_matchers',
3989
3678
        'bzrlib.tests.test_memorytree',
3990
3679
        'bzrlib.tests.test_merge',
3991
3680
        'bzrlib.tests.test_merge3',
3992
3681
        'bzrlib.tests.test_merge_core',
3993
3682
        'bzrlib.tests.test_merge_directive',
3994
 
        'bzrlib.tests.test_mergetools',
3995
3683
        'bzrlib.tests.test_missing',
3996
3684
        'bzrlib.tests.test_msgeditor',
3997
3685
        'bzrlib.tests.test_multiparent',
4006
3694
        'bzrlib.tests.test_permissions',
4007
3695
        'bzrlib.tests.test_plugins',
4008
3696
        'bzrlib.tests.test_progress',
4009
 
        'bzrlib.tests.test_pyutils',
4010
3697
        'bzrlib.tests.test_read_bundle',
4011
3698
        'bzrlib.tests.test_reconcile',
4012
3699
        'bzrlib.tests.test_reconfigure',
4021
3708
        'bzrlib.tests.test_rio',
4022
3709
        'bzrlib.tests.test_rules',
4023
3710
        'bzrlib.tests.test_sampler',
4024
 
        'bzrlib.tests.test_scenarios',
4025
3711
        'bzrlib.tests.test_script',
4026
3712
        'bzrlib.tests.test_selftest',
4027
3713
        'bzrlib.tests.test_serializer',
4043
3729
        'bzrlib.tests.test_switch',
4044
3730
        'bzrlib.tests.test_symbol_versioning',
4045
3731
        'bzrlib.tests.test_tag',
4046
 
        'bzrlib.tests.test_test_server',
4047
3732
        'bzrlib.tests.test_testament',
4048
3733
        'bzrlib.tests.test_textfile',
4049
3734
        'bzrlib.tests.test_textmerge',
4050
 
        'bzrlib.tests.test_cethread',
4051
3735
        'bzrlib.tests.test_timestamp',
4052
3736
        'bzrlib.tests.test_trace',
4053
3737
        'bzrlib.tests.test_transactions',
4056
3740
        'bzrlib.tests.test_transport_log',
4057
3741
        'bzrlib.tests.test_tree',
4058
3742
        'bzrlib.tests.test_treebuilder',
4059
 
        'bzrlib.tests.test_treeshape',
4060
3743
        'bzrlib.tests.test_tsort',
4061
3744
        'bzrlib.tests.test_tuned_gzip',
4062
3745
        'bzrlib.tests.test_ui',
4064
3747
        'bzrlib.tests.test_upgrade',
4065
3748
        'bzrlib.tests.test_upgrade_stacked',
4066
3749
        'bzrlib.tests.test_urlutils',
4067
 
        'bzrlib.tests.test_utextwrap',
4068
3750
        'bzrlib.tests.test_version',
4069
3751
        'bzrlib.tests.test_version_info',
4070
 
        'bzrlib.tests.test_versionedfile',
4071
3752
        'bzrlib.tests.test_weave',
4072
3753
        'bzrlib.tests.test_whitebox',
4073
3754
        'bzrlib.tests.test_win32utils',
4079
3760
 
4080
3761
 
4081
3762
def _test_suite_modules_to_doctest():
4082
 
    """Return the list of modules to doctest."""
4083
 
    if __doc__ is None:
4084
 
        # GZ 2009-03-31: No docstrings with -OO so there's nothing to doctest
4085
 
        return []
 
3763
    """Return the list of modules to doctest."""   
4086
3764
    return [
4087
3765
        'bzrlib',
4088
3766
        'bzrlib.branchbuilder',
4089
3767
        'bzrlib.decorators',
 
3768
        'bzrlib.export',
4090
3769
        'bzrlib.inventory',
4091
3770
        'bzrlib.iterablefile',
4092
3771
        'bzrlib.lockdir',
4093
3772
        'bzrlib.merge3',
4094
3773
        'bzrlib.option',
4095
 
        'bzrlib.pyutils',
4096
3774
        'bzrlib.symbol_versioning',
4097
3775
        'bzrlib.tests',
4098
 
        'bzrlib.tests.fixtures',
4099
3776
        'bzrlib.timestamp',
4100
 
        'bzrlib.transport.http',
4101
3777
        'bzrlib.version_info_formats.format_custom',
4102
3778
        ]
4103
3779
 
4156
3832
        try:
4157
3833
            # note that this really does mean "report only" -- doctest
4158
3834
            # still runs the rest of the examples
4159
 
            doc_suite = IsolatedDocTestSuite(
4160
 
                mod, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
 
3835
            doc_suite = doctest.DocTestSuite(mod,
 
3836
                optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
4161
3837
        except ValueError, e:
4162
3838
            print '**failed to get doctest for: %s\n%s' % (mod, e)
4163
3839
            raise
4166
3842
        suite.addTest(doc_suite)
4167
3843
 
4168
3844
    default_encoding = sys.getdefaultencoding()
4169
 
    for name, plugin in _mod_plugin.plugins().items():
 
3845
    for name, plugin in bzrlib.plugin.plugins().items():
4170
3846
        if not interesting_module(plugin.module.__name__):
4171
3847
            continue
4172
3848
        plugin_suite = plugin.test_suite()
4178
3854
        if plugin_suite is not None:
4179
3855
            suite.addTest(plugin_suite)
4180
3856
        if default_encoding != sys.getdefaultencoding():
4181
 
            trace.warning(
 
3857
            bzrlib.trace.warning(
4182
3858
                'Plugin "%s" tried to reset default encoding to: %s', name,
4183
3859
                sys.getdefaultencoding())
4184
3860
            reload(sys)
4199
3875
            # Some tests mentioned in the list are not in the test suite. The
4200
3876
            # list may be out of date, report to the tester.
4201
3877
            for id in not_found:
4202
 
                trace.warning('"%s" not found in the test suite', id)
 
3878
                bzrlib.trace.warning('"%s" not found in the test suite', id)
4203
3879
        for id in duplicates:
4204
 
            trace.warning('"%s" is used as an id by several tests', id)
 
3880
            bzrlib.trace.warning('"%s" is used as an id by several tests', id)
4205
3881
 
4206
3882
    return suite
4207
3883
 
4208
3884
 
4209
 
def multiply_scenarios(*scenarios):
4210
 
    """Multiply two or more iterables of scenarios.
4211
 
 
4212
 
    It is safe to pass scenario generators or iterators.
4213
 
 
4214
 
    :returns: A list of compound scenarios: the cross-product of all 
4215
 
        scenarios, with the names concatenated and the parameters
4216
 
        merged together.
4217
 
    """
4218
 
    return reduce(_multiply_two_scenarios, map(list, scenarios))
4219
 
 
4220
 
 
4221
 
def _multiply_two_scenarios(scenarios_left, scenarios_right):
 
3885
def multiply_scenarios(scenarios_left, scenarios_right):
4222
3886
    """Multiply two sets of scenarios.
4223
3887
 
4224
3888
    :returns: the cartesian product of the two sets of scenarios, that is
4255
3919
    ...     bzrlib.tests.test_sampler.DemoTest('test_nothing'),
4256
3920
    ...     [('one', dict(param=1)),
4257
3921
    ...      ('two', dict(param=2))],
4258
 
    ...     TestUtil.TestSuite())
 
3922
    ...     TestSuite())
4259
3923
    >>> tests = list(iter_suite_tests(r))
4260
3924
    >>> len(tests)
4261
3925
    2
4308
3972
    :param new_id: The id to assign to it.
4309
3973
    :return: The new test.
4310
3974
    """
4311
 
    new_test = copy.copy(test)
 
3975
    new_test = copy(test)
4312
3976
    new_test.id = lambda: new_id
4313
 
    # XXX: Workaround <https://bugs.launchpad.net/testtools/+bug/637725>, which
4314
 
    # causes cloned tests to share the 'details' dict.  This makes it hard to
4315
 
    # read the test output for parameterized tests, because tracebacks will be
4316
 
    # associated with irrelevant tests.
4317
 
    try:
4318
 
        details = new_test._TestCase__details
4319
 
    except AttributeError:
4320
 
        # must be a different version of testtools than expected.  Do nothing.
4321
 
        pass
4322
 
    else:
4323
 
        # Reset the '__details' dict.
4324
 
        new_test._TestCase__details = {}
4325
3977
    return new_test
4326
3978
 
4327
3979
 
4348
4000
        the module is available.
4349
4001
    """
4350
4002
 
4351
 
    from bzrlib.tests.features import ModuleAvailableFeature
4352
 
    py_module = pyutils.get_named_object(py_module_name)
 
4003
    py_module = __import__(py_module_name, {}, {}, ['NO_SUCH_ATTRIB'])
4353
4004
    scenarios = [
4354
4005
        ('python', {'module': py_module}),
4355
4006
    ]
4388
4039
        if test_id != None:
4389
4040
            ui.ui_factory.clear_term()
4390
4041
            sys.stderr.write('\nWhile running: %s\n' % (test_id,))
4391
 
        # Ugly, but the last thing we want here is fail, so bear with it.
4392
 
        printable_e = str(e).decode(osutils.get_user_encoding(), 'replace'
4393
 
                                    ).encode('ascii', 'replace')
4394
4042
        sys.stderr.write('Unable to remove testing dir %s\n%s'
4395
 
                         % (os.path.basename(dirname), printable_e))
 
4043
                         % (os.path.basename(dirname), e))
 
4044
 
 
4045
 
 
4046
class Feature(object):
 
4047
    """An operating system Feature."""
 
4048
 
 
4049
    def __init__(self):
 
4050
        self._available = None
 
4051
 
 
4052
    def available(self):
 
4053
        """Is the feature available?
 
4054
 
 
4055
        :return: True if the feature is available.
 
4056
        """
 
4057
        if self._available is None:
 
4058
            self._available = self._probe()
 
4059
        return self._available
 
4060
 
 
4061
    def _probe(self):
 
4062
        """Implement this method in concrete features.
 
4063
 
 
4064
        :return: True if the feature is available.
 
4065
        """
 
4066
        raise NotImplementedError
 
4067
 
 
4068
    def __str__(self):
 
4069
        if getattr(self, 'feature_name', None):
 
4070
            return self.feature_name()
 
4071
        return self.__class__.__name__
 
4072
 
 
4073
 
 
4074
class _SymlinkFeature(Feature):
 
4075
 
 
4076
    def _probe(self):
 
4077
        return osutils.has_symlinks()
 
4078
 
 
4079
    def feature_name(self):
 
4080
        return 'symlinks'
 
4081
 
 
4082
SymlinkFeature = _SymlinkFeature()
 
4083
 
 
4084
 
 
4085
class _HardlinkFeature(Feature):
 
4086
 
 
4087
    def _probe(self):
 
4088
        return osutils.has_hardlinks()
 
4089
 
 
4090
    def feature_name(self):
 
4091
        return 'hardlinks'
 
4092
 
 
4093
HardlinkFeature = _HardlinkFeature()
 
4094
 
 
4095
 
 
4096
class _OsFifoFeature(Feature):
 
4097
 
 
4098
    def _probe(self):
 
4099
        return getattr(os, 'mkfifo', None)
 
4100
 
 
4101
    def feature_name(self):
 
4102
        return 'filesystem fifos'
 
4103
 
 
4104
OsFifoFeature = _OsFifoFeature()
 
4105
 
 
4106
 
 
4107
class _UnicodeFilenameFeature(Feature):
 
4108
    """Does the filesystem support Unicode filenames?"""
 
4109
 
 
4110
    def _probe(self):
 
4111
        try:
 
4112
            # Check for character combinations unlikely to be covered by any
 
4113
            # single non-unicode encoding. We use the characters
 
4114
            # - greek small letter alpha (U+03B1) and
 
4115
            # - braille pattern dots-123456 (U+283F).
 
4116
            os.stat(u'\u03b1\u283f')
 
4117
        except UnicodeEncodeError:
 
4118
            return False
 
4119
        except (IOError, OSError):
 
4120
            # The filesystem allows the Unicode filename but the file doesn't
 
4121
            # exist.
 
4122
            return True
 
4123
        else:
 
4124
            # The filesystem allows the Unicode filename and the file exists,
 
4125
            # for some reason.
 
4126
            return True
 
4127
 
 
4128
UnicodeFilenameFeature = _UnicodeFilenameFeature()
 
4129
 
 
4130
 
 
4131
class _CompatabilityThunkFeature(Feature):
 
4132
    """This feature is just a thunk to another feature.
 
4133
 
 
4134
    It issues a deprecation warning if it is accessed, to let you know that you
 
4135
    should really use a different feature.
 
4136
    """
 
4137
 
 
4138
    def __init__(self, dep_version, module, name,
 
4139
                 replacement_name, replacement_module=None):
 
4140
        super(_CompatabilityThunkFeature, self).__init__()
 
4141
        self._module = module
 
4142
        if replacement_module is None:
 
4143
            replacement_module = module
 
4144
        self._replacement_module = replacement_module
 
4145
        self._name = name
 
4146
        self._replacement_name = replacement_name
 
4147
        self._dep_version = dep_version
 
4148
        self._feature = None
 
4149
 
 
4150
    def _ensure(self):
 
4151
        if self._feature is None:
 
4152
            depr_msg = self._dep_version % ('%s.%s'
 
4153
                                            % (self._module, self._name))
 
4154
            use_msg = ' Use %s.%s instead.' % (self._replacement_module,
 
4155
                                               self._replacement_name)
 
4156
            symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
 
4157
            # Import the new feature and use it as a replacement for the
 
4158
            # deprecated one.
 
4159
            mod = __import__(self._replacement_module, {}, {},
 
4160
                             [self._replacement_name])
 
4161
            self._feature = getattr(mod, self._replacement_name)
 
4162
 
 
4163
    def _probe(self):
 
4164
        self._ensure()
 
4165
        return self._feature._probe()
 
4166
 
 
4167
 
 
4168
class ModuleAvailableFeature(Feature):
 
4169
    """This is a feature than describes a module we want to be available.
 
4170
 
 
4171
    Declare the name of the module in __init__(), and then after probing, the
 
4172
    module will be available as 'self.module'.
 
4173
 
 
4174
    :ivar module: The module if it is available, else None.
 
4175
    """
 
4176
 
 
4177
    def __init__(self, module_name):
 
4178
        super(ModuleAvailableFeature, self).__init__()
 
4179
        self.module_name = module_name
 
4180
 
 
4181
    def _probe(self):
 
4182
        try:
 
4183
            self._module = __import__(self.module_name, {}, {}, [''])
 
4184
            return True
 
4185
        except ImportError:
 
4186
            return False
 
4187
 
 
4188
    @property
 
4189
    def module(self):
 
4190
        if self.available(): # Make sure the probe has been done
 
4191
            return self._module
 
4192
        return None
 
4193
 
 
4194
    def feature_name(self):
 
4195
        return self.module_name
 
4196
 
 
4197
 
 
4198
# This is kept here for compatibility, it is recommended to use
 
4199
# 'bzrlib.tests.feature.paramiko' instead
 
4200
ParamikoFeature = _CompatabilityThunkFeature(
 
4201
    deprecated_in((2,1,0)),
 
4202
    'bzrlib.tests.features', 'ParamikoFeature', 'paramiko')
4396
4203
 
4397
4204
 
4398
4205
def probe_unicode_in_user_encoding():
4428
4235
    return None
4429
4236
 
4430
4237
 
 
4238
class _HTTPSServerFeature(Feature):
 
4239
    """Some tests want an https Server, check if one is available.
 
4240
 
 
4241
    Right now, the only way this is available is under python2.6 which provides
 
4242
    an ssl module.
 
4243
    """
 
4244
 
 
4245
    def _probe(self):
 
4246
        try:
 
4247
            import ssl
 
4248
            return True
 
4249
        except ImportError:
 
4250
            return False
 
4251
 
 
4252
    def feature_name(self):
 
4253
        return 'HTTPSServer'
 
4254
 
 
4255
 
 
4256
HTTPSServerFeature = _HTTPSServerFeature()
 
4257
 
 
4258
 
 
4259
class _UnicodeFilename(Feature):
 
4260
    """Does the filesystem support Unicode filenames?"""
 
4261
 
 
4262
    def _probe(self):
 
4263
        try:
 
4264
            os.stat(u'\u03b1')
 
4265
        except UnicodeEncodeError:
 
4266
            return False
 
4267
        except (IOError, OSError):
 
4268
            # The filesystem allows the Unicode filename but the file doesn't
 
4269
            # exist.
 
4270
            return True
 
4271
        else:
 
4272
            # The filesystem allows the Unicode filename and the file exists,
 
4273
            # for some reason.
 
4274
            return True
 
4275
 
 
4276
UnicodeFilename = _UnicodeFilename()
 
4277
 
 
4278
 
 
4279
class _UTF8Filesystem(Feature):
 
4280
    """Is the filesystem UTF-8?"""
 
4281
 
 
4282
    def _probe(self):
 
4283
        if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
 
4284
            return True
 
4285
        return False
 
4286
 
 
4287
UTF8Filesystem = _UTF8Filesystem()
 
4288
 
 
4289
 
 
4290
class _BreakinFeature(Feature):
 
4291
    """Does this platform support the breakin feature?"""
 
4292
 
 
4293
    def _probe(self):
 
4294
        from bzrlib import breakin
 
4295
        if breakin.determine_signal() is None:
 
4296
            return False
 
4297
        if sys.platform == 'win32':
 
4298
            # Windows doesn't have os.kill, and we catch the SIGBREAK signal.
 
4299
            # We trigger SIGBREAK via a Console api so we need ctypes to
 
4300
            # access the function
 
4301
            try:
 
4302
                import ctypes
 
4303
            except OSError:
 
4304
                return False
 
4305
        return True
 
4306
 
 
4307
    def feature_name(self):
 
4308
        return "SIGQUIT or SIGBREAK w/ctypes on win32"
 
4309
 
 
4310
 
 
4311
BreakinFeature = _BreakinFeature()
 
4312
 
 
4313
 
 
4314
class _CaseInsCasePresFilenameFeature(Feature):
 
4315
    """Is the file-system case insensitive, but case-preserving?"""
 
4316
 
 
4317
    def _probe(self):
 
4318
        fileno, name = tempfile.mkstemp(prefix='MixedCase')
 
4319
        try:
 
4320
            # first check truly case-preserving for created files, then check
 
4321
            # case insensitive when opening existing files.
 
4322
            name = osutils.normpath(name)
 
4323
            base, rel = osutils.split(name)
 
4324
            found_rel = osutils.canonical_relpath(base, name)
 
4325
            return (found_rel == rel
 
4326
                    and os.path.isfile(name.upper())
 
4327
                    and os.path.isfile(name.lower()))
 
4328
        finally:
 
4329
            os.close(fileno)
 
4330
            os.remove(name)
 
4331
 
 
4332
    def feature_name(self):
 
4333
        return "case-insensitive case-preserving filesystem"
 
4334
 
 
4335
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
 
4336
 
 
4337
 
 
4338
class _CaseInsensitiveFilesystemFeature(Feature):
 
4339
    """Check if underlying filesystem is case-insensitive but *not* case
 
4340
    preserving.
 
4341
    """
 
4342
    # Note that on Windows, Cygwin, MacOS etc, the file-systems are far
 
4343
    # more likely to be case preserving, so this case is rare.
 
4344
 
 
4345
    def _probe(self):
 
4346
        if CaseInsCasePresFilenameFeature.available():
 
4347
            return False
 
4348
 
 
4349
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
 
4350
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
 
4351
            TestCaseWithMemoryTransport.TEST_ROOT = root
 
4352
        else:
 
4353
            root = TestCaseWithMemoryTransport.TEST_ROOT
 
4354
        tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
 
4355
            dir=root)
 
4356
        name_a = osutils.pathjoin(tdir, 'a')
 
4357
        name_A = osutils.pathjoin(tdir, 'A')
 
4358
        os.mkdir(name_a)
 
4359
        result = osutils.isdir(name_A)
 
4360
        _rmtree_temp_dir(tdir)
 
4361
        return result
 
4362
 
 
4363
    def feature_name(self):
 
4364
        return 'case-insensitive filesystem'
 
4365
 
 
4366
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
 
4367
 
 
4368
 
 
4369
# Kept for compatibility, use bzrlib.tests.features.subunit instead
 
4370
SubUnitFeature = _CompatabilityThunkFeature(
 
4371
    deprecated_in((2,1,0)),
 
4372
    'bzrlib.tests.features', 'SubUnitFeature', 'subunit')
4431
4373
# Only define SubUnitBzrRunner if subunit is available.
4432
4374
try:
4433
4375
    from subunit import TestProtocolClient
4434
4376
    from subunit.test_results import AutoTimingTestResultDecorator
4435
 
    class SubUnitBzrProtocolClient(TestProtocolClient):
4436
 
 
4437
 
        def addSuccess(self, test, details=None):
4438
 
            # The subunit client always includes the details in the subunit
4439
 
            # stream, but we don't want to include it in ours.
4440
 
            if details is not None and 'log' in details:
4441
 
                del details['log']
4442
 
            return super(SubUnitBzrProtocolClient, self).addSuccess(
4443
 
                test, details)
4444
 
 
4445
4377
    class SubUnitBzrRunner(TextTestRunner):
4446
4378
        def run(self, test):
4447
4379
            result = AutoTimingTestResultDecorator(
4448
 
                SubUnitBzrProtocolClient(self.stream))
 
4380
                TestProtocolClient(self.stream))
4449
4381
            test.run(result)
4450
4382
            return result
4451
4383
except ImportError:
4452
4384
    pass
4453
 
 
4454
 
 
4455
 
@deprecated_function(deprecated_in((2, 5, 0)))
4456
 
def ModuleAvailableFeature(name):
4457
 
    from bzrlib.tests import features
4458
 
    return features.ModuleAvailableFeature(name)
4459