1
# Copyright (C) 2005-2011 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
"""Tests for the test framework."""
19
from cStringIO import StringIO
29
from testtools import (
30
ExtendedToOriginalDecorator,
32
__version__ as testtools_version,
34
from testtools.content import Content
35
from testtools.content_type import ContentType
36
from testtools.matchers import (
40
import testtools.testresult.doubles
60
from bzrlib.repofmt import (
63
from bzrlib.symbol_versioning import (
68
from bzrlib.tests import (
74
from bzrlib.trace import note, mutter
75
from bzrlib.transport import memory
78
def _test_ids(test_suite):
79
"""Get the ids for the tests in a test suite."""
80
return [t.id() for t in tests.iter_suite_tests(test_suite)]
83
class MetaTestLog(tests.TestCase):
85
def test_logging(self):
86
"""Test logs are captured when a test fails."""
87
self.log('a test message')
88
details = self.getDetails()
90
self.assertThat(log.content_type, Equals(ContentType(
91
"text", "plain", {"charset": "utf8"})))
92
self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
93
self.assertThat(self.get_log(),
94
DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
97
class TestTreeShape(tests.TestCaseInTempDir):
99
def test_unicode_paths(self):
100
self.requireFeature(features.UnicodeFilenameFeature)
102
filename = u'hell\u00d8'
103
self.build_tree_contents([(filename, 'contents of hello')])
104
self.assertPathExists(filename)
107
class TestClassesAvailable(tests.TestCase):
108
"""As a convenience we expose Test* classes from bzrlib.tests"""
110
def test_test_case(self):
111
from bzrlib.tests import TestCase
113
def test_test_loader(self):
114
from bzrlib.tests import TestLoader
116
def test_test_suite(self):
117
from bzrlib.tests import TestSuite
120
class TestTransportScenarios(tests.TestCase):
121
"""A group of tests that test the transport implementation adaption core.
123
This is a meta test that the tests are applied to all available
126
This will be generalised in the future which is why it is in this
127
test file even though it is specific to transport tests at the moment.
130
def test_get_transport_permutations(self):
131
# this checks that get_test_permutations defined by the module is
132
# called by the get_transport_test_permutations function.
133
class MockModule(object):
134
def get_test_permutations(self):
135
return sample_permutation
136
sample_permutation = [(1,2), (3,4)]
137
from bzrlib.tests.per_transport import get_transport_test_permutations
138
self.assertEqual(sample_permutation,
139
get_transport_test_permutations(MockModule()))
141
def test_scenarios_include_all_modules(self):
142
# this checks that the scenario generator returns as many permutations
143
# as there are in all the registered transport modules - we assume if
144
# this matches its probably doing the right thing especially in
145
# combination with the tests for setting the right classes below.
146
from bzrlib.tests.per_transport import transport_test_permutations
147
from bzrlib.transport import _get_transport_modules
148
modules = _get_transport_modules()
149
permutation_count = 0
150
for module in modules:
152
permutation_count += len(reduce(getattr,
153
(module + ".get_test_permutations").split('.')[1:],
154
__import__(module))())
155
except errors.DependencyNotPresent:
157
scenarios = transport_test_permutations()
158
self.assertEqual(permutation_count, len(scenarios))
160
def test_scenarios_include_transport_class(self):
161
# This test used to know about all the possible transports and the
162
# order they were returned but that seems overly brittle (mbp
164
from bzrlib.tests.per_transport import transport_test_permutations
165
scenarios = transport_test_permutations()
166
# there are at least that many builtin transports
167
self.assertTrue(len(scenarios) > 6)
168
one_scenario = scenarios[0]
169
self.assertIsInstance(one_scenario[0], str)
170
self.assertTrue(issubclass(one_scenario[1]["transport_class"],
171
bzrlib.transport.Transport))
172
self.assertTrue(issubclass(one_scenario[1]["transport_server"],
173
bzrlib.transport.Server))
176
class TestBranchScenarios(tests.TestCase):
178
def test_scenarios(self):
179
# check that constructor parameters are passed through to the adapted
181
from bzrlib.tests.per_branch import make_scenarios
184
formats = [("c", "C"), ("d", "D")]
185
scenarios = make_scenarios(server1, server2, formats)
186
self.assertEqual(2, len(scenarios))
189
{'branch_format': 'c',
190
'bzrdir_format': 'C',
191
'transport_readonly_server': 'b',
192
'transport_server': 'a'}),
194
{'branch_format': 'd',
195
'bzrdir_format': 'D',
196
'transport_readonly_server': 'b',
197
'transport_server': 'a'})],
201
class TestBzrDirScenarios(tests.TestCase):
203
def test_scenarios(self):
204
# check that constructor parameters are passed through to the adapted
206
from bzrlib.tests.per_controldir import make_scenarios
211
scenarios = make_scenarios(vfs_factory, server1, server2, formats)
214
{'bzrdir_format': 'c',
215
'transport_readonly_server': 'b',
216
'transport_server': 'a',
217
'vfs_transport_factory': 'v'}),
219
{'bzrdir_format': 'd',
220
'transport_readonly_server': 'b',
221
'transport_server': 'a',
222
'vfs_transport_factory': 'v'})],
226
class TestRepositoryScenarios(tests.TestCase):
228
def test_formats_to_scenarios(self):
229
from bzrlib.tests.per_repository import formats_to_scenarios
230
formats = [("(c)", remote.RemoteRepositoryFormat()),
231
("(d)", repository.format_registry.get(
232
'Bazaar repository format 2a (needs bzr 1.16 or later)\n'))]
233
no_vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
235
vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
236
vfs_transport_factory="vfs")
237
# no_vfs generate scenarios without vfs_transport_factory
239
('RemoteRepositoryFormat(c)',
240
{'bzrdir_format': remote.RemoteBzrDirFormat(),
241
'repository_format': remote.RemoteRepositoryFormat(),
242
'transport_readonly_server': 'readonly',
243
'transport_server': 'server'}),
244
('RepositoryFormat2a(d)',
245
{'bzrdir_format': bzrdir.BzrDirMetaFormat1(),
246
'repository_format': groupcompress_repo.RepositoryFormat2a(),
247
'transport_readonly_server': 'readonly',
248
'transport_server': 'server'})]
249
self.assertEqual(expected, no_vfs_scenarios)
251
('RemoteRepositoryFormat(c)',
252
{'bzrdir_format': remote.RemoteBzrDirFormat(),
253
'repository_format': remote.RemoteRepositoryFormat(),
254
'transport_readonly_server': 'readonly',
255
'transport_server': 'server',
256
'vfs_transport_factory': 'vfs'}),
257
('RepositoryFormat2a(d)',
258
{'bzrdir_format': bzrdir.BzrDirMetaFormat1(),
259
'repository_format': groupcompress_repo.RepositoryFormat2a(),
260
'transport_readonly_server': 'readonly',
261
'transport_server': 'server',
262
'vfs_transport_factory': 'vfs'})],
266
class TestTestScenarioApplication(tests.TestCase):
267
"""Tests for the test adaption facilities."""
269
def test_apply_scenario(self):
270
from bzrlib.tests import apply_scenario
271
input_test = TestTestScenarioApplication("test_apply_scenario")
272
# setup two adapted tests
273
adapted_test1 = apply_scenario(input_test,
275
{"bzrdir_format":"bzr_format",
276
"repository_format":"repo_fmt",
277
"transport_server":"transport_server",
278
"transport_readonly_server":"readonly-server"}))
279
adapted_test2 = apply_scenario(input_test,
280
("new id 2", {"bzrdir_format":None}))
281
# input_test should have been altered.
282
self.assertRaises(AttributeError, getattr, input_test, "bzrdir_format")
283
# the new tests are mutually incompatible, ensuring it has
284
# made new ones, and unspecified elements in the scenario
285
# should not have been altered.
286
self.assertEqual("bzr_format", adapted_test1.bzrdir_format)
287
self.assertEqual("repo_fmt", adapted_test1.repository_format)
288
self.assertEqual("transport_server", adapted_test1.transport_server)
289
self.assertEqual("readonly-server",
290
adapted_test1.transport_readonly_server)
292
"bzrlib.tests.test_selftest.TestTestScenarioApplication."
293
"test_apply_scenario(new id)",
295
self.assertEqual(None, adapted_test2.bzrdir_format)
297
"bzrlib.tests.test_selftest.TestTestScenarioApplication."
298
"test_apply_scenario(new id 2)",
302
class TestInterRepositoryScenarios(tests.TestCase):
304
def test_scenarios(self):
305
# check that constructor parameters are passed through to the adapted
307
from bzrlib.tests.per_interrepository import make_scenarios
310
formats = [("C0", "C1", "C2", "C3"), ("D0", "D1", "D2", "D3")]
311
scenarios = make_scenarios(server1, server2, formats)
314
{'repository_format': 'C1',
315
'repository_format_to': 'C2',
316
'transport_readonly_server': 'b',
317
'transport_server': 'a',
318
'extra_setup': 'C3'}),
320
{'repository_format': 'D1',
321
'repository_format_to': 'D2',
322
'transport_readonly_server': 'b',
323
'transport_server': 'a',
324
'extra_setup': 'D3'})],
328
class TestWorkingTreeScenarios(tests.TestCase):
330
def test_scenarios(self):
331
# check that constructor parameters are passed through to the adapted
333
from bzrlib.tests.per_workingtree import make_scenarios
336
formats = [workingtree_4.WorkingTreeFormat4(),
337
workingtree_3.WorkingTreeFormat3(),]
338
scenarios = make_scenarios(server1, server2, formats)
340
('WorkingTreeFormat4',
341
{'bzrdir_format': formats[0]._matchingbzrdir,
342
'transport_readonly_server': 'b',
343
'transport_server': 'a',
344
'workingtree_format': formats[0]}),
345
('WorkingTreeFormat3',
346
{'bzrdir_format': formats[1]._matchingbzrdir,
347
'transport_readonly_server': 'b',
348
'transport_server': 'a',
349
'workingtree_format': formats[1]})],
353
class TestTreeScenarios(tests.TestCase):
355
def test_scenarios(self):
356
# the tree implementation scenario generator is meant to setup one
357
# instance for each working tree format, and one additional instance
358
# that will use the default wt format, but create a revision tree for
359
# the tests. this means that the wt ones should have the
360
# workingtree_to_test_tree attribute set to 'return_parameter' and the
361
# revision one set to revision_tree_from_workingtree.
363
from bzrlib.tests.per_tree import (
364
_dirstate_tree_from_workingtree,
369
revision_tree_from_workingtree
373
formats = [workingtree_4.WorkingTreeFormat4(),
374
workingtree_3.WorkingTreeFormat3(),]
375
scenarios = make_scenarios(server1, server2, formats)
376
self.assertEqual(7, len(scenarios))
377
default_wt_format = workingtree.format_registry.get_default()
378
wt4_format = workingtree_4.WorkingTreeFormat4()
379
wt5_format = workingtree_4.WorkingTreeFormat5()
380
expected_scenarios = [
381
('WorkingTreeFormat4',
382
{'bzrdir_format': formats[0]._matchingbzrdir,
383
'transport_readonly_server': 'b',
384
'transport_server': 'a',
385
'workingtree_format': formats[0],
386
'_workingtree_to_test_tree': return_parameter,
388
('WorkingTreeFormat3',
389
{'bzrdir_format': formats[1]._matchingbzrdir,
390
'transport_readonly_server': 'b',
391
'transport_server': 'a',
392
'workingtree_format': formats[1],
393
'_workingtree_to_test_tree': return_parameter,
396
{'_workingtree_to_test_tree': revision_tree_from_workingtree,
397
'bzrdir_format': default_wt_format._matchingbzrdir,
398
'transport_readonly_server': 'b',
399
'transport_server': 'a',
400
'workingtree_format': default_wt_format,
402
('DirStateRevisionTree,WT4',
403
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
404
'bzrdir_format': wt4_format._matchingbzrdir,
405
'transport_readonly_server': 'b',
406
'transport_server': 'a',
407
'workingtree_format': wt4_format,
409
('DirStateRevisionTree,WT5',
410
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
411
'bzrdir_format': wt5_format._matchingbzrdir,
412
'transport_readonly_server': 'b',
413
'transport_server': 'a',
414
'workingtree_format': wt5_format,
417
{'_workingtree_to_test_tree': preview_tree_pre,
418
'bzrdir_format': default_wt_format._matchingbzrdir,
419
'transport_readonly_server': 'b',
420
'transport_server': 'a',
421
'workingtree_format': default_wt_format}),
423
{'_workingtree_to_test_tree': preview_tree_post,
424
'bzrdir_format': default_wt_format._matchingbzrdir,
425
'transport_readonly_server': 'b',
426
'transport_server': 'a',
427
'workingtree_format': default_wt_format}),
429
self.assertEqual(expected_scenarios, scenarios)
432
class TestInterTreeScenarios(tests.TestCase):
433
"""A group of tests that test the InterTreeTestAdapter."""
435
def test_scenarios(self):
436
# check that constructor parameters are passed through to the adapted
438
# for InterTree tests we want the machinery to bring up two trees in
439
# each instance: the base one, and the one we are interacting with.
440
# because each optimiser can be direction specific, we need to test
441
# each optimiser in its chosen direction.
442
# unlike the TestProviderAdapter we dont want to automatically add a
443
# parameterized one for WorkingTree - the optimisers will tell us what
445
from bzrlib.tests.per_tree import (
448
from bzrlib.tests.per_intertree import (
451
from bzrlib.workingtree_3 import WorkingTreeFormat3
452
from bzrlib.workingtree_4 import WorkingTreeFormat4
453
input_test = TestInterTreeScenarios(
457
format1 = WorkingTreeFormat4()
458
format2 = WorkingTreeFormat3()
459
formats = [("1", str, format1, format2, "converter1"),
460
("2", int, format2, format1, "converter2")]
461
scenarios = make_scenarios(server1, server2, formats)
462
self.assertEqual(2, len(scenarios))
463
expected_scenarios = [
465
"bzrdir_format": format1._matchingbzrdir,
466
"intertree_class": formats[0][1],
467
"workingtree_format": formats[0][2],
468
"workingtree_format_to": formats[0][3],
469
"mutable_trees_to_test_trees": formats[0][4],
470
"_workingtree_to_test_tree": return_parameter,
471
"transport_server": server1,
472
"transport_readonly_server": server2,
475
"bzrdir_format": format2._matchingbzrdir,
476
"intertree_class": formats[1][1],
477
"workingtree_format": formats[1][2],
478
"workingtree_format_to": formats[1][3],
479
"mutable_trees_to_test_trees": formats[1][4],
480
"_workingtree_to_test_tree": return_parameter,
481
"transport_server": server1,
482
"transport_readonly_server": server2,
485
self.assertEqual(scenarios, expected_scenarios)
488
class TestTestCaseInTempDir(tests.TestCaseInTempDir):
490
def test_home_is_not_working(self):
491
self.assertNotEqual(self.test_dir, self.test_home_dir)
492
cwd = osutils.getcwd()
493
self.assertIsSameRealPath(self.test_dir, cwd)
494
self.assertIsSameRealPath(self.test_home_dir, os.environ['HOME'])
496
def test_assertEqualStat_equal(self):
497
from bzrlib.tests.test_dirstate import _FakeStat
498
self.build_tree(["foo"])
499
real = os.lstat("foo")
500
fake = _FakeStat(real.st_size, real.st_mtime, real.st_ctime,
501
real.st_dev, real.st_ino, real.st_mode)
502
self.assertEqualStat(real, fake)
504
def test_assertEqualStat_notequal(self):
505
self.build_tree(["foo", "longname"])
506
self.assertRaises(AssertionError, self.assertEqualStat,
507
os.lstat("foo"), os.lstat("longname"))
509
def test_failUnlessExists(self):
510
"""Deprecated failUnlessExists and failIfExists"""
511
self.applyDeprecated(
512
deprecated_in((2, 4)),
513
self.failUnlessExists, '.')
514
self.build_tree(['foo/', 'foo/bar'])
515
self.applyDeprecated(
516
deprecated_in((2, 4)),
517
self.failUnlessExists, 'foo/bar')
518
self.applyDeprecated(
519
deprecated_in((2, 4)),
520
self.failIfExists, 'foo/foo')
522
def test_assertPathExists(self):
523
self.assertPathExists('.')
524
self.build_tree(['foo/', 'foo/bar'])
525
self.assertPathExists('foo/bar')
526
self.assertPathDoesNotExist('foo/foo')
529
class TestTestCaseWithMemoryTransport(tests.TestCaseWithMemoryTransport):
531
def test_home_is_non_existant_dir_under_root(self):
532
"""The test_home_dir for TestCaseWithMemoryTransport is missing.
534
This is because TestCaseWithMemoryTransport is for tests that do not
535
need any disk resources: they should be hooked into bzrlib in such a
536
way that no global settings are being changed by the test (only a
537
few tests should need to do that), and having a missing dir as home is
538
an effective way to ensure that this is the case.
540
self.assertIsSameRealPath(
541
self.TEST_ROOT + "/MemoryTransportMissingHomeDir",
543
self.assertIsSameRealPath(self.test_home_dir, os.environ['HOME'])
545
def test_cwd_is_TEST_ROOT(self):
546
self.assertIsSameRealPath(self.test_dir, self.TEST_ROOT)
547
cwd = osutils.getcwd()
548
self.assertIsSameRealPath(self.test_dir, cwd)
550
def test_BZR_HOME_and_HOME_are_bytestrings(self):
551
"""The $BZR_HOME and $HOME environment variables should not be unicode.
553
See https://bugs.launchpad.net/bzr/+bug/464174
555
self.assertIsInstance(os.environ['BZR_HOME'], str)
556
self.assertIsInstance(os.environ['HOME'], str)
558
def test_make_branch_and_memory_tree(self):
559
"""In TestCaseWithMemoryTransport we should not make the branch on disk.
561
This is hard to comprehensively robustly test, so we settle for making
562
a branch and checking no directory was created at its relpath.
564
tree = self.make_branch_and_memory_tree('dir')
565
# Guard against regression into MemoryTransport leaking
566
# files to disk instead of keeping them in memory.
567
self.assertFalse(osutils.lexists('dir'))
568
self.assertIsInstance(tree, memorytree.MemoryTree)
570
def test_make_branch_and_memory_tree_with_format(self):
571
"""make_branch_and_memory_tree should accept a format option."""
572
format = bzrdir.BzrDirMetaFormat1()
573
format.repository_format = repository.format_registry.get_default()
574
tree = self.make_branch_and_memory_tree('dir', format=format)
575
# Guard against regression into MemoryTransport leaking
576
# files to disk instead of keeping them in memory.
577
self.assertFalse(osutils.lexists('dir'))
578
self.assertIsInstance(tree, memorytree.MemoryTree)
579
self.assertEqual(format.repository_format.__class__,
580
tree.branch.repository._format.__class__)
582
def test_make_branch_builder(self):
583
builder = self.make_branch_builder('dir')
584
self.assertIsInstance(builder, branchbuilder.BranchBuilder)
585
# Guard against regression into MemoryTransport leaking
586
# files to disk instead of keeping them in memory.
587
self.assertFalse(osutils.lexists('dir'))
589
def test_make_branch_builder_with_format(self):
590
# Use a repo layout that doesn't conform to a 'named' layout, to ensure
591
# that the format objects are used.
592
format = bzrdir.BzrDirMetaFormat1()
593
repo_format = repository.format_registry.get_default()
594
format.repository_format = repo_format
595
builder = self.make_branch_builder('dir', format=format)
596
the_branch = builder.get_branch()
597
# Guard against regression into MemoryTransport leaking
598
# files to disk instead of keeping them in memory.
599
self.assertFalse(osutils.lexists('dir'))
600
self.assertEqual(format.repository_format.__class__,
601
the_branch.repository._format.__class__)
602
self.assertEqual(repo_format.get_format_string(),
603
self.get_transport().get_bytes(
604
'dir/.bzr/repository/format'))
606
def test_make_branch_builder_with_format_name(self):
607
builder = self.make_branch_builder('dir', format='knit')
608
the_branch = builder.get_branch()
609
# Guard against regression into MemoryTransport leaking
610
# files to disk instead of keeping them in memory.
611
self.assertFalse(osutils.lexists('dir'))
612
dir_format = bzrdir.format_registry.make_bzrdir('knit')
613
self.assertEqual(dir_format.repository_format.__class__,
614
the_branch.repository._format.__class__)
615
self.assertEqual('Bazaar-NG Knit Repository Format 1',
616
self.get_transport().get_bytes(
617
'dir/.bzr/repository/format'))
619
def test_dangling_locks_cause_failures(self):
620
class TestDanglingLock(tests.TestCaseWithMemoryTransport):
621
def test_function(self):
622
t = self.get_transport('.')
623
l = lockdir.LockDir(t, 'lock')
626
test = TestDanglingLock('test_function')
628
total_failures = result.errors + result.failures
629
if self._lock_check_thorough:
630
self.assertEqual(1, len(total_failures))
632
# When _lock_check_thorough is disabled, then we don't trigger a
634
self.assertEqual(0, len(total_failures))
637
class TestTestCaseWithTransport(tests.TestCaseWithTransport):
638
"""Tests for the convenience functions TestCaseWithTransport introduces."""
640
def test_get_readonly_url_none(self):
641
from bzrlib.transport.readonly import ReadonlyTransportDecorator
642
self.vfs_transport_factory = memory.MemoryServer
643
self.transport_readonly_server = None
644
# calling get_readonly_transport() constructs a decorator on the url
646
url = self.get_readonly_url()
647
url2 = self.get_readonly_url('foo/bar')
648
t = transport.get_transport(url)
649
t2 = transport.get_transport(url2)
650
self.assertIsInstance(t, ReadonlyTransportDecorator)
651
self.assertIsInstance(t2, ReadonlyTransportDecorator)
652
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
654
def test_get_readonly_url_http(self):
655
from bzrlib.tests.http_server import HttpServer
656
from bzrlib.transport.http import HttpTransportBase
657
self.transport_server = test_server.LocalURLServer
658
self.transport_readonly_server = HttpServer
659
# calling get_readonly_transport() gives us a HTTP server instance.
660
url = self.get_readonly_url()
661
url2 = self.get_readonly_url('foo/bar')
662
# the transport returned may be any HttpTransportBase subclass
663
t = transport.get_transport(url)
664
t2 = transport.get_transport(url2)
665
self.assertIsInstance(t, HttpTransportBase)
666
self.assertIsInstance(t2, HttpTransportBase)
667
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
669
def test_is_directory(self):
670
"""Test assertIsDirectory assertion"""
671
t = self.get_transport()
672
self.build_tree(['a_dir/', 'a_file'], transport=t)
673
self.assertIsDirectory('a_dir', t)
674
self.assertRaises(AssertionError, self.assertIsDirectory, 'a_file', t)
675
self.assertRaises(AssertionError, self.assertIsDirectory, 'not_here', t)
677
def test_make_branch_builder(self):
678
builder = self.make_branch_builder('dir')
679
rev_id = builder.build_commit()
680
self.assertPathExists('dir')
681
a_dir = bzrdir.BzrDir.open('dir')
682
self.assertRaises(errors.NoWorkingTree, a_dir.open_workingtree)
683
a_branch = a_dir.open_branch()
684
builder_branch = builder.get_branch()
685
self.assertEqual(a_branch.base, builder_branch.base)
686
self.assertEqual((1, rev_id), builder_branch.last_revision_info())
687
self.assertEqual((1, rev_id), a_branch.last_revision_info())
690
class TestTestCaseTransports(tests.TestCaseWithTransport):
693
super(TestTestCaseTransports, self).setUp()
694
self.vfs_transport_factory = memory.MemoryServer
696
def test_make_bzrdir_preserves_transport(self):
697
t = self.get_transport()
698
result_bzrdir = self.make_bzrdir('subdir')
699
self.assertIsInstance(result_bzrdir.transport,
700
memory.MemoryTransport)
701
# should not be on disk, should only be in memory
702
self.assertPathDoesNotExist('subdir')
705
class TestChrootedTest(tests.ChrootedTestCase):
707
def test_root_is_root(self):
708
t = transport.get_transport(self.get_readonly_url())
710
self.assertEqual(url, t.clone('..').base)
713
class TestProfileResult(tests.TestCase):
715
def test_profiles_tests(self):
716
self.requireFeature(features.lsprof_feature)
717
terminal = testtools.testresult.doubles.ExtendedTestResult()
718
result = tests.ProfileResult(terminal)
719
class Sample(tests.TestCase):
721
self.sample_function()
722
def sample_function(self):
726
case = terminal._events[0][1]
727
self.assertLength(1, case._benchcalls)
728
# We must be able to unpack it as the test reporting code wants
729
(_, _, _), stats = case._benchcalls[0]
730
self.assertTrue(callable(stats.pprint))
733
class TestTestResult(tests.TestCase):
735
def check_timing(self, test_case, expected_re):
736
result = bzrlib.tests.TextTestResult(self._log_file,
740
capture = testtools.testresult.doubles.ExtendedTestResult()
741
test_case.run(MultiTestResult(result, capture))
742
run_case = capture._events[0][1]
743
timed_string = result._testTimeString(run_case)
744
self.assertContainsRe(timed_string, expected_re)
746
def test_test_reporting(self):
747
class ShortDelayTestCase(tests.TestCase):
748
def test_short_delay(self):
750
def test_short_benchmark(self):
751
self.time(time.sleep, 0.003)
752
self.check_timing(ShortDelayTestCase('test_short_delay'),
754
# if a benchmark time is given, we now show just that time followed by
756
self.check_timing(ShortDelayTestCase('test_short_benchmark'),
759
def test_unittest_reporting_unittest_class(self):
760
# getting the time from a non-bzrlib test works ok
761
class ShortDelayTestCase(unittest.TestCase):
762
def test_short_delay(self):
764
self.check_timing(ShortDelayTestCase('test_short_delay'),
767
def _time_hello_world_encoding(self):
768
"""Profile two sleep calls
770
This is used to exercise the test framework.
772
self.time(unicode, 'hello', errors='replace')
773
self.time(unicode, 'world', errors='replace')
775
def test_lsprofiling(self):
776
"""Verbose test result prints lsprof statistics from test cases."""
777
self.requireFeature(features.lsprof_feature)
778
result_stream = StringIO()
779
result = bzrlib.tests.VerboseTestResult(
784
# we want profile a call of some sort and check it is output by
785
# addSuccess. We dont care about addError or addFailure as they
786
# are not that interesting for performance tuning.
787
# make a new test instance that when run will generate a profile
788
example_test_case = TestTestResult("_time_hello_world_encoding")
789
example_test_case._gather_lsprof_in_benchmarks = True
790
# execute the test, which should succeed and record profiles
791
example_test_case.run(result)
792
# lsprofile_something()
793
# if this worked we want
794
# LSProf output for <built in function unicode> (['hello'], {'errors': 'replace'})
795
# CallCount Recursive Total(ms) Inline(ms) module:lineno(function)
796
# (the lsprof header)
797
# ... an arbitrary number of lines
798
# and the function call which is time.sleep.
799
# 1 0 ??? ??? ???(sleep)
800
# and then repeated but with 'world', rather than 'hello'.
801
# this should appear in the output stream of our test result.
802
output = result_stream.getvalue()
803
self.assertContainsRe(output,
804
r"LSProf output for <type 'unicode'>\(\('hello',\), {'errors': 'replace'}\)")
805
self.assertContainsRe(output,
806
r" *CallCount *Recursive *Total\(ms\) *Inline\(ms\) *module:lineno\(function\)\n")
807
self.assertContainsRe(output,
808
r"( +1 +0 +0\.\d+ +0\.\d+ +<method 'disable' of '_lsprof\.Profiler' objects>\n)?")
809
self.assertContainsRe(output,
810
r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
812
def test_uses_time_from_testtools(self):
813
"""Test case timings in verbose results should use testtools times"""
815
class TimeAddedVerboseTestResult(tests.VerboseTestResult):
816
def startTest(self, test):
817
self.time(datetime.datetime.utcfromtimestamp(1.145))
818
super(TimeAddedVerboseTestResult, self).startTest(test)
819
def addSuccess(self, test):
820
self.time(datetime.datetime.utcfromtimestamp(51.147))
821
super(TimeAddedVerboseTestResult, self).addSuccess(test)
822
def report_tests_starting(self): pass
824
self.get_passing_test().run(TimeAddedVerboseTestResult(sio, 0, 2))
825
self.assertEndsWith(sio.getvalue(), "OK 50002ms\n")
827
def test_known_failure(self):
828
"""Using knownFailure should trigger several result actions."""
829
class InstrumentedTestResult(tests.ExtendedTestResult):
830
def stopTestRun(self): pass
831
def report_tests_starting(self): pass
832
def report_known_failure(self, test, err=None, details=None):
833
self._call = test, 'known failure'
834
result = InstrumentedTestResult(None, None, None, None)
835
class Test(tests.TestCase):
836
def test_function(self):
837
self.knownFailure('failed!')
838
test = Test("test_function")
840
# it should invoke 'report_known_failure'.
841
self.assertEqual(2, len(result._call))
842
self.assertEqual(test.id(), result._call[0].id())
843
self.assertEqual('known failure', result._call[1])
844
# we dont introspec the traceback, if the rest is ok, it would be
845
# exceptional for it not to be.
846
# it should update the known_failure_count on the object.
847
self.assertEqual(1, result.known_failure_count)
848
# the result should be successful.
849
self.assertTrue(result.wasSuccessful())
851
def test_verbose_report_known_failure(self):
852
# verbose test output formatting
853
result_stream = StringIO()
854
result = bzrlib.tests.VerboseTestResult(
859
_get_test("test_xfail").run(result)
860
self.assertContainsRe(result_stream.getvalue(),
861
"\n\\S+\\.test_xfail\\s+XFAIL\\s+\\d+ms\n"
862
"\\s*(?:Text attachment: )?reason"
867
def get_passing_test(self):
868
"""Return a test object that can't be run usefully."""
871
return unittest.FunctionTestCase(passing_test)
873
def test_add_not_supported(self):
874
"""Test the behaviour of invoking addNotSupported."""
875
class InstrumentedTestResult(tests.ExtendedTestResult):
876
def stopTestRun(self): pass
877
def report_tests_starting(self): pass
878
def report_unsupported(self, test, feature):
879
self._call = test, feature
880
result = InstrumentedTestResult(None, None, None, None)
881
test = SampleTestCase('_test_pass')
882
feature = features.Feature()
883
result.startTest(test)
884
result.addNotSupported(test, feature)
885
# it should invoke 'report_unsupported'.
886
self.assertEqual(2, len(result._call))
887
self.assertEqual(test, result._call[0])
888
self.assertEqual(feature, result._call[1])
889
# the result should be successful.
890
self.assertTrue(result.wasSuccessful())
891
# it should record the test against a count of tests not run due to
893
self.assertEqual(1, result.unsupported['Feature'])
894
# and invoking it again should increment that counter
895
result.addNotSupported(test, feature)
896
self.assertEqual(2, result.unsupported['Feature'])
898
def test_verbose_report_unsupported(self):
899
# verbose test output formatting
900
result_stream = StringIO()
901
result = bzrlib.tests.VerboseTestResult(
906
test = self.get_passing_test()
907
feature = features.Feature()
908
result.startTest(test)
909
prefix = len(result_stream.getvalue())
910
result.report_unsupported(test, feature)
911
output = result_stream.getvalue()[prefix:]
912
lines = output.splitlines()
913
# We don't check for the final '0ms' since it may fail on slow hosts
914
self.assertStartsWith(lines[0], 'NODEP')
915
self.assertEqual(lines[1],
916
" The feature 'Feature' is not available.")
918
def test_unavailable_exception(self):
919
"""An UnavailableFeature being raised should invoke addNotSupported."""
920
class InstrumentedTestResult(tests.ExtendedTestResult):
921
def stopTestRun(self): pass
922
def report_tests_starting(self): pass
923
def addNotSupported(self, test, feature):
924
self._call = test, feature
925
result = InstrumentedTestResult(None, None, None, None)
926
feature = features.Feature()
927
class Test(tests.TestCase):
928
def test_function(self):
929
raise tests.UnavailableFeature(feature)
930
test = Test("test_function")
932
# it should invoke 'addNotSupported'.
933
self.assertEqual(2, len(result._call))
934
self.assertEqual(test.id(), result._call[0].id())
935
self.assertEqual(feature, result._call[1])
936
# and not count as an error
937
self.assertEqual(0, result.error_count)
939
def test_strict_with_unsupported_feature(self):
940
result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
942
test = self.get_passing_test()
943
feature = "Unsupported Feature"
944
result.addNotSupported(test, feature)
945
self.assertFalse(result.wasStrictlySuccessful())
946
self.assertEqual(None, result._extractBenchmarkTime(test))
948
def test_strict_with_known_failure(self):
949
result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
951
test = _get_test("test_xfail")
953
self.assertFalse(result.wasStrictlySuccessful())
954
self.assertEqual(None, result._extractBenchmarkTime(test))
956
def test_strict_with_success(self):
957
result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
959
test = self.get_passing_test()
960
result.addSuccess(test)
961
self.assertTrue(result.wasStrictlySuccessful())
962
self.assertEqual(None, result._extractBenchmarkTime(test))
964
def test_startTests(self):
965
"""Starting the first test should trigger startTests."""
966
class InstrumentedTestResult(tests.ExtendedTestResult):
968
def startTests(self): self.calls += 1
969
result = InstrumentedTestResult(None, None, None, None)
972
test = unittest.FunctionTestCase(test_function)
974
self.assertEquals(1, result.calls)
976
def test_startTests_only_once(self):
977
"""With multiple tests startTests should still only be called once"""
978
class InstrumentedTestResult(tests.ExtendedTestResult):
980
def startTests(self): self.calls += 1
981
result = InstrumentedTestResult(None, None, None, None)
982
suite = unittest.TestSuite([
983
unittest.FunctionTestCase(lambda: None),
984
unittest.FunctionTestCase(lambda: None)])
986
self.assertEquals(1, result.calls)
987
self.assertEquals(2, result.count)
990
class TestRunner(tests.TestCase):
992
def dummy_test(self):
995
def run_test_runner(self, testrunner, test):
996
"""Run suite in testrunner, saving global state and restoring it.
998
This current saves and restores:
999
TestCaseInTempDir.TEST_ROOT
1001
There should be no tests in this file that use
1002
bzrlib.tests.TextTestRunner without using this convenience method,
1003
because of our use of global state.
1005
old_root = tests.TestCaseInTempDir.TEST_ROOT
1007
tests.TestCaseInTempDir.TEST_ROOT = None
1008
return testrunner.run(test)
1010
tests.TestCaseInTempDir.TEST_ROOT = old_root
1012
def test_known_failure_failed_run(self):
1013
# run a test that generates a known failure which should be printed in
1014
# the final output when real failures occur.
1015
class Test(tests.TestCase):
1016
def known_failure_test(self):
1017
self.expectFailure('failed', self.assertTrue, False)
1018
test = unittest.TestSuite()
1019
test.addTest(Test("known_failure_test"))
1021
raise AssertionError('foo')
1022
test.addTest(unittest.FunctionTestCase(failing_test))
1024
runner = tests.TextTestRunner(stream=stream)
1025
result = self.run_test_runner(runner, test)
1026
lines = stream.getvalue().splitlines()
1027
self.assertContainsRe(stream.getvalue(),
1028
'(?sm)^bzr selftest.*$'
1030
'^======================================================================\n'
1031
'^FAIL: failing_test\n'
1032
'^----------------------------------------------------------------------\n'
1033
'Traceback \\(most recent call last\\):\n'
1034
' .*' # File .*, line .*, in failing_test' - but maybe not from .pyc
1035
' raise AssertionError\\(\'foo\'\\)\n'
1037
'^----------------------------------------------------------------------\n'
1039
'FAILED \\(failures=1, known_failure_count=1\\)'
1042
def test_known_failure_ok_run(self):
1043
# run a test that generates a known failure which should be printed in
1045
class Test(tests.TestCase):
1046
def known_failure_test(self):
1047
self.knownFailure("Never works...")
1048
test = Test("known_failure_test")
1050
runner = tests.TextTestRunner(stream=stream)
1051
result = self.run_test_runner(runner, test)
1052
self.assertContainsRe(stream.getvalue(),
1055
'Ran 1 test in .*\n'
1057
'OK \\(known_failures=1\\)\n')
1059
def test_unexpected_success_bad(self):
1060
class Test(tests.TestCase):
1061
def test_truth(self):
1062
self.expectFailure("No absolute truth", self.assertTrue, True)
1063
runner = tests.TextTestRunner(stream=StringIO())
1064
result = self.run_test_runner(runner, Test("test_truth"))
1065
if testtools_version[:3] <= (0, 9, 11):
1066
self.assertContainsRe(runner.stream.getvalue(),
1068
"FAIL: \\S+\.test_truth\n"
1071
"No absolute truth\n"
1074
"Ran 1 test in .*\n"
1076
"FAILED \\(failures=1\\)\n\\Z")
1078
self.assertContainsRe(runner.stream.getvalue(),
1080
"FAIL: \\S+\.test_truth\n"
1082
"Empty attachments:\n"
1085
"reason: {{{No absolute truth}}}\n"
1087
"Ran 1 test in .*\n"
1089
"FAILED \\(failures=1\\)\n\\Z")
1091
def test_result_decorator(self):
1094
class LoggingDecorator(ExtendedToOriginalDecorator):
1095
def startTest(self, test):
1096
ExtendedToOriginalDecorator.startTest(self, test)
1097
calls.append('start')
1098
test = unittest.FunctionTestCase(lambda:None)
1100
runner = tests.TextTestRunner(stream=stream,
1101
result_decorators=[LoggingDecorator])
1102
result = self.run_test_runner(runner, test)
1103
self.assertLength(1, calls)
1105
def test_skipped_test(self):
1106
# run a test that is skipped, and check the suite as a whole still
1108
# skipping_test must be hidden in here so it's not run as a real test
1109
class SkippingTest(tests.TestCase):
1110
def skipping_test(self):
1111
raise tests.TestSkipped('test intentionally skipped')
1112
runner = tests.TextTestRunner(stream=self._log_file)
1113
test = SkippingTest("skipping_test")
1114
result = self.run_test_runner(runner, test)
1115
self.assertTrue(result.wasSuccessful())
1117
def test_skipped_from_setup(self):
1119
class SkippedSetupTest(tests.TestCase):
1122
calls.append('setUp')
1123
self.addCleanup(self.cleanup)
1124
raise tests.TestSkipped('skipped setup')
1126
def test_skip(self):
1127
self.fail('test reached')
1130
calls.append('cleanup')
1132
runner = tests.TextTestRunner(stream=self._log_file)
1133
test = SkippedSetupTest('test_skip')
1134
result = self.run_test_runner(runner, test)
1135
self.assertTrue(result.wasSuccessful())
1136
# Check if cleanup was called the right number of times.
1137
self.assertEqual(['setUp', 'cleanup'], calls)
1139
def test_skipped_from_test(self):
1141
class SkippedTest(tests.TestCase):
1144
tests.TestCase.setUp(self)
1145
calls.append('setUp')
1146
self.addCleanup(self.cleanup)
1148
def test_skip(self):
1149
raise tests.TestSkipped('skipped test')
1152
calls.append('cleanup')
1154
runner = tests.TextTestRunner(stream=self._log_file)
1155
test = SkippedTest('test_skip')
1156
result = self.run_test_runner(runner, test)
1157
self.assertTrue(result.wasSuccessful())
1158
# Check if cleanup was called the right number of times.
1159
self.assertEqual(['setUp', 'cleanup'], calls)
1161
def test_not_applicable(self):
1162
# run a test that is skipped because it's not applicable
1163
class Test(tests.TestCase):
1164
def not_applicable_test(self):
1165
raise tests.TestNotApplicable('this test never runs')
1167
runner = tests.TextTestRunner(stream=out, verbosity=2)
1168
test = Test("not_applicable_test")
1169
result = self.run_test_runner(runner, test)
1170
self._log_file.write(out.getvalue())
1171
self.assertTrue(result.wasSuccessful())
1172
self.assertTrue(result.wasStrictlySuccessful())
1173
self.assertContainsRe(out.getvalue(),
1174
r'(?m)not_applicable_test * N/A')
1175
self.assertContainsRe(out.getvalue(),
1176
r'(?m)^ this test never runs')
1178
def test_unsupported_features_listed(self):
1179
"""When unsupported features are encountered they are detailed."""
1180
class Feature1(features.Feature):
1181
def _probe(self): return False
1182
class Feature2(features.Feature):
1183
def _probe(self): return False
1184
# create sample tests
1185
test1 = SampleTestCase('_test_pass')
1186
test1._test_needs_features = [Feature1()]
1187
test2 = SampleTestCase('_test_pass')
1188
test2._test_needs_features = [Feature2()]
1189
test = unittest.TestSuite()
1193
runner = tests.TextTestRunner(stream=stream)
1194
result = self.run_test_runner(runner, test)
1195
lines = stream.getvalue().splitlines()
1198
"Missing feature 'Feature1' skipped 1 tests.",
1199
"Missing feature 'Feature2' skipped 1 tests.",
1203
def test_verbose_test_count(self):
1204
"""A verbose test run reports the right test count at the start"""
1205
suite = TestUtil.TestSuite([
1206
unittest.FunctionTestCase(lambda:None),
1207
unittest.FunctionTestCase(lambda:None)])
1208
self.assertEqual(suite.countTestCases(), 2)
1210
runner = tests.TextTestRunner(stream=stream, verbosity=2)
1211
# Need to use the CountingDecorator as that's what sets num_tests
1212
result = self.run_test_runner(runner, tests.CountingDecorator(suite))
1213
self.assertStartsWith(stream.getvalue(), "running 2 tests")
1215
def test_startTestRun(self):
1216
"""run should call result.startTestRun()"""
1218
class LoggingDecorator(ExtendedToOriginalDecorator):
1219
def startTestRun(self):
1220
ExtendedToOriginalDecorator.startTestRun(self)
1221
calls.append('startTestRun')
1222
test = unittest.FunctionTestCase(lambda:None)
1224
runner = tests.TextTestRunner(stream=stream,
1225
result_decorators=[LoggingDecorator])
1226
result = self.run_test_runner(runner, test)
1227
self.assertLength(1, calls)
1229
def test_stopTestRun(self):
1230
"""run should call result.stopTestRun()"""
1232
class LoggingDecorator(ExtendedToOriginalDecorator):
1233
def stopTestRun(self):
1234
ExtendedToOriginalDecorator.stopTestRun(self)
1235
calls.append('stopTestRun')
1236
test = unittest.FunctionTestCase(lambda:None)
1238
runner = tests.TextTestRunner(stream=stream,
1239
result_decorators=[LoggingDecorator])
1240
result = self.run_test_runner(runner, test)
1241
self.assertLength(1, calls)
1243
def test_unicode_test_output_on_ascii_stream(self):
1244
"""Showing results should always succeed even on an ascii console"""
1245
class FailureWithUnicode(tests.TestCase):
1246
def test_log_unicode(self):
1248
self.fail("Now print that log!")
1250
self.overrideAttr(osutils, "get_terminal_encoding",
1251
lambda trace=False: "ascii")
1252
result = self.run_test_runner(tests.TextTestRunner(stream=out),
1253
FailureWithUnicode("test_log_unicode"))
1254
if testtools_version[:3] > (0, 9, 11):
1255
self.assertContainsRe(out.getvalue(), "log: {{{\d+\.\d+ \\\\u2606}}}")
1257
self.assertContainsRe(out.getvalue(),
1258
"Text attachment: log\n"
1260
"\d+\.\d+ \\\\u2606\n"
1264
class SampleTestCase(tests.TestCase):
1266
def _test_pass(self):
1269
class _TestException(Exception):
1273
class TestTestCase(tests.TestCase):
1274
"""Tests that test the core bzrlib TestCase."""
1276
def test_assertLength_matches_empty(self):
1278
self.assertLength(0, a_list)
1280
def test_assertLength_matches_nonempty(self):
1282
self.assertLength(3, a_list)
1284
def test_assertLength_fails_different(self):
1286
self.assertRaises(AssertionError, self.assertLength, 1, a_list)
1288
def test_assertLength_shows_sequence_in_failure(self):
1290
exception = self.assertRaises(AssertionError, self.assertLength, 2,
1292
self.assertEqual('Incorrect length: wanted 2, got 3 for [1, 2, 3]',
1295
def test_base_setUp_not_called_causes_failure(self):
1296
class TestCaseWithBrokenSetUp(tests.TestCase):
1298
pass # does not call TestCase.setUp
1301
test = TestCaseWithBrokenSetUp('test_foo')
1302
result = unittest.TestResult()
1304
self.assertFalse(result.wasSuccessful())
1305
self.assertEqual(1, result.testsRun)
1307
def test_base_tearDown_not_called_causes_failure(self):
1308
class TestCaseWithBrokenTearDown(tests.TestCase):
1310
pass # does not call TestCase.tearDown
1313
test = TestCaseWithBrokenTearDown('test_foo')
1314
result = unittest.TestResult()
1316
self.assertFalse(result.wasSuccessful())
1317
self.assertEqual(1, result.testsRun)
1319
def test_debug_flags_sanitised(self):
1320
"""The bzrlib debug flags should be sanitised by setUp."""
1321
if 'allow_debug' in tests.selftest_debug_flags:
1322
raise tests.TestNotApplicable(
1323
'-Eallow_debug option prevents debug flag sanitisation')
1324
# we could set something and run a test that will check
1325
# it gets santised, but this is probably sufficient for now:
1326
# if someone runs the test with -Dsomething it will error.
1328
if self._lock_check_thorough:
1329
flags.add('strict_locks')
1330
self.assertEqual(flags, bzrlib.debug.debug_flags)
1332
def change_selftest_debug_flags(self, new_flags):
1333
self.overrideAttr(tests, 'selftest_debug_flags', set(new_flags))
1335
def test_allow_debug_flag(self):
1336
"""The -Eallow_debug flag prevents bzrlib.debug.debug_flags from being
1337
sanitised (i.e. cleared) before running a test.
1339
self.change_selftest_debug_flags(set(['allow_debug']))
1340
bzrlib.debug.debug_flags = set(['a-flag'])
1341
class TestThatRecordsFlags(tests.TestCase):
1342
def test_foo(nested_self):
1343
self.flags = set(bzrlib.debug.debug_flags)
1344
test = TestThatRecordsFlags('test_foo')
1345
test.run(self.make_test_result())
1346
flags = set(['a-flag'])
1347
if 'disable_lock_checks' not in tests.selftest_debug_flags:
1348
flags.add('strict_locks')
1349
self.assertEqual(flags, self.flags)
1351
def test_disable_lock_checks(self):
1352
"""The -Edisable_lock_checks flag disables thorough checks."""
1353
class TestThatRecordsFlags(tests.TestCase):
1354
def test_foo(nested_self):
1355
self.flags = set(bzrlib.debug.debug_flags)
1356
self.test_lock_check_thorough = nested_self._lock_check_thorough
1357
self.change_selftest_debug_flags(set())
1358
test = TestThatRecordsFlags('test_foo')
1359
test.run(self.make_test_result())
1360
# By default we do strict lock checking and thorough lock/unlock
1362
self.assertTrue(self.test_lock_check_thorough)
1363
self.assertEqual(set(['strict_locks']), self.flags)
1364
# Now set the disable_lock_checks flag, and show that this changed.
1365
self.change_selftest_debug_flags(set(['disable_lock_checks']))
1366
test = TestThatRecordsFlags('test_foo')
1367
test.run(self.make_test_result())
1368
self.assertFalse(self.test_lock_check_thorough)
1369
self.assertEqual(set(), self.flags)
1371
def test_this_fails_strict_lock_check(self):
1372
class TestThatRecordsFlags(tests.TestCase):
1373
def test_foo(nested_self):
1374
self.flags1 = set(bzrlib.debug.debug_flags)
1375
self.thisFailsStrictLockCheck()
1376
self.flags2 = set(bzrlib.debug.debug_flags)
1377
# Make sure lock checking is active
1378
self.change_selftest_debug_flags(set())
1379
test = TestThatRecordsFlags('test_foo')
1380
test.run(self.make_test_result())
1381
self.assertEqual(set(['strict_locks']), self.flags1)
1382
self.assertEqual(set(), self.flags2)
1384
def test_debug_flags_restored(self):
1385
"""The bzrlib debug flags should be restored to their original state
1386
after the test was run, even if allow_debug is set.
1388
self.change_selftest_debug_flags(set(['allow_debug']))
1389
# Now run a test that modifies debug.debug_flags.
1390
bzrlib.debug.debug_flags = set(['original-state'])
1391
class TestThatModifiesFlags(tests.TestCase):
1393
bzrlib.debug.debug_flags = set(['modified'])
1394
test = TestThatModifiesFlags('test_foo')
1395
test.run(self.make_test_result())
1396
self.assertEqual(set(['original-state']), bzrlib.debug.debug_flags)
1398
def make_test_result(self):
1399
"""Get a test result that writes to the test log file."""
1400
return tests.TextTestResult(self._log_file, descriptions=0, verbosity=1)
1402
def inner_test(self):
1403
# the inner child test
1406
def outer_child(self):
1407
# the outer child test
1409
self.inner_test = TestTestCase("inner_child")
1410
result = self.make_test_result()
1411
self.inner_test.run(result)
1412
note("outer finish")
1413
self.addCleanup(osutils.delete_any, self._log_file_name)
1415
def test_trace_nesting(self):
1416
# this tests that each test case nests its trace facility correctly.
1417
# we do this by running a test case manually. That test case (A)
1418
# should setup a new log, log content to it, setup a child case (B),
1419
# which should log independently, then case (A) should log a trailer
1421
# we do two nested children so that we can verify the state of the
1422
# logs after the outer child finishes is correct, which a bad clean
1423
# up routine in tearDown might trigger a fault in our test with only
1424
# one child, we should instead see the bad result inside our test with
1426
# the outer child test
1427
original_trace = bzrlib.trace._trace_file
1428
outer_test = TestTestCase("outer_child")
1429
result = self.make_test_result()
1430
outer_test.run(result)
1431
self.assertEqual(original_trace, bzrlib.trace._trace_file)
1433
def method_that_times_a_bit_twice(self):
1434
# call self.time twice to ensure it aggregates
1435
self.time(time.sleep, 0.007)
1436
self.time(time.sleep, 0.007)
1438
def test_time_creates_benchmark_in_result(self):
1439
"""Test that the TestCase.time() method accumulates a benchmark time."""
1440
sample_test = TestTestCase("method_that_times_a_bit_twice")
1441
output_stream = StringIO()
1442
result = bzrlib.tests.VerboseTestResult(
1446
sample_test.run(result)
1447
self.assertContainsRe(
1448
output_stream.getvalue(),
1451
def test_hooks_sanitised(self):
1452
"""The bzrlib hooks should be sanitised by setUp."""
1453
# Note this test won't fail with hooks that the core library doesn't
1454
# use - but it trigger with a plugin that adds hooks, so its still a
1455
# useful warning in that case.
1456
self.assertEqual(bzrlib.branch.BranchHooks(), bzrlib.branch.Branch.hooks)
1458
bzrlib.smart.server.SmartServerHooks(),
1459
bzrlib.smart.server.SmartTCPServer.hooks)
1461
bzrlib.commands.CommandHooks(), bzrlib.commands.Command.hooks)
1463
def test__gather_lsprof_in_benchmarks(self):
1464
"""When _gather_lsprof_in_benchmarks is on, accumulate profile data.
1466
Each self.time() call is individually and separately profiled.
1468
self.requireFeature(features.lsprof_feature)
1469
# overrides the class member with an instance member so no cleanup
1471
self._gather_lsprof_in_benchmarks = True
1472
self.time(time.sleep, 0.000)
1473
self.time(time.sleep, 0.003)
1474
self.assertEqual(2, len(self._benchcalls))
1475
self.assertEqual((time.sleep, (0.000,), {}), self._benchcalls[0][0])
1476
self.assertEqual((time.sleep, (0.003,), {}), self._benchcalls[1][0])
1477
self.assertIsInstance(self._benchcalls[0][1], bzrlib.lsprof.Stats)
1478
self.assertIsInstance(self._benchcalls[1][1], bzrlib.lsprof.Stats)
1479
del self._benchcalls[:]
1481
def test_knownFailure(self):
1482
"""Self.knownFailure() should raise a KnownFailure exception."""
1483
self.assertRaises(tests.KnownFailure, self.knownFailure, "A Failure")
1485
def test_open_bzrdir_safe_roots(self):
1486
# even a memory transport should fail to open when its url isn't
1488
# Manually set one up (TestCase doesn't and shouldn't provide magic
1490
transport_server = memory.MemoryServer()
1491
transport_server.start_server()
1492
self.addCleanup(transport_server.stop_server)
1493
t = transport.get_transport(transport_server.get_url())
1494
bzrdir.BzrDir.create(t.base)
1495
self.assertRaises(errors.BzrError,
1496
bzrdir.BzrDir.open_from_transport, t)
1497
# But if we declare this as safe, we can open the bzrdir.
1498
self.permit_url(t.base)
1499
self._bzr_selftest_roots.append(t.base)
1500
bzrdir.BzrDir.open_from_transport(t)
1502
def test_requireFeature_available(self):
1503
"""self.requireFeature(available) is a no-op."""
1504
class Available(features.Feature):
1505
def _probe(self):return True
1506
feature = Available()
1507
self.requireFeature(feature)
1509
def test_requireFeature_unavailable(self):
1510
"""self.requireFeature(unavailable) raises UnavailableFeature."""
1511
class Unavailable(features.Feature):
1512
def _probe(self):return False
1513
feature = Unavailable()
1514
self.assertRaises(tests.UnavailableFeature,
1515
self.requireFeature, feature)
1517
def test_run_no_parameters(self):
1518
test = SampleTestCase('_test_pass')
1521
def test_run_enabled_unittest_result(self):
1522
"""Test we revert to regular behaviour when the test is enabled."""
1523
test = SampleTestCase('_test_pass')
1524
class EnabledFeature(object):
1525
def available(self):
1527
test._test_needs_features = [EnabledFeature()]
1528
result = unittest.TestResult()
1530
self.assertEqual(1, result.testsRun)
1531
self.assertEqual([], result.errors)
1532
self.assertEqual([], result.failures)
1534
def test_run_disabled_unittest_result(self):
1535
"""Test our compatability for disabled tests with unittest results."""
1536
test = SampleTestCase('_test_pass')
1537
class DisabledFeature(object):
1538
def available(self):
1540
test._test_needs_features = [DisabledFeature()]
1541
result = unittest.TestResult()
1543
self.assertEqual(1, result.testsRun)
1544
self.assertEqual([], result.errors)
1545
self.assertEqual([], result.failures)
1547
def test_run_disabled_supporting_result(self):
1548
"""Test disabled tests behaviour with support aware results."""
1549
test = SampleTestCase('_test_pass')
1550
class DisabledFeature(object):
1551
def __eq__(self, other):
1552
return isinstance(other, DisabledFeature)
1553
def available(self):
1555
the_feature = DisabledFeature()
1556
test._test_needs_features = [the_feature]
1557
class InstrumentedTestResult(unittest.TestResult):
1559
unittest.TestResult.__init__(self)
1561
def startTest(self, test):
1562
self.calls.append(('startTest', test))
1563
def stopTest(self, test):
1564
self.calls.append(('stopTest', test))
1565
def addNotSupported(self, test, feature):
1566
self.calls.append(('addNotSupported', test, feature))
1567
result = InstrumentedTestResult()
1569
case = result.calls[0][1]
1571
('startTest', case),
1572
('addNotSupported', case, the_feature),
1577
def test_start_server_registers_url(self):
1578
transport_server = memory.MemoryServer()
1579
# A little strict, but unlikely to be changed soon.
1580
self.assertEqual([], self._bzr_selftest_roots)
1581
self.start_server(transport_server)
1582
self.assertSubset([transport_server.get_url()],
1583
self._bzr_selftest_roots)
1585
def test_assert_list_raises_on_generator(self):
1586
def generator_which_will_raise():
1587
# This will not raise until after the first yield
1589
raise _TestException()
1591
e = self.assertListRaises(_TestException, generator_which_will_raise)
1592
self.assertIsInstance(e, _TestException)
1594
e = self.assertListRaises(Exception, generator_which_will_raise)
1595
self.assertIsInstance(e, _TestException)
1597
def test_assert_list_raises_on_plain(self):
1598
def plain_exception():
1599
raise _TestException()
1602
e = self.assertListRaises(_TestException, plain_exception)
1603
self.assertIsInstance(e, _TestException)
1605
e = self.assertListRaises(Exception, plain_exception)
1606
self.assertIsInstance(e, _TestException)
1608
def test_assert_list_raises_assert_wrong_exception(self):
1609
class _NotTestException(Exception):
1612
def wrong_exception():
1613
raise _NotTestException()
1615
def wrong_exception_generator():
1618
raise _NotTestException()
1620
# Wrong exceptions are not intercepted
1621
self.assertRaises(_NotTestException,
1622
self.assertListRaises, _TestException, wrong_exception)
1623
self.assertRaises(_NotTestException,
1624
self.assertListRaises, _TestException, wrong_exception_generator)
1626
def test_assert_list_raises_no_exception(self):
1630
def success_generator():
1634
self.assertRaises(AssertionError,
1635
self.assertListRaises, _TestException, success)
1637
self.assertRaises(AssertionError,
1638
self.assertListRaises, _TestException, success_generator)
1640
def test_overrideAttr_without_value(self):
1641
self.test_attr = 'original' # Define a test attribute
1642
obj = self # Make 'obj' visible to the embedded test
1643
class Test(tests.TestCase):
1646
tests.TestCase.setUp(self)
1647
self.orig = self.overrideAttr(obj, 'test_attr')
1649
def test_value(self):
1650
self.assertEqual('original', self.orig)
1651
self.assertEqual('original', obj.test_attr)
1652
obj.test_attr = 'modified'
1653
self.assertEqual('modified', obj.test_attr)
1655
test = Test('test_value')
1656
test.run(unittest.TestResult())
1657
self.assertEqual('original', obj.test_attr)
1659
def test_overrideAttr_with_value(self):
1660
self.test_attr = 'original' # Define a test attribute
1661
obj = self # Make 'obj' visible to the embedded test
1662
class Test(tests.TestCase):
1665
tests.TestCase.setUp(self)
1666
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1668
def test_value(self):
1669
self.assertEqual('original', self.orig)
1670
self.assertEqual('modified', obj.test_attr)
1672
test = Test('test_value')
1673
test.run(unittest.TestResult())
1674
self.assertEqual('original', obj.test_attr)
1676
def test_recordCalls(self):
1677
from bzrlib.tests import test_selftest
1678
calls = self.recordCalls(
1679
test_selftest, '_add_numbers')
1680
self.assertEqual(test_selftest._add_numbers(2, 10),
1682
self.assertEquals(calls, [((2, 10), {})])
1685
def _add_numbers(a, b):
1689
class _MissingFeature(features.Feature):
1692
missing_feature = _MissingFeature()
1695
def _get_test(name):
1696
"""Get an instance of a specific example test.
1698
We protect this in a function so that they don't auto-run in the test
1702
class ExampleTests(tests.TestCase):
1704
def test_fail(self):
1705
mutter('this was a failing test')
1706
self.fail('this test will fail')
1708
def test_error(self):
1709
mutter('this test errored')
1710
raise RuntimeError('gotcha')
1712
def test_missing_feature(self):
1713
mutter('missing the feature')
1714
self.requireFeature(missing_feature)
1716
def test_skip(self):
1717
mutter('this test will be skipped')
1718
raise tests.TestSkipped('reason')
1720
def test_success(self):
1721
mutter('this test succeeds')
1723
def test_xfail(self):
1724
mutter('test with expected failure')
1725
self.knownFailure('this_fails')
1727
def test_unexpected_success(self):
1728
mutter('test with unexpected success')
1729
self.expectFailure('should_fail', lambda: None)
1731
return ExampleTests(name)
1734
class TestTestCaseLogDetails(tests.TestCase):
1736
def _run_test(self, test_name):
1737
test = _get_test(test_name)
1738
result = testtools.TestResult()
1742
def test_fail_has_log(self):
1743
result = self._run_test('test_fail')
1744
self.assertEqual(1, len(result.failures))
1745
result_content = result.failures[0][1]
1746
if testtools_version < (0, 9, 12):
1747
self.assertContainsRe(result_content, 'Text attachment: log')
1748
self.assertContainsRe(result_content, 'this was a failing test')
1750
def test_error_has_log(self):
1751
result = self._run_test('test_error')
1752
self.assertEqual(1, len(result.errors))
1753
result_content = result.errors[0][1]
1754
if testtools_version < (0, 9, 12):
1755
self.assertContainsRe(result_content, 'Text attachment: log')
1756
self.assertContainsRe(result_content, 'this test errored')
1758
def test_skip_has_no_log(self):
1759
result = self._run_test('test_skip')
1760
self.assertEqual(['reason'], result.skip_reasons.keys())
1761
skips = result.skip_reasons['reason']
1762
self.assertEqual(1, len(skips))
1764
self.assertFalse('log' in test.getDetails())
1766
def test_missing_feature_has_no_log(self):
1767
# testtools doesn't know about addNotSupported, so it just gets
1768
# considered as a skip
1769
result = self._run_test('test_missing_feature')
1770
self.assertEqual([missing_feature], result.skip_reasons.keys())
1771
skips = result.skip_reasons[missing_feature]
1772
self.assertEqual(1, len(skips))
1774
self.assertFalse('log' in test.getDetails())
1776
def test_xfail_has_no_log(self):
1777
result = self._run_test('test_xfail')
1778
self.assertEqual(1, len(result.expectedFailures))
1779
result_content = result.expectedFailures[0][1]
1780
self.assertNotContainsRe(result_content, 'Text attachment: log')
1781
self.assertNotContainsRe(result_content, 'test with expected failure')
1783
def test_unexpected_success_has_log(self):
1784
result = self._run_test('test_unexpected_success')
1785
self.assertEqual(1, len(result.unexpectedSuccesses))
1786
# Inconsistency, unexpectedSuccesses is a list of tests,
1787
# expectedFailures is a list of reasons?
1788
test = result.unexpectedSuccesses[0]
1789
details = test.getDetails()
1790
self.assertTrue('log' in details)
1793
class TestTestCloning(tests.TestCase):
1794
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1796
def test_cloned_testcase_does_not_share_details(self):
1797
"""A TestCase cloned with clone_test does not share mutable attributes
1798
such as details or cleanups.
1800
class Test(tests.TestCase):
1802
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1803
orig_test = Test('test_foo')
1804
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1805
orig_test.run(unittest.TestResult())
1806
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1807
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1809
def test_double_apply_scenario_preserves_first_scenario(self):
1810
"""Applying two levels of scenarios to a test preserves the attributes
1811
added by both scenarios.
1813
class Test(tests.TestCase):
1816
test = Test('test_foo')
1817
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1818
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1819
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1820
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1821
all_tests = list(tests.iter_suite_tests(suite))
1822
self.assertLength(4, all_tests)
1823
all_xys = sorted((t.x, t.y) for t in all_tests)
1824
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1827
# NB: Don't delete this; it's not actually from 0.11!
1828
@deprecated_function(deprecated_in((0, 11, 0)))
1829
def sample_deprecated_function():
1830
"""A deprecated function to test applyDeprecated with."""
1834
def sample_undeprecated_function(a_param):
1835
"""A undeprecated function to test applyDeprecated with."""
1838
class ApplyDeprecatedHelper(object):
1839
"""A helper class for ApplyDeprecated tests."""
1841
@deprecated_method(deprecated_in((0, 11, 0)))
1842
def sample_deprecated_method(self, param_one):
1843
"""A deprecated method for testing with."""
1846
def sample_normal_method(self):
1847
"""A undeprecated method."""
1849
@deprecated_method(deprecated_in((0, 10, 0)))
1850
def sample_nested_deprecation(self):
1851
return sample_deprecated_function()
1854
class TestExtraAssertions(tests.TestCase):
1855
"""Tests for new test assertions in bzrlib test suite"""
1857
def test_assert_isinstance(self):
1858
self.assertIsInstance(2, int)
1859
self.assertIsInstance(u'', basestring)
1860
e = self.assertRaises(AssertionError, self.assertIsInstance, None, int)
1861
self.assertEquals(str(e),
1862
"None is an instance of <type 'NoneType'> rather than <type 'int'>")
1863
self.assertRaises(AssertionError, self.assertIsInstance, 23.3, int)
1864
e = self.assertRaises(AssertionError,
1865
self.assertIsInstance, None, int, "it's just not")
1866
self.assertEquals(str(e),
1867
"None is an instance of <type 'NoneType'> rather than <type 'int'>"
1870
def test_assertEndsWith(self):
1871
self.assertEndsWith('foo', 'oo')
1872
self.assertRaises(AssertionError, self.assertEndsWith, 'o', 'oo')
1874
def test_assertEqualDiff(self):
1875
e = self.assertRaises(AssertionError,
1876
self.assertEqualDiff, '', '\n')
1877
self.assertEquals(str(e),
1878
# Don't blink ! The '+' applies to the second string
1879
'first string is missing a final newline.\n+ \n')
1880
e = self.assertRaises(AssertionError,
1881
self.assertEqualDiff, '\n', '')
1882
self.assertEquals(str(e),
1883
# Don't blink ! The '-' applies to the second string
1884
'second string is missing a final newline.\n- \n')
1887
class TestDeprecations(tests.TestCase):
1889
def test_applyDeprecated_not_deprecated(self):
1890
sample_object = ApplyDeprecatedHelper()
1891
# calling an undeprecated callable raises an assertion
1892
self.assertRaises(AssertionError, self.applyDeprecated,
1893
deprecated_in((0, 11, 0)),
1894
sample_object.sample_normal_method)
1895
self.assertRaises(AssertionError, self.applyDeprecated,
1896
deprecated_in((0, 11, 0)),
1897
sample_undeprecated_function, "a param value")
1898
# calling a deprecated callable (function or method) with the wrong
1899
# expected deprecation fails.
1900
self.assertRaises(AssertionError, self.applyDeprecated,
1901
deprecated_in((0, 10, 0)),
1902
sample_object.sample_deprecated_method, "a param value")
1903
self.assertRaises(AssertionError, self.applyDeprecated,
1904
deprecated_in((0, 10, 0)),
1905
sample_deprecated_function)
1906
# calling a deprecated callable (function or method) with the right
1907
# expected deprecation returns the functions result.
1908
self.assertEqual("a param value",
1909
self.applyDeprecated(deprecated_in((0, 11, 0)),
1910
sample_object.sample_deprecated_method, "a param value"))
1911
self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 11, 0)),
1912
sample_deprecated_function))
1913
# calling a nested deprecation with the wrong deprecation version
1914
# fails even if a deeper nested function was deprecated with the
1916
self.assertRaises(AssertionError, self.applyDeprecated,
1917
deprecated_in((0, 11, 0)), sample_object.sample_nested_deprecation)
1918
# calling a nested deprecation with the right deprecation value
1919
# returns the calls result.
1920
self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 10, 0)),
1921
sample_object.sample_nested_deprecation))
1923
def test_callDeprecated(self):
1924
def testfunc(be_deprecated, result=None):
1925
if be_deprecated is True:
1926
symbol_versioning.warn('i am deprecated', DeprecationWarning,
1929
result = self.callDeprecated(['i am deprecated'], testfunc, True)
1930
self.assertIs(None, result)
1931
result = self.callDeprecated([], testfunc, False, 'result')
1932
self.assertEqual('result', result)
1933
self.callDeprecated(['i am deprecated'], testfunc, be_deprecated=True)
1934
self.callDeprecated([], testfunc, be_deprecated=False)
1937
class TestWarningTests(tests.TestCase):
1938
"""Tests for calling methods that raise warnings."""
1940
def test_callCatchWarnings(self):
1942
warnings.warn("this is your last warning")
1944
wlist, result = self.callCatchWarnings(meth, 1, 2)
1945
self.assertEquals(3, result)
1946
# would like just to compare them, but UserWarning doesn't implement
1949
self.assertIsInstance(w0, UserWarning)
1950
self.assertEquals("this is your last warning", str(w0))
1953
class TestConvenienceMakers(tests.TestCaseWithTransport):
1954
"""Test for the make_* convenience functions."""
1956
def test_make_branch_and_tree_with_format(self):
1957
# we should be able to supply a format to make_branch_and_tree
1958
self.make_branch_and_tree('a', format=bzrlib.bzrdir.BzrDirMetaFormat1())
1959
self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('a')._format,
1960
bzrlib.bzrdir.BzrDirMetaFormat1)
1962
def test_make_branch_and_memory_tree(self):
1963
# we should be able to get a new branch and a mutable tree from
1964
# TestCaseWithTransport
1965
tree = self.make_branch_and_memory_tree('a')
1966
self.assertIsInstance(tree, bzrlib.memorytree.MemoryTree)
1968
def test_make_tree_for_local_vfs_backed_transport(self):
1969
# make_branch_and_tree has to use local branch and repositories
1970
# when the vfs transport and local disk are colocated, even if
1971
# a different transport is in use for url generation.
1972
self.transport_server = test_server.FakeVFATServer
1973
self.assertFalse(self.get_url('t1').startswith('file://'))
1974
tree = self.make_branch_and_tree('t1')
1975
base = tree.bzrdir.root_transport.base
1976
self.assertStartsWith(base, 'file://')
1977
self.assertEquals(tree.bzrdir.root_transport,
1978
tree.branch.bzrdir.root_transport)
1979
self.assertEquals(tree.bzrdir.root_transport,
1980
tree.branch.repository.bzrdir.root_transport)
1983
class SelfTestHelper(object):
1985
def run_selftest(self, **kwargs):
1986
"""Run selftest returning its output."""
1988
old_transport = bzrlib.tests.default_transport
1989
old_root = tests.TestCaseWithMemoryTransport.TEST_ROOT
1990
tests.TestCaseWithMemoryTransport.TEST_ROOT = None
1992
self.assertEqual(True, tests.selftest(stream=output, **kwargs))
1994
bzrlib.tests.default_transport = old_transport
1995
tests.TestCaseWithMemoryTransport.TEST_ROOT = old_root
2000
class TestSelftest(tests.TestCase, SelfTestHelper):
2001
"""Tests of bzrlib.tests.selftest."""
2003
def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(self):
2006
factory_called.append(True)
2007
return TestUtil.TestSuite()
2010
self.apply_redirected(out, err, None, bzrlib.tests.selftest,
2011
test_suite_factory=factory)
2012
self.assertEqual([True], factory_called)
2015
"""A test suite factory."""
2016
class Test(tests.TestCase):
2023
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
2025
def test_list_only(self):
2026
output = self.run_selftest(test_suite_factory=self.factory,
2028
self.assertEqual(3, len(output.readlines()))
2030
def test_list_only_filtered(self):
2031
output = self.run_selftest(test_suite_factory=self.factory,
2032
list_only=True, pattern="Test.b")
2033
self.assertEndsWith(output.getvalue(), "Test.b\n")
2034
self.assertLength(1, output.readlines())
2036
def test_list_only_excludes(self):
2037
output = self.run_selftest(test_suite_factory=self.factory,
2038
list_only=True, exclude_pattern="Test.b")
2039
self.assertNotContainsRe("Test.b", output.getvalue())
2040
self.assertLength(2, output.readlines())
2042
def test_lsprof_tests(self):
2043
self.requireFeature(features.lsprof_feature)
2046
def __call__(test, result):
2048
def run(test, result):
2049
results.append(result)
2050
def countTestCases(self):
2052
self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
2053
self.assertLength(1, results)
2054
self.assertIsInstance(results.pop(), ExtendedToOriginalDecorator)
2056
def test_random(self):
2057
# test randomising by listing a number of tests.
2058
output_123 = self.run_selftest(test_suite_factory=self.factory,
2059
list_only=True, random_seed="123")
2060
output_234 = self.run_selftest(test_suite_factory=self.factory,
2061
list_only=True, random_seed="234")
2062
self.assertNotEqual(output_123, output_234)
2063
# "Randominzing test order..\n\n
2064
self.assertLength(5, output_123.readlines())
2065
self.assertLength(5, output_234.readlines())
2067
def test_random_reuse_is_same_order(self):
2068
# test randomising by listing a number of tests.
2069
expected = self.run_selftest(test_suite_factory=self.factory,
2070
list_only=True, random_seed="123")
2071
repeated = self.run_selftest(test_suite_factory=self.factory,
2072
list_only=True, random_seed="123")
2073
self.assertEqual(expected.getvalue(), repeated.getvalue())
2075
def test_runner_class(self):
2076
self.requireFeature(features.subunit)
2077
from subunit import ProtocolTestCase
2078
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2079
test_suite_factory=self.factory)
2080
test = ProtocolTestCase(stream)
2081
result = unittest.TestResult()
2083
self.assertEqual(3, result.testsRun)
2085
def test_starting_with_single_argument(self):
2086
output = self.run_selftest(test_suite_factory=self.factory,
2087
starting_with=['bzrlib.tests.test_selftest.Test.a'],
2089
self.assertEqual('bzrlib.tests.test_selftest.Test.a\n',
2092
def test_starting_with_multiple_argument(self):
2093
output = self.run_selftest(test_suite_factory=self.factory,
2094
starting_with=['bzrlib.tests.test_selftest.Test.a',
2095
'bzrlib.tests.test_selftest.Test.b'],
2097
self.assertEqual('bzrlib.tests.test_selftest.Test.a\n'
2098
'bzrlib.tests.test_selftest.Test.b\n',
2101
def check_transport_set(self, transport_server):
2102
captured_transport = []
2103
def seen_transport(a_transport):
2104
captured_transport.append(a_transport)
2105
class Capture(tests.TestCase):
2107
seen_transport(bzrlib.tests.default_transport)
2109
return TestUtil.TestSuite([Capture("a")])
2110
self.run_selftest(transport=transport_server, test_suite_factory=factory)
2111
self.assertEqual(transport_server, captured_transport[0])
2113
def test_transport_sftp(self):
2114
self.requireFeature(features.paramiko)
2115
from bzrlib.tests import stub_sftp
2116
self.check_transport_set(stub_sftp.SFTPAbsoluteServer)
2118
def test_transport_memory(self):
2119
self.check_transport_set(memory.MemoryServer)
2122
class TestSelftestWithIdList(tests.TestCaseInTempDir, SelfTestHelper):
2123
# Does IO: reads test.list
2125
def test_load_list(self):
2126
# Provide a list with one test - this test.
2127
test_id_line = '%s\n' % self.id()
2128
self.build_tree_contents([('test.list', test_id_line)])
2129
# And generate a list of the tests in the suite.
2130
stream = self.run_selftest(load_list='test.list', list_only=True)
2131
self.assertEqual(test_id_line, stream.getvalue())
2133
def test_load_unknown(self):
2134
# Provide a list with one test - this test.
2135
# And generate a list of the tests in the suite.
2136
err = self.assertRaises(errors.NoSuchFile, self.run_selftest,
2137
load_list='missing file name', list_only=True)
2140
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2142
_test_needs_features = [features.subunit]
2144
def run_subunit_stream(self, test_name):
2145
from subunit import ProtocolTestCase
2147
return TestUtil.TestSuite([_get_test(test_name)])
2148
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2149
test_suite_factory=factory)
2150
test = ProtocolTestCase(stream)
2151
result = testtools.TestResult()
2153
content = stream.getvalue()
2154
return content, result
2156
def test_fail_has_log(self):
2157
content, result = self.run_subunit_stream('test_fail')
2158
self.assertEqual(1, len(result.failures))
2159
self.assertContainsRe(content, '(?m)^log$')
2160
self.assertContainsRe(content, 'this test will fail')
2162
def test_error_has_log(self):
2163
content, result = self.run_subunit_stream('test_error')
2164
self.assertContainsRe(content, '(?m)^log$')
2165
self.assertContainsRe(content, 'this test errored')
2167
def test_skip_has_no_log(self):
2168
content, result = self.run_subunit_stream('test_skip')
2169
self.assertNotContainsRe(content, '(?m)^log$')
2170
self.assertNotContainsRe(content, 'this test will be skipped')
2171
self.assertEqual(['reason'], result.skip_reasons.keys())
2172
skips = result.skip_reasons['reason']
2173
self.assertEqual(1, len(skips))
2175
# RemotedTestCase doesn't preserve the "details"
2176
## self.assertFalse('log' in test.getDetails())
2178
def test_missing_feature_has_no_log(self):
2179
content, result = self.run_subunit_stream('test_missing_feature')
2180
self.assertNotContainsRe(content, '(?m)^log$')
2181
self.assertNotContainsRe(content, 'missing the feature')
2182
self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2183
skips = result.skip_reasons['_MissingFeature\n']
2184
self.assertEqual(1, len(skips))
2186
# RemotedTestCase doesn't preserve the "details"
2187
## self.assertFalse('log' in test.getDetails())
2189
def test_xfail_has_no_log(self):
2190
content, result = self.run_subunit_stream('test_xfail')
2191
self.assertNotContainsRe(content, '(?m)^log$')
2192
self.assertNotContainsRe(content, 'test with expected failure')
2193
self.assertEqual(1, len(result.expectedFailures))
2194
result_content = result.expectedFailures[0][1]
2195
self.assertNotContainsRe(result_content, 'Text attachment: log')
2196
self.assertNotContainsRe(result_content, 'test with expected failure')
2198
def test_unexpected_success_has_log(self):
2199
content, result = self.run_subunit_stream('test_unexpected_success')
2200
self.assertContainsRe(content, '(?m)^log$')
2201
self.assertContainsRe(content, 'test with unexpected success')
2202
# GZ 2011-05-18: Old versions of subunit treat unexpected success as a
2203
# success, if a min version check is added remove this
2204
from subunit import TestProtocolClient as _Client
2205
if _Client.addUnexpectedSuccess.im_func is _Client.addSuccess.im_func:
2206
self.expectFailure('subunit treats "unexpectedSuccess"'
2207
' as a plain success',
2208
self.assertEqual, 1, len(result.unexpectedSuccesses))
2209
self.assertEqual(1, len(result.unexpectedSuccesses))
2210
test = result.unexpectedSuccesses[0]
2211
# RemotedTestCase doesn't preserve the "details"
2212
## self.assertTrue('log' in test.getDetails())
2214
def test_success_has_no_log(self):
2215
content, result = self.run_subunit_stream('test_success')
2216
self.assertEqual(1, result.testsRun)
2217
self.assertNotContainsRe(content, '(?m)^log$')
2218
self.assertNotContainsRe(content, 'this test succeeds')
2221
class TestRunBzr(tests.TestCase):
2226
def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None,
2228
"""Override _run_bzr_core to test how it is invoked by run_bzr.
2230
Attempts to run bzr from inside this class don't actually run it.
2232
We test how run_bzr actually invokes bzr in another location. Here we
2233
only need to test that it passes the right parameters to run_bzr.
2235
self.argv = list(argv)
2236
self.retcode = retcode
2237
self.encoding = encoding
2239
self.working_dir = working_dir
2240
return self.retcode, self.out, self.err
2242
def test_run_bzr_error(self):
2243
self.out = "It sure does!\n"
2244
out, err = self.run_bzr_error(['^$'], ['rocks'], retcode=34)
2245
self.assertEqual(['rocks'], self.argv)
2246
self.assertEqual(34, self.retcode)
2247
self.assertEqual('It sure does!\n', out)
2248
self.assertEquals(out, self.out)
2249
self.assertEqual('', err)
2250
self.assertEquals(err, self.err)
2252
def test_run_bzr_error_regexes(self):
2254
self.err = "bzr: ERROR: foobarbaz is not versioned"
2255
out, err = self.run_bzr_error(
2256
["bzr: ERROR: foobarbaz is not versioned"],
2257
['file-id', 'foobarbaz'])
2259
def test_encoding(self):
2260
"""Test that run_bzr passes encoding to _run_bzr_core"""
2261
self.run_bzr('foo bar')
2262
self.assertEqual(None, self.encoding)
2263
self.assertEqual(['foo', 'bar'], self.argv)
2265
self.run_bzr('foo bar', encoding='baz')
2266
self.assertEqual('baz', self.encoding)
2267
self.assertEqual(['foo', 'bar'], self.argv)
2269
def test_retcode(self):
2270
"""Test that run_bzr passes retcode to _run_bzr_core"""
2271
# Default is retcode == 0
2272
self.run_bzr('foo bar')
2273
self.assertEqual(0, self.retcode)
2274
self.assertEqual(['foo', 'bar'], self.argv)
2276
self.run_bzr('foo bar', retcode=1)
2277
self.assertEqual(1, self.retcode)
2278
self.assertEqual(['foo', 'bar'], self.argv)
2280
self.run_bzr('foo bar', retcode=None)
2281
self.assertEqual(None, self.retcode)
2282
self.assertEqual(['foo', 'bar'], self.argv)
2284
self.run_bzr(['foo', 'bar'], retcode=3)
2285
self.assertEqual(3, self.retcode)
2286
self.assertEqual(['foo', 'bar'], self.argv)
2288
def test_stdin(self):
2289
# test that the stdin keyword to run_bzr is passed through to
2290
# _run_bzr_core as-is. We do this by overriding
2291
# _run_bzr_core in this class, and then calling run_bzr,
2292
# which is a convenience function for _run_bzr_core, so
2294
self.run_bzr('foo bar', stdin='gam')
2295
self.assertEqual('gam', self.stdin)
2296
self.assertEqual(['foo', 'bar'], self.argv)
2298
self.run_bzr('foo bar', stdin='zippy')
2299
self.assertEqual('zippy', self.stdin)
2300
self.assertEqual(['foo', 'bar'], self.argv)
2302
def test_working_dir(self):
2303
"""Test that run_bzr passes working_dir to _run_bzr_core"""
2304
self.run_bzr('foo bar')
2305
self.assertEqual(None, self.working_dir)
2306
self.assertEqual(['foo', 'bar'], self.argv)
2308
self.run_bzr('foo bar', working_dir='baz')
2309
self.assertEqual('baz', self.working_dir)
2310
self.assertEqual(['foo', 'bar'], self.argv)
2312
def test_reject_extra_keyword_arguments(self):
2313
self.assertRaises(TypeError, self.run_bzr, "foo bar",
2314
error_regex=['error message'])
2317
class TestRunBzrCaptured(tests.TestCaseWithTransport):
2318
# Does IO when testing the working_dir parameter.
2320
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
2321
a_callable=None, *args, **kwargs):
2323
self.factory_stdin = getattr(bzrlib.ui.ui_factory, "stdin", None)
2324
self.factory = bzrlib.ui.ui_factory
2325
self.working_dir = osutils.getcwd()
2326
stdout.write('foo\n')
2327
stderr.write('bar\n')
2330
def test_stdin(self):
2331
# test that the stdin keyword to _run_bzr_core is passed through to
2332
# apply_redirected as a StringIO. We do this by overriding
2333
# apply_redirected in this class, and then calling _run_bzr_core,
2334
# which calls apply_redirected.
2335
self.run_bzr(['foo', 'bar'], stdin='gam')
2336
self.assertEqual('gam', self.stdin.read())
2337
self.assertTrue(self.stdin is self.factory_stdin)
2338
self.run_bzr(['foo', 'bar'], stdin='zippy')
2339
self.assertEqual('zippy', self.stdin.read())
2340
self.assertTrue(self.stdin is self.factory_stdin)
2342
def test_ui_factory(self):
2343
# each invocation of self.run_bzr should get its
2344
# own UI factory, which is an instance of TestUIFactory,
2345
# with stdin, stdout and stderr attached to the stdin,
2346
# stdout and stderr of the invoked run_bzr
2347
current_factory = bzrlib.ui.ui_factory
2348
self.run_bzr(['foo'])
2349
self.assertFalse(current_factory is self.factory)
2350
self.assertNotEqual(sys.stdout, self.factory.stdout)
2351
self.assertNotEqual(sys.stderr, self.factory.stderr)
2352
self.assertEqual('foo\n', self.factory.stdout.getvalue())
2353
self.assertEqual('bar\n', self.factory.stderr.getvalue())
2354
self.assertIsInstance(self.factory, tests.TestUIFactory)
2356
def test_working_dir(self):
2357
self.build_tree(['one/', 'two/'])
2358
cwd = osutils.getcwd()
2360
# Default is to work in the current directory
2361
self.run_bzr(['foo', 'bar'])
2362
self.assertEqual(cwd, self.working_dir)
2364
self.run_bzr(['foo', 'bar'], working_dir=None)
2365
self.assertEqual(cwd, self.working_dir)
2367
# The function should be run in the alternative directory
2368
# but afterwards the current working dir shouldn't be changed
2369
self.run_bzr(['foo', 'bar'], working_dir='one')
2370
self.assertNotEqual(cwd, self.working_dir)
2371
self.assertEndsWith(self.working_dir, 'one')
2372
self.assertEqual(cwd, osutils.getcwd())
2374
self.run_bzr(['foo', 'bar'], working_dir='two')
2375
self.assertNotEqual(cwd, self.working_dir)
2376
self.assertEndsWith(self.working_dir, 'two')
2377
self.assertEqual(cwd, osutils.getcwd())
2380
class StubProcess(object):
2381
"""A stub process for testing run_bzr_subprocess."""
2383
def __init__(self, out="", err="", retcode=0):
2386
self.returncode = retcode
2388
def communicate(self):
2389
return self.out, self.err
2392
class TestWithFakedStartBzrSubprocess(tests.TestCaseWithTransport):
2393
"""Base class for tests testing how we might run bzr."""
2396
tests.TestCaseWithTransport.setUp(self)
2397
self.subprocess_calls = []
2399
def start_bzr_subprocess(self, process_args, env_changes=None,
2400
skip_if_plan_to_signal=False,
2402
allow_plugins=False):
2403
"""capture what run_bzr_subprocess tries to do."""
2404
self.subprocess_calls.append({'process_args':process_args,
2405
'env_changes':env_changes,
2406
'skip_if_plan_to_signal':skip_if_plan_to_signal,
2407
'working_dir':working_dir, 'allow_plugins':allow_plugins})
2408
return self.next_subprocess
2411
class TestRunBzrSubprocess(TestWithFakedStartBzrSubprocess):
2413
def assertRunBzrSubprocess(self, expected_args, process, *args, **kwargs):
2414
"""Run run_bzr_subprocess with args and kwargs using a stubbed process.
2416
Inside TestRunBzrSubprocessCommands we use a stub start_bzr_subprocess
2417
that will return static results. This assertion method populates those
2418
results and also checks the arguments run_bzr_subprocess generates.
2420
self.next_subprocess = process
2422
result = self.run_bzr_subprocess(*args, **kwargs)
2424
self.next_subprocess = None
2425
for key, expected in expected_args.iteritems():
2426
self.assertEqual(expected, self.subprocess_calls[-1][key])
2429
self.next_subprocess = None
2430
for key, expected in expected_args.iteritems():
2431
self.assertEqual(expected, self.subprocess_calls[-1][key])
2434
def test_run_bzr_subprocess(self):
2435
"""The run_bzr_helper_external command behaves nicely."""
2436
self.assertRunBzrSubprocess({'process_args':['--version']},
2437
StubProcess(), '--version')
2438
self.assertRunBzrSubprocess({'process_args':['--version']},
2439
StubProcess(), ['--version'])
2440
# retcode=None disables retcode checking
2441
result = self.assertRunBzrSubprocess({},
2442
StubProcess(retcode=3), '--version', retcode=None)
2443
result = self.assertRunBzrSubprocess({},
2444
StubProcess(out="is free software"), '--version')
2445
self.assertContainsRe(result[0], 'is free software')
2446
# Running a subcommand that is missing errors
2447
self.assertRaises(AssertionError, self.assertRunBzrSubprocess,
2448
{'process_args':['--versionn']}, StubProcess(retcode=3),
2450
# Unless it is told to expect the error from the subprocess
2451
result = self.assertRunBzrSubprocess({},
2452
StubProcess(retcode=3), '--versionn', retcode=3)
2453
# Or to ignore retcode checking
2454
result = self.assertRunBzrSubprocess({},
2455
StubProcess(err="unknown command", retcode=3), '--versionn',
2457
self.assertContainsRe(result[1], 'unknown command')
2459
def test_env_change_passes_through(self):
2460
self.assertRunBzrSubprocess(
2461
{'env_changes':{'new':'value', 'changed':'newvalue', 'deleted':None}},
2463
env_changes={'new':'value', 'changed':'newvalue', 'deleted':None})
2465
def test_no_working_dir_passed_as_None(self):
2466
self.assertRunBzrSubprocess({'working_dir': None}, StubProcess(), '')
2468
def test_no_working_dir_passed_through(self):
2469
self.assertRunBzrSubprocess({'working_dir': 'dir'}, StubProcess(), '',
2472
def test_run_bzr_subprocess_no_plugins(self):
2473
self.assertRunBzrSubprocess({'allow_plugins': False},
2476
def test_allow_plugins(self):
2477
self.assertRunBzrSubprocess({'allow_plugins': True},
2478
StubProcess(), '', allow_plugins=True)
2481
class TestFinishBzrSubprocess(TestWithFakedStartBzrSubprocess):
2483
def test_finish_bzr_subprocess_with_error(self):
2484
"""finish_bzr_subprocess allows specification of the desired exit code.
2486
process = StubProcess(err="unknown command", retcode=3)
2487
result = self.finish_bzr_subprocess(process, retcode=3)
2488
self.assertEqual('', result[0])
2489
self.assertContainsRe(result[1], 'unknown command')
2491
def test_finish_bzr_subprocess_ignoring_retcode(self):
2492
"""finish_bzr_subprocess allows the exit code to be ignored."""
2493
process = StubProcess(err="unknown command", retcode=3)
2494
result = self.finish_bzr_subprocess(process, retcode=None)
2495
self.assertEqual('', result[0])
2496
self.assertContainsRe(result[1], 'unknown command')
2498
def test_finish_subprocess_with_unexpected_retcode(self):
2499
"""finish_bzr_subprocess raises self.failureException if the retcode is
2500
not the expected one.
2502
process = StubProcess(err="unknown command", retcode=3)
2503
self.assertRaises(self.failureException, self.finish_bzr_subprocess,
2507
class _DontSpawnProcess(Exception):
2508
"""A simple exception which just allows us to skip unnecessary steps"""
2511
class TestStartBzrSubProcess(tests.TestCase):
2512
"""Stub test start_bzr_subprocess."""
2514
def _subprocess_log_cleanup(self):
2515
"""Inhibits the base version as we don't produce a log file."""
2517
def _popen(self, *args, **kwargs):
2518
"""Override the base version to record the command that is run.
2520
From there we can ensure it is correct without spawning a real process.
2522
self.check_popen_state()
2523
self._popen_args = args
2524
self._popen_kwargs = kwargs
2525
raise _DontSpawnProcess()
2527
def check_popen_state(self):
2528
"""Replace to make assertions when popen is called."""
2530
def test_run_bzr_subprocess_no_plugins(self):
2531
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
2532
command = self._popen_args[0]
2533
self.assertEqual(sys.executable, command[0])
2534
self.assertEqual(self.get_bzr_path(), command[1])
2535
self.assertEqual(['--no-plugins'], command[2:])
2537
def test_allow_plugins(self):
2538
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2540
command = self._popen_args[0]
2541
self.assertEqual([], command[2:])
2543
def test_set_env(self):
2544
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2546
def check_environment():
2547
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2548
self.check_popen_state = check_environment
2549
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2550
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2551
# not set in theparent
2552
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2554
def test_run_bzr_subprocess_env_del(self):
2555
"""run_bzr_subprocess can remove environment variables too."""
2556
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2557
def check_environment():
2558
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2559
os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2560
self.check_popen_state = check_environment
2561
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2562
env_changes={'EXISTANT_ENV_VAR':None})
2563
# Still set in parent
2564
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2565
del os.environ['EXISTANT_ENV_VAR']
2567
def test_env_del_missing(self):
2568
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2569
def check_environment():
2570
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2571
self.check_popen_state = check_environment
2572
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2573
env_changes={'NON_EXISTANT_ENV_VAR':None})
2575
def test_working_dir(self):
2576
"""Test that we can specify the working dir for the child"""
2577
orig_getcwd = osutils.getcwd
2578
orig_chdir = os.chdir
2582
self.overrideAttr(os, 'chdir', chdir)
2585
self.overrideAttr(osutils, 'getcwd', getcwd)
2586
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2588
self.assertEqual(['foo', 'current'], chdirs)
2590
def test_get_bzr_path_with_cwd_bzrlib(self):
2591
self.get_source_path = lambda: ""
2592
self.overrideAttr(os.path, "isfile", lambda path: True)
2593
self.assertEqual(self.get_bzr_path(), "bzr")
2596
class TestActuallyStartBzrSubprocess(tests.TestCaseWithTransport):
2597
"""Tests that really need to do things with an external bzr."""
2599
def test_start_and_stop_bzr_subprocess_send_signal(self):
2600
"""finish_bzr_subprocess raises self.failureException if the retcode is
2601
not the expected one.
2603
self.disable_missing_extensions_warning()
2604
process = self.start_bzr_subprocess(['wait-until-signalled'],
2605
skip_if_plan_to_signal=True)
2606
self.assertEqual('running\n', process.stdout.readline())
2607
result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT,
2609
self.assertEqual('', result[0])
2610
self.assertEqual('bzr: interrupted\n', result[1])
2613
class TestSelftestFiltering(tests.TestCase):
2616
tests.TestCase.setUp(self)
2617
self.suite = TestUtil.TestSuite()
2618
self.loader = TestUtil.TestLoader()
2619
self.suite.addTest(self.loader.loadTestsFromModule(
2620
sys.modules['bzrlib.tests.test_selftest']))
2621
self.all_names = _test_ids(self.suite)
2623
def test_condition_id_re(self):
2624
test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2625
'test_condition_id_re')
2626
filtered_suite = tests.filter_suite_by_condition(
2627
self.suite, tests.condition_id_re('test_condition_id_re'))
2628
self.assertEqual([test_name], _test_ids(filtered_suite))
2630
def test_condition_id_in_list(self):
2631
test_names = ['bzrlib.tests.test_selftest.TestSelftestFiltering.'
2632
'test_condition_id_in_list']
2633
id_list = tests.TestIdList(test_names)
2634
filtered_suite = tests.filter_suite_by_condition(
2635
self.suite, tests.condition_id_in_list(id_list))
2636
my_pattern = 'TestSelftestFiltering.*test_condition_id_in_list'
2637
re_filtered = tests.filter_suite_by_re(self.suite, my_pattern)
2638
self.assertEqual(_test_ids(re_filtered), _test_ids(filtered_suite))
2640
def test_condition_id_startswith(self):
2641
klass = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2642
start1 = klass + 'test_condition_id_starts'
2643
start2 = klass + 'test_condition_id_in'
2644
test_names = [ klass + 'test_condition_id_in_list',
2645
klass + 'test_condition_id_startswith',
2647
filtered_suite = tests.filter_suite_by_condition(
2648
self.suite, tests.condition_id_startswith([start1, start2]))
2649
self.assertEqual(test_names, _test_ids(filtered_suite))
2651
def test_condition_isinstance(self):
2652
filtered_suite = tests.filter_suite_by_condition(
2653
self.suite, tests.condition_isinstance(self.__class__))
2654
class_pattern = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2655
re_filtered = tests.filter_suite_by_re(self.suite, class_pattern)
2656
self.assertEqual(_test_ids(re_filtered), _test_ids(filtered_suite))
2658
def test_exclude_tests_by_condition(self):
2659
excluded_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2660
'test_exclude_tests_by_condition')
2661
filtered_suite = tests.exclude_tests_by_condition(self.suite,
2662
lambda x:x.id() == excluded_name)
2663
self.assertEqual(len(self.all_names) - 1,
2664
filtered_suite.countTestCases())
2665
self.assertFalse(excluded_name in _test_ids(filtered_suite))
2666
remaining_names = list(self.all_names)
2667
remaining_names.remove(excluded_name)
2668
self.assertEqual(remaining_names, _test_ids(filtered_suite))
2670
def test_exclude_tests_by_re(self):
2671
self.all_names = _test_ids(self.suite)
2672
filtered_suite = tests.exclude_tests_by_re(self.suite,
2673
'exclude_tests_by_re')
2674
excluded_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2675
'test_exclude_tests_by_re')
2676
self.assertEqual(len(self.all_names) - 1,
2677
filtered_suite.countTestCases())
2678
self.assertFalse(excluded_name in _test_ids(filtered_suite))
2679
remaining_names = list(self.all_names)
2680
remaining_names.remove(excluded_name)
2681
self.assertEqual(remaining_names, _test_ids(filtered_suite))
2683
def test_filter_suite_by_condition(self):
2684
test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2685
'test_filter_suite_by_condition')
2686
filtered_suite = tests.filter_suite_by_condition(self.suite,
2687
lambda x:x.id() == test_name)
2688
self.assertEqual([test_name], _test_ids(filtered_suite))
2690
def test_filter_suite_by_re(self):
2691
filtered_suite = tests.filter_suite_by_re(self.suite,
2692
'test_filter_suite_by_r')
2693
filtered_names = _test_ids(filtered_suite)
2694
self.assertEqual(filtered_names, ['bzrlib.tests.test_selftest.'
2695
'TestSelftestFiltering.test_filter_suite_by_re'])
2697
def test_filter_suite_by_id_list(self):
2698
test_list = ['bzrlib.tests.test_selftest.'
2699
'TestSelftestFiltering.test_filter_suite_by_id_list']
2700
filtered_suite = tests.filter_suite_by_id_list(
2701
self.suite, tests.TestIdList(test_list))
2702
filtered_names = _test_ids(filtered_suite)
2705
['bzrlib.tests.test_selftest.'
2706
'TestSelftestFiltering.test_filter_suite_by_id_list'])
2708
def test_filter_suite_by_id_startswith(self):
2709
# By design this test may fail if another test is added whose name also
2710
# begins with one of the start value used.
2711
klass = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2712
start1 = klass + 'test_filter_suite_by_id_starts'
2713
start2 = klass + 'test_filter_suite_by_id_li'
2714
test_list = [klass + 'test_filter_suite_by_id_list',
2715
klass + 'test_filter_suite_by_id_startswith',
2717
filtered_suite = tests.filter_suite_by_id_startswith(
2718
self.suite, [start1, start2])
2721
_test_ids(filtered_suite),
2724
def test_preserve_input(self):
2725
# NB: Surely this is something in the stdlib to do this?
2726
self.assertTrue(self.suite is tests.preserve_input(self.suite))
2727
self.assertTrue("@#$" is tests.preserve_input("@#$"))
2729
def test_randomize_suite(self):
2730
randomized_suite = tests.randomize_suite(self.suite)
2731
# randomizing should not add or remove test names.
2732
self.assertEqual(set(_test_ids(self.suite)),
2733
set(_test_ids(randomized_suite)))
2734
# Technically, this *can* fail, because random.shuffle(list) can be
2735
# equal to list. Trying multiple times just pushes the frequency back.
2736
# As its len(self.all_names)!:1, the failure frequency should be low
2737
# enough to ignore. RBC 20071021.
2738
# It should change the order.
2739
self.assertNotEqual(self.all_names, _test_ids(randomized_suite))
2740
# But not the length. (Possibly redundant with the set test, but not
2742
self.assertEqual(len(self.all_names), len(_test_ids(randomized_suite)))
2744
def test_split_suit_by_condition(self):
2745
self.all_names = _test_ids(self.suite)
2746
condition = tests.condition_id_re('test_filter_suite_by_r')
2747
split_suite = tests.split_suite_by_condition(self.suite, condition)
2748
filtered_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2749
'test_filter_suite_by_re')
2750
self.assertEqual([filtered_name], _test_ids(split_suite[0]))
2751
self.assertFalse(filtered_name in _test_ids(split_suite[1]))
2752
remaining_names = list(self.all_names)
2753
remaining_names.remove(filtered_name)
2754
self.assertEqual(remaining_names, _test_ids(split_suite[1]))
2756
def test_split_suit_by_re(self):
2757
self.all_names = _test_ids(self.suite)
2758
split_suite = tests.split_suite_by_re(self.suite,
2759
'test_filter_suite_by_r')
2760
filtered_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2761
'test_filter_suite_by_re')
2762
self.assertEqual([filtered_name], _test_ids(split_suite[0]))
2763
self.assertFalse(filtered_name in _test_ids(split_suite[1]))
2764
remaining_names = list(self.all_names)
2765
remaining_names.remove(filtered_name)
2766
self.assertEqual(remaining_names, _test_ids(split_suite[1]))
2769
class TestCheckTreeShape(tests.TestCaseWithTransport):
2771
def test_check_tree_shape(self):
2772
files = ['a', 'b/', 'b/c']
2773
tree = self.make_branch_and_tree('.')
2774
self.build_tree(files)
2778
self.check_tree_shape(tree, files)
2783
class TestBlackboxSupport(tests.TestCase):
2784
"""Tests for testsuite blackbox features."""
2786
def test_run_bzr_failure_not_caught(self):
2787
# When we run bzr in blackbox mode, we want any unexpected errors to
2788
# propagate up to the test suite so that it can show the error in the
2789
# usual way, and we won't get a double traceback.
2790
e = self.assertRaises(
2792
self.run_bzr, ['assert-fail'])
2793
# make sure we got the real thing, not an error from somewhere else in
2794
# the test framework
2795
self.assertEquals('always fails', str(e))
2796
# check that there's no traceback in the test log
2797
self.assertNotContainsRe(self.get_log(), r'Traceback')
2799
def test_run_bzr_user_error_caught(self):
2800
# Running bzr in blackbox mode, normal/expected/user errors should be
2801
# caught in the regular way and turned into an error message plus exit
2803
transport_server = memory.MemoryServer()
2804
transport_server.start_server()
2805
self.addCleanup(transport_server.stop_server)
2806
url = transport_server.get_url()
2807
self.permit_url(url)
2808
out, err = self.run_bzr(["log", "%s/nonexistantpath" % url], retcode=3)
2809
self.assertEqual(out, '')
2810
self.assertContainsRe(err,
2811
'bzr: ERROR: Not a branch: ".*nonexistantpath/".\n')
2814
class TestTestLoader(tests.TestCase):
2815
"""Tests for the test loader."""
2817
def _get_loader_and_module(self):
2818
"""Gets a TestLoader and a module with one test in it."""
2819
loader = TestUtil.TestLoader()
2821
class Stub(tests.TestCase):
2824
class MyModule(object):
2826
MyModule.a_class = Stub
2828
return loader, module
2830
def test_module_no_load_tests_attribute_loads_classes(self):
2831
loader, module = self._get_loader_and_module()
2832
self.assertEqual(1, loader.loadTestsFromModule(module).countTestCases())
2834
def test_module_load_tests_attribute_gets_called(self):
2835
loader, module = self._get_loader_and_module()
2836
# 'self' is here because we're faking the module with a class. Regular
2837
# load_tests do not need that :)
2838
def load_tests(self, standard_tests, module, loader):
2839
result = loader.suiteClass()
2840
for test in tests.iter_suite_tests(standard_tests):
2841
result.addTests([test, test])
2843
# add a load_tests() method which multiplies the tests from the module.
2844
module.__class__.load_tests = load_tests
2845
self.assertEqual(2, loader.loadTestsFromModule(module).countTestCases())
2847
def test_load_tests_from_module_name_smoke_test(self):
2848
loader = TestUtil.TestLoader()
2849
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
2850
self.assertEquals(['bzrlib.tests.test_sampler.DemoTest.test_nothing'],
2853
def test_load_tests_from_module_name_with_bogus_module_name(self):
2854
loader = TestUtil.TestLoader()
2855
self.assertRaises(ImportError, loader.loadTestsFromModuleName, 'bogus')
2858
class TestTestIdList(tests.TestCase):
2860
def _create_id_list(self, test_list):
2861
return tests.TestIdList(test_list)
2863
def _create_suite(self, test_id_list):
2865
class Stub(tests.TestCase):
2869
def _create_test_id(id):
2872
suite = TestUtil.TestSuite()
2873
for id in test_id_list:
2874
t = Stub('test_foo')
2875
t.id = _create_test_id(id)
2879
def _test_ids(self, test_suite):
2880
"""Get the ids for the tests in a test suite."""
2881
return [t.id() for t in tests.iter_suite_tests(test_suite)]
2883
def test_empty_list(self):
2884
id_list = self._create_id_list([])
2885
self.assertEquals({}, id_list.tests)
2886
self.assertEquals({}, id_list.modules)
2888
def test_valid_list(self):
2889
id_list = self._create_id_list(
2890
['mod1.cl1.meth1', 'mod1.cl1.meth2',
2891
'mod1.func1', 'mod1.cl2.meth2',
2893
'mod1.submod2.cl1.meth1', 'mod1.submod2.cl2.meth2',
2895
self.assertTrue(id_list.refers_to('mod1'))
2896
self.assertTrue(id_list.refers_to('mod1.submod1'))
2897
self.assertTrue(id_list.refers_to('mod1.submod2'))
2898
self.assertTrue(id_list.includes('mod1.cl1.meth1'))
2899
self.assertTrue(id_list.includes('mod1.submod1'))
2900
self.assertTrue(id_list.includes('mod1.func1'))
2902
def test_bad_chars_in_params(self):
2903
id_list = self._create_id_list(['mod1.cl1.meth1(xx.yy)'])
2904
self.assertTrue(id_list.refers_to('mod1'))
2905
self.assertTrue(id_list.includes('mod1.cl1.meth1(xx.yy)'))
2907
def test_module_used(self):
2908
id_list = self._create_id_list(['mod.class.meth'])
2909
self.assertTrue(id_list.refers_to('mod'))
2910
self.assertTrue(id_list.refers_to('mod.class'))
2911
self.assertTrue(id_list.refers_to('mod.class.meth'))
2913
def test_test_suite_matches_id_list_with_unknown(self):
2914
loader = TestUtil.TestLoader()
2915
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
2916
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing',
2918
not_found, duplicates = tests.suite_matches_id_list(suite, test_list)
2919
self.assertEquals(['bogus'], not_found)
2920
self.assertEquals([], duplicates)
2922
def test_suite_matches_id_list_with_duplicates(self):
2923
loader = TestUtil.TestLoader()
2924
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
2925
dupes = loader.suiteClass()
2926
for test in tests.iter_suite_tests(suite):
2928
dupes.addTest(test) # Add it again
2930
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing',]
2931
not_found, duplicates = tests.suite_matches_id_list(
2933
self.assertEquals([], not_found)
2934
self.assertEquals(['bzrlib.tests.test_sampler.DemoTest.test_nothing'],
2938
class TestTestSuite(tests.TestCase):
2940
def test__test_suite_testmod_names(self):
2941
# Test that a plausible list of test module names are returned
2942
# by _test_suite_testmod_names.
2943
test_list = tests._test_suite_testmod_names()
2945
'bzrlib.tests.blackbox',
2946
'bzrlib.tests.per_transport',
2947
'bzrlib.tests.test_selftest',
2951
def test__test_suite_modules_to_doctest(self):
2952
# Test that a plausible list of modules to doctest is returned
2953
# by _test_suite_modules_to_doctest.
2954
test_list = tests._test_suite_modules_to_doctest()
2956
# When docstrings are stripped, there are no modules to doctest
2957
self.assertEqual([], test_list)
2964
def test_test_suite(self):
2965
# test_suite() loads the entire test suite to operate. To avoid this
2966
# overhead, and yet still be confident that things are happening,
2967
# we temporarily replace two functions used by test_suite with
2968
# test doubles that supply a few sample tests to load, and check they
2971
def testmod_names():
2972
calls.append("testmod_names")
2974
'bzrlib.tests.blackbox.test_branch',
2975
'bzrlib.tests.per_transport',
2976
'bzrlib.tests.test_selftest',
2978
self.overrideAttr(tests, '_test_suite_testmod_names', testmod_names)
2980
calls.append("modules_to_doctest")
2983
return ['bzrlib.timestamp']
2984
self.overrideAttr(tests, '_test_suite_modules_to_doctest', doctests)
2985
expected_test_list = [
2987
'bzrlib.tests.blackbox.test_branch.TestBranch.test_branch',
2988
('bzrlib.tests.per_transport.TransportTests'
2989
'.test_abspath(LocalTransport,LocalURLServer)'),
2990
'bzrlib.tests.test_selftest.TestTestSuite.test_test_suite',
2991
# plugins can't be tested that way since selftest may be run with
2994
if __doc__ is not None:
2995
expected_test_list.extend([
2996
# modules_to_doctest
2997
'bzrlib.timestamp.format_highres_date',
2999
suite = tests.test_suite()
3000
self.assertEqual(set(["testmod_names", "modules_to_doctest"]),
3002
self.assertSubset(expected_test_list, _test_ids(suite))
3004
def test_test_suite_list_and_start(self):
3005
# We cannot test this at the same time as the main load, because we want
3006
# to know that starting_with == None works. So a second load is
3007
# incurred - note that the starting_with parameter causes a partial load
3008
# rather than a full load so this test should be pretty quick.
3009
test_list = ['bzrlib.tests.test_selftest.TestTestSuite.test_test_suite']
3010
suite = tests.test_suite(test_list,
3011
['bzrlib.tests.test_selftest.TestTestSuite'])
3012
# test_test_suite_list_and_start is not included
3013
self.assertEquals(test_list, _test_ids(suite))
3016
class TestLoadTestIdList(tests.TestCaseInTempDir):
3018
def _create_test_list_file(self, file_name, content):
3019
fl = open(file_name, 'wt')
3023
def test_load_unknown(self):
3024
self.assertRaises(errors.NoSuchFile,
3025
tests.load_test_id_list, 'i_do_not_exist')
3027
def test_load_test_list(self):
3028
test_list_fname = 'test.list'
3029
self._create_test_list_file(test_list_fname,
3030
'mod1.cl1.meth1\nmod2.cl2.meth2\n')
3031
tlist = tests.load_test_id_list(test_list_fname)
3032
self.assertEquals(2, len(tlist))
3033
self.assertEquals('mod1.cl1.meth1', tlist[0])
3034
self.assertEquals('mod2.cl2.meth2', tlist[1])
3036
def test_load_dirty_file(self):
3037
test_list_fname = 'test.list'
3038
self._create_test_list_file(test_list_fname,
3039
' mod1.cl1.meth1\n\nmod2.cl2.meth2 \n'
3041
tlist = tests.load_test_id_list(test_list_fname)
3042
self.assertEquals(4, len(tlist))
3043
self.assertEquals('mod1.cl1.meth1', tlist[0])
3044
self.assertEquals('', tlist[1])
3045
self.assertEquals('mod2.cl2.meth2', tlist[2])
3046
self.assertEquals('bar baz', tlist[3])
3049
class TestFilteredByModuleTestLoader(tests.TestCase):
3051
def _create_loader(self, test_list):
3052
id_filter = tests.TestIdList(test_list)
3053
loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
3056
def test_load_tests(self):
3057
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3058
loader = self._create_loader(test_list)
3059
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3060
self.assertEquals(test_list, _test_ids(suite))
3062
def test_exclude_tests(self):
3063
test_list = ['bogus']
3064
loader = self._create_loader(test_list)
3065
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3066
self.assertEquals([], _test_ids(suite))
3069
class TestFilteredByNameStartTestLoader(tests.TestCase):
3071
def _create_loader(self, name_start):
3072
def needs_module(name):
3073
return name.startswith(name_start) or name_start.startswith(name)
3074
loader = TestUtil.FilteredByModuleTestLoader(needs_module)
3077
def test_load_tests(self):
3078
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3079
loader = self._create_loader('bzrlib.tests.test_samp')
3081
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3082
self.assertEquals(test_list, _test_ids(suite))
3084
def test_load_tests_inside_module(self):
3085
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3086
loader = self._create_loader('bzrlib.tests.test_sampler.Demo')
3088
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3089
self.assertEquals(test_list, _test_ids(suite))
3091
def test_exclude_tests(self):
3092
test_list = ['bogus']
3093
loader = self._create_loader('bogus')
3095
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3096
self.assertEquals([], _test_ids(suite))
3099
class TestTestPrefixRegistry(tests.TestCase):
3101
def _get_registry(self):
3102
tp_registry = tests.TestPrefixAliasRegistry()
3105
def test_register_new_prefix(self):
3106
tpr = self._get_registry()
3107
tpr.register('foo', 'fff.ooo.ooo')
3108
self.assertEquals('fff.ooo.ooo', tpr.get('foo'))
3110
def test_register_existing_prefix(self):
3111
tpr = self._get_registry()
3112
tpr.register('bar', 'bbb.aaa.rrr')
3113
tpr.register('bar', 'bBB.aAA.rRR')
3114
self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
3115
self.assertThat(self.get_log(),
3116
DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
3119
def test_get_unknown_prefix(self):
3120
tpr = self._get_registry()
3121
self.assertRaises(KeyError, tpr.get, 'I am not a prefix')
3123
def test_resolve_prefix(self):
3124
tpr = self._get_registry()
3125
tpr.register('bar', 'bb.aa.rr')
3126
self.assertEquals('bb.aa.rr', tpr.resolve_alias('bar'))
3128
def test_resolve_unknown_alias(self):
3129
tpr = self._get_registry()
3130
self.assertRaises(errors.BzrCommandError,
3131
tpr.resolve_alias, 'I am not a prefix')
3133
def test_predefined_prefixes(self):
3134
tpr = tests.test_prefix_alias_registry
3135
self.assertEquals('bzrlib', tpr.resolve_alias('bzrlib'))
3136
self.assertEquals('bzrlib.doc', tpr.resolve_alias('bd'))
3137
self.assertEquals('bzrlib.utils', tpr.resolve_alias('bu'))
3138
self.assertEquals('bzrlib.tests', tpr.resolve_alias('bt'))
3139
self.assertEquals('bzrlib.tests.blackbox', tpr.resolve_alias('bb'))
3140
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3143
class TestThreadLeakDetection(tests.TestCase):
3144
"""Ensure when tests leak threads we detect and report it"""
3146
class LeakRecordingResult(tests.ExtendedTestResult):
3148
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3150
def _report_thread_leak(self, test, leaks, alive):
3151
self.leaks.append((test, leaks))
3153
def test_testcase_without_addCleanups(self):
3154
"""Check old TestCase instances don't break with leak detection"""
3155
class Test(unittest.TestCase):
3158
result = self.LeakRecordingResult()
3160
result.startTestRun()
3162
result.stopTestRun()
3163
self.assertEqual(result._tests_leaking_threads_count, 0)
3164
self.assertEqual(result.leaks, [])
3166
def test_thread_leak(self):
3167
"""Ensure a thread that outlives the running of a test is reported
3169
Uses a thread that blocks on an event, and is started by the inner
3170
test case. As the thread outlives the inner case's run, it should be
3171
detected as a leak, but the event is then set so that the thread can
3172
be safely joined in cleanup so it's not leaked for real.
3174
event = threading.Event()
3175
thread = threading.Thread(name="Leaker", target=event.wait)
3176
class Test(tests.TestCase):
3177
def test_leak(self):
3179
result = self.LeakRecordingResult()
3180
test = Test("test_leak")
3181
self.addCleanup(thread.join)
3182
self.addCleanup(event.set)
3183
result.startTestRun()
3185
result.stopTestRun()
3186
self.assertEqual(result._tests_leaking_threads_count, 1)
3187
self.assertEqual(result._first_thread_leaker_id, test.id())
3188
self.assertEqual(result.leaks, [(test, set([thread]))])
3189
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3191
def test_multiple_leaks(self):
3192
"""Check multiple leaks are blamed on the test cases at fault
3194
Same concept as the previous test, but has one inner test method that
3195
leaks two threads, and one that doesn't leak at all.
3197
event = threading.Event()
3198
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3199
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3200
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3201
class Test(tests.TestCase):
3202
def test_first_leak(self):
3204
def test_second_no_leak(self):
3206
def test_third_leak(self):
3209
result = self.LeakRecordingResult()
3210
first_test = Test("test_first_leak")
3211
third_test = Test("test_third_leak")
3212
self.addCleanup(thread_a.join)
3213
self.addCleanup(thread_b.join)
3214
self.addCleanup(thread_c.join)
3215
self.addCleanup(event.set)
3216
result.startTestRun()
3218
[first_test, Test("test_second_no_leak"), third_test]
3220
result.stopTestRun()
3221
self.assertEqual(result._tests_leaking_threads_count, 2)
3222
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3223
self.assertEqual(result.leaks, [
3224
(first_test, set([thread_b])),
3225
(third_test, set([thread_a, thread_c]))])
3226
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3229
class TestPostMortemDebugging(tests.TestCase):
3230
"""Check post mortem debugging works when tests fail or error"""
3232
class TracebackRecordingResult(tests.ExtendedTestResult):
3234
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3235
self.postcode = None
3236
def _post_mortem(self, tb=None):
3237
"""Record the code object at the end of the current traceback"""
3238
tb = tb or sys.exc_info()[2]
3241
while next is not None:
3244
self.postcode = tb.tb_frame.f_code
3245
def report_error(self, test, err):
3247
def report_failure(self, test, err):
3250
def test_location_unittest_error(self):
3251
"""Needs right post mortem traceback with erroring unittest case"""
3252
class Test(unittest.TestCase):
3255
result = self.TracebackRecordingResult()
3257
self.assertEqual(result.postcode, Test.runTest.func_code)
3259
def test_location_unittest_failure(self):
3260
"""Needs right post mortem traceback with failing unittest case"""
3261
class Test(unittest.TestCase):
3263
raise self.failureException
3264
result = self.TracebackRecordingResult()
3266
self.assertEqual(result.postcode, Test.runTest.func_code)
3268
def test_location_bt_error(self):
3269
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3270
class Test(tests.TestCase):
3271
def test_error(self):
3273
result = self.TracebackRecordingResult()
3274
Test("test_error").run(result)
3275
self.assertEqual(result.postcode, Test.test_error.func_code)
3277
def test_location_bt_failure(self):
3278
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3279
class Test(tests.TestCase):
3280
def test_failure(self):
3281
raise self.failureException
3282
result = self.TracebackRecordingResult()
3283
Test("test_failure").run(result)
3284
self.assertEqual(result.postcode, Test.test_failure.func_code)
3286
def test_env_var_triggers_post_mortem(self):
3287
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3289
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3290
post_mortem_calls = []
3291
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3292
self.overrideEnv('BZR_TEST_PDB', None)
3293
result._post_mortem(1)
3294
self.overrideEnv('BZR_TEST_PDB', 'on')
3295
result._post_mortem(2)
3296
self.assertEqual([2], post_mortem_calls)
3299
class TestRunSuite(tests.TestCase):
3301
def test_runner_class(self):
3302
"""run_suite accepts and uses a runner_class keyword argument."""
3303
class Stub(tests.TestCase):
3306
suite = Stub("test_foo")
3308
class MyRunner(tests.TextTestRunner):
3309
def run(self, test):
3311
return tests.ExtendedTestResult(self.stream, self.descriptions,
3313
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3314
self.assertLength(1, calls)
3317
class TestEnvironHandling(tests.TestCase):
3319
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3320
self.assertFalse('MYVAR' in os.environ)
3321
self.overrideEnv('MYVAR', '42')
3322
# We use an embedded test to make sure we fix the _captureVar bug
3323
class Test(tests.TestCase):
3325
# The first call save the 42 value
3326
self.overrideEnv('MYVAR', None)
3327
self.assertEquals(None, os.environ.get('MYVAR'))
3328
# Make sure we can call it twice
3329
self.overrideEnv('MYVAR', None)
3330
self.assertEquals(None, os.environ.get('MYVAR'))
3332
result = tests.TextTestResult(output, 0, 1)
3333
Test('test_me').run(result)
3334
if not result.wasStrictlySuccessful():
3335
self.fail(output.getvalue())
3336
# We get our value back
3337
self.assertEquals('42', os.environ.get('MYVAR'))
3340
class TestIsolatedEnv(tests.TestCase):
3341
"""Test isolating tests from os.environ.
3343
Since we use tests that are already isolated from os.environ a bit of care
3344
should be taken when designing the tests to avoid bootstrap side-effects.
3345
The tests start an already clean os.environ which allow doing valid
3346
assertions about which variables are present or not and design tests around
3350
class ScratchMonkey(tests.TestCase):
3355
def test_basics(self):
3356
# Make sure we know the definition of BZR_HOME: not part of os.environ
3357
# for tests.TestCase.
3358
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3359
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3360
# Being part of isolated_environ, BZR_HOME should not appear here
3361
self.assertFalse('BZR_HOME' in os.environ)
3362
# Make sure we know the definition of LINES: part of os.environ for
3364
self.assertTrue('LINES' in tests.isolated_environ)
3365
self.assertEquals('25', tests.isolated_environ['LINES'])
3366
self.assertEquals('25', os.environ['LINES'])
3368
def test_injecting_unknown_variable(self):
3369
# BZR_HOME is known to be absent from os.environ
3370
test = self.ScratchMonkey('test_me')
3371
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3372
self.assertEquals('foo', os.environ['BZR_HOME'])
3373
tests.restore_os_environ(test)
3374
self.assertFalse('BZR_HOME' in os.environ)
3376
def test_injecting_known_variable(self):
3377
test = self.ScratchMonkey('test_me')
3378
# LINES is known to be present in os.environ
3379
tests.override_os_environ(test, {'LINES': '42'})
3380
self.assertEquals('42', os.environ['LINES'])
3381
tests.restore_os_environ(test)
3382
self.assertEquals('25', os.environ['LINES'])
3384
def test_deleting_variable(self):
3385
test = self.ScratchMonkey('test_me')
3386
# LINES is known to be present in os.environ
3387
tests.override_os_environ(test, {'LINES': None})
3388
self.assertTrue('LINES' not in os.environ)
3389
tests.restore_os_environ(test)
3390
self.assertEquals('25', os.environ['LINES'])
3393
class TestDocTestSuiteIsolation(tests.TestCase):
3394
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3396
Since tests.TestCase alreay provides an isolation from os.environ, we use
3397
the clean environment as a base for testing. To precisely capture the
3398
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3401
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3402
not `os.environ` so each test overrides it to suit its needs.
3406
def get_doctest_suite_for_string(self, klass, string):
3407
class Finder(doctest.DocTestFinder):
3409
def find(*args, **kwargs):
3410
test = doctest.DocTestParser().get_doctest(
3411
string, {}, 'foo', 'foo.py', 0)
3414
suite = klass(test_finder=Finder())
3417
def run_doctest_suite_for_string(self, klass, string):
3418
suite = self.get_doctest_suite_for_string(klass, string)
3420
result = tests.TextTestResult(output, 0, 1)
3422
return result, output
3424
def assertDocTestStringSucceds(self, klass, string):
3425
result, output = self.run_doctest_suite_for_string(klass, string)
3426
if not result.wasStrictlySuccessful():
3427
self.fail(output.getvalue())
3429
def assertDocTestStringFails(self, klass, string):
3430
result, output = self.run_doctest_suite_for_string(klass, string)
3431
if result.wasStrictlySuccessful():
3432
self.fail(output.getvalue())
3434
def test_injected_variable(self):
3435
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3438
>>> os.environ['LINES']
3441
# doctest.DocTestSuite fails as it sees '25'
3442
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3443
# tests.DocTestSuite sees '42'
3444
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3446
def test_deleted_variable(self):
3447
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3450
>>> os.environ.get('LINES')
3452
# doctest.DocTestSuite fails as it sees '25'
3453
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3454
# tests.DocTestSuite sees None
3455
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3458
class TestSelftestExcludePatterns(tests.TestCase):
3461
super(TestSelftestExcludePatterns, self).setUp()
3462
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3464
def suite_factory(self, keep_only=None, starting_with=None):
3465
"""A test suite factory with only a few tests."""
3466
class Test(tests.TestCase):
3468
# We don't need the full class path
3469
return self._testMethodName
3476
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3478
def assertTestList(self, expected, *selftest_args):
3479
# We rely on setUp installing the right test suite factory so we can
3480
# test at the command level without loading the whole test suite
3481
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3482
actual = out.splitlines()
3483
self.assertEquals(expected, actual)
3485
def test_full_list(self):
3486
self.assertTestList(['a', 'b', 'c'])
3488
def test_single_exclude(self):
3489
self.assertTestList(['b', 'c'], '-x', 'a')
3491
def test_mutiple_excludes(self):
3492
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3495
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3497
_test_needs_features = [features.subunit]
3500
super(TestCounterHooks, self).setUp()
3501
class Test(tests.TestCase):
3504
super(Test, self).setUp()
3505
self.hooks = hooks.Hooks()
3506
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3507
self.install_counter_hook(self.hooks, 'myhook')
3512
def run_hook_once(self):
3513
for hook in self.hooks['myhook']:
3516
self.test_class = Test
3518
def assertHookCalls(self, expected_calls, test_name):
3519
test = self.test_class(test_name)
3520
result = unittest.TestResult()
3522
self.assertTrue(hasattr(test, '_counters'))
3523
self.assertTrue(test._counters.has_key('myhook'))
3524
self.assertEquals(expected_calls, test._counters['myhook'])
3526
def test_no_hook(self):
3527
self.assertHookCalls(0, 'no_hook')
3529
def test_run_hook_once(self):
3530
tt = features.testtools
3531
if tt.module.__version__ < (0, 9, 8):
3532
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3533
self.assertHookCalls(1, 'run_hook_once')