~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2006-11-10 15:38:16 UTC
  • mto: This revision was merged to the branch mainline in revision 2129.
  • Revision ID: john@arbash-meinel.com-20061110153816-46acf76fc86a512b
use try/finally to clean up a nested progress bar during weave fetching

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 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
26
26
# general style of bzrlib.  Please continue that consistency when adding e.g.
27
27
# new assertFoo() methods.
28
28
 
29
 
import atexit
30
29
import codecs
31
30
from cStringIO import StringIO
32
31
import difflib
34
33
import errno
35
34
import logging
36
35
import os
37
 
from pprint import pformat
38
 
import random
39
36
import re
40
37
import shlex
41
38
import stat
44
41
import tempfile
45
42
import unittest
46
43
import time
47
 
import warnings
48
44
 
49
45
 
50
46
from bzrlib import (
54
50
    memorytree,
55
51
    osutils,
56
52
    progress,
57
 
    ui,
58
53
    urlutils,
59
 
    workingtree,
60
54
    )
61
55
import bzrlib.branch
62
56
import bzrlib.commands
63
 
import bzrlib.timestamp
 
57
import bzrlib.bundle.serializer
64
58
import bzrlib.export
65
59
import bzrlib.inventory
66
60
import bzrlib.iterablefile
77
71
from bzrlib.revision import common_ancestor
78
72
import bzrlib.store
79
73
from bzrlib import symbol_versioning
80
 
from bzrlib.symbol_versioning import (
81
 
    deprecated_method,
82
 
    zero_eighteen,
83
 
    )
84
74
import bzrlib.trace
85
75
from bzrlib.transport import get_transport
86
76
import bzrlib.transport
89
79
from bzrlib.transport.readonly import ReadonlyServer
90
80
from bzrlib.trace import mutter, note
91
81
from bzrlib.tests import TestUtil
92
 
from bzrlib.tests.HttpServer import HttpServer
93
82
from bzrlib.tests.TestUtil import (
94
83
                          TestSuite,
95
84
                          TestLoader,
97
86
from bzrlib.tests.treeshape import build_tree_contents
98
87
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
99
88
 
100
 
# Mark this python module as being part of the implementation
101
 
# of unittest: this gives us better tracebacks where the last
102
 
# shown frame is the test code, not our assertXYZ.
103
 
__unittest = 1
104
 
 
105
89
default_transport = LocalURLServer
106
90
 
107
91
MODULES_TO_TEST = []
108
92
MODULES_TO_DOCTEST = [
109
 
                      bzrlib.timestamp,
 
93
                      bzrlib.bundle.serializer,
110
94
                      bzrlib.errors,
111
95
                      bzrlib.export,
112
96
                      bzrlib.inventory,
131
115
    import bzrlib.tests.interrepository_implementations
132
116
    import bzrlib.tests.interversionedfile_implementations
133
117
    import bzrlib.tests.intertree_implementations
134
 
    import bzrlib.tests.per_lock
135
118
    import bzrlib.tests.repository_implementations
136
119
    import bzrlib.tests.revisionstore_implementations
137
120
    import bzrlib.tests.tree_implementations
144
127
            bzrlib.tests.interrepository_implementations,
145
128
            bzrlib.tests.interversionedfile_implementations,
146
129
            bzrlib.tests.intertree_implementations,
147
 
            bzrlib.tests.per_lock,
148
130
            bzrlib.tests.repository_implementations,
149
131
            bzrlib.tests.revisionstore_implementations,
150
132
            bzrlib.tests.tree_implementations,
165
147
    def __init__(self, stream, descriptions, verbosity,
166
148
                 bench_history=None,
167
149
                 num_tests=None,
168
 
                 use_numbered_dirs=False,
169
150
                 ):
170
151
        """Construct new TestResult.
171
152
 
188
169
                revision_id = ''
189
170
            bench_history.write("--date %s %s\n" % (time.time(), revision_id))
190
171
        self._bench_history = bench_history
191
 
        self.ui = ui.ui_factory
 
172
        self.ui = bzrlib.ui.ui_factory
192
173
        self.num_tests = num_tests
193
174
        self.error_count = 0
194
175
        self.failure_count = 0
195
 
        self.known_failure_count = 0
196
176
        self.skip_count = 0
197
 
        self.unsupported = {}
198
177
        self.count = 0
199
 
        self.use_numbered_dirs = use_numbered_dirs
200
178
        self._overall_start_time = time.time()
201
179
    
202
180
    def extractBenchmarkTime(self, testCase):
213
191
                self._formatTime(self._benchmarkTime),
214
192
                self._elapsedTestTimeString())
215
193
        else:
216
 
            return "           %s" % self._elapsedTestTimeString()
 
194
            return "      %s" % self._elapsedTestTimeString()
217
195
 
218
196
    def _formatTime(self, seconds):
219
197
        """Format seconds as milliseconds with leading spaces."""
220
 
        # some benchmarks can take thousands of seconds to run, so we need 8
221
 
        # places
222
 
        return "%8dms" % (1000 * seconds)
 
198
        return "%5dms" % (1000 * seconds)
223
199
 
224
200
    def _shortened_test_description(self, test):
225
201
        what = test.id()
226
 
        what = re.sub(r'^bzrlib\.(tests|benchmarks)\.', '', what)
 
202
        what = re.sub(r'^bzrlib\.(tests|benchmark)\.', '', what)
227
203
        return what
228
204
 
229
205
    def startTest(self, test):
230
206
        unittest.TestResult.startTest(self, test)
231
207
        self.report_test_start(test)
232
 
        test.number = self.count
233
208
        self._recordTestStartTime()
234
209
 
235
210
    def _recordTestStartTime(self):
236
211
        """Record that a test has started."""
237
212
        self._start_time = time.time()
238
213
 
239
 
    def _cleanupLogFile(self, test):
240
 
        # We can only do this if we have one of our TestCases, not if
241
 
        # we have a doctest.
242
 
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
243
 
        if setKeepLogfile is not None:
244
 
            setKeepLogfile()
245
 
 
246
214
    def addError(self, test, err):
247
 
        self.extractBenchmarkTime(test)
248
 
        self._cleanupLogFile(test)
249
215
        if isinstance(err[1], TestSkipped):
250
 
            return self.addSkipped(test, err)
251
 
        elif isinstance(err[1], UnavailableFeature):
252
 
            return self.addNotSupported(test, err[1].args[0])
 
216
            return self.addSkipped(test, err)    
253
217
        unittest.TestResult.addError(self, test, err)
254
 
        self.error_count += 1
 
218
        # We can only do this if we have one of our TestCases, not if
 
219
        # we have a doctest.
 
220
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
221
        if setKeepLogfile is not None:
 
222
            setKeepLogfile()
 
223
        self.extractBenchmarkTime(test)
255
224
        self.report_error(test, err)
256
225
        if self.stop_early:
257
226
            self.stop()
258
227
 
259
228
    def addFailure(self, test, err):
260
 
        self._cleanupLogFile(test)
261
 
        self.extractBenchmarkTime(test)
262
 
        if isinstance(err[1], KnownFailure):
263
 
            return self.addKnownFailure(test, err)
264
229
        unittest.TestResult.addFailure(self, test, err)
265
 
        self.failure_count += 1
 
230
        # We can only do this if we have one of our TestCases, not if
 
231
        # we have a doctest.
 
232
        setKeepLogfile = getattr(test, 'setKeepLogfile', None)
 
233
        if setKeepLogfile is not None:
 
234
            setKeepLogfile()
 
235
        self.extractBenchmarkTime(test)
266
236
        self.report_failure(test, err)
267
237
        if self.stop_early:
268
238
            self.stop()
269
239
 
270
 
    def addKnownFailure(self, test, err):
271
 
        self.known_failure_count += 1
272
 
        self.report_known_failure(test, err)
273
 
 
274
 
    def addNotSupported(self, test, feature):
275
 
        self.unsupported.setdefault(str(feature), 0)
276
 
        self.unsupported[str(feature)] += 1
277
 
        self.report_unsupported(test, feature)
278
 
 
279
240
    def addSuccess(self, test):
280
241
        self.extractBenchmarkTime(test)
281
242
        if self._bench_history is not None:
287
248
        unittest.TestResult.addSuccess(self, test)
288
249
 
289
250
    def addSkipped(self, test, skip_excinfo):
 
251
        self.extractBenchmarkTime(test)
290
252
        self.report_skip(test, skip_excinfo)
291
253
        # seems best to treat this as success from point-of-view of unittest
292
254
        # -- it actually does nothing so it barely matters :)
302
264
    def printErrorList(self, flavour, errors):
303
265
        for test, err in errors:
304
266
            self.stream.writeln(self.separator1)
305
 
            self.stream.write("%s: " % flavour)
306
 
            if self.use_numbered_dirs:
307
 
                self.stream.write('#%d ' % test.number)
308
 
            self.stream.writeln(self.getDescription(test))
 
267
            self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
309
268
            if getattr(test, '_get_log', None) is not None:
310
269
                print >>self.stream
311
270
                print >>self.stream, \
329
288
class TextTestResult(ExtendedTestResult):
330
289
    """Displays progress and results of tests in text form"""
331
290
 
332
 
    def __init__(self, stream, descriptions, verbosity,
333
 
                 bench_history=None,
334
 
                 num_tests=None,
335
 
                 pb=None,
336
 
                 use_numbered_dirs=False,
337
 
                 ):
338
 
        ExtendedTestResult.__init__(self, stream, descriptions, verbosity,
339
 
            bench_history, num_tests, use_numbered_dirs)
340
 
        if pb is None:
341
 
            self.pb = self.ui.nested_progress_bar()
342
 
            self._supplied_pb = False
343
 
        else:
344
 
            self.pb = pb
345
 
            self._supplied_pb = True
 
291
    def __init__(self, *args, **kw):
 
292
        ExtendedTestResult.__init__(self, *args, **kw)
 
293
        self.pb = self.ui.nested_progress_bar()
346
294
        self.pb.show_pct = False
347
295
        self.pb.show_spinner = False
348
 
        self.pb.show_eta = False,
 
296
        self.pb.show_eta = False, 
349
297
        self.pb.show_count = False
350
298
        self.pb.show_bar = False
351
299
 
361
309
            a += ', %d errors' % self.error_count
362
310
        if self.failure_count:
363
311
            a += ', %d failed' % self.failure_count
364
 
        if self.known_failure_count:
365
 
            a += ', %d known failures' % self.known_failure_count
366
312
        if self.skip_count:
367
313
            a += ', %d skipped' % self.skip_count
368
 
        if self.unsupported:
369
 
            a += ', %d missing features' % len(self.unsupported)
370
314
        a += ']'
371
315
        return a
372
316
 
377
321
                + ' ' 
378
322
                + self._shortened_test_description(test))
379
323
 
380
 
    def _test_description(self, test):
381
 
        if self.use_numbered_dirs:
382
 
            return '#%d %s' % (self.count,
383
 
                               self._shortened_test_description(test))
384
 
        else:
385
 
            return self._shortened_test_description(test)
386
 
 
387
324
    def report_error(self, test, err):
388
 
        self.pb.note('ERROR: %s\n    %s\n', 
389
 
            self._test_description(test),
 
325
        self.error_count += 1
 
326
        self.pb.note('ERROR: %s\n    %s\n' % (
 
327
            self._shortened_test_description(test),
390
328
            err[1],
391
 
            )
 
329
            ))
392
330
 
393
331
    def report_failure(self, test, err):
394
 
        self.pb.note('FAIL: %s\n    %s\n', 
395
 
            self._test_description(test),
 
332
        self.failure_count += 1
 
333
        self.pb.note('FAIL: %s\n    %s\n' % (
 
334
            self._shortened_test_description(test),
396
335
            err[1],
397
 
            )
398
 
 
399
 
    def report_known_failure(self, test, err):
400
 
        self.pb.note('XFAIL: %s\n%s\n',
401
 
            self._test_description(test), err[1])
 
336
            ))
402
337
 
403
338
    def report_skip(self, test, skip_excinfo):
404
339
        self.skip_count += 1
408
343
            # to see them.
409
344
            if False:
410
345
                # show test and reason for skip
411
 
                self.pb.note('SKIP: %s\n    %s\n', 
 
346
                self.pb.note('SKIP: %s\n    %s\n' % (
412
347
                    self._shortened_test_description(test),
413
 
                    skip_excinfo[1])
 
348
                    skip_excinfo[1]))
414
349
            else:
415
350
                # since the class name was left behind in the still-visible
416
351
                # progress bar...
417
 
                self.pb.note('SKIP: %s', skip_excinfo[1])
 
352
                self.pb.note('SKIP: %s' % (skip_excinfo[1]))
418
353
 
419
 
    def report_unsupported(self, test, feature):
420
 
        """test cannot be run because feature is missing."""
421
 
                  
422
354
    def report_cleaning_up(self):
423
355
        self.pb.update('cleaning up...')
424
356
 
425
357
    def finished(self):
426
 
        if not self._supplied_pb:
427
 
            self.pb.finished()
 
358
        self.pb.finished()
428
359
 
429
360
 
430
361
class VerboseTestResult(ExtendedTestResult):
444
375
    def report_test_start(self, test):
445
376
        self.count += 1
446
377
        name = self._shortened_test_description(test)
447
 
        # width needs space for 6 char status, plus 1 for slash, plus 2 10-char
448
 
        # numbers, plus a trailing blank
449
 
        # when NUMBERED_DIRS: plus 5 chars on test number, plus 1 char on space
450
 
        if self.use_numbered_dirs:
451
 
            self.stream.write('%5d ' % self.count)
452
 
            self.stream.write(self._ellipsize_to_right(name,
453
 
                                osutils.terminal_width()-36))
454
 
        else:
455
 
            self.stream.write(self._ellipsize_to_right(name,
456
 
                                osutils.terminal_width()-30))
 
378
        self.stream.write(self._ellipsize_to_right(name, 60))
457
379
        self.stream.flush()
458
380
 
459
 
    def _error_summary(self, err):
460
 
        indent = ' ' * 4
461
 
        if self.use_numbered_dirs:
462
 
            indent += ' ' * 6
463
 
        return '%s%s' % (indent, err[1])
464
 
 
465
381
    def report_error(self, test, err):
466
 
        self.stream.writeln('ERROR %s\n%s'
467
 
                % (self._testTimeString(),
468
 
                   self._error_summary(err)))
 
382
        self.error_count += 1
 
383
        self.stream.writeln('ERROR %s\n    %s' 
 
384
                % (self._testTimeString(), err[1]))
469
385
 
470
386
    def report_failure(self, test, err):
471
 
        self.stream.writeln(' FAIL %s\n%s'
472
 
                % (self._testTimeString(),
473
 
                   self._error_summary(err)))
474
 
 
475
 
    def report_known_failure(self, test, err):
476
 
        self.stream.writeln('XFAIL %s\n%s'
477
 
                % (self._testTimeString(),
478
 
                   self._error_summary(err)))
 
387
        self.failure_count += 1
 
388
        self.stream.writeln('FAIL %s\n    %s'
 
389
                % (self._testTimeString(), err[1]))
479
390
 
480
391
    def report_success(self, test):
481
392
        self.stream.writeln('   OK %s' % self._testTimeString())
482
393
        for bench_called, stats in getattr(test, '_benchcalls', []):
483
394
            self.stream.writeln('LSProf output for %s(%s, %s)' % bench_called)
484
395
            stats.pprint(file=self.stream)
485
 
        # flush the stream so that we get smooth output. This verbose mode is
486
 
        # used to show the output in PQM.
487
396
        self.stream.flush()
488
397
 
489
398
    def report_skip(self, test, skip_excinfo):
490
 
        self.skip_count += 1
491
 
        self.stream.writeln(' SKIP %s\n%s'
492
 
                % (self._testTimeString(),
493
 
                   self._error_summary(skip_excinfo)))
494
 
 
495
 
    def report_unsupported(self, test, feature):
496
 
        """test cannot be run because feature is missing."""
497
 
        self.stream.writeln("NODEP %s\n    The feature '%s' is not available."
498
 
                %(self._testTimeString(), feature))
499
 
                  
 
399
        print >>self.stream, ' SKIP %s' % self._testTimeString()
 
400
        print >>self.stream, '     %s' % skip_excinfo[1]
500
401
 
501
402
 
502
403
class TextTestRunner(object):
506
407
                 stream=sys.stderr,
507
408
                 descriptions=0,
508
409
                 verbosity=1,
509
 
                 bench_history=None,
510
 
                 use_numbered_dirs=False,
511
 
                 list_only=False
512
 
                 ):
 
410
                 keep_output=False,
 
411
                 bench_history=None):
513
412
        self.stream = unittest._WritelnDecorator(stream)
514
413
        self.descriptions = descriptions
515
414
        self.verbosity = verbosity
 
415
        self.keep_output = keep_output
516
416
        self._bench_history = bench_history
517
 
        self.use_numbered_dirs = use_numbered_dirs
518
 
        self.list_only = list_only
519
417
 
520
418
    def run(self, test):
521
419
        "Run the given test case or test suite."
529
427
                              self.verbosity,
530
428
                              bench_history=self._bench_history,
531
429
                              num_tests=test.countTestCases(),
532
 
                              use_numbered_dirs=self.use_numbered_dirs,
533
430
                              )
534
431
        result.stop_early = self.stop_on_failure
535
432
        result.report_starting()
536
 
        if self.list_only:
537
 
            if self.verbosity >= 2:
538
 
                self.stream.writeln("Listing tests only ...\n")
539
 
            run = 0
540
 
            for t in iter_suite_tests(test):
541
 
                self.stream.writeln("%s" % (t.id()))
542
 
                run += 1
543
 
            actionTaken = "Listed"
544
 
        else: 
545
 
            test.run(result)
546
 
            run = result.testsRun
547
 
            actionTaken = "Ran"
 
433
        test.run(result)
548
434
        stopTime = time.time()
549
435
        timeTaken = stopTime - startTime
550
436
        result.printErrors()
551
437
        self.stream.writeln(result.separator2)
552
 
        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
553
 
                            run, run != 1 and "s" or "", timeTaken))
 
438
        run = result.testsRun
 
439
        self.stream.writeln("Ran %d test%s in %.3fs" %
 
440
                            (run, run != 1 and "s" or "", timeTaken))
554
441
        self.stream.writeln()
555
442
        if not result.wasSuccessful():
556
443
            self.stream.write("FAILED (")
560
447
            if errored:
561
448
                if failed: self.stream.write(", ")
562
449
                self.stream.write("errors=%d" % errored)
563
 
            if result.known_failure_count:
564
 
                if failed or errored: self.stream.write(", ")
565
 
                self.stream.write("known_failure_count=%d" %
566
 
                    result.known_failure_count)
567
450
            self.stream.writeln(")")
568
451
        else:
569
 
            if result.known_failure_count:
570
 
                self.stream.writeln("OK (known_failures=%d)" %
571
 
                    result.known_failure_count)
572
 
            else:
573
 
                self.stream.writeln("OK")
574
 
        if result.skip_count > 0:
575
 
            skipped = result.skip_count
576
 
            self.stream.writeln('%d test%s skipped' %
577
 
                                (skipped, skipped != 1 and "s" or ""))
578
 
        if result.unsupported:
579
 
            for feature, count in sorted(result.unsupported.items()):
580
 
                self.stream.writeln("Missing feature '%s' skipped %d tests." %
581
 
                    (feature, count))
 
452
            self.stream.writeln("OK")
 
453
        result.report_cleaning_up()
 
454
        # This is still a little bogus, 
 
455
        # but only a little. Folk not using our testrunner will
 
456
        # have to delete their temp directories themselves.
 
457
        test_root = TestCaseWithMemoryTransport.TEST_ROOT
 
458
        if result.wasSuccessful() or not self.keep_output:
 
459
            if test_root is not None:
 
460
                # If LANG=C we probably have created some bogus paths
 
461
                # which rmtree(unicode) will fail to delete
 
462
                # so make sure we are using rmtree(str) to delete everything
 
463
                # except on win32, where rmtree(str) will fail
 
464
                # since it doesn't have the property of byte-stream paths
 
465
                # (they are either ascii or mbcs)
 
466
                if sys.platform == 'win32':
 
467
                    # make sure we are using the unicode win32 api
 
468
                    test_root = unicode(test_root)
 
469
                else:
 
470
                    test_root = test_root.encode(
 
471
                        sys.getfilesystemencoding())
 
472
                osutils.rmtree(test_root)
 
473
        else:
 
474
            note("Failed tests working directories are in '%s'\n", test_root)
 
475
        TestCaseWithMemoryTransport.TEST_ROOT = None
582
476
        result.finished()
583
477
        return result
584
478
 
600
494
    """Indicates that a test was intentionally skipped, rather than failing."""
601
495
 
602
496
 
603
 
class KnownFailure(AssertionError):
604
 
    """Indicates that a test failed in a precisely expected manner.
605
 
 
606
 
    Such failures dont block the whole test suite from passing because they are
607
 
    indicators of partially completed code or of future work. We have an
608
 
    explicit error for them so that we can ensure that they are always visible:
609
 
    KnownFailures are always shown in the output of bzr selftest.
610
 
    """
611
 
 
612
 
 
613
 
class UnavailableFeature(Exception):
614
 
    """A feature required for this test was not available.
615
 
 
616
 
    The feature should be used to construct the exception.
617
 
    """
618
 
 
619
 
 
620
497
class CommandFailed(Exception):
621
498
    pass
622
499
 
647
524
            return setattr(self._cstring, name, val)
648
525
 
649
526
 
650
 
class TestUIFactory(ui.CLIUIFactory):
651
 
    """A UI Factory for testing.
652
 
 
653
 
    Hide the progress bar but emit note()s.
654
 
    Redirect stdin.
655
 
    Allows get_password to be tested without real tty attached.
656
 
    """
657
 
 
658
 
    def __init__(self,
659
 
                 stdout=None,
660
 
                 stderr=None,
661
 
                 stdin=None):
662
 
        super(TestUIFactory, self).__init__()
663
 
        if stdin is not None:
664
 
            # We use a StringIOWrapper to be able to test various
665
 
            # encodings, but the user is still responsible to
666
 
            # encode the string and to set the encoding attribute
667
 
            # of StringIOWrapper.
668
 
            self.stdin = StringIOWrapper(stdin)
669
 
        if stdout is None:
670
 
            self.stdout = sys.stdout
671
 
        else:
672
 
            self.stdout = stdout
673
 
        if stderr is None:
674
 
            self.stderr = sys.stderr
675
 
        else:
676
 
            self.stderr = stderr
677
 
 
678
 
    def clear(self):
679
 
        """See progress.ProgressBar.clear()."""
680
 
 
681
 
    def clear_term(self):
682
 
        """See progress.ProgressBar.clear_term()."""
683
 
 
684
 
    def clear_term(self):
685
 
        """See progress.ProgressBar.clear_term()."""
686
 
 
687
 
    def finished(self):
688
 
        """See progress.ProgressBar.finished()."""
689
 
 
690
 
    def note(self, fmt_string, *args, **kwargs):
691
 
        """See progress.ProgressBar.note()."""
692
 
        self.stdout.write((fmt_string + "\n") % args)
693
 
 
694
 
    def progress_bar(self):
695
 
        return self
696
 
 
697
 
    def nested_progress_bar(self):
698
 
        return self
699
 
 
700
 
    def update(self, message, count=None, total=None):
701
 
        """See progress.ProgressBar.update()."""
702
 
 
703
 
    def get_non_echoed_password(self, prompt):
704
 
        """Get password from stdin without trying to handle the echo mode"""
705
 
        if prompt:
706
 
            self.stdout.write(prompt.encode(self.stdout.encoding, 'replace'))
707
 
        password = self.stdin.readline()
708
 
        if not password:
709
 
            raise EOFError
710
 
        if password[-1] == '\n':
711
 
            password = password[:-1]
712
 
        return password
713
 
 
714
 
 
715
527
class TestCase(unittest.TestCase):
716
528
    """Base class for bzr unit tests.
717
529
    
751
563
        self._startLogFile()
752
564
        self._benchcalls = []
753
565
        self._benchtime = None
754
 
        self._clear_hooks()
755
 
        self._clear_debug_flags()
756
 
 
757
 
    def _clear_debug_flags(self):
758
 
        """Prevent externally set debug flags affecting tests.
759
 
        
760
 
        Tests that want to use debug flags can just set them in the
761
 
        debug_flags set during setup/teardown.
762
 
        """
763
 
        self._preserved_debug_flags = set(debug.debug_flags)
764
 
        debug.debug_flags.clear()
765
 
        self.addCleanup(self._restore_debug_flags)
766
 
 
767
 
    def _clear_hooks(self):
768
 
        # prevent hooks affecting tests
769
 
        import bzrlib.branch
770
 
        import bzrlib.smart.server
771
 
        self._preserved_hooks = {
772
 
            bzrlib.branch.Branch: bzrlib.branch.Branch.hooks,
773
 
            bzrlib.smart.server.SmartTCPServer: bzrlib.smart.server.SmartTCPServer.hooks,
774
 
            }
775
 
        self.addCleanup(self._restoreHooks)
776
 
        # reset all hooks to an empty instance of the appropriate type
777
 
        bzrlib.branch.Branch.hooks = bzrlib.branch.BranchHooks()
778
 
        bzrlib.smart.server.SmartTCPServer.hooks = bzrlib.smart.server.SmartServerHooks()
779
566
 
780
567
    def _silenceUI(self):
781
568
        """Turn off UI for duration of test"""
782
569
        # by default the UI is off; tests can turn it on if they want it.
783
 
        saved = ui.ui_factory
 
570
        saved = bzrlib.ui.ui_factory
784
571
        def _restore():
785
 
            ui.ui_factory = saved
786
 
        ui.ui_factory = ui.SilentUIFactory()
 
572
            bzrlib.ui.ui_factory = saved
 
573
        bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
787
574
        self.addCleanup(_restore)
788
575
 
789
576
    def _ndiff_strings(self, a, b):
801
588
                                  charjunk=lambda x: False)
802
589
        return ''.join(difflines)
803
590
 
804
 
    def assertEqual(self, a, b, message=''):
805
 
        try:
806
 
            if a == b:
807
 
                return
808
 
        except UnicodeError, e:
809
 
            # If we can't compare without getting a UnicodeError, then
810
 
            # obviously they are different
811
 
            mutter('UnicodeError: %s', e)
812
 
        if message:
813
 
            message += '\n'
814
 
        raise AssertionError("%snot equal:\na = %s\nb = %s\n"
815
 
            % (message,
816
 
               pformat(a), pformat(b)))
817
 
 
818
 
    assertEquals = assertEqual
819
 
 
820
591
    def assertEqualDiff(self, a, b, message=None):
821
592
        """Assert two texts are equal, if not raise an exception.
822
593
        
828
599
            return
829
600
        if message is None:
830
601
            message = "texts not equal:\n"
831
 
        raise AssertionError(message +
832
 
                             self._ndiff_strings(a, b))
 
602
        raise AssertionError(message + 
 
603
                             self._ndiff_strings(a, b))      
833
604
        
834
605
    def assertEqualMode(self, mode, mode_test):
835
606
        self.assertEqual(mode, mode_test,
847
618
    def assertContainsRe(self, haystack, needle_re):
848
619
        """Assert that a contains something matching a regular expression."""
849
620
        if not re.search(needle_re, haystack):
850
 
            if '\n' in haystack or len(haystack) > 60:
851
 
                # a long string, format it in a more readable way
852
 
                raise AssertionError(
853
 
                        'pattern "%s" not found in\n"""\\\n%s"""\n'
854
 
                        % (needle_re, haystack))
855
 
            else:
856
 
                raise AssertionError('pattern "%s" not found in "%s"'
857
 
                        % (needle_re, haystack))
 
621
            raise AssertionError('pattern "%s" not found in "%s"'
 
622
                    % (needle_re, haystack))
858
623
 
859
624
    def assertNotContainsRe(self, haystack, needle_re):
860
625
        """Assert that a does not match a regular expression"""
872
637
            raise AssertionError("value(s) %r not present in container %r" % 
873
638
                                 (missing, superlist))
874
639
 
875
 
    def assertListRaises(self, excClass, func, *args, **kwargs):
876
 
        """Fail unless excClass is raised when the iterator from func is used.
877
 
        
878
 
        Many functions can return generators this makes sure
879
 
        to wrap them in a list() call to make sure the whole generator
880
 
        is run, and that the proper exception is raised.
881
 
        """
882
 
        try:
883
 
            list(func(*args, **kwargs))
884
 
        except excClass:
885
 
            return
886
 
        else:
887
 
            if getattr(excClass,'__name__', None) is not None:
888
 
                excName = excClass.__name__
889
 
            else:
890
 
                excName = str(excClass)
891
 
            raise self.failureException, "%s not raised" % excName
892
 
 
893
 
    def assertRaises(self, excClass, callableObj, *args, **kwargs):
894
 
        """Assert that a callable raises a particular exception.
895
 
 
896
 
        :param excClass: As for the except statement, this may be either an
897
 
            exception class, or a tuple of classes.
898
 
        :param callableObj: A callable, will be passed ``*args`` and
899
 
            ``**kwargs``.
900
 
 
901
 
        Returns the exception so that you can examine it.
902
 
        """
903
 
        try:
904
 
            callableObj(*args, **kwargs)
905
 
        except excClass, e:
906
 
            return e
907
 
        else:
908
 
            if getattr(excClass,'__name__', None) is not None:
909
 
                excName = excClass.__name__
910
 
            else:
911
 
                # probably a tuple
912
 
                excName = str(excClass)
913
 
            raise self.failureException, "%s not raised" % excName
914
 
 
915
 
    def assertIs(self, left, right, message=None):
 
640
    def assertIs(self, left, right):
916
641
        if not (left is right):
917
 
            if message is not None:
918
 
                raise AssertionError(message)
919
 
            else:
920
 
                raise AssertionError("%r is not %r." % (left, right))
921
 
 
922
 
    def assertIsNot(self, left, right, message=None):
923
 
        if (left is right):
924
 
            if message is not None:
925
 
                raise AssertionError(message)
926
 
            else:
927
 
                raise AssertionError("%r is %r." % (left, right))
 
642
            raise AssertionError("%r is not %r." % (left, right))
928
643
 
929
644
    def assertTransportMode(self, transport, path, mode):
930
645
        """Fail if a path does not have mode mode.
944
659
            self.fail("%r is an instance of %s rather than %s" % (
945
660
                obj, obj.__class__, kls))
946
661
 
947
 
    def expectFailure(self, reason, assertion, *args, **kwargs):
948
 
        """Invoke a test, expecting it to fail for the given reason.
949
 
 
950
 
        This is for assertions that ought to succeed, but currently fail.
951
 
        (The failure is *expected* but not *wanted*.)  Please be very precise
952
 
        about the failure you're expecting.  If a new bug is introduced,
953
 
        AssertionError should be raised, not KnownFailure.
954
 
 
955
 
        Frequently, expectFailure should be followed by an opposite assertion.
956
 
        See example below.
957
 
 
958
 
        Intended to be used with a callable that raises AssertionError as the
959
 
        'assertion' parameter.  args and kwargs are passed to the 'assertion'.
960
 
 
961
 
        Raises KnownFailure if the test fails.  Raises AssertionError if the
962
 
        test succeeds.
963
 
 
964
 
        example usage::
965
 
 
966
 
          self.expectFailure('Math is broken', self.assertNotEqual, 54,
967
 
                             dynamic_val)
968
 
          self.assertEqual(42, dynamic_val)
969
 
 
970
 
          This means that a dynamic_val of 54 will cause the test to raise
971
 
          a KnownFailure.  Once math is fixed and the expectFailure is removed,
972
 
          only a dynamic_val of 42 will allow the test to pass.  Anything other
973
 
          than 54 or 42 will cause an AssertionError.
974
 
        """
975
 
        try:
976
 
            assertion(*args, **kwargs)
977
 
        except AssertionError:
978
 
            raise KnownFailure(reason)
979
 
        else:
980
 
            self.fail('Unexpected success.  Should have failed: %s' % reason)
981
 
 
982
662
    def _capture_warnings(self, a_callable, *args, **kwargs):
983
663
        """A helper for callDeprecated and applyDeprecated.
984
664
 
986
666
        :param args: The positional arguments for the callable
987
667
        :param kwargs: The keyword arguments for the callable
988
668
        :return: A tuple (warnings, result). result is the result of calling
989
 
            a_callable(``*args``, ``**kwargs``).
 
669
            a_callable(*args, **kwargs).
990
670
        """
991
671
        local_warnings = []
992
672
        def capture_warnings(msg, cls=None, stacklevel=None):
1005
685
    def applyDeprecated(self, deprecation_format, a_callable, *args, **kwargs):
1006
686
        """Call a deprecated callable without warning the user.
1007
687
 
1008
 
        Note that this only captures warnings raised by symbol_versioning.warn,
1009
 
        not other callers that go direct to the warning module.
1010
 
 
1011
688
        :param deprecation_format: The deprecation format that the callable
1012
 
            should have been deprecated with. This is the same type as the
1013
 
            parameter to deprecated_method/deprecated_function. If the
 
689
            should have been deprecated with. This is the same type as the 
 
690
            parameter to deprecated_method/deprecated_function. If the 
1014
691
            callable is not deprecated with this format, an assertion error
1015
692
            will be raised.
1016
693
        :param a_callable: A callable to call. This may be a bound method or
1017
 
            a regular function. It will be called with ``*args`` and
1018
 
            ``**kwargs``.
 
694
            a regular function. It will be called with *args and **kwargs.
1019
695
        :param args: The positional arguments for the callable
1020
696
        :param kwargs: The keyword arguments for the callable
1021
 
        :return: The result of a_callable(``*args``, ``**kwargs``)
 
697
        :return: The result of a_callable(*args, **kwargs)
1022
698
        """
1023
699
        call_warnings, result = self._capture_warnings(a_callable,
1024
700
            *args, **kwargs)
1025
701
        expected_first_warning = symbol_versioning.deprecation_string(
1026
702
            a_callable, deprecation_format)
1027
703
        if len(call_warnings) == 0:
1028
 
            self.fail("No deprecation warning generated by call to %s" %
 
704
            self.fail("No assertion generated by call to %s" %
1029
705
                a_callable)
1030
706
        self.assertEqual(expected_first_warning, call_warnings[0])
1031
707
        return result
1038
714
        as it allows you to simply specify the deprecation format being used
1039
715
        and will ensure that that is issued for the function being called.
1040
716
 
1041
 
        Note that this only captures warnings raised by symbol_versioning.warn,
1042
 
        not other callers that go direct to the warning module.
1043
 
 
1044
717
        :param expected: a list of the deprecation warnings expected, in order
1045
718
        :param callable: The callable to call
1046
719
        :param args: The positional arguments for the callable
1095
768
        new_env = {
1096
769
            'BZR_HOME': None, # Don't inherit BZR_HOME to all the tests.
1097
770
            'HOME': os.getcwd(),
1098
 
            'APPDATA': None,  # bzr now use Win32 API and don't rely on APPDATA
 
771
            'APPDATA': os.getcwd(),
1099
772
            'BZR_EMAIL': None,
1100
773
            'BZREMAIL': None, # may still be present in the environment
1101
774
            'EMAIL': None,
1102
775
            'BZR_PROGRESS_BAR': None,
1103
 
            # Proxies
1104
 
            'http_proxy': None,
1105
 
            'HTTP_PROXY': None,
1106
 
            'https_proxy': None,
1107
 
            'HTTPS_PROXY': None,
1108
 
            'no_proxy': None,
1109
 
            'NO_PROXY': None,
1110
 
            'all_proxy': None,
1111
 
            'ALL_PROXY': None,
1112
 
            # Nobody cares about these ones AFAIK. So far at
1113
 
            # least. If you do (care), please update this comment
1114
 
            # -- vila 20061212
1115
 
            'ftp_proxy': None,
1116
 
            'FTP_PROXY': None,
1117
 
            'BZR_REMOTE_PATH': None,
1118
776
        }
1119
777
        self.__old_env = {}
1120
778
        self.addCleanup(self._restoreEnvironment)
1125
783
        """Set an environment variable, and reset it when finished."""
1126
784
        self.__old_env[name] = osutils.set_or_unset_env(name, newvalue)
1127
785
 
1128
 
    def _restore_debug_flags(self):
1129
 
        debug.debug_flags.clear()
1130
 
        debug.debug_flags.update(self._preserved_debug_flags)
1131
 
 
1132
786
    def _restoreEnvironment(self):
1133
787
        for name, value in self.__old_env.iteritems():
1134
788
            osutils.set_or_unset_env(name, value)
1135
789
 
1136
 
    def _restoreHooks(self):
1137
 
        for klass, hooks in self._preserved_hooks.items():
1138
 
            setattr(klass, 'hooks', hooks)
1139
 
 
1140
 
    def knownFailure(self, reason):
1141
 
        """This test has failed for some known reason."""
1142
 
        raise KnownFailure(reason)
1143
 
 
1144
 
    def run(self, result=None):
1145
 
        if result is None: result = self.defaultTestResult()
1146
 
        for feature in getattr(self, '_test_needs_features', []):
1147
 
            if not feature.available():
1148
 
                result.startTest(self)
1149
 
                if getattr(result, 'addNotSupported', None):
1150
 
                    result.addNotSupported(self, feature)
1151
 
                else:
1152
 
                    result.addSuccess(self)
1153
 
                result.stopTest(self)
1154
 
                return
1155
 
        return unittest.TestCase.run(self, result)
1156
 
 
1157
790
    def tearDown(self):
1158
791
        self._runCleanups()
1159
792
        unittest.TestCase.tearDown(self)
1187
820
        """
1188
821
        # TODO: Perhaps this should keep running cleanups even if 
1189
822
        # one of them fails?
1190
 
 
1191
 
        # Actually pop the cleanups from the list so tearDown running
1192
 
        # twice is safe (this happens for skipped tests).
1193
 
        while self._cleanups:
1194
 
            self._cleanups.pop()()
 
823
        for cleanup_fn in reversed(self._cleanups):
 
824
            cleanup_fn()
1195
825
 
1196
826
    def log(self, *args):
1197
827
        mutter(*args)
1213
843
                logfile.close()
1214
844
            if not keep_log_file:
1215
845
                self._log_contents = log_contents
1216
 
                try:
1217
 
                    os.remove(self._log_file_name)
1218
 
                except OSError, e:
1219
 
                    if sys.platform == 'win32' and e.errno == errno.EACCES:
1220
 
                        print >>sys.stderr, ('Unable to delete log file '
1221
 
                                             ' %r' % self._log_file_name)
1222
 
                    else:
1223
 
                        raise
 
846
                os.remove(self._log_file_name)
1224
847
            return log_contents
1225
848
        else:
1226
849
            return "DELETED log file to reduce memory footprint"
1227
850
 
1228
 
    @deprecated_method(zero_eighteen)
1229
851
    def capture(self, cmd, retcode=0):
1230
852
        """Shortcut that splits cmd into words, runs, and returns stdout"""
1231
853
        return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
1232
854
 
1233
 
    def requireFeature(self, feature):
1234
 
        """This test requires a specific feature is available.
1235
 
 
1236
 
        :raises UnavailableFeature: When feature is not available.
1237
 
        """
1238
 
        if not feature.available():
1239
 
            raise UnavailableFeature(feature)
1240
 
 
1241
 
    @deprecated_method(zero_eighteen)
1242
855
    def run_bzr_captured(self, argv, retcode=0, encoding=None, stdin=None,
1243
856
                         working_dir=None):
1244
857
        """Invoke bzr and return (stdout, stderr).
1245
858
 
1246
 
        Don't call this method, just use run_bzr() which is equivalent.
1247
 
 
1248
 
        :param argv: Arguments to invoke bzr.  This may be either a 
1249
 
            single string, in which case it is split by shlex into words, 
1250
 
            or a list of arguments.
1251
 
        :param retcode: Expected return code, or None for don't-care.
1252
 
        :param encoding: Encoding for sys.stdout and sys.stderr
 
859
        Useful for code that wants to check the contents of the
 
860
        output, the way error messages are presented, etc.
 
861
 
 
862
        This should be the main method for tests that want to exercise the
 
863
        overall behavior of the bzr application (rather than a unit test
 
864
        or a functional test of the library.)
 
865
 
 
866
        Much of the old code runs bzr by forking a new copy of Python, but
 
867
        that is slower, harder to debug, and generally not necessary.
 
868
 
 
869
        This runs bzr through the interface that catches and reports
 
870
        errors, and with logging set to something approximating the
 
871
        default, so that error reporting can be checked.
 
872
 
 
873
        :param argv: arguments to invoke bzr
 
874
        :param retcode: expected return code, or None for don't-care.
 
875
        :param encoding: encoding for sys.stdout and sys.stderr
1253
876
        :param stdin: A string to be used as stdin for the command.
1254
877
        :param working_dir: Change to this directory before running
1255
878
        """
1256
 
        return self._run_bzr_autosplit(argv, retcode=retcode,
1257
 
                encoding=encoding, stdin=stdin, working_dir=working_dir,
1258
 
                )
1259
 
 
1260
 
    def _run_bzr_autosplit(self, args, retcode, encoding, stdin,
1261
 
            working_dir):
1262
 
        """Run bazaar command line, splitting up a string command line."""
1263
 
        if isinstance(args, basestring):
1264
 
            args = list(shlex.split(args))
1265
 
        return self._run_bzr_core(args, retcode=retcode,
1266
 
                encoding=encoding, stdin=stdin, working_dir=working_dir,
1267
 
                )
1268
 
 
1269
 
    def _run_bzr_core(self, args, retcode, encoding, stdin,
1270
 
            working_dir):
1271
879
        if encoding is None:
1272
880
            encoding = bzrlib.user_encoding
 
881
        if stdin is not None:
 
882
            stdin = StringIO(stdin)
1273
883
        stdout = StringIOWrapper()
1274
884
        stderr = StringIOWrapper()
1275
885
        stdout.encoding = encoding
1276
886
        stderr.encoding = encoding
1277
887
 
1278
 
        self.log('run bzr: %r', args)
 
888
        self.log('run bzr: %r', argv)
1279
889
        # FIXME: don't call into logging here
1280
890
        handler = logging.StreamHandler(stderr)
1281
891
        handler.setLevel(logging.INFO)
1282
892
        logger = logging.getLogger('')
1283
893
        logger.addHandler(handler)
1284
 
        old_ui_factory = ui.ui_factory
1285
 
        ui.ui_factory = TestUIFactory(stdin=stdin, stdout=stdout, stderr=stderr)
 
894
        old_ui_factory = bzrlib.ui.ui_factory
 
895
        bzrlib.ui.ui_factory = bzrlib.tests.blackbox.TestUIFactory(
 
896
            stdout=stdout,
 
897
            stderr=stderr)
 
898
        bzrlib.ui.ui_factory.stdin = stdin
1286
899
 
1287
900
        cwd = None
1288
901
        if working_dir is not None:
1290
903
            os.chdir(working_dir)
1291
904
 
1292
905
        try:
1293
 
            result = self.apply_redirected(ui.ui_factory.stdin,
1294
 
                stdout, stderr,
1295
 
                bzrlib.commands.run_bzr_catch_errors,
1296
 
                args)
 
906
            saved_debug_flags = frozenset(debug.debug_flags)
 
907
            debug.debug_flags.clear()
 
908
            try:
 
909
                result = self.apply_redirected(stdin, stdout, stderr,
 
910
                                               bzrlib.commands.run_bzr_catch_errors,
 
911
                                               argv)
 
912
            finally:
 
913
                debug.debug_flags.update(saved_debug_flags)
1297
914
        finally:
1298
915
            logger.removeHandler(handler)
1299
 
            ui.ui_factory = old_ui_factory
 
916
            bzrlib.ui.ui_factory = old_ui_factory
1300
917
            if cwd is not None:
1301
918
                os.chdir(cwd)
1302
919
 
1307
924
        if err:
1308
925
            self.log('errors:\n%r', err)
1309
926
        if retcode is not None:
1310
 
            self.assertEquals(retcode, result,
1311
 
                              message='Unexpected return code')
 
927
            self.assertEquals(retcode, result)
1312
928
        return out, err
1313
929
 
1314
930
    def run_bzr(self, *args, **kwargs):
1315
931
        """Invoke bzr, as if it were run from the command line.
1316
932
 
1317
 
        The argument list should not include the bzr program name - the
1318
 
        first argument is normally the bzr command.  Arguments may be
1319
 
        passed in three ways:
1320
 
 
1321
 
        1- A list of strings, eg ["commit", "a"].  This is recommended
1322
 
        when the command contains whitespace or metacharacters, or 
1323
 
        is built up at run time.
1324
 
 
1325
 
        2- A single string, eg "add a".  This is the most convenient 
1326
 
        for hardcoded commands.
1327
 
 
1328
 
        3- Several varargs parameters, eg run_bzr("add", "a").  
1329
 
        This is not recommended for new code.
1330
 
 
1331
 
        This runs bzr through the interface that catches and reports
1332
 
        errors, and with logging set to something approximating the
1333
 
        default, so that error reporting can be checked.
1334
 
 
1335
933
        This should be the main method for tests that want to exercise the
1336
934
        overall behavior of the bzr application (rather than a unit test
1337
935
        or a functional test of the library.)
1339
937
        This sends the stdout/stderr results into the test's log,
1340
938
        where it may be useful for debugging.  See also run_captured.
1341
939
 
1342
 
        :keyword stdin: A string to be used as stdin for the command.
1343
 
        :keyword retcode: The status code the command should return;
1344
 
            default 0.
1345
 
        :keyword working_dir: The directory to run the command in
1346
 
        :keyword error_regexes: A list of expected error messages.  If
1347
 
            specified they must be seen in the error output of the command.
 
940
        :param stdin: A string to be used as stdin for the command.
1348
941
        """
1349
942
        retcode = kwargs.pop('retcode', 0)
1350
943
        encoding = kwargs.pop('encoding', None)
1351
944
        stdin = kwargs.pop('stdin', None)
1352
945
        working_dir = kwargs.pop('working_dir', None)
1353
 
        error_regexes = kwargs.pop('error_regexes', [])
1354
 
 
1355
 
        if len(args) == 1:
1356
 
            if isinstance(args[0], (list, basestring)):
1357
 
                args = args[0]
1358
 
        else:
1359
 
            symbol_versioning.warn(zero_eighteen % "passing varargs to run_bzr",
1360
 
                                   DeprecationWarning, stacklevel=3)
1361
 
 
1362
 
        out, err = self._run_bzr_autosplit(args=args,
1363
 
            retcode=retcode,
1364
 
            encoding=encoding, stdin=stdin, working_dir=working_dir,
1365
 
            )
1366
 
 
1367
 
        for regex in error_regexes:
1368
 
            self.assertContainsRe(err, regex)
1369
 
        return out, err
 
946
        return self.run_bzr_captured(args, retcode=retcode, encoding=encoding,
 
947
                                     stdin=stdin, working_dir=working_dir)
1370
948
 
1371
949
    def run_bzr_decode(self, *args, **kwargs):
1372
950
        if 'encoding' in kwargs:
1377
955
 
1378
956
    def run_bzr_error(self, error_regexes, *args, **kwargs):
1379
957
        """Run bzr, and check that stderr contains the supplied regexes
1380
 
 
1381
 
        :param error_regexes: Sequence of regular expressions which
 
958
        
 
959
        :param error_regexes: Sequence of regular expressions which 
1382
960
            must each be found in the error output. The relative ordering
1383
961
            is not enforced.
1384
962
        :param args: command-line arguments for bzr
1385
963
        :param kwargs: Keyword arguments which are interpreted by run_bzr
1386
964
            This function changes the default value of retcode to be 3,
1387
965
            since in most cases this is run when you expect bzr to fail.
1388
 
 
1389
 
        :return: (out, err) The actual output of running the command (in case
1390
 
            you want to do more inspection)
1391
 
 
1392
 
        Examples of use::
1393
 
 
 
966
        :return: (out, err) The actual output of running the command (in case you
 
967
                 want to do more inspection)
 
968
 
 
969
        Examples of use:
1394
970
            # Make sure that commit is failing because there is nothing to do
1395
971
            self.run_bzr_error(['no changes to commit'],
1396
972
                               'commit', '-m', 'my commit comment')
1401
977
                               'commit', '--strict', '-m', 'my commit comment')
1402
978
        """
1403
979
        kwargs.setdefault('retcode', 3)
1404
 
        kwargs['error_regexes'] = error_regexes
1405
980
        out, err = self.run_bzr(*args, **kwargs)
 
981
        for regex in error_regexes:
 
982
            self.assertContainsRe(err, regex)
1406
983
        return out, err
1407
984
 
1408
985
    def run_bzr_subprocess(self, *args, **kwargs):
1414
991
        handling, or early startup code, etc.  Subprocess code can't be 
1415
992
        profiled or debugged so easily.
1416
993
 
1417
 
        :keyword retcode: The status code that is expected.  Defaults to 0.  If
 
994
        :param retcode: The status code that is expected.  Defaults to 0.  If
1418
995
            None is supplied, the status code is not checked.
1419
 
        :keyword env_changes: A dictionary which lists changes to environment
 
996
        :param env_changes: A dictionary which lists changes to environment
1420
997
            variables. A value of None will unset the env variable.
1421
998
            The values must be strings. The change will only occur in the
1422
999
            child, so you don't need to fix the environment after running.
1423
 
        :keyword universal_newlines: Convert CRLF => LF
1424
 
        :keyword allow_plugins: By default the subprocess is run with
 
1000
        :param universal_newlines: Convert CRLF => LF
 
1001
        :param allow_plugins: By default the subprocess is run with
1425
1002
            --no-plugins to ensure test reproducibility. Also, it is possible
1426
1003
            for system-wide plugins to create unexpected output on stderr,
1427
1004
            which can cause unnecessary test failures.
1451
1028
        profiled or debugged so easily.
1452
1029
 
1453
1030
        :param process_args: a list of arguments to pass to the bzr executable,
1454
 
            for example ``['--version']``.
 
1031
            for example `['--version']`.
1455
1032
        :param env_changes: A dictionary which lists changes to environment
1456
1033
            variables. A value of None will unset the env variable.
1457
1034
            The values must be strings. The change will only occur in the
1555
1132
        shape = list(shape)             # copy
1556
1133
        for path, ie in inv.entries():
1557
1134
            name = path.replace('\\', '/')
1558
 
            if ie.kind == 'directory':
 
1135
            if ie.kind == 'dir':
1559
1136
                name = name + '/'
1560
1137
            if name in shape:
1561
1138
                shape.remove(name)
1598
1175
            sys.stderr = real_stderr
1599
1176
            sys.stdin = real_stdin
1600
1177
 
1601
 
    def reduceLockdirTimeout(self):
1602
 
        """Reduce the default lock timeout for the duration of the test, so that
1603
 
        if LockContention occurs during a test, it does so quickly.
 
1178
    @symbol_versioning.deprecated_method(symbol_versioning.zero_eleven)
 
1179
    def merge(self, branch_from, wt_to):
 
1180
        """A helper for tests to do a ui-less merge.
1604
1181
 
1605
 
        Tests that expect to provoke LockContention errors should call this.
 
1182
        This should move to the main library when someone has time to integrate
 
1183
        it in.
1606
1184
        """
1607
 
        orig_timeout = bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS
1608
 
        def resetTimeout():
1609
 
            bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = orig_timeout
1610
 
        self.addCleanup(resetTimeout)
1611
 
        bzrlib.lockdir._DEFAULT_TIMEOUT_SECONDS = 0
 
1185
        # minimal ui-less merge.
 
1186
        wt_to.branch.fetch(branch_from)
 
1187
        base_rev = common_ancestor(branch_from.last_revision(),
 
1188
                                   wt_to.branch.last_revision(),
 
1189
                                   wt_to.branch.repository)
 
1190
        merge_inner(wt_to.branch, branch_from.basis_tree(),
 
1191
                    wt_to.branch.repository.revision_tree(base_rev),
 
1192
                    this_tree=wt_to)
 
1193
        wt_to.add_parent_tree_id(branch_from.last_revision())
 
1194
 
 
1195
 
 
1196
BzrTestBase = TestCase
1612
1197
 
1613
1198
 
1614
1199
class TestCaseWithMemoryTransport(TestCase):
1625
1210
    file defaults for the transport in tests, nor does it obey the command line
1626
1211
    override, so tests that accidentally write to the common directory should
1627
1212
    be rare.
1628
 
 
1629
 
    :cvar TEST_ROOT: Directory containing all temporary directories, plus
1630
 
    a .bzr directory that stops us ascending higher into the filesystem.
1631
1213
    """
1632
1214
 
1633
1215
    TEST_ROOT = None
1634
1216
    _TEST_NAME = 'test'
1635
1217
 
 
1218
 
1636
1219
    def __init__(self, methodName='runTest'):
1637
1220
        # allow test parameterisation after test construction and before test
1638
1221
        # execution. Variables that the parameteriser sets need to be 
1639
1222
        # ones that are not set by setUp, or setUp will trash them.
1640
1223
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
1641
 
        self.vfs_transport_factory = default_transport
1642
 
        self.transport_server = None
 
1224
        self.transport_server = default_transport
1643
1225
        self.transport_readonly_server = None
1644
 
        self.__vfs_server = None
1645
 
 
1646
 
    def get_transport(self, relpath=None):
1647
 
        """Return a writeable transport.
1648
 
 
1649
 
        This transport is for the test scratch space relative to
1650
 
        "self._test_root""
 
1226
 
 
1227
    def failUnlessExists(self, path):
 
1228
        """Fail unless path, which may be abs or relative, exists."""
 
1229
        self.failUnless(osutils.lexists(path))
 
1230
 
 
1231
    def failIfExists(self, path):
 
1232
        """Fail if path, which may be abs or relative, exists."""
 
1233
        self.failIf(osutils.lexists(path))
1651
1234
        
1652
 
        :param relpath: a path relative to the base url.
1653
 
        """
1654
 
        t = get_transport(self.get_url(relpath))
 
1235
    def get_transport(self):
 
1236
        """Return a writeable transport for the test scratch space"""
 
1237
        t = get_transport(self.get_url())
1655
1238
        self.assertFalse(t.is_readonly())
1656
1239
        return t
1657
1240
 
1658
 
    def get_readonly_transport(self, relpath=None):
 
1241
    def get_readonly_transport(self):
1659
1242
        """Return a readonly transport for the test scratch space
1660
1243
        
1661
1244
        This can be used to test that operations which should only need
1662
1245
        readonly access in fact do not try to write.
1663
 
 
1664
 
        :param relpath: a path relative to the base url.
1665
1246
        """
1666
 
        t = get_transport(self.get_readonly_url(relpath))
 
1247
        t = get_transport(self.get_readonly_url())
1667
1248
        self.assertTrue(t.is_readonly())
1668
1249
        return t
1669
1250
 
1670
 
    def create_transport_readonly_server(self):
1671
 
        """Create a transport server from class defined at init.
1672
 
 
1673
 
        This is mostly a hook for daughter classes.
1674
 
        """
1675
 
        return self.transport_readonly_server()
1676
 
 
1677
1251
    def get_readonly_server(self):
1678
1252
        """Get the server instance for the readonly transport
1679
1253
 
1683
1257
            if self.transport_readonly_server is None:
1684
1258
                # readonly decorator requested
1685
1259
                # bring up the server
 
1260
                self.get_url()
1686
1261
                self.__readonly_server = ReadonlyServer()
1687
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
 
1262
                self.__readonly_server.setUp(self.__server)
1688
1263
            else:
1689
 
                self.__readonly_server = self.create_transport_readonly_server()
1690
 
                self.__readonly_server.setUp(self.get_vfs_only_server())
 
1264
                self.__readonly_server = self.transport_readonly_server()
 
1265
                self.__readonly_server.setUp()
1691
1266
            self.addCleanup(self.__readonly_server.tearDown)
1692
1267
        return self.__readonly_server
1693
1268
 
1700
1275
        These should only be downwards relative, not upwards.
1701
1276
        """
1702
1277
        base = self.get_readonly_server().get_url()
1703
 
        return self._adjust_url(base, relpath)
 
1278
        if relpath is not None:
 
1279
            if not base.endswith('/'):
 
1280
                base = base + '/'
 
1281
            base = base + relpath
 
1282
        return base
1704
1283
 
1705
 
    def get_vfs_only_server(self):
1706
 
        """Get the vfs only read/write server instance.
 
1284
    def get_server(self):
 
1285
        """Get the read/write server instance.
1707
1286
 
1708
1287
        This is useful for some tests with specific servers that need
1709
1288
        diagnostics.
1711
1290
        For TestCaseWithMemoryTransport this is always a MemoryServer, and there
1712
1291
        is no means to override it.
1713
1292
        """
1714
 
        if self.__vfs_server is None:
1715
 
            self.__vfs_server = MemoryServer()
1716
 
            self.__vfs_server.setUp()
1717
 
            self.addCleanup(self.__vfs_server.tearDown)
1718
 
        return self.__vfs_server
1719
 
 
1720
 
    def get_server(self):
1721
 
        """Get the read/write server instance.
1722
 
 
1723
 
        This is useful for some tests with specific servers that need
1724
 
        diagnostics.
1725
 
 
1726
 
        This is built from the self.transport_server factory. If that is None,
1727
 
        then the self.get_vfs_server is returned.
1728
 
        """
1729
1293
        if self.__server is None:
1730
 
            if self.transport_server is None or self.transport_server is self.vfs_transport_factory:
1731
 
                return self.get_vfs_only_server()
1732
 
            else:
1733
 
                # bring up a decorated means of access to the vfs only server.
1734
 
                self.__server = self.transport_server()
1735
 
                try:
1736
 
                    self.__server.setUp(self.get_vfs_only_server())
1737
 
                except TypeError, e:
1738
 
                    # This should never happen; the try:Except here is to assist
1739
 
                    # developers having to update code rather than seeing an
1740
 
                    # uninformative TypeError.
1741
 
                    raise Exception, "Old server API in use: %s, %s" % (self.__server, e)
 
1294
            self.__server = MemoryServer()
 
1295
            self.__server.setUp()
1742
1296
            self.addCleanup(self.__server.tearDown)
1743
1297
        return self.__server
1744
1298
 
1745
 
    def _adjust_url(self, base, relpath):
 
1299
    def get_url(self, relpath=None):
1746
1300
        """Get a URL (or maybe a path) for the readwrite transport.
1747
1301
 
1748
1302
        This will either be backed by '.' or to an equivalent non-file based
1750
1304
        relpath provides for clients to get a path relative to the base url.
1751
1305
        These should only be downwards relative, not upwards.
1752
1306
        """
 
1307
        base = self.get_server().get_url()
1753
1308
        if relpath is not None and relpath != '.':
1754
1309
            if not base.endswith('/'):
1755
1310
                base = base + '/'
1763
1318
                base += urlutils.escape(relpath)
1764
1319
        return base
1765
1320
 
1766
 
    def get_url(self, relpath=None):
1767
 
        """Get a URL (or maybe a path) for the readwrite transport.
1768
 
 
1769
 
        This will either be backed by '.' or to an equivalent non-file based
1770
 
        facility.
1771
 
        relpath provides for clients to get a path relative to the base url.
1772
 
        These should only be downwards relative, not upwards.
1773
 
        """
1774
 
        base = self.get_server().get_url()
1775
 
        return self._adjust_url(base, relpath)
1776
 
 
1777
 
    def get_vfs_only_url(self, relpath=None):
1778
 
        """Get a URL (or maybe a path for the plain old vfs transport.
1779
 
 
1780
 
        This will never be a smart protocol.  It always has all the
1781
 
        capabilities of the local filesystem, but it might actually be a
1782
 
        MemoryTransport or some other similar virtual filesystem.
1783
 
 
1784
 
        This is the backing transport (if any) of the server returned by
1785
 
        get_url and get_readonly_url.
1786
 
 
1787
 
        :param relpath: provides for clients to get a path relative to the base
1788
 
            url.  These should only be downwards relative, not upwards.
1789
 
        :return: A URL
1790
 
        """
1791
 
        base = self.get_vfs_only_server().get_url()
1792
 
        return self._adjust_url(base, relpath)
1793
 
 
1794
1321
    def _make_test_root(self):
1795
1322
        if TestCaseWithMemoryTransport.TEST_ROOT is not None:
1796
1323
            return
1797
 
        root = tempfile.mkdtemp(prefix='testbzr-', suffix='.tmp')
1798
 
        TestCaseWithMemoryTransport.TEST_ROOT = root
1799
 
        
 
1324
        i = 0
 
1325
        while True:
 
1326
            root = u'test%04d.tmp' % i
 
1327
            try:
 
1328
                os.mkdir(root)
 
1329
            except OSError, e:
 
1330
                if e.errno == errno.EEXIST:
 
1331
                    i += 1
 
1332
                    continue
 
1333
                else:
 
1334
                    raise
 
1335
            # successfully created
 
1336
            TestCaseWithMemoryTransport.TEST_ROOT = osutils.abspath(root)
 
1337
            break
1800
1338
        # make a fake bzr directory there to prevent any tests propagating
1801
1339
        # up onto the source directory's real branch
1802
 
        bzrdir.BzrDir.create_standalone_workingtree(root)
1803
 
 
1804
 
        # The same directory is used by all tests, and we're not specifically
1805
 
        # told when all tests are finished.  This will do.
1806
 
        atexit.register(_rmtree_temp_dir, root)
 
1340
        bzrdir.BzrDir.create_standalone_workingtree(
 
1341
            TestCaseWithMemoryTransport.TEST_ROOT)
1807
1342
 
1808
1343
    def makeAndChdirToTestDir(self):
1809
1344
        """Create a temporary directories for this one test.
1829
1364
            segments = maybe_a_url.rsplit('/', 1)
1830
1365
            t = get_transport(maybe_a_url)
1831
1366
            if len(segments) > 1 and segments[-1] not in ('', '.'):
1832
 
                t.ensure_base()
 
1367
                try:
 
1368
                    t.mkdir('.')
 
1369
                except errors.FileExists:
 
1370
                    pass
1833
1371
            if format is None:
1834
 
                format = 'default'
1835
 
            if isinstance(format, basestring):
1836
 
                format = bzrdir.format_registry.make_bzrdir(format)
 
1372
                format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
1837
1373
            return format.initialize_on_transport(t)
1838
1374
        except errors.UninitializableFormat:
1839
1375
            raise TestSkipped("Format %s is not initializable." % format)
1840
1376
 
1841
1377
    def make_repository(self, relpath, shared=False, format=None):
1842
 
        """Create a repository on our default transport at relpath.
1843
 
        
1844
 
        Note that relpath must be a relative path, not a full url.
1845
 
        """
1846
 
        # FIXME: If you create a remoterepository this returns the underlying
1847
 
        # real format, which is incorrect.  Actually we should make sure that 
1848
 
        # RemoteBzrDir returns a RemoteRepository.
1849
 
        # maybe  mbp 20070410
 
1378
        """Create a repository on our default transport at relpath."""
1850
1379
        made_control = self.make_bzrdir(relpath, format=format)
1851
1380
        return made_control.create_repository(shared=shared)
1852
1381
 
1857
1386
 
1858
1387
    def overrideEnvironmentForTesting(self):
1859
1388
        os.environ['HOME'] = self.test_home_dir
1860
 
        os.environ['BZR_HOME'] = self.test_home_dir
 
1389
        os.environ['APPDATA'] = self.test_home_dir
1861
1390
        
1862
1391
    def setUp(self):
1863
1392
        super(TestCaseWithMemoryTransport, self).setUp()
1870
1399
        self.overrideEnvironmentForTesting()
1871
1400
        self.__readonly_server = None
1872
1401
        self.__server = None
1873
 
        self.reduceLockdirTimeout()
1874
1402
 
1875
1403
     
1876
1404
class TestCaseInTempDir(TestCaseWithMemoryTransport):
1883
1411
    All test cases create their own directory within that.  If the
1884
1412
    tests complete successfully, the directory is removed.
1885
1413
 
1886
 
    :ivar test_base_dir: The path of the top-level directory for this 
1887
 
    test, which contains a home directory and a work directory.
1888
 
 
1889
 
    :ivar test_home_dir: An initially empty directory under test_base_dir
1890
 
    which is used as $HOME for this test.
1891
 
 
1892
 
    :ivar test_dir: A directory under test_base_dir used as the current
1893
 
    directory when the test proper is run.
 
1414
    InTempDir is an old alias for FunctionalTestCase.
1894
1415
    """
1895
1416
 
1896
1417
    OVERRIDE_PYTHON = 'python'
1897
 
    use_numbered_dirs = False
1898
1418
 
1899
1419
    def check_file_contents(self, filename, expect):
1900
1420
        self.log("check contents of file %s" % filename)
1910
1430
        For TestCaseInTempDir we create a temporary directory based on the test
1911
1431
        name and then create two subdirs - test and home under it.
1912
1432
        """
1913
 
        # create a directory within the top level test directory
1914
 
        candidate_dir = tempfile.mkdtemp(dir=self.TEST_ROOT)
1915
 
        # now create test and home directories within this dir
1916
 
        self.test_base_dir = candidate_dir
1917
 
        self.test_home_dir = self.test_base_dir + '/home'
1918
 
        os.mkdir(self.test_home_dir)
1919
 
        self.test_dir = self.test_base_dir + '/work'
1920
 
        os.mkdir(self.test_dir)
1921
 
        os.chdir(self.test_dir)
1922
 
        # put name of test inside
1923
 
        f = file(self.test_base_dir + '/name', 'w')
1924
 
        try:
1925
 
            f.write(self.id())
1926
 
        finally:
1927
 
            f.close()
1928
 
        self.addCleanup(self.deleteTestDir)
1929
 
 
1930
 
    def deleteTestDir(self):
1931
 
        os.chdir(self.TEST_ROOT)
1932
 
        _rmtree_temp_dir(self.test_base_dir)
1933
 
 
1934
 
    def build_tree(self, shape, line_endings='binary', transport=None):
 
1433
        # shorten the name, to avoid test failures due to path length
 
1434
        short_id = self.id().replace('bzrlib.tests.', '') \
 
1435
                   .replace('__main__.', '')[-100:]
 
1436
        # it's possible the same test class is run several times for
 
1437
        # parameterized tests, so make sure the names don't collide.  
 
1438
        i = 0
 
1439
        while True:
 
1440
            if i > 0:
 
1441
                candidate_dir = '%s/%s.%d' % (self.TEST_ROOT, short_id, i)
 
1442
            else:
 
1443
                candidate_dir = '%s/%s' % (self.TEST_ROOT, short_id)
 
1444
            if os.path.exists(candidate_dir):
 
1445
                i = i + 1
 
1446
                continue
 
1447
            else:
 
1448
                os.mkdir(candidate_dir)
 
1449
                self.test_home_dir = candidate_dir + '/home'
 
1450
                os.mkdir(self.test_home_dir)
 
1451
                self.test_dir = candidate_dir + '/work'
 
1452
                os.mkdir(self.test_dir)
 
1453
                os.chdir(self.test_dir)
 
1454
                break
 
1455
 
 
1456
    def build_tree(self, shape, line_endings='native', transport=None):
1935
1457
        """Build a test tree according to a pattern.
1936
1458
 
1937
1459
        shape is a sequence of file specifications.  If the final
1940
1462
        This assumes that all the elements in the tree being built are new.
1941
1463
 
1942
1464
        This doesn't add anything to a branch.
1943
 
 
1944
1465
        :param line_endings: Either 'binary' or 'native'
1945
 
            in binary mode, exact contents are written in native mode, the
1946
 
            line endings match the default platform endings.
1947
 
        :param transport: A transport to write to, for building trees on VFS's.
1948
 
            If the transport is readonly or None, "." is opened automatically.
1949
 
        :return: None
 
1466
                             in binary mode, exact contents are written
 
1467
                             in native mode, the line endings match the
 
1468
                             default platform endings.
 
1469
 
 
1470
        :param transport: A transport to write to, for building trees on 
 
1471
                          VFS's. If the transport is readonly or None,
 
1472
                          "." is opened automatically.
1950
1473
        """
1951
1474
        # It's OK to just create them using forward slashes on windows.
1952
1475
        if transport is None or transport.is_readonly():
1961
1484
                elif line_endings == 'native':
1962
1485
                    end = os.linesep
1963
1486
                else:
1964
 
                    raise errors.BzrError(
1965
 
                        'Invalid line ending request %r' % line_endings)
 
1487
                    raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
1966
1488
                content = "contents of %s%s" % (name.encode('utf-8'), end)
 
1489
                # Technically 'put()' is the right command. However, put
 
1490
                # uses an AtomicFile, which requires an extra rename into place
 
1491
                # As long as the files didn't exist in the past, append() will
 
1492
                # do the same thing as put()
 
1493
                # On jam's machine, make_kernel_like_tree is:
 
1494
                #   put:    4.5-7.5s (averaging 6s)
 
1495
                #   append: 2.9-4.5s
 
1496
                #   put_non_atomic: 2.9-4.5s
1967
1497
                transport.put_bytes_non_atomic(urlutils.escape(name), content)
1968
1498
 
1969
1499
    def build_tree_contents(self, shape):
1971
1501
 
1972
1502
    def assertFileEqual(self, content, path):
1973
1503
        """Fail if path does not contain 'content'."""
1974
 
        self.failUnlessExists(path)
1975
 
        f = file(path, 'rb')
1976
 
        try:
1977
 
            s = f.read()
1978
 
        finally:
1979
 
            f.close()
1980
 
        self.assertEqualDiff(content, s)
1981
 
 
1982
 
    def failUnlessExists(self, path):
1983
 
        """Fail unless path or paths, which may be abs or relative, exist."""
1984
 
        if not isinstance(path, basestring):
1985
 
            for p in path:
1986
 
                self.failUnlessExists(p)
1987
 
        else:
1988
 
            self.failUnless(osutils.lexists(path),path+" does not exist")
1989
 
 
1990
 
    def failIfExists(self, path):
1991
 
        """Fail if path or paths, which may be abs or relative, exist."""
1992
 
        if not isinstance(path, basestring):
1993
 
            for p in path:
1994
 
                self.failIfExists(p)
1995
 
        else:
1996
 
            self.failIf(osutils.lexists(path),path+" exists")
1997
 
 
1998
 
    def assertInWorkingTree(self,path,root_path='.',tree=None):
1999
 
        """Assert whether path or paths are in the WorkingTree"""
2000
 
        if tree is None:
2001
 
            tree = workingtree.WorkingTree.open(root_path)
2002
 
        if not isinstance(path, basestring):
2003
 
            for p in path:
2004
 
                self.assertInWorkingTree(p,tree=tree)
2005
 
        else:
2006
 
            self.assertIsNot(tree.path2id(path), None,
2007
 
                path+' not in working tree.')
2008
 
 
2009
 
    def assertNotInWorkingTree(self,path,root_path='.',tree=None):
2010
 
        """Assert whether path or paths are not in the WorkingTree"""
2011
 
        if tree is None:
2012
 
            tree = workingtree.WorkingTree.open(root_path)
2013
 
        if not isinstance(path, basestring):
2014
 
            for p in path:
2015
 
                self.assertNotInWorkingTree(p,tree=tree)
2016
 
        else:
2017
 
            self.assertIs(tree.path2id(path), None, path+' in working tree.')
 
1504
        self.failUnless(osutils.lexists(path))
 
1505
        # TODO: jam 20060427 Shouldn't this be 'rb'?
 
1506
        self.assertEqualDiff(content, open(path, 'r').read())
2018
1507
 
2019
1508
 
2020
1509
class TestCaseWithTransport(TestCaseInTempDir):
2031
1520
    readwrite one must both define get_url() as resolving to os.getcwd().
2032
1521
    """
2033
1522
 
2034
 
    def get_vfs_only_server(self):
 
1523
    def get_server(self):
2035
1524
        """See TestCaseWithMemoryTransport.
2036
1525
 
2037
1526
        This is useful for some tests with specific servers that need
2038
1527
        diagnostics.
2039
1528
        """
2040
 
        if self.__vfs_server is None:
2041
 
            self.__vfs_server = self.vfs_transport_factory()
2042
 
            self.__vfs_server.setUp()
2043
 
            self.addCleanup(self.__vfs_server.tearDown)
2044
 
        return self.__vfs_server
 
1529
        if self.__server is None:
 
1530
            self.__server = self.transport_server()
 
1531
            self.__server.setUp()
 
1532
            self.addCleanup(self.__server.tearDown)
 
1533
        return self.__server
2045
1534
 
2046
1535
    def make_branch_and_tree(self, relpath, format=None):
2047
1536
        """Create a branch on the transport and a tree locally.
2048
1537
 
2049
1538
        If the transport is not a LocalTransport, the Tree can't be created on
2050
 
        the transport.  In that case if the vfs_transport_factory is
2051
 
        LocalURLServer the working tree is created in the local
2052
 
        directory backing the transport, and the returned tree's branch and
2053
 
        repository will also be accessed locally. Otherwise a lightweight
2054
 
        checkout is created and returned.
 
1539
        the transport.  In that case the working tree is created in the local
 
1540
        directory, and the returned tree's branch and repository will also be
 
1541
        accessed locally.
 
1542
 
 
1543
        This will fail if the original default transport for this test
 
1544
        case wasn't backed by the working directory, as the branch won't
 
1545
        be on disk for us to open it.  
2055
1546
 
2056
1547
        :param format: The BzrDirFormat.
2057
1548
        :returns: the WorkingTree.
2065
1556
            return b.bzrdir.create_workingtree()
2066
1557
        except errors.NotLocalUrl:
2067
1558
            # We can only make working trees locally at the moment.  If the
2068
 
            # transport can't support them, then we keep the non-disk-backed
2069
 
            # branch and create a local checkout.
2070
 
            if self.vfs_transport_factory is LocalURLServer:
2071
 
                # the branch is colocated on disk, we cannot create a checkout.
2072
 
                # hopefully callers will expect this.
2073
 
                local_controldir= bzrdir.BzrDir.open(self.get_vfs_only_url(relpath))
2074
 
                return local_controldir.create_workingtree()
2075
 
            else:
2076
 
                return b.create_checkout(relpath, lightweight=True)
 
1559
            # transport can't support them, then reopen the branch on a local
 
1560
            # transport, and create the working tree there.  
 
1561
            #
 
1562
            # Possibly we should instead keep
 
1563
            # the non-disk-backed branch and create a local checkout?
 
1564
            bd = bzrdir.BzrDir.open(relpath)
 
1565
            return bd.create_workingtree()
2077
1566
 
2078
1567
    def assertIsDirectory(self, relpath, transport):
2079
1568
        """Assert that relpath within transport is a directory.
2090
1579
            self.fail("path %s is not a directory; has mode %#o"
2091
1580
                      % (relpath, mode))
2092
1581
 
2093
 
    def assertTreesEqual(self, left, right):
2094
 
        """Check that left and right have the same content and properties."""
2095
 
        # we use a tree delta to check for equality of the content, and we
2096
 
        # manually check for equality of other things such as the parents list.
2097
 
        self.assertEqual(left.get_parent_ids(), right.get_parent_ids())
2098
 
        differences = left.changes_from(right)
2099
 
        self.assertFalse(differences.has_changed(),
2100
 
            "Trees %r and %r are different: %r" % (left, right, differences))
2101
 
 
2102
1582
    def setUp(self):
2103
1583
        super(TestCaseWithTransport, self).setUp()
2104
 
        self.__vfs_server = None
 
1584
        self.__server = None
2105
1585
 
2106
1586
 
2107
1587
class ChrootedTestCase(TestCaseWithTransport):
2118
1598
 
2119
1599
    def setUp(self):
2120
1600
        super(ChrootedTestCase, self).setUp()
2121
 
        if not self.vfs_transport_factory == MemoryServer:
2122
 
            self.transport_readonly_server = HttpServer
2123
 
 
2124
 
 
2125
 
def filter_suite_by_re(suite, pattern, exclude_pattern=None,
2126
 
                       random_order=False):
2127
 
    """Create a test suite by filtering another one.
2128
 
    
2129
 
    :param suite:           the source suite
2130
 
    :param pattern:         pattern that names must match
2131
 
    :param exclude_pattern: pattern that names must not match, if any
2132
 
    :param random_order:    if True, tests in the new suite will be put in
2133
 
                            random order
2134
 
    :returns: the newly created suite
2135
 
    """ 
2136
 
    return sort_suite_by_re(suite, pattern, exclude_pattern,
2137
 
        random_order, False)
2138
 
 
2139
 
 
2140
 
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
2141
 
                     random_order=False, append_rest=True):
2142
 
    """Create a test suite by sorting another one.
2143
 
    
2144
 
    :param suite:           the source suite
2145
 
    :param pattern:         pattern that names must match in order to go
2146
 
                            first in the new suite
2147
 
    :param exclude_pattern: pattern that names must not match, if any
2148
 
    :param random_order:    if True, tests in the new suite will be put in
2149
 
                            random order
2150
 
    :param append_rest:     if False, pattern is a strict filter and not
2151
 
                            just an ordering directive
2152
 
    :returns: the newly created suite
2153
 
    """ 
2154
 
    first = []
2155
 
    second = []
 
1601
        if not self.transport_server == bzrlib.transport.memory.MemoryServer:
 
1602
            self.transport_readonly_server = bzrlib.transport.http.HttpServer
 
1603
 
 
1604
 
 
1605
def filter_suite_by_re(suite, pattern):
 
1606
    result = TestUtil.TestSuite()
2156
1607
    filter_re = re.compile(pattern)
2157
 
    if exclude_pattern is not None:
2158
 
        exclude_re = re.compile(exclude_pattern)
2159
1608
    for test in iter_suite_tests(suite):
2160
 
        test_id = test.id()
2161
 
        if exclude_pattern is None or not exclude_re.search(test_id):
2162
 
            if filter_re.search(test_id):
2163
 
                first.append(test)
2164
 
            elif append_rest:
2165
 
                second.append(test)
2166
 
    if random_order:
2167
 
        random.shuffle(first)
2168
 
        random.shuffle(second)
2169
 
    return TestUtil.TestSuite(first + second)
 
1609
        if filter_re.search(test.id()):
 
1610
            result.addTest(test)
 
1611
    return result
2170
1612
 
2171
1613
 
2172
1614
def run_suite(suite, name='test', verbose=False, pattern=".*",
2173
 
              stop_on_failure=False,
2174
 
              transport=None, lsprof_timed=None, bench_history=None,
2175
 
              matching_tests_first=None,
2176
 
              numbered_dirs=None,
2177
 
              list_only=False,
2178
 
              random_seed=None,
2179
 
              exclude_pattern=None,
2180
 
              ):
2181
 
    use_numbered_dirs = bool(numbered_dirs)
2182
 
 
 
1615
              stop_on_failure=False, keep_output=False,
 
1616
              transport=None, lsprof_timed=None, bench_history=None):
2183
1617
    TestCase._gather_lsprof_in_benchmarks = lsprof_timed
2184
 
    if numbered_dirs is not None:
2185
 
        TestCaseInTempDir.use_numbered_dirs = use_numbered_dirs
2186
1618
    if verbose:
2187
1619
        verbosity = 2
2188
1620
    else:
2190
1622
    runner = TextTestRunner(stream=sys.stdout,
2191
1623
                            descriptions=0,
2192
1624
                            verbosity=verbosity,
2193
 
                            bench_history=bench_history,
2194
 
                            use_numbered_dirs=use_numbered_dirs,
2195
 
                            list_only=list_only,
2196
 
                            )
 
1625
                            keep_output=keep_output,
 
1626
                            bench_history=bench_history)
2197
1627
    runner.stop_on_failure=stop_on_failure
2198
 
    # Initialise the random number generator and display the seed used.
2199
 
    # We convert the seed to a long to make it reuseable across invocations.
2200
 
    random_order = False
2201
 
    if random_seed is not None:
2202
 
        random_order = True
2203
 
        if random_seed == "now":
2204
 
            random_seed = long(time.time())
2205
 
        else:
2206
 
            # Convert the seed to a long if we can
2207
 
            try:
2208
 
                random_seed = long(random_seed)
2209
 
            except:
2210
 
                pass
2211
 
        runner.stream.writeln("Randomizing test order using seed %s\n" %
2212
 
            (random_seed))
2213
 
        random.seed(random_seed)
2214
 
    # Customise the list of tests if requested
2215
 
    if pattern != '.*' or exclude_pattern is not None or random_order:
2216
 
        if matching_tests_first:
2217
 
            suite = sort_suite_by_re(suite, pattern, exclude_pattern,
2218
 
                random_order)
2219
 
        else:
2220
 
            suite = filter_suite_by_re(suite, pattern, exclude_pattern,
2221
 
                random_order)
 
1628
    if pattern != '.*':
 
1629
        suite = filter_suite_by_re(suite, pattern)
2222
1630
    result = runner.run(suite)
2223
1631
    return result.wasSuccessful()
2224
1632
 
2225
1633
 
2226
1634
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
 
1635
             keep_output=False,
2227
1636
             transport=None,
2228
1637
             test_suite_factory=None,
2229
1638
             lsprof_timed=None,
2230
 
             bench_history=None,
2231
 
             matching_tests_first=None,
2232
 
             numbered_dirs=None,
2233
 
             list_only=False,
2234
 
             random_seed=None,
2235
 
             exclude_pattern=None):
 
1639
             bench_history=None):
2236
1640
    """Run the whole test suite under the enhanced runner"""
2237
1641
    # XXX: Very ugly way to do this...
2238
1642
    # Disable warning about old formats because we don't want it to disturb
2251
1655
        else:
2252
1656
            suite = test_suite_factory()
2253
1657
        return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
2254
 
                     stop_on_failure=stop_on_failure,
 
1658
                     stop_on_failure=stop_on_failure, keep_output=keep_output,
2255
1659
                     transport=transport,
2256
1660
                     lsprof_timed=lsprof_timed,
2257
 
                     bench_history=bench_history,
2258
 
                     matching_tests_first=matching_tests_first,
2259
 
                     numbered_dirs=numbered_dirs,
2260
 
                     list_only=list_only,
2261
 
                     random_seed=random_seed,
2262
 
                     exclude_pattern=exclude_pattern)
 
1661
                     bench_history=bench_history)
2263
1662
    finally:
2264
1663
        default_transport = old_transport
2265
1664
 
2272
1671
    """
2273
1672
    testmod_names = [
2274
1673
                   'bzrlib.tests.test_ancestry',
2275
 
                   'bzrlib.tests.test_annotate',
2276
1674
                   'bzrlib.tests.test_api',
2277
1675
                   'bzrlib.tests.test_atomicfile',
2278
1676
                   'bzrlib.tests.test_bad_files',
2279
1677
                   'bzrlib.tests.test_branch',
2280
 
                   'bzrlib.tests.test_branchbuilder',
2281
 
                   'bzrlib.tests.test_bugtracker',
2282
1678
                   'bzrlib.tests.test_bundle',
2283
1679
                   'bzrlib.tests.test_bzrdir',
2284
1680
                   'bzrlib.tests.test_cache_utf8',
2285
 
                   'bzrlib.tests.test_commands',
 
1681
                   'bzrlib.tests.test_command',
2286
1682
                   'bzrlib.tests.test_commit',
2287
1683
                   'bzrlib.tests.test_commit_merge',
2288
1684
                   'bzrlib.tests.test_config',
2289
1685
                   'bzrlib.tests.test_conflicts',
2290
 
                   'bzrlib.tests.test_pack',
2291
 
                   'bzrlib.tests.test_counted_lock',
2292
1686
                   'bzrlib.tests.test_decorators',
2293
 
                   'bzrlib.tests.test_delta',
2294
 
                   'bzrlib.tests.test_deprecated_graph',
2295
1687
                   'bzrlib.tests.test_diff',
2296
 
                   'bzrlib.tests.test_dirstate',
 
1688
                   'bzrlib.tests.test_doc_generate',
2297
1689
                   'bzrlib.tests.test_errors',
2298
1690
                   'bzrlib.tests.test_escaped_store',
2299
 
                   'bzrlib.tests.test_extract',
2300
1691
                   'bzrlib.tests.test_fetch',
2301
1692
                   'bzrlib.tests.test_ftp_transport',
2302
 
                   'bzrlib.tests.test_generate_docs',
2303
 
                   'bzrlib.tests.test_generate_ids',
2304
 
                   'bzrlib.tests.test_globbing',
2305
1693
                   'bzrlib.tests.test_gpg',
2306
1694
                   'bzrlib.tests.test_graph',
2307
1695
                   'bzrlib.tests.test_hashcache',
2308
 
                   'bzrlib.tests.test_help',
2309
 
                   'bzrlib.tests.test_hooks',
2310
1696
                   'bzrlib.tests.test_http',
2311
1697
                   'bzrlib.tests.test_http_response',
2312
 
                   'bzrlib.tests.test_https_ca_bundle',
2313
1698
                   'bzrlib.tests.test_identitymap',
2314
1699
                   'bzrlib.tests.test_ignores',
2315
 
                   'bzrlib.tests.test_info',
2316
1700
                   'bzrlib.tests.test_inv',
2317
1701
                   'bzrlib.tests.test_knit',
2318
1702
                   'bzrlib.tests.test_lazy_import',
2320
1704
                   'bzrlib.tests.test_lockdir',
2321
1705
                   'bzrlib.tests.test_lockable_files',
2322
1706
                   'bzrlib.tests.test_log',
2323
 
                   'bzrlib.tests.test_lsprof',
2324
1707
                   'bzrlib.tests.test_memorytree',
2325
1708
                   'bzrlib.tests.test_merge',
2326
1709
                   'bzrlib.tests.test_merge3',
2327
1710
                   'bzrlib.tests.test_merge_core',
2328
 
                   'bzrlib.tests.test_merge_directive',
2329
1711
                   'bzrlib.tests.test_missing',
2330
1712
                   'bzrlib.tests.test_msgeditor',
2331
1713
                   'bzrlib.tests.test_nonascii',
2332
1714
                   'bzrlib.tests.test_options',
2333
1715
                   'bzrlib.tests.test_osutils',
2334
 
                   'bzrlib.tests.test_osutils_encodings',
2335
1716
                   'bzrlib.tests.test_patch',
2336
1717
                   'bzrlib.tests.test_patches',
2337
1718
                   'bzrlib.tests.test_permissions',
2339
1720
                   'bzrlib.tests.test_progress',
2340
1721
                   'bzrlib.tests.test_reconcile',
2341
1722
                   'bzrlib.tests.test_registry',
2342
 
                   'bzrlib.tests.test_remote',
2343
1723
                   'bzrlib.tests.test_repository',
2344
1724
                   'bzrlib.tests.test_revert',
2345
1725
                   'bzrlib.tests.test_revision',
2350
1730
                   'bzrlib.tests.test_selftest',
2351
1731
                   'bzrlib.tests.test_setup',
2352
1732
                   'bzrlib.tests.test_sftp_transport',
2353
 
                   'bzrlib.tests.test_smart',
2354
1733
                   'bzrlib.tests.test_smart_add',
2355
1734
                   'bzrlib.tests.test_smart_transport',
2356
 
                   'bzrlib.tests.test_smtp_connection',
2357
1735
                   'bzrlib.tests.test_source',
2358
 
                   'bzrlib.tests.test_ssh_transport',
2359
1736
                   'bzrlib.tests.test_status',
2360
1737
                   'bzrlib.tests.test_store',
2361
 
                   'bzrlib.tests.test_strace',
2362
 
                   'bzrlib.tests.test_subsume',
2363
1738
                   'bzrlib.tests.test_symbol_versioning',
2364
 
                   'bzrlib.tests.test_tag',
2365
1739
                   'bzrlib.tests.test_testament',
2366
1740
                   'bzrlib.tests.test_textfile',
2367
1741
                   'bzrlib.tests.test_textmerge',
2368
 
                   'bzrlib.tests.test_timestamp',
2369
1742
                   'bzrlib.tests.test_trace',
2370
1743
                   'bzrlib.tests.test_transactions',
2371
1744
                   'bzrlib.tests.test_transform',
2383
1756
                   'bzrlib.tests.test_weave',
2384
1757
                   'bzrlib.tests.test_whitebox',
2385
1758
                   'bzrlib.tests.test_workingtree',
2386
 
                   'bzrlib.tests.test_workingtree_4',
2387
 
                   'bzrlib.tests.test_wsgi',
2388
1759
                   'bzrlib.tests.test_xml',
2389
1760
                   ]
2390
1761
    test_transport_implementations = [
2394
1765
    suite = TestUtil.TestSuite()
2395
1766
    loader = TestUtil.TestLoader()
2396
1767
    suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2397
 
    from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
 
1768
    from bzrlib.transport import TransportTestProviderAdapter
2398
1769
    adapter = TransportTestProviderAdapter()
2399
1770
    adapt_modules(test_transport_implementations, adapter, loader, suite)
2400
1771
    for package in packages_to_test():
2409
1780
            raise
2410
1781
    for name, plugin in bzrlib.plugin.all_plugins().items():
2411
1782
        if getattr(plugin, 'test_suite', None) is not None:
2412
 
            default_encoding = sys.getdefaultencoding()
2413
 
            try:
2414
 
                plugin_suite = plugin.test_suite()
2415
 
            except ImportError, e:
2416
 
                bzrlib.trace.warning(
2417
 
                    'Unable to test plugin "%s": %s', name, e)
2418
 
            else:
2419
 
                suite.addTest(plugin_suite)
2420
 
            if default_encoding != sys.getdefaultencoding():
2421
 
                bzrlib.trace.warning(
2422
 
                    'Plugin "%s" tried to reset default encoding to: %s', name,
2423
 
                    sys.getdefaultencoding())
2424
 
                reload(sys)
2425
 
                sys.setdefaultencoding(default_encoding)
 
1783
            suite.addTest(plugin.test_suite())
2426
1784
    return suite
2427
1785
 
2428
1786
 
2430
1788
    """Adapt the modules in mods_list using adapter and add to suite."""
2431
1789
    for test in iter_suite_tests(loader.loadTestsFromModuleNames(mods_list)):
2432
1790
        suite.addTests(adapter.adapt(test))
2433
 
 
2434
 
 
2435
 
def _rmtree_temp_dir(dirname):
2436
 
    # If LANG=C we probably have created some bogus paths
2437
 
    # which rmtree(unicode) will fail to delete
2438
 
    # so make sure we are using rmtree(str) to delete everything
2439
 
    # except on win32, where rmtree(str) will fail
2440
 
    # since it doesn't have the property of byte-stream paths
2441
 
    # (they are either ascii or mbcs)
2442
 
    if sys.platform == 'win32':
2443
 
        # make sure we are using the unicode win32 api
2444
 
        dirname = unicode(dirname)
2445
 
    else:
2446
 
        dirname = dirname.encode(sys.getfilesystemencoding())
2447
 
    try:
2448
 
        osutils.rmtree(dirname)
2449
 
    except OSError, e:
2450
 
        if sys.platform == 'win32' and e.errno == errno.EACCES:
2451
 
            print >>sys.stderr, ('Permission denied: '
2452
 
                                 'unable to remove testing dir '
2453
 
                                 '%s' % os.path.basename(dirname))
2454
 
        else:
2455
 
            raise
2456
 
 
2457
 
 
2458
 
def clean_selftest_output(root=None, quiet=False):
2459
 
    """Remove all selftest output directories from root directory.
2460
 
 
2461
 
    :param  root:   root directory for clean
2462
 
                    (if ommitted or None then clean current directory).
2463
 
    :param  quiet:  suppress report about deleting directories
2464
 
    """
2465
 
    import re
2466
 
    re_dir = re.compile(r'''test\d\d\d\d\.tmp''')
2467
 
    if root is None:
2468
 
        root = u'.'
2469
 
    for i in os.listdir(root):
2470
 
        if os.path.isdir(i) and re_dir.match(i):
2471
 
            if not quiet:
2472
 
                print 'delete directory:', i
2473
 
            _rmtree_temp_dir(i)
2474
 
 
2475
 
 
2476
 
class Feature(object):
2477
 
    """An operating system Feature."""
2478
 
 
2479
 
    def __init__(self):
2480
 
        self._available = None
2481
 
 
2482
 
    def available(self):
2483
 
        """Is the feature available?
2484
 
 
2485
 
        :return: True if the feature is available.
2486
 
        """
2487
 
        if self._available is None:
2488
 
            self._available = self._probe()
2489
 
        return self._available
2490
 
 
2491
 
    def _probe(self):
2492
 
        """Implement this method in concrete features.
2493
 
 
2494
 
        :return: True if the feature is available.
2495
 
        """
2496
 
        raise NotImplementedError
2497
 
 
2498
 
    def __str__(self):
2499
 
        if getattr(self, 'feature_name', None):
2500
 
            return self.feature_name()
2501
 
        return self.__class__.__name__
2502
 
 
2503
 
 
2504
 
class TestScenarioApplier(object):
2505
 
    """A tool to apply scenarios to tests."""
2506
 
 
2507
 
    def adapt(self, test):
2508
 
        """Return a TestSuite containing a copy of test for each scenario."""
2509
 
        result = unittest.TestSuite()
2510
 
        for scenario in self.scenarios:
2511
 
            result.addTest(self.adapt_test_to_scenario(test, scenario))
2512
 
        return result
2513
 
 
2514
 
    def adapt_test_to_scenario(self, test, scenario):
2515
 
        """Copy test and apply scenario to it.
2516
 
 
2517
 
        :param test: A test to adapt.
2518
 
        :param scenario: A tuple describing the scenarion.
2519
 
            The first element of the tuple is the new test id.
2520
 
            The second element is a dict containing attributes to set on the
2521
 
            test.
2522
 
        :return: The adapted test.
2523
 
        """
2524
 
        from copy import deepcopy
2525
 
        new_test = deepcopy(test)
2526
 
        for name, value in scenario[1].items():
2527
 
            setattr(new_test, name, value)
2528
 
        new_id = "%s(%s)" % (new_test.id(), scenario[0])
2529
 
        new_test.id = lambda: new_id
2530
 
        return new_test