1
# Copyright (C) 2005-2010 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
20
from doctest import ELLIPSIS
29
from testtools import MultiTestResult
30
from testtools.content import Content
31
from testtools.content_type import ContentType
32
from testtools.matchers import (
36
import testtools.tests.helpers
54
from bzrlib.repofmt import (
59
from bzrlib.symbol_versioning import (
64
from bzrlib.tests import (
71
from bzrlib.trace import note, mutter
72
from bzrlib.transport import memory
73
from bzrlib.version import _get_bzr_source_tree
76
def _test_ids(test_suite):
77
"""Get the ids for the tests in a test suite."""
78
return [t.id() for t in tests.iter_suite_tests(test_suite)]
81
class SelftestTests(tests.TestCase):
83
def test_import_tests(self):
84
mod = TestUtil._load_module_by_name('bzrlib.tests.test_selftest')
85
self.assertEqual(mod.SelftestTests, SelftestTests)
87
def test_import_test_failure(self):
88
self.assertRaises(ImportError,
89
TestUtil._load_module_by_name,
93
class MetaTestLog(tests.TestCase):
95
def test_logging(self):
96
"""Test logs are captured when a test fails."""
97
self.log('a test message')
98
details = self.getDetails()
100
self.assertThat(log.content_type, Equals(ContentType(
101
"text", "plain", {"charset": "utf8"})))
102
self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
103
self.assertThat(self.get_log(),
104
DocTestMatches(u"...a test message\n", ELLIPSIS))
107
class TestUnicodeFilename(tests.TestCase):
109
def test_probe_passes(self):
110
"""UnicodeFilename._probe passes."""
111
# We can't test much more than that because the behaviour depends
113
tests.UnicodeFilename._probe()
116
class TestTreeShape(tests.TestCaseInTempDir):
118
def test_unicode_paths(self):
119
self.requireFeature(tests.UnicodeFilename)
121
filename = u'hell\u00d8'
122
self.build_tree_contents([(filename, 'contents of hello')])
123
self.failUnlessExists(filename)
126
class TestClassesAvailable(tests.TestCase):
127
"""As a convenience we expose Test* classes from bzrlib.tests"""
129
def test_test_case(self):
130
from bzrlib.tests import TestCase
132
def test_test_loader(self):
133
from bzrlib.tests import TestLoader
135
def test_test_suite(self):
136
from bzrlib.tests import TestSuite
139
class TestTransportScenarios(tests.TestCase):
140
"""A group of tests that test the transport implementation adaption core.
142
This is a meta test that the tests are applied to all available
145
This will be generalised in the future which is why it is in this
146
test file even though it is specific to transport tests at the moment.
149
def test_get_transport_permutations(self):
150
# this checks that get_test_permutations defined by the module is
151
# called by the get_transport_test_permutations function.
152
class MockModule(object):
153
def get_test_permutations(self):
154
return sample_permutation
155
sample_permutation = [(1,2), (3,4)]
156
from bzrlib.tests.per_transport import get_transport_test_permutations
157
self.assertEqual(sample_permutation,
158
get_transport_test_permutations(MockModule()))
160
def test_scenarios_include_all_modules(self):
161
# this checks that the scenario generator returns as many permutations
162
# as there are in all the registered transport modules - we assume if
163
# this matches its probably doing the right thing especially in
164
# combination with the tests for setting the right classes below.
165
from bzrlib.tests.per_transport import transport_test_permutations
166
from bzrlib.transport import _get_transport_modules
167
modules = _get_transport_modules()
168
permutation_count = 0
169
for module in modules:
171
permutation_count += len(reduce(getattr,
172
(module + ".get_test_permutations").split('.')[1:],
173
__import__(module))())
174
except errors.DependencyNotPresent:
176
scenarios = transport_test_permutations()
177
self.assertEqual(permutation_count, len(scenarios))
179
def test_scenarios_include_transport_class(self):
180
# This test used to know about all the possible transports and the
181
# order they were returned but that seems overly brittle (mbp
183
from bzrlib.tests.per_transport import transport_test_permutations
184
scenarios = transport_test_permutations()
185
# there are at least that many builtin transports
186
self.assertTrue(len(scenarios) > 6)
187
one_scenario = scenarios[0]
188
self.assertIsInstance(one_scenario[0], str)
189
self.assertTrue(issubclass(one_scenario[1]["transport_class"],
190
bzrlib.transport.Transport))
191
self.assertTrue(issubclass(one_scenario[1]["transport_server"],
192
bzrlib.transport.Server))
195
class TestBranchScenarios(tests.TestCase):
197
def test_scenarios(self):
198
# check that constructor parameters are passed through to the adapted
200
from bzrlib.tests.per_branch import make_scenarios
203
formats = [("c", "C"), ("d", "D")]
204
scenarios = make_scenarios(server1, server2, formats)
205
self.assertEqual(2, len(scenarios))
208
{'branch_format': 'c',
209
'bzrdir_format': 'C',
210
'transport_readonly_server': 'b',
211
'transport_server': 'a'}),
213
{'branch_format': 'd',
214
'bzrdir_format': 'D',
215
'transport_readonly_server': 'b',
216
'transport_server': 'a'})],
220
class TestBzrDirScenarios(tests.TestCase):
222
def test_scenarios(self):
223
# check that constructor parameters are passed through to the adapted
225
from bzrlib.tests.per_controldir import make_scenarios
230
scenarios = make_scenarios(vfs_factory, server1, server2, formats)
233
{'bzrdir_format': 'c',
234
'transport_readonly_server': 'b',
235
'transport_server': 'a',
236
'vfs_transport_factory': 'v'}),
238
{'bzrdir_format': 'd',
239
'transport_readonly_server': 'b',
240
'transport_server': 'a',
241
'vfs_transport_factory': 'v'})],
245
class TestRepositoryScenarios(tests.TestCase):
247
def test_formats_to_scenarios(self):
248
from bzrlib.tests.per_repository import formats_to_scenarios
249
formats = [("(c)", remote.RemoteRepositoryFormat()),
250
("(d)", repository.format_registry.get(
251
'Bazaar repository format 2a (needs bzr 1.16 or later)\n'))]
252
no_vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
254
vfs_scenarios = formats_to_scenarios(formats, "server", "readonly",
255
vfs_transport_factory="vfs")
256
# no_vfs generate scenarios without vfs_transport_factory
258
('RemoteRepositoryFormat(c)',
259
{'bzrdir_format': remote.RemoteBzrDirFormat(),
260
'repository_format': remote.RemoteRepositoryFormat(),
261
'transport_readonly_server': 'readonly',
262
'transport_server': 'server'}),
263
('RepositoryFormat2a(d)',
264
{'bzrdir_format': bzrdir.BzrDirMetaFormat1(),
265
'repository_format': groupcompress_repo.RepositoryFormat2a(),
266
'transport_readonly_server': 'readonly',
267
'transport_server': 'server'})]
268
self.assertEqual(expected, no_vfs_scenarios)
270
('RemoteRepositoryFormat(c)',
271
{'bzrdir_format': remote.RemoteBzrDirFormat(),
272
'repository_format': remote.RemoteRepositoryFormat(),
273
'transport_readonly_server': 'readonly',
274
'transport_server': 'server',
275
'vfs_transport_factory': 'vfs'}),
276
('RepositoryFormat2a(d)',
277
{'bzrdir_format': bzrdir.BzrDirMetaFormat1(),
278
'repository_format': groupcompress_repo.RepositoryFormat2a(),
279
'transport_readonly_server': 'readonly',
280
'transport_server': 'server',
281
'vfs_transport_factory': 'vfs'})],
285
class TestTestScenarioApplication(tests.TestCase):
286
"""Tests for the test adaption facilities."""
288
def test_apply_scenario(self):
289
from bzrlib.tests import apply_scenario
290
input_test = TestTestScenarioApplication("test_apply_scenario")
291
# setup two adapted tests
292
adapted_test1 = apply_scenario(input_test,
294
{"bzrdir_format":"bzr_format",
295
"repository_format":"repo_fmt",
296
"transport_server":"transport_server",
297
"transport_readonly_server":"readonly-server"}))
298
adapted_test2 = apply_scenario(input_test,
299
("new id 2", {"bzrdir_format":None}))
300
# input_test should have been altered.
301
self.assertRaises(AttributeError, getattr, input_test, "bzrdir_format")
302
# the new tests are mutually incompatible, ensuring it has
303
# made new ones, and unspecified elements in the scenario
304
# should not have been altered.
305
self.assertEqual("bzr_format", adapted_test1.bzrdir_format)
306
self.assertEqual("repo_fmt", adapted_test1.repository_format)
307
self.assertEqual("transport_server", adapted_test1.transport_server)
308
self.assertEqual("readonly-server",
309
adapted_test1.transport_readonly_server)
311
"bzrlib.tests.test_selftest.TestTestScenarioApplication."
312
"test_apply_scenario(new id)",
314
self.assertEqual(None, adapted_test2.bzrdir_format)
316
"bzrlib.tests.test_selftest.TestTestScenarioApplication."
317
"test_apply_scenario(new id 2)",
321
class TestInterRepositoryScenarios(tests.TestCase):
323
def test_scenarios(self):
324
# check that constructor parameters are passed through to the adapted
326
from bzrlib.tests.per_interrepository import make_scenarios
329
formats = [("C0", "C1", "C2", "C3"), ("D0", "D1", "D2", "D3")]
330
scenarios = make_scenarios(server1, server2, formats)
333
{'repository_format': 'C1',
334
'repository_format_to': 'C2',
335
'transport_readonly_server': 'b',
336
'transport_server': 'a',
337
'extra_setup': 'C3'}),
339
{'repository_format': 'D1',
340
'repository_format_to': 'D2',
341
'transport_readonly_server': 'b',
342
'transport_server': 'a',
343
'extra_setup': 'D3'})],
347
class TestWorkingTreeScenarios(tests.TestCase):
349
def test_scenarios(self):
350
# check that constructor parameters are passed through to the adapted
352
from bzrlib.tests.per_workingtree import make_scenarios
355
formats = [workingtree.WorkingTreeFormat2(),
356
workingtree.WorkingTreeFormat3(),]
357
scenarios = make_scenarios(server1, server2, formats)
359
('WorkingTreeFormat2',
360
{'bzrdir_format': formats[0]._matchingbzrdir,
361
'transport_readonly_server': 'b',
362
'transport_server': 'a',
363
'workingtree_format': formats[0]}),
364
('WorkingTreeFormat3',
365
{'bzrdir_format': formats[1]._matchingbzrdir,
366
'transport_readonly_server': 'b',
367
'transport_server': 'a',
368
'workingtree_format': formats[1]})],
372
class TestTreeScenarios(tests.TestCase):
374
def test_scenarios(self):
375
# the tree implementation scenario generator is meant to setup one
376
# instance for each working tree format, and one additional instance
377
# that will use the default wt format, but create a revision tree for
378
# the tests. this means that the wt ones should have the
379
# workingtree_to_test_tree attribute set to 'return_parameter' and the
380
# revision one set to revision_tree_from_workingtree.
382
from bzrlib.tests.per_tree import (
383
_dirstate_tree_from_workingtree,
388
revision_tree_from_workingtree
392
formats = [workingtree.WorkingTreeFormat2(),
393
workingtree.WorkingTreeFormat3(),]
394
scenarios = make_scenarios(server1, server2, formats)
395
self.assertEqual(7, len(scenarios))
396
default_wt_format = workingtree.WorkingTreeFormat4._default_format
397
wt4_format = workingtree.WorkingTreeFormat4()
398
wt5_format = workingtree.WorkingTreeFormat5()
399
expected_scenarios = [
400
('WorkingTreeFormat2',
401
{'bzrdir_format': formats[0]._matchingbzrdir,
402
'transport_readonly_server': 'b',
403
'transport_server': 'a',
404
'workingtree_format': formats[0],
405
'_workingtree_to_test_tree': return_parameter,
407
('WorkingTreeFormat3',
408
{'bzrdir_format': formats[1]._matchingbzrdir,
409
'transport_readonly_server': 'b',
410
'transport_server': 'a',
411
'workingtree_format': formats[1],
412
'_workingtree_to_test_tree': return_parameter,
415
{'_workingtree_to_test_tree': revision_tree_from_workingtree,
416
'bzrdir_format': default_wt_format._matchingbzrdir,
417
'transport_readonly_server': 'b',
418
'transport_server': 'a',
419
'workingtree_format': default_wt_format,
421
('DirStateRevisionTree,WT4',
422
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
423
'bzrdir_format': wt4_format._matchingbzrdir,
424
'transport_readonly_server': 'b',
425
'transport_server': 'a',
426
'workingtree_format': wt4_format,
428
('DirStateRevisionTree,WT5',
429
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
430
'bzrdir_format': wt5_format._matchingbzrdir,
431
'transport_readonly_server': 'b',
432
'transport_server': 'a',
433
'workingtree_format': wt5_format,
436
{'_workingtree_to_test_tree': preview_tree_pre,
437
'bzrdir_format': default_wt_format._matchingbzrdir,
438
'transport_readonly_server': 'b',
439
'transport_server': 'a',
440
'workingtree_format': default_wt_format}),
442
{'_workingtree_to_test_tree': preview_tree_post,
443
'bzrdir_format': default_wt_format._matchingbzrdir,
444
'transport_readonly_server': 'b',
445
'transport_server': 'a',
446
'workingtree_format': default_wt_format}),
448
self.assertEqual(expected_scenarios, scenarios)
451
class TestInterTreeScenarios(tests.TestCase):
452
"""A group of tests that test the InterTreeTestAdapter."""
454
def test_scenarios(self):
455
# check that constructor parameters are passed through to the adapted
457
# for InterTree tests we want the machinery to bring up two trees in
458
# each instance: the base one, and the one we are interacting with.
459
# because each optimiser can be direction specific, we need to test
460
# each optimiser in its chosen direction.
461
# unlike the TestProviderAdapter we dont want to automatically add a
462
# parameterized one for WorkingTree - the optimisers will tell us what
464
from bzrlib.tests.per_tree import (
466
revision_tree_from_workingtree
468
from bzrlib.tests.per_intertree import (
471
from bzrlib.workingtree import WorkingTreeFormat2, WorkingTreeFormat3
472
input_test = TestInterTreeScenarios(
476
format1 = WorkingTreeFormat2()
477
format2 = WorkingTreeFormat3()
478
formats = [("1", str, format1, format2, "converter1"),
479
("2", int, format2, format1, "converter2")]
480
scenarios = make_scenarios(server1, server2, formats)
481
self.assertEqual(2, len(scenarios))
482
expected_scenarios = [
484
"bzrdir_format": format1._matchingbzrdir,
485
"intertree_class": formats[0][1],
486
"workingtree_format": formats[0][2],
487
"workingtree_format_to": formats[0][3],
488
"mutable_trees_to_test_trees": formats[0][4],
489
"_workingtree_to_test_tree": return_parameter,
490
"transport_server": server1,
491
"transport_readonly_server": server2,
494
"bzrdir_format": format2._matchingbzrdir,
495
"intertree_class": formats[1][1],
496
"workingtree_format": formats[1][2],
497
"workingtree_format_to": formats[1][3],
498
"mutable_trees_to_test_trees": formats[1][4],
499
"_workingtree_to_test_tree": return_parameter,
500
"transport_server": server1,
501
"transport_readonly_server": server2,
504
self.assertEqual(scenarios, expected_scenarios)
507
class TestTestCaseInTempDir(tests.TestCaseInTempDir):
509
def test_home_is_not_working(self):
510
self.assertNotEqual(self.test_dir, self.test_home_dir)
511
cwd = osutils.getcwd()
512
self.assertIsSameRealPath(self.test_dir, cwd)
513
self.assertIsSameRealPath(self.test_home_dir, os.environ['HOME'])
515
def test_assertEqualStat_equal(self):
516
from bzrlib.tests.test_dirstate import _FakeStat
517
self.build_tree(["foo"])
518
real = os.lstat("foo")
519
fake = _FakeStat(real.st_size, real.st_mtime, real.st_ctime,
520
real.st_dev, real.st_ino, real.st_mode)
521
self.assertEqualStat(real, fake)
523
def test_assertEqualStat_notequal(self):
524
self.build_tree(["foo", "longname"])
525
self.assertRaises(AssertionError, self.assertEqualStat,
526
os.lstat("foo"), os.lstat("longname"))
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.failIf(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 = weaverepo.RepositoryFormat7()
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.failIf(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.failIf(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 = weaverepo.RepositoryFormat7()
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.failIf(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.failIf(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.failUnless(isinstance(t, ReadonlyTransportDecorator))
651
self.failUnless(isinstance(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.failUnless(isinstance(t, HttpTransportBase))
666
self.failUnless(isinstance(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.failUnlessExists('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.failIfExists('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(test_lsprof.LSProfFeature)
717
terminal = testtools.tests.helpers.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.tests.helpers.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 _patch_get_bzr_source_tree(self):
768
# Reading from the actual source tree breaks isolation, but we don't
769
# want to assume that thats *all* that would happen.
770
self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', lambda: None)
772
def test_assigned_benchmark_file_stores_date(self):
773
self._patch_get_bzr_source_tree()
775
result = bzrlib.tests.TextTestResult(self._log_file,
780
output_string = output.getvalue()
781
# if you are wondering about the regexp please read the comment in
782
# test_bench_history (bzrlib.tests.test_selftest.TestRunner)
783
# XXX: what comment? -- Andrew Bennetts
784
self.assertContainsRe(output_string, "--date [0-9.]+")
786
def test_benchhistory_records_test_times(self):
787
self._patch_get_bzr_source_tree()
788
result_stream = StringIO()
789
result = bzrlib.tests.TextTestResult(
793
bench_history=result_stream
796
# we want profile a call and check that its test duration is recorded
797
# make a new test instance that when run will generate a benchmark
798
example_test_case = TestTestResult("_time_hello_world_encoding")
799
# execute the test, which should succeed and record times
800
example_test_case.run(result)
801
lines = result_stream.getvalue().splitlines()
802
self.assertEqual(2, len(lines))
803
self.assertContainsRe(lines[1],
804
" *[0-9]+ms bzrlib.tests.test_selftest.TestTestResult"
805
"._time_hello_world_encoding")
807
def _time_hello_world_encoding(self):
808
"""Profile two sleep calls
810
This is used to exercise the test framework.
812
self.time(unicode, 'hello', errors='replace')
813
self.time(unicode, 'world', errors='replace')
815
def test_lsprofiling(self):
816
"""Verbose test result prints lsprof statistics from test cases."""
817
self.requireFeature(test_lsprof.LSProfFeature)
818
result_stream = StringIO()
819
result = bzrlib.tests.VerboseTestResult(
824
# we want profile a call of some sort and check it is output by
825
# addSuccess. We dont care about addError or addFailure as they
826
# are not that interesting for performance tuning.
827
# make a new test instance that when run will generate a profile
828
example_test_case = TestTestResult("_time_hello_world_encoding")
829
example_test_case._gather_lsprof_in_benchmarks = True
830
# execute the test, which should succeed and record profiles
831
example_test_case.run(result)
832
# lsprofile_something()
833
# if this worked we want
834
# LSProf output for <built in function unicode> (['hello'], {'errors': 'replace'})
835
# CallCount Recursive Total(ms) Inline(ms) module:lineno(function)
836
# (the lsprof header)
837
# ... an arbitrary number of lines
838
# and the function call which is time.sleep.
839
# 1 0 ??? ??? ???(sleep)
840
# and then repeated but with 'world', rather than 'hello'.
841
# this should appear in the output stream of our test result.
842
output = result_stream.getvalue()
843
self.assertContainsRe(output,
844
r"LSProf output for <type 'unicode'>\(\('hello',\), {'errors': 'replace'}\)")
845
self.assertContainsRe(output,
846
r" *CallCount *Recursive *Total\(ms\) *Inline\(ms\) *module:lineno\(function\)\n")
847
self.assertContainsRe(output,
848
r"( +1 +0 +0\.\d+ +0\.\d+ +<method 'disable' of '_lsprof\.Profiler' objects>\n)?")
849
self.assertContainsRe(output,
850
r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
852
def test_known_failure(self):
853
"""A KnownFailure being raised should trigger several result actions."""
854
class InstrumentedTestResult(tests.ExtendedTestResult):
855
def stopTestRun(self): pass
856
def report_tests_starting(self): pass
857
def report_known_failure(self, test, err=None, details=None):
858
self._call = test, 'known failure'
859
result = InstrumentedTestResult(None, None, None, None)
860
class Test(tests.TestCase):
861
def test_function(self):
862
raise tests.KnownFailure('failed!')
863
test = Test("test_function")
865
# it should invoke 'report_known_failure'.
866
self.assertEqual(2, len(result._call))
867
self.assertEqual(test.id(), result._call[0].id())
868
self.assertEqual('known failure', result._call[1])
869
# we dont introspec the traceback, if the rest is ok, it would be
870
# exceptional for it not to be.
871
# it should update the known_failure_count on the object.
872
self.assertEqual(1, result.known_failure_count)
873
# the result should be successful.
874
self.assertTrue(result.wasSuccessful())
876
def test_verbose_report_known_failure(self):
877
# verbose test output formatting
878
result_stream = StringIO()
879
result = bzrlib.tests.VerboseTestResult(
884
test = self.get_passing_test()
885
result.startTest(test)
886
prefix = len(result_stream.getvalue())
887
# the err parameter has the shape:
888
# (class, exception object, traceback)
889
# KnownFailures dont get their tracebacks shown though, so we
891
err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
892
result.report_known_failure(test, err)
893
output = result_stream.getvalue()[prefix:]
894
lines = output.splitlines()
895
self.assertContainsRe(lines[0], r'XFAIL *\d+ms$')
896
if sys.version_info > (2, 7):
897
self.expectFailure("_ExpectedFailure on 2.7 loses the message",
898
self.assertNotEqual, lines[1], ' ')
899
self.assertEqual(lines[1], ' foo')
900
self.assertEqual(2, len(lines))
902
def get_passing_test(self):
903
"""Return a test object that can't be run usefully."""
906
return unittest.FunctionTestCase(passing_test)
908
def test_add_not_supported(self):
909
"""Test the behaviour of invoking addNotSupported."""
910
class InstrumentedTestResult(tests.ExtendedTestResult):
911
def stopTestRun(self): pass
912
def report_tests_starting(self): pass
913
def report_unsupported(self, test, feature):
914
self._call = test, feature
915
result = InstrumentedTestResult(None, None, None, None)
916
test = SampleTestCase('_test_pass')
917
feature = tests.Feature()
918
result.startTest(test)
919
result.addNotSupported(test, feature)
920
# it should invoke 'report_unsupported'.
921
self.assertEqual(2, len(result._call))
922
self.assertEqual(test, result._call[0])
923
self.assertEqual(feature, result._call[1])
924
# the result should be successful.
925
self.assertTrue(result.wasSuccessful())
926
# it should record the test against a count of tests not run due to
928
self.assertEqual(1, result.unsupported['Feature'])
929
# and invoking it again should increment that counter
930
result.addNotSupported(test, feature)
931
self.assertEqual(2, result.unsupported['Feature'])
933
def test_verbose_report_unsupported(self):
934
# verbose test output formatting
935
result_stream = StringIO()
936
result = bzrlib.tests.VerboseTestResult(
941
test = self.get_passing_test()
942
feature = tests.Feature()
943
result.startTest(test)
944
prefix = len(result_stream.getvalue())
945
result.report_unsupported(test, feature)
946
output = result_stream.getvalue()[prefix:]
947
lines = output.splitlines()
948
# We don't check for the final '0ms' since it may fail on slow hosts
949
self.assertStartsWith(lines[0], 'NODEP')
950
self.assertEqual(lines[1],
951
" The feature 'Feature' is not available.")
953
def test_unavailable_exception(self):
954
"""An UnavailableFeature being raised should invoke addNotSupported."""
955
class InstrumentedTestResult(tests.ExtendedTestResult):
956
def stopTestRun(self): pass
957
def report_tests_starting(self): pass
958
def addNotSupported(self, test, feature):
959
self._call = test, feature
960
result = InstrumentedTestResult(None, None, None, None)
961
feature = tests.Feature()
962
class Test(tests.TestCase):
963
def test_function(self):
964
raise tests.UnavailableFeature(feature)
965
test = Test("test_function")
967
# it should invoke 'addNotSupported'.
968
self.assertEqual(2, len(result._call))
969
self.assertEqual(test.id(), result._call[0].id())
970
self.assertEqual(feature, result._call[1])
971
# and not count as an error
972
self.assertEqual(0, result.error_count)
974
def test_strict_with_unsupported_feature(self):
975
result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
977
test = self.get_passing_test()
978
feature = "Unsupported Feature"
979
result.addNotSupported(test, feature)
980
self.assertFalse(result.wasStrictlySuccessful())
981
self.assertEqual(None, result._extractBenchmarkTime(test))
983
def test_strict_with_known_failure(self):
984
result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
986
test = self.get_passing_test()
987
err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
988
result.addExpectedFailure(test, err)
989
self.assertFalse(result.wasStrictlySuccessful())
990
self.assertEqual(None, result._extractBenchmarkTime(test))
992
def test_strict_with_success(self):
993
result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
995
test = self.get_passing_test()
996
result.addSuccess(test)
997
self.assertTrue(result.wasStrictlySuccessful())
998
self.assertEqual(None, result._extractBenchmarkTime(test))
1000
def test_startTests(self):
1001
"""Starting the first test should trigger startTests."""
1002
class InstrumentedTestResult(tests.ExtendedTestResult):
1004
def startTests(self): self.calls += 1
1005
result = InstrumentedTestResult(None, None, None, None)
1006
def test_function():
1008
test = unittest.FunctionTestCase(test_function)
1010
self.assertEquals(1, result.calls)
1012
def test_startTests_only_once(self):
1013
"""With multiple tests startTests should still only be called once"""
1014
class InstrumentedTestResult(tests.ExtendedTestResult):
1016
def startTests(self): self.calls += 1
1017
result = InstrumentedTestResult(None, None, None, None)
1018
suite = unittest.TestSuite([
1019
unittest.FunctionTestCase(lambda: None),
1020
unittest.FunctionTestCase(lambda: None)])
1022
self.assertEquals(1, result.calls)
1023
self.assertEquals(2, result.count)
1026
class TestUnicodeFilenameFeature(tests.TestCase):
1028
def test_probe_passes(self):
1029
"""UnicodeFilenameFeature._probe passes."""
1030
# We can't test much more than that because the behaviour depends
1032
tests.UnicodeFilenameFeature._probe()
1035
class TestRunner(tests.TestCase):
1037
def dummy_test(self):
1040
def run_test_runner(self, testrunner, test):
1041
"""Run suite in testrunner, saving global state and restoring it.
1043
This current saves and restores:
1044
TestCaseInTempDir.TEST_ROOT
1046
There should be no tests in this file that use
1047
bzrlib.tests.TextTestRunner without using this convenience method,
1048
because of our use of global state.
1050
old_root = tests.TestCaseInTempDir.TEST_ROOT
1052
tests.TestCaseInTempDir.TEST_ROOT = None
1053
return testrunner.run(test)
1055
tests.TestCaseInTempDir.TEST_ROOT = old_root
1057
def test_known_failure_failed_run(self):
1058
# run a test that generates a known failure which should be printed in
1059
# the final output when real failures occur.
1060
class Test(tests.TestCase):
1061
def known_failure_test(self):
1062
self.expectFailure('failed', self.assertTrue, False)
1063
test = unittest.TestSuite()
1064
test.addTest(Test("known_failure_test"))
1067
test.addTest(unittest.FunctionTestCase(failing_test))
1069
runner = tests.TextTestRunner(stream=stream)
1070
result = self.run_test_runner(runner, test)
1071
lines = stream.getvalue().splitlines()
1072
self.assertContainsRe(stream.getvalue(),
1073
'(?sm)^bzr selftest.*$'
1075
'^======================================================================\n'
1076
'^FAIL: failing_test\n'
1077
'^----------------------------------------------------------------------\n'
1078
'Traceback \\(most recent call last\\):\n'
1079
' .*' # File .*, line .*, in failing_test' - but maybe not from .pyc
1080
' self.fail\\(\'foo\'\\)\n'
1082
'^----------------------------------------------------------------------\n'
1084
'FAILED \\(failures=1, known_failure_count=1\\)'
1087
def test_known_failure_ok_run(self):
1088
# run a test that generates a known failure which should be printed in
1090
class Test(tests.TestCase):
1091
def known_failure_test(self):
1092
self.expectFailure('failed', self.assertTrue, False)
1093
test = Test("known_failure_test")
1095
runner = tests.TextTestRunner(stream=stream)
1096
result = self.run_test_runner(runner, test)
1097
self.assertContainsRe(stream.getvalue(),
1100
'Ran 1 test in .*\n'
1102
'OK \\(known_failures=1\\)\n')
1104
def test_result_decorator(self):
1107
class LoggingDecorator(tests.ForwardingResult):
1108
def startTest(self, test):
1109
tests.ForwardingResult.startTest(self, test)
1110
calls.append('start')
1111
test = unittest.FunctionTestCase(lambda:None)
1113
runner = tests.TextTestRunner(stream=stream,
1114
result_decorators=[LoggingDecorator])
1115
result = self.run_test_runner(runner, test)
1116
self.assertLength(1, calls)
1118
def test_skipped_test(self):
1119
# run a test that is skipped, and check the suite as a whole still
1121
# skipping_test must be hidden in here so it's not run as a real test
1122
class SkippingTest(tests.TestCase):
1123
def skipping_test(self):
1124
raise tests.TestSkipped('test intentionally skipped')
1125
runner = tests.TextTestRunner(stream=self._log_file)
1126
test = SkippingTest("skipping_test")
1127
result = self.run_test_runner(runner, test)
1128
self.assertTrue(result.wasSuccessful())
1130
def test_skipped_from_setup(self):
1132
class SkippedSetupTest(tests.TestCase):
1135
calls.append('setUp')
1136
self.addCleanup(self.cleanup)
1137
raise tests.TestSkipped('skipped setup')
1139
def test_skip(self):
1140
self.fail('test reached')
1143
calls.append('cleanup')
1145
runner = tests.TextTestRunner(stream=self._log_file)
1146
test = SkippedSetupTest('test_skip')
1147
result = self.run_test_runner(runner, test)
1148
self.assertTrue(result.wasSuccessful())
1149
# Check if cleanup was called the right number of times.
1150
self.assertEqual(['setUp', 'cleanup'], calls)
1152
def test_skipped_from_test(self):
1154
class SkippedTest(tests.TestCase):
1157
tests.TestCase.setUp(self)
1158
calls.append('setUp')
1159
self.addCleanup(self.cleanup)
1161
def test_skip(self):
1162
raise tests.TestSkipped('skipped test')
1165
calls.append('cleanup')
1167
runner = tests.TextTestRunner(stream=self._log_file)
1168
test = SkippedTest('test_skip')
1169
result = self.run_test_runner(runner, test)
1170
self.assertTrue(result.wasSuccessful())
1171
# Check if cleanup was called the right number of times.
1172
self.assertEqual(['setUp', 'cleanup'], calls)
1174
def test_not_applicable(self):
1175
# run a test that is skipped because it's not applicable
1176
class Test(tests.TestCase):
1177
def not_applicable_test(self):
1178
raise tests.TestNotApplicable('this test never runs')
1180
runner = tests.TextTestRunner(stream=out, verbosity=2)
1181
test = Test("not_applicable_test")
1182
result = self.run_test_runner(runner, test)
1183
self._log_file.write(out.getvalue())
1184
self.assertTrue(result.wasSuccessful())
1185
self.assertTrue(result.wasStrictlySuccessful())
1186
self.assertContainsRe(out.getvalue(),
1187
r'(?m)not_applicable_test * N/A')
1188
self.assertContainsRe(out.getvalue(),
1189
r'(?m)^ this test never runs')
1191
def test_unsupported_features_listed(self):
1192
"""When unsupported features are encountered they are detailed."""
1193
class Feature1(tests.Feature):
1194
def _probe(self): return False
1195
class Feature2(tests.Feature):
1196
def _probe(self): return False
1197
# create sample tests
1198
test1 = SampleTestCase('_test_pass')
1199
test1._test_needs_features = [Feature1()]
1200
test2 = SampleTestCase('_test_pass')
1201
test2._test_needs_features = [Feature2()]
1202
test = unittest.TestSuite()
1206
runner = tests.TextTestRunner(stream=stream)
1207
result = self.run_test_runner(runner, test)
1208
lines = stream.getvalue().splitlines()
1211
"Missing feature 'Feature1' skipped 1 tests.",
1212
"Missing feature 'Feature2' skipped 1 tests.",
1216
def _patch_get_bzr_source_tree(self):
1217
# Reading from the actual source tree breaks isolation, but we don't
1218
# want to assume that thats *all* that would happen.
1219
self._get_source_tree_calls = []
1221
self._get_source_tree_calls.append("called")
1223
self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', new_get)
1225
def test_bench_history(self):
1226
# tests that the running the benchmark passes bench_history into
1227
# the test result object. We can tell that happens if
1228
# _get_bzr_source_tree is called.
1229
self._patch_get_bzr_source_tree()
1230
test = TestRunner('dummy_test')
1232
runner = tests.TextTestRunner(stream=self._log_file,
1233
bench_history=output)
1234
result = self.run_test_runner(runner, test)
1235
output_string = output.getvalue()
1236
self.assertContainsRe(output_string, "--date [0-9.]+")
1237
self.assertLength(1, self._get_source_tree_calls)
1239
def test_verbose_test_count(self):
1240
"""A verbose test run reports the right test count at the start"""
1241
suite = TestUtil.TestSuite([
1242
unittest.FunctionTestCase(lambda:None),
1243
unittest.FunctionTestCase(lambda:None)])
1244
self.assertEqual(suite.countTestCases(), 2)
1246
runner = tests.TextTestRunner(stream=stream, verbosity=2)
1247
# Need to use the CountingDecorator as that's what sets num_tests
1248
result = self.run_test_runner(runner, tests.CountingDecorator(suite))
1249
self.assertStartsWith(stream.getvalue(), "running 2 tests")
1251
def test_startTestRun(self):
1252
"""run should call result.startTestRun()"""
1254
class LoggingDecorator(tests.ForwardingResult):
1255
def startTestRun(self):
1256
tests.ForwardingResult.startTestRun(self)
1257
calls.append('startTestRun')
1258
test = unittest.FunctionTestCase(lambda:None)
1260
runner = tests.TextTestRunner(stream=stream,
1261
result_decorators=[LoggingDecorator])
1262
result = self.run_test_runner(runner, test)
1263
self.assertLength(1, calls)
1265
def test_stopTestRun(self):
1266
"""run should call result.stopTestRun()"""
1268
class LoggingDecorator(tests.ForwardingResult):
1269
def stopTestRun(self):
1270
tests.ForwardingResult.stopTestRun(self)
1271
calls.append('stopTestRun')
1272
test = unittest.FunctionTestCase(lambda:None)
1274
runner = tests.TextTestRunner(stream=stream,
1275
result_decorators=[LoggingDecorator])
1276
result = self.run_test_runner(runner, test)
1277
self.assertLength(1, calls)
1280
class SampleTestCase(tests.TestCase):
1282
def _test_pass(self):
1285
class _TestException(Exception):
1289
class TestTestCase(tests.TestCase):
1290
"""Tests that test the core bzrlib TestCase."""
1292
def test_assertLength_matches_empty(self):
1294
self.assertLength(0, a_list)
1296
def test_assertLength_matches_nonempty(self):
1298
self.assertLength(3, a_list)
1300
def test_assertLength_fails_different(self):
1302
self.assertRaises(AssertionError, self.assertLength, 1, a_list)
1304
def test_assertLength_shows_sequence_in_failure(self):
1306
exception = self.assertRaises(AssertionError, self.assertLength, 2,
1308
self.assertEqual('Incorrect length: wanted 2, got 3 for [1, 2, 3]',
1311
def test_base_setUp_not_called_causes_failure(self):
1312
class TestCaseWithBrokenSetUp(tests.TestCase):
1314
pass # does not call TestCase.setUp
1317
test = TestCaseWithBrokenSetUp('test_foo')
1318
result = unittest.TestResult()
1320
self.assertFalse(result.wasSuccessful())
1321
self.assertEqual(1, result.testsRun)
1323
def test_base_tearDown_not_called_causes_failure(self):
1324
class TestCaseWithBrokenTearDown(tests.TestCase):
1326
pass # does not call TestCase.tearDown
1329
test = TestCaseWithBrokenTearDown('test_foo')
1330
result = unittest.TestResult()
1332
self.assertFalse(result.wasSuccessful())
1333
self.assertEqual(1, result.testsRun)
1335
def test_debug_flags_sanitised(self):
1336
"""The bzrlib debug flags should be sanitised by setUp."""
1337
if 'allow_debug' in tests.selftest_debug_flags:
1338
raise tests.TestNotApplicable(
1339
'-Eallow_debug option prevents debug flag sanitisation')
1340
# we could set something and run a test that will check
1341
# it gets santised, but this is probably sufficient for now:
1342
# if someone runs the test with -Dsomething it will error.
1344
if self._lock_check_thorough:
1345
flags.add('strict_locks')
1346
self.assertEqual(flags, bzrlib.debug.debug_flags)
1348
def change_selftest_debug_flags(self, new_flags):
1349
self.overrideAttr(tests, 'selftest_debug_flags', set(new_flags))
1351
def test_allow_debug_flag(self):
1352
"""The -Eallow_debug flag prevents bzrlib.debug.debug_flags from being
1353
sanitised (i.e. cleared) before running a test.
1355
self.change_selftest_debug_flags(set(['allow_debug']))
1356
bzrlib.debug.debug_flags = set(['a-flag'])
1357
class TestThatRecordsFlags(tests.TestCase):
1358
def test_foo(nested_self):
1359
self.flags = set(bzrlib.debug.debug_flags)
1360
test = TestThatRecordsFlags('test_foo')
1361
test.run(self.make_test_result())
1362
flags = set(['a-flag'])
1363
if 'disable_lock_checks' not in tests.selftest_debug_flags:
1364
flags.add('strict_locks')
1365
self.assertEqual(flags, self.flags)
1367
def test_disable_lock_checks(self):
1368
"""The -Edisable_lock_checks flag disables thorough checks."""
1369
class TestThatRecordsFlags(tests.TestCase):
1370
def test_foo(nested_self):
1371
self.flags = set(bzrlib.debug.debug_flags)
1372
self.test_lock_check_thorough = nested_self._lock_check_thorough
1373
self.change_selftest_debug_flags(set())
1374
test = TestThatRecordsFlags('test_foo')
1375
test.run(self.make_test_result())
1376
# By default we do strict lock checking and thorough lock/unlock
1378
self.assertTrue(self.test_lock_check_thorough)
1379
self.assertEqual(set(['strict_locks']), self.flags)
1380
# Now set the disable_lock_checks flag, and show that this changed.
1381
self.change_selftest_debug_flags(set(['disable_lock_checks']))
1382
test = TestThatRecordsFlags('test_foo')
1383
test.run(self.make_test_result())
1384
self.assertFalse(self.test_lock_check_thorough)
1385
self.assertEqual(set(), self.flags)
1387
def test_this_fails_strict_lock_check(self):
1388
class TestThatRecordsFlags(tests.TestCase):
1389
def test_foo(nested_self):
1390
self.flags1 = set(bzrlib.debug.debug_flags)
1391
self.thisFailsStrictLockCheck()
1392
self.flags2 = set(bzrlib.debug.debug_flags)
1393
# Make sure lock checking is active
1394
self.change_selftest_debug_flags(set())
1395
test = TestThatRecordsFlags('test_foo')
1396
test.run(self.make_test_result())
1397
self.assertEqual(set(['strict_locks']), self.flags1)
1398
self.assertEqual(set(), self.flags2)
1400
def test_debug_flags_restored(self):
1401
"""The bzrlib debug flags should be restored to their original state
1402
after the test was run, even if allow_debug is set.
1404
self.change_selftest_debug_flags(set(['allow_debug']))
1405
# Now run a test that modifies debug.debug_flags.
1406
bzrlib.debug.debug_flags = set(['original-state'])
1407
class TestThatModifiesFlags(tests.TestCase):
1409
bzrlib.debug.debug_flags = set(['modified'])
1410
test = TestThatModifiesFlags('test_foo')
1411
test.run(self.make_test_result())
1412
self.assertEqual(set(['original-state']), bzrlib.debug.debug_flags)
1414
def make_test_result(self):
1415
"""Get a test result that writes to the test log file."""
1416
return tests.TextTestResult(self._log_file, descriptions=0, verbosity=1)
1418
def inner_test(self):
1419
# the inner child test
1422
def outer_child(self):
1423
# the outer child test
1425
self.inner_test = TestTestCase("inner_child")
1426
result = self.make_test_result()
1427
self.inner_test.run(result)
1428
note("outer finish")
1429
self.addCleanup(osutils.delete_any, self._log_file_name)
1431
def test_trace_nesting(self):
1432
# this tests that each test case nests its trace facility correctly.
1433
# we do this by running a test case manually. That test case (A)
1434
# should setup a new log, log content to it, setup a child case (B),
1435
# which should log independently, then case (A) should log a trailer
1437
# we do two nested children so that we can verify the state of the
1438
# logs after the outer child finishes is correct, which a bad clean
1439
# up routine in tearDown might trigger a fault in our test with only
1440
# one child, we should instead see the bad result inside our test with
1442
# the outer child test
1443
original_trace = bzrlib.trace._trace_file
1444
outer_test = TestTestCase("outer_child")
1445
result = self.make_test_result()
1446
outer_test.run(result)
1447
self.assertEqual(original_trace, bzrlib.trace._trace_file)
1449
def method_that_times_a_bit_twice(self):
1450
# call self.time twice to ensure it aggregates
1451
self.time(time.sleep, 0.007)
1452
self.time(time.sleep, 0.007)
1454
def test_time_creates_benchmark_in_result(self):
1455
"""Test that the TestCase.time() method accumulates a benchmark time."""
1456
sample_test = TestTestCase("method_that_times_a_bit_twice")
1457
output_stream = StringIO()
1458
result = bzrlib.tests.VerboseTestResult(
1462
sample_test.run(result)
1463
self.assertContainsRe(
1464
output_stream.getvalue(),
1467
def test_hooks_sanitised(self):
1468
"""The bzrlib hooks should be sanitised by setUp."""
1469
# Note this test won't fail with hooks that the core library doesn't
1470
# use - but it trigger with a plugin that adds hooks, so its still a
1471
# useful warning in that case.
1472
self.assertEqual(bzrlib.branch.BranchHooks(),
1473
bzrlib.branch.Branch.hooks)
1474
self.assertEqual(bzrlib.smart.server.SmartServerHooks(),
1475
bzrlib.smart.server.SmartTCPServer.hooks)
1476
self.assertEqual(bzrlib.commands.CommandHooks(),
1477
bzrlib.commands.Command.hooks)
1479
def test__gather_lsprof_in_benchmarks(self):
1480
"""When _gather_lsprof_in_benchmarks is on, accumulate profile data.
1482
Each self.time() call is individually and separately profiled.
1484
self.requireFeature(test_lsprof.LSProfFeature)
1485
# overrides the class member with an instance member so no cleanup
1487
self._gather_lsprof_in_benchmarks = True
1488
self.time(time.sleep, 0.000)
1489
self.time(time.sleep, 0.003)
1490
self.assertEqual(2, len(self._benchcalls))
1491
self.assertEqual((time.sleep, (0.000,), {}), self._benchcalls[0][0])
1492
self.assertEqual((time.sleep, (0.003,), {}), self._benchcalls[1][0])
1493
self.assertIsInstance(self._benchcalls[0][1], bzrlib.lsprof.Stats)
1494
self.assertIsInstance(self._benchcalls[1][1], bzrlib.lsprof.Stats)
1495
del self._benchcalls[:]
1497
def test_knownFailure(self):
1498
"""Self.knownFailure() should raise a KnownFailure exception."""
1499
self.assertRaises(tests.KnownFailure, self.knownFailure, "A Failure")
1501
def test_open_bzrdir_safe_roots(self):
1502
# even a memory transport should fail to open when its url isn't
1504
# Manually set one up (TestCase doesn't and shouldn't provide magic
1506
transport_server = memory.MemoryServer()
1507
transport_server.start_server()
1508
self.addCleanup(transport_server.stop_server)
1509
t = transport.get_transport(transport_server.get_url())
1510
bzrdir.BzrDir.create(t.base)
1511
self.assertRaises(errors.BzrError,
1512
bzrdir.BzrDir.open_from_transport, t)
1513
# But if we declare this as safe, we can open the bzrdir.
1514
self.permit_url(t.base)
1515
self._bzr_selftest_roots.append(t.base)
1516
bzrdir.BzrDir.open_from_transport(t)
1518
def test_requireFeature_available(self):
1519
"""self.requireFeature(available) is a no-op."""
1520
class Available(tests.Feature):
1521
def _probe(self):return True
1522
feature = Available()
1523
self.requireFeature(feature)
1525
def test_requireFeature_unavailable(self):
1526
"""self.requireFeature(unavailable) raises UnavailableFeature."""
1527
class Unavailable(tests.Feature):
1528
def _probe(self):return False
1529
feature = Unavailable()
1530
self.assertRaises(tests.UnavailableFeature,
1531
self.requireFeature, feature)
1533
def test_run_no_parameters(self):
1534
test = SampleTestCase('_test_pass')
1537
def test_run_enabled_unittest_result(self):
1538
"""Test we revert to regular behaviour when the test is enabled."""
1539
test = SampleTestCase('_test_pass')
1540
class EnabledFeature(object):
1541
def available(self):
1543
test._test_needs_features = [EnabledFeature()]
1544
result = unittest.TestResult()
1546
self.assertEqual(1, result.testsRun)
1547
self.assertEqual([], result.errors)
1548
self.assertEqual([], result.failures)
1550
def test_run_disabled_unittest_result(self):
1551
"""Test our compatability for disabled tests with unittest results."""
1552
test = SampleTestCase('_test_pass')
1553
class DisabledFeature(object):
1554
def available(self):
1556
test._test_needs_features = [DisabledFeature()]
1557
result = unittest.TestResult()
1559
self.assertEqual(1, result.testsRun)
1560
self.assertEqual([], result.errors)
1561
self.assertEqual([], result.failures)
1563
def test_run_disabled_supporting_result(self):
1564
"""Test disabled tests behaviour with support aware results."""
1565
test = SampleTestCase('_test_pass')
1566
class DisabledFeature(object):
1567
def __eq__(self, other):
1568
return isinstance(other, DisabledFeature)
1569
def available(self):
1571
the_feature = DisabledFeature()
1572
test._test_needs_features = [the_feature]
1573
class InstrumentedTestResult(unittest.TestResult):
1575
unittest.TestResult.__init__(self)
1577
def startTest(self, test):
1578
self.calls.append(('startTest', test))
1579
def stopTest(self, test):
1580
self.calls.append(('stopTest', test))
1581
def addNotSupported(self, test, feature):
1582
self.calls.append(('addNotSupported', test, feature))
1583
result = InstrumentedTestResult()
1585
case = result.calls[0][1]
1587
('startTest', case),
1588
('addNotSupported', case, the_feature),
1593
def test_start_server_registers_url(self):
1594
transport_server = memory.MemoryServer()
1595
# A little strict, but unlikely to be changed soon.
1596
self.assertEqual([], self._bzr_selftest_roots)
1597
self.start_server(transport_server)
1598
self.assertSubset([transport_server.get_url()],
1599
self._bzr_selftest_roots)
1601
def test_assert_list_raises_on_generator(self):
1602
def generator_which_will_raise():
1603
# This will not raise until after the first yield
1605
raise _TestException()
1607
e = self.assertListRaises(_TestException, generator_which_will_raise)
1608
self.assertIsInstance(e, _TestException)
1610
e = self.assertListRaises(Exception, generator_which_will_raise)
1611
self.assertIsInstance(e, _TestException)
1613
def test_assert_list_raises_on_plain(self):
1614
def plain_exception():
1615
raise _TestException()
1618
e = self.assertListRaises(_TestException, plain_exception)
1619
self.assertIsInstance(e, _TestException)
1621
e = self.assertListRaises(Exception, plain_exception)
1622
self.assertIsInstance(e, _TestException)
1624
def test_assert_list_raises_assert_wrong_exception(self):
1625
class _NotTestException(Exception):
1628
def wrong_exception():
1629
raise _NotTestException()
1631
def wrong_exception_generator():
1634
raise _NotTestException()
1636
# Wrong exceptions are not intercepted
1637
self.assertRaises(_NotTestException,
1638
self.assertListRaises, _TestException, wrong_exception)
1639
self.assertRaises(_NotTestException,
1640
self.assertListRaises, _TestException, wrong_exception_generator)
1642
def test_assert_list_raises_no_exception(self):
1646
def success_generator():
1650
self.assertRaises(AssertionError,
1651
self.assertListRaises, _TestException, success)
1653
self.assertRaises(AssertionError,
1654
self.assertListRaises, _TestException, success_generator)
1656
def test_overrideAttr_without_value(self):
1657
self.test_attr = 'original' # Define a test attribute
1658
obj = self # Make 'obj' visible to the embedded test
1659
class Test(tests.TestCase):
1662
tests.TestCase.setUp(self)
1663
self.orig = self.overrideAttr(obj, 'test_attr')
1665
def test_value(self):
1666
self.assertEqual('original', self.orig)
1667
self.assertEqual('original', obj.test_attr)
1668
obj.test_attr = 'modified'
1669
self.assertEqual('modified', obj.test_attr)
1671
test = Test('test_value')
1672
test.run(unittest.TestResult())
1673
self.assertEqual('original', obj.test_attr)
1675
def test_overrideAttr_with_value(self):
1676
self.test_attr = 'original' # Define a test attribute
1677
obj = self # Make 'obj' visible to the embedded test
1678
class Test(tests.TestCase):
1681
tests.TestCase.setUp(self)
1682
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1684
def test_value(self):
1685
self.assertEqual('original', self.orig)
1686
self.assertEqual('modified', obj.test_attr)
1688
test = Test('test_value')
1689
test.run(unittest.TestResult())
1690
self.assertEqual('original', obj.test_attr)
1693
class _MissingFeature(tests.Feature):
1696
missing_feature = _MissingFeature()
1699
def _get_test(name):
1700
"""Get an instance of a specific example test.
1702
We protect this in a function so that they don't auto-run in the test
1706
class ExampleTests(tests.TestCase):
1708
def test_fail(self):
1709
mutter('this was a failing test')
1710
self.fail('this test will fail')
1712
def test_error(self):
1713
mutter('this test errored')
1714
raise RuntimeError('gotcha')
1716
def test_missing_feature(self):
1717
mutter('missing the feature')
1718
self.requireFeature(missing_feature)
1720
def test_skip(self):
1721
mutter('this test will be skipped')
1722
raise tests.TestSkipped('reason')
1724
def test_success(self):
1725
mutter('this test succeeds')
1727
def test_xfail(self):
1728
mutter('test with expected failure')
1729
self.knownFailure('this_fails')
1731
def test_unexpected_success(self):
1732
mutter('test with unexpected success')
1733
self.expectFailure('should_fail', lambda: None)
1735
return ExampleTests(name)
1738
class TestTestCaseLogDetails(tests.TestCase):
1740
def _run_test(self, test_name):
1741
test = _get_test(test_name)
1742
result = testtools.TestResult()
1746
def test_fail_has_log(self):
1747
result = self._run_test('test_fail')
1748
self.assertEqual(1, len(result.failures))
1749
result_content = result.failures[0][1]
1750
self.assertContainsRe(result_content, 'Text attachment: log')
1751
self.assertContainsRe(result_content, 'this was a failing test')
1753
def test_error_has_log(self):
1754
result = self._run_test('test_error')
1755
self.assertEqual(1, len(result.errors))
1756
result_content = result.errors[0][1]
1757
self.assertContainsRe(result_content, 'Text attachment: log')
1758
self.assertContainsRe(result_content, 'this test errored')
1760
def test_skip_has_no_log(self):
1761
result = self._run_test('test_skip')
1762
self.assertEqual(['reason'], result.skip_reasons.keys())
1763
skips = result.skip_reasons['reason']
1764
self.assertEqual(1, len(skips))
1766
self.assertFalse('log' in test.getDetails())
1768
def test_missing_feature_has_no_log(self):
1769
# testtools doesn't know about addNotSupported, so it just gets
1770
# considered as a skip
1771
result = self._run_test('test_missing_feature')
1772
self.assertEqual([missing_feature], result.skip_reasons.keys())
1773
skips = result.skip_reasons[missing_feature]
1774
self.assertEqual(1, len(skips))
1776
self.assertFalse('log' in test.getDetails())
1778
def test_xfail_has_no_log(self):
1779
result = self._run_test('test_xfail')
1780
self.assertEqual(1, len(result.expectedFailures))
1781
result_content = result.expectedFailures[0][1]
1782
self.assertNotContainsRe(result_content, 'Text attachment: log')
1783
self.assertNotContainsRe(result_content, 'test with expected failure')
1785
def test_unexpected_success_has_log(self):
1786
result = self._run_test('test_unexpected_success')
1787
self.assertEqual(1, len(result.unexpectedSuccesses))
1788
# Inconsistency, unexpectedSuccesses is a list of tests,
1789
# expectedFailures is a list of reasons?
1790
test = result.unexpectedSuccesses[0]
1791
details = test.getDetails()
1792
self.assertTrue('log' in details)
1795
class TestTestCloning(tests.TestCase):
1796
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1798
def test_cloned_testcase_does_not_share_details(self):
1799
"""A TestCase cloned with clone_test does not share mutable attributes
1800
such as details or cleanups.
1802
class Test(tests.TestCase):
1804
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1805
orig_test = Test('test_foo')
1806
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1807
orig_test.run(unittest.TestResult())
1808
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1809
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1811
def test_double_apply_scenario_preserves_first_scenario(self):
1812
"""Applying two levels of scenarios to a test preserves the attributes
1813
added by both scenarios.
1815
class Test(tests.TestCase):
1818
test = Test('test_foo')
1819
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1820
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1821
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1822
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1823
all_tests = list(tests.iter_suite_tests(suite))
1824
self.assertLength(4, all_tests)
1825
all_xys = sorted((t.x, t.y) for t in all_tests)
1826
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1829
# NB: Don't delete this; it's not actually from 0.11!
1830
@deprecated_function(deprecated_in((0, 11, 0)))
1831
def sample_deprecated_function():
1832
"""A deprecated function to test applyDeprecated with."""
1836
def sample_undeprecated_function(a_param):
1837
"""A undeprecated function to test applyDeprecated with."""
1840
class ApplyDeprecatedHelper(object):
1841
"""A helper class for ApplyDeprecated tests."""
1843
@deprecated_method(deprecated_in((0, 11, 0)))
1844
def sample_deprecated_method(self, param_one):
1845
"""A deprecated method for testing with."""
1848
def sample_normal_method(self):
1849
"""A undeprecated method."""
1851
@deprecated_method(deprecated_in((0, 10, 0)))
1852
def sample_nested_deprecation(self):
1853
return sample_deprecated_function()
1856
class TestExtraAssertions(tests.TestCase):
1857
"""Tests for new test assertions in bzrlib test suite"""
1859
def test_assert_isinstance(self):
1860
self.assertIsInstance(2, int)
1861
self.assertIsInstance(u'', basestring)
1862
e = self.assertRaises(AssertionError, self.assertIsInstance, None, int)
1863
self.assertEquals(str(e),
1864
"None is an instance of <type 'NoneType'> rather than <type 'int'>")
1865
self.assertRaises(AssertionError, self.assertIsInstance, 23.3, int)
1866
e = self.assertRaises(AssertionError,
1867
self.assertIsInstance, None, int, "it's just not")
1868
self.assertEquals(str(e),
1869
"None is an instance of <type 'NoneType'> rather than <type 'int'>"
1872
def test_assertEndsWith(self):
1873
self.assertEndsWith('foo', 'oo')
1874
self.assertRaises(AssertionError, self.assertEndsWith, 'o', 'oo')
1876
def test_assertEqualDiff(self):
1877
e = self.assertRaises(AssertionError,
1878
self.assertEqualDiff, '', '\n')
1879
self.assertEquals(str(e),
1880
# Don't blink ! The '+' applies to the second string
1881
'first string is missing a final newline.\n+ \n')
1882
e = self.assertRaises(AssertionError,
1883
self.assertEqualDiff, '\n', '')
1884
self.assertEquals(str(e),
1885
# Don't blink ! The '-' applies to the second string
1886
'second string is missing a final newline.\n- \n')
1889
class TestDeprecations(tests.TestCase):
1891
def test_applyDeprecated_not_deprecated(self):
1892
sample_object = ApplyDeprecatedHelper()
1893
# calling an undeprecated callable raises an assertion
1894
self.assertRaises(AssertionError, self.applyDeprecated,
1895
deprecated_in((0, 11, 0)),
1896
sample_object.sample_normal_method)
1897
self.assertRaises(AssertionError, self.applyDeprecated,
1898
deprecated_in((0, 11, 0)),
1899
sample_undeprecated_function, "a param value")
1900
# calling a deprecated callable (function or method) with the wrong
1901
# expected deprecation fails.
1902
self.assertRaises(AssertionError, self.applyDeprecated,
1903
deprecated_in((0, 10, 0)),
1904
sample_object.sample_deprecated_method, "a param value")
1905
self.assertRaises(AssertionError, self.applyDeprecated,
1906
deprecated_in((0, 10, 0)),
1907
sample_deprecated_function)
1908
# calling a deprecated callable (function or method) with the right
1909
# expected deprecation returns the functions result.
1910
self.assertEqual("a param value",
1911
self.applyDeprecated(deprecated_in((0, 11, 0)),
1912
sample_object.sample_deprecated_method, "a param value"))
1913
self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 11, 0)),
1914
sample_deprecated_function))
1915
# calling a nested deprecation with the wrong deprecation version
1916
# fails even if a deeper nested function was deprecated with the
1918
self.assertRaises(AssertionError, self.applyDeprecated,
1919
deprecated_in((0, 11, 0)), sample_object.sample_nested_deprecation)
1920
# calling a nested deprecation with the right deprecation value
1921
# returns the calls result.
1922
self.assertEqual(2, self.applyDeprecated(deprecated_in((0, 10, 0)),
1923
sample_object.sample_nested_deprecation))
1925
def test_callDeprecated(self):
1926
def testfunc(be_deprecated, result=None):
1927
if be_deprecated is True:
1928
symbol_versioning.warn('i am deprecated', DeprecationWarning,
1931
result = self.callDeprecated(['i am deprecated'], testfunc, True)
1932
self.assertIs(None, result)
1933
result = self.callDeprecated([], testfunc, False, 'result')
1934
self.assertEqual('result', result)
1935
self.callDeprecated(['i am deprecated'], testfunc, be_deprecated=True)
1936
self.callDeprecated([], testfunc, be_deprecated=False)
1939
class TestWarningTests(tests.TestCase):
1940
"""Tests for calling methods that raise warnings."""
1942
def test_callCatchWarnings(self):
1944
warnings.warn("this is your last warning")
1946
wlist, result = self.callCatchWarnings(meth, 1, 2)
1947
self.assertEquals(3, result)
1948
# would like just to compare them, but UserWarning doesn't implement
1951
self.assertIsInstance(w0, UserWarning)
1952
self.assertEquals("this is your last warning", str(w0))
1955
class TestConvenienceMakers(tests.TestCaseWithTransport):
1956
"""Test for the make_* convenience functions."""
1958
def test_make_branch_and_tree_with_format(self):
1959
# we should be able to supply a format to make_branch_and_tree
1960
self.make_branch_and_tree('a', format=bzrlib.bzrdir.BzrDirMetaFormat1())
1961
self.make_branch_and_tree('b', format=bzrlib.bzrdir.BzrDirFormat6())
1962
self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('a')._format,
1963
bzrlib.bzrdir.BzrDirMetaFormat1)
1964
self.assertIsInstance(bzrlib.bzrdir.BzrDir.open('b')._format,
1965
bzrlib.bzrdir.BzrDirFormat6)
1967
def test_make_branch_and_memory_tree(self):
1968
# we should be able to get a new branch and a mutable tree from
1969
# TestCaseWithTransport
1970
tree = self.make_branch_and_memory_tree('a')
1971
self.assertIsInstance(tree, bzrlib.memorytree.MemoryTree)
1973
def test_make_tree_for_local_vfs_backed_transport(self):
1974
# make_branch_and_tree has to use local branch and repositories
1975
# when the vfs transport and local disk are colocated, even if
1976
# a different transport is in use for url generation.
1977
self.transport_server = test_server.FakeVFATServer
1978
self.assertFalse(self.get_url('t1').startswith('file://'))
1979
tree = self.make_branch_and_tree('t1')
1980
base = tree.bzrdir.root_transport.base
1981
self.assertStartsWith(base, 'file://')
1982
self.assertEquals(tree.bzrdir.root_transport,
1983
tree.branch.bzrdir.root_transport)
1984
self.assertEquals(tree.bzrdir.root_transport,
1985
tree.branch.repository.bzrdir.root_transport)
1988
class SelfTestHelper(object):
1990
def run_selftest(self, **kwargs):
1991
"""Run selftest returning its output."""
1993
old_transport = bzrlib.tests.default_transport
1994
old_root = tests.TestCaseWithMemoryTransport.TEST_ROOT
1995
tests.TestCaseWithMemoryTransport.TEST_ROOT = None
1997
self.assertEqual(True, tests.selftest(stream=output, **kwargs))
1999
bzrlib.tests.default_transport = old_transport
2000
tests.TestCaseWithMemoryTransport.TEST_ROOT = old_root
2005
class TestSelftest(tests.TestCase, SelfTestHelper):
2006
"""Tests of bzrlib.tests.selftest."""
2008
def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(self):
2011
factory_called.append(True)
2012
return TestUtil.TestSuite()
2015
self.apply_redirected(out, err, None, bzrlib.tests.selftest,
2016
test_suite_factory=factory)
2017
self.assertEqual([True], factory_called)
2020
"""A test suite factory."""
2021
class Test(tests.TestCase):
2028
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
2030
def test_list_only(self):
2031
output = self.run_selftest(test_suite_factory=self.factory,
2033
self.assertEqual(3, len(output.readlines()))
2035
def test_list_only_filtered(self):
2036
output = self.run_selftest(test_suite_factory=self.factory,
2037
list_only=True, pattern="Test.b")
2038
self.assertEndsWith(output.getvalue(), "Test.b\n")
2039
self.assertLength(1, output.readlines())
2041
def test_list_only_excludes(self):
2042
output = self.run_selftest(test_suite_factory=self.factory,
2043
list_only=True, exclude_pattern="Test.b")
2044
self.assertNotContainsRe("Test.b", output.getvalue())
2045
self.assertLength(2, output.readlines())
2047
def test_lsprof_tests(self):
2048
self.requireFeature(test_lsprof.LSProfFeature)
2051
def __call__(test, result):
2053
def run(test, result):
2054
self.assertIsInstance(result, tests.ForwardingResult)
2055
calls.append("called")
2056
def countTestCases(self):
2058
self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
2059
self.assertLength(1, calls)
2061
def test_random(self):
2062
# test randomising by listing a number of tests.
2063
output_123 = self.run_selftest(test_suite_factory=self.factory,
2064
list_only=True, random_seed="123")
2065
output_234 = self.run_selftest(test_suite_factory=self.factory,
2066
list_only=True, random_seed="234")
2067
self.assertNotEqual(output_123, output_234)
2068
# "Randominzing test order..\n\n
2069
self.assertLength(5, output_123.readlines())
2070
self.assertLength(5, output_234.readlines())
2072
def test_random_reuse_is_same_order(self):
2073
# test randomising by listing a number of tests.
2074
expected = self.run_selftest(test_suite_factory=self.factory,
2075
list_only=True, random_seed="123")
2076
repeated = self.run_selftest(test_suite_factory=self.factory,
2077
list_only=True, random_seed="123")
2078
self.assertEqual(expected.getvalue(), repeated.getvalue())
2080
def test_runner_class(self):
2081
self.requireFeature(features.subunit)
2082
from subunit import ProtocolTestCase
2083
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2084
test_suite_factory=self.factory)
2085
test = ProtocolTestCase(stream)
2086
result = unittest.TestResult()
2088
self.assertEqual(3, result.testsRun)
2090
def test_starting_with_single_argument(self):
2091
output = self.run_selftest(test_suite_factory=self.factory,
2092
starting_with=['bzrlib.tests.test_selftest.Test.a'],
2094
self.assertEqual('bzrlib.tests.test_selftest.Test.a\n',
2097
def test_starting_with_multiple_argument(self):
2098
output = self.run_selftest(test_suite_factory=self.factory,
2099
starting_with=['bzrlib.tests.test_selftest.Test.a',
2100
'bzrlib.tests.test_selftest.Test.b'],
2102
self.assertEqual('bzrlib.tests.test_selftest.Test.a\n'
2103
'bzrlib.tests.test_selftest.Test.b\n',
2106
def check_transport_set(self, transport_server):
2107
captured_transport = []
2108
def seen_transport(a_transport):
2109
captured_transport.append(a_transport)
2110
class Capture(tests.TestCase):
2112
seen_transport(bzrlib.tests.default_transport)
2114
return TestUtil.TestSuite([Capture("a")])
2115
self.run_selftest(transport=transport_server, test_suite_factory=factory)
2116
self.assertEqual(transport_server, captured_transport[0])
2118
def test_transport_sftp(self):
2119
self.requireFeature(features.paramiko)
2120
from bzrlib.tests import stub_sftp
2121
self.check_transport_set(stub_sftp.SFTPAbsoluteServer)
2123
def test_transport_memory(self):
2124
self.check_transport_set(memory.MemoryServer)
2127
class TestSelftestWithIdList(tests.TestCaseInTempDir, SelfTestHelper):
2128
# Does IO: reads test.list
2130
def test_load_list(self):
2131
# Provide a list with one test - this test.
2132
test_id_line = '%s\n' % self.id()
2133
self.build_tree_contents([('test.list', test_id_line)])
2134
# And generate a list of the tests in the suite.
2135
stream = self.run_selftest(load_list='test.list', list_only=True)
2136
self.assertEqual(test_id_line, stream.getvalue())
2138
def test_load_unknown(self):
2139
# Provide a list with one test - this test.
2140
# And generate a list of the tests in the suite.
2141
err = self.assertRaises(errors.NoSuchFile, self.run_selftest,
2142
load_list='missing file name', list_only=True)
2145
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2147
_test_needs_features = [features.subunit]
2149
def run_subunit_stream(self, test_name):
2150
from subunit import ProtocolTestCase
2152
return TestUtil.TestSuite([_get_test(test_name)])
2153
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2154
test_suite_factory=factory)
2155
test = ProtocolTestCase(stream)
2156
result = testtools.TestResult()
2158
content = stream.getvalue()
2159
return content, result
2161
def test_fail_has_log(self):
2162
content, result = self.run_subunit_stream('test_fail')
2163
self.assertEqual(1, len(result.failures))
2164
self.assertContainsRe(content, '(?m)^log$')
2165
self.assertContainsRe(content, 'this test will fail')
2167
def test_error_has_log(self):
2168
content, result = self.run_subunit_stream('test_error')
2169
self.assertContainsRe(content, '(?m)^log$')
2170
self.assertContainsRe(content, 'this test errored')
2172
def test_skip_has_no_log(self):
2173
content, result = self.run_subunit_stream('test_skip')
2174
self.assertNotContainsRe(content, '(?m)^log$')
2175
self.assertNotContainsRe(content, 'this test will be skipped')
2176
self.assertEqual(['reason'], result.skip_reasons.keys())
2177
skips = result.skip_reasons['reason']
2178
self.assertEqual(1, len(skips))
2180
# RemotedTestCase doesn't preserve the "details"
2181
## self.assertFalse('log' in test.getDetails())
2183
def test_missing_feature_has_no_log(self):
2184
content, result = self.run_subunit_stream('test_missing_feature')
2185
self.assertNotContainsRe(content, '(?m)^log$')
2186
self.assertNotContainsRe(content, 'missing the feature')
2187
self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2188
skips = result.skip_reasons['_MissingFeature\n']
2189
self.assertEqual(1, len(skips))
2191
# RemotedTestCase doesn't preserve the "details"
2192
## self.assertFalse('log' in test.getDetails())
2194
def test_xfail_has_no_log(self):
2195
content, result = self.run_subunit_stream('test_xfail')
2196
self.assertNotContainsRe(content, '(?m)^log$')
2197
self.assertNotContainsRe(content, 'test with expected failure')
2198
self.assertEqual(1, len(result.expectedFailures))
2199
result_content = result.expectedFailures[0][1]
2200
self.assertNotContainsRe(result_content, 'Text attachment: log')
2201
self.assertNotContainsRe(result_content, 'test with expected failure')
2203
def test_unexpected_success_has_log(self):
2204
content, result = self.run_subunit_stream('test_unexpected_success')
2205
self.assertContainsRe(content, '(?m)^log$')
2206
self.assertContainsRe(content, 'test with unexpected success')
2207
self.expectFailure('subunit treats "unexpectedSuccess"'
2208
' as a plain success',
2209
self.assertEqual, 1, len(result.unexpectedSuccesses))
2210
self.assertEqual(1, len(result.unexpectedSuccesses))
2211
test = result.unexpectedSuccesses[0]
2212
# RemotedTestCase doesn't preserve the "details"
2213
## self.assertTrue('log' in test.getDetails())
2215
def test_success_has_no_log(self):
2216
content, result = self.run_subunit_stream('test_success')
2217
self.assertEqual(1, result.testsRun)
2218
self.assertNotContainsRe(content, '(?m)^log$')
2219
self.assertNotContainsRe(content, 'this test succeeds')
2222
class TestRunBzr(tests.TestCase):
2227
def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None,
2229
"""Override _run_bzr_core to test how it is invoked by run_bzr.
2231
Attempts to run bzr from inside this class don't actually run it.
2233
We test how run_bzr actually invokes bzr in another location. Here we
2234
only need to test that it passes the right parameters to run_bzr.
2236
self.argv = list(argv)
2237
self.retcode = retcode
2238
self.encoding = encoding
2240
self.working_dir = working_dir
2241
return self.retcode, self.out, self.err
2243
def test_run_bzr_error(self):
2244
self.out = "It sure does!\n"
2245
out, err = self.run_bzr_error(['^$'], ['rocks'], retcode=34)
2246
self.assertEqual(['rocks'], self.argv)
2247
self.assertEqual(34, self.retcode)
2248
self.assertEqual('It sure does!\n', out)
2249
self.assertEquals(out, self.out)
2250
self.assertEqual('', err)
2251
self.assertEquals(err, self.err)
2253
def test_run_bzr_error_regexes(self):
2255
self.err = "bzr: ERROR: foobarbaz is not versioned"
2256
out, err = self.run_bzr_error(
2257
["bzr: ERROR: foobarbaz is not versioned"],
2258
['file-id', 'foobarbaz'])
2260
def test_encoding(self):
2261
"""Test that run_bzr passes encoding to _run_bzr_core"""
2262
self.run_bzr('foo bar')
2263
self.assertEqual(None, self.encoding)
2264
self.assertEqual(['foo', 'bar'], self.argv)
2266
self.run_bzr('foo bar', encoding='baz')
2267
self.assertEqual('baz', self.encoding)
2268
self.assertEqual(['foo', 'bar'], self.argv)
2270
def test_retcode(self):
2271
"""Test that run_bzr passes retcode to _run_bzr_core"""
2272
# Default is retcode == 0
2273
self.run_bzr('foo bar')
2274
self.assertEqual(0, self.retcode)
2275
self.assertEqual(['foo', 'bar'], self.argv)
2277
self.run_bzr('foo bar', retcode=1)
2278
self.assertEqual(1, self.retcode)
2279
self.assertEqual(['foo', 'bar'], self.argv)
2281
self.run_bzr('foo bar', retcode=None)
2282
self.assertEqual(None, self.retcode)
2283
self.assertEqual(['foo', 'bar'], self.argv)
2285
self.run_bzr(['foo', 'bar'], retcode=3)
2286
self.assertEqual(3, self.retcode)
2287
self.assertEqual(['foo', 'bar'], self.argv)
2289
def test_stdin(self):
2290
# test that the stdin keyword to run_bzr is passed through to
2291
# _run_bzr_core as-is. We do this by overriding
2292
# _run_bzr_core in this class, and then calling run_bzr,
2293
# which is a convenience function for _run_bzr_core, so
2295
self.run_bzr('foo bar', stdin='gam')
2296
self.assertEqual('gam', self.stdin)
2297
self.assertEqual(['foo', 'bar'], self.argv)
2299
self.run_bzr('foo bar', stdin='zippy')
2300
self.assertEqual('zippy', self.stdin)
2301
self.assertEqual(['foo', 'bar'], self.argv)
2303
def test_working_dir(self):
2304
"""Test that run_bzr passes working_dir to _run_bzr_core"""
2305
self.run_bzr('foo bar')
2306
self.assertEqual(None, self.working_dir)
2307
self.assertEqual(['foo', 'bar'], self.argv)
2309
self.run_bzr('foo bar', working_dir='baz')
2310
self.assertEqual('baz', self.working_dir)
2311
self.assertEqual(['foo', 'bar'], self.argv)
2313
def test_reject_extra_keyword_arguments(self):
2314
self.assertRaises(TypeError, self.run_bzr, "foo bar",
2315
error_regex=['error message'])
2318
class TestRunBzrCaptured(tests.TestCaseWithTransport):
2319
# Does IO when testing the working_dir parameter.
2321
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
2322
a_callable=None, *args, **kwargs):
2324
self.factory_stdin = getattr(bzrlib.ui.ui_factory, "stdin", None)
2325
self.factory = bzrlib.ui.ui_factory
2326
self.working_dir = osutils.getcwd()
2327
stdout.write('foo\n')
2328
stderr.write('bar\n')
2331
def test_stdin(self):
2332
# test that the stdin keyword to _run_bzr_core is passed through to
2333
# apply_redirected as a StringIO. We do this by overriding
2334
# apply_redirected in this class, and then calling _run_bzr_core,
2335
# which calls apply_redirected.
2336
self.run_bzr(['foo', 'bar'], stdin='gam')
2337
self.assertEqual('gam', self.stdin.read())
2338
self.assertTrue(self.stdin is self.factory_stdin)
2339
self.run_bzr(['foo', 'bar'], stdin='zippy')
2340
self.assertEqual('zippy', self.stdin.read())
2341
self.assertTrue(self.stdin is self.factory_stdin)
2343
def test_ui_factory(self):
2344
# each invocation of self.run_bzr should get its
2345
# own UI factory, which is an instance of TestUIFactory,
2346
# with stdin, stdout and stderr attached to the stdin,
2347
# stdout and stderr of the invoked run_bzr
2348
current_factory = bzrlib.ui.ui_factory
2349
self.run_bzr(['foo'])
2350
self.failIf(current_factory is self.factory)
2351
self.assertNotEqual(sys.stdout, self.factory.stdout)
2352
self.assertNotEqual(sys.stderr, self.factory.stderr)
2353
self.assertEqual('foo\n', self.factory.stdout.getvalue())
2354
self.assertEqual('bar\n', self.factory.stderr.getvalue())
2355
self.assertIsInstance(self.factory, tests.TestUIFactory)
2357
def test_working_dir(self):
2358
self.build_tree(['one/', 'two/'])
2359
cwd = osutils.getcwd()
2361
# Default is to work in the current directory
2362
self.run_bzr(['foo', 'bar'])
2363
self.assertEqual(cwd, self.working_dir)
2365
self.run_bzr(['foo', 'bar'], working_dir=None)
2366
self.assertEqual(cwd, self.working_dir)
2368
# The function should be run in the alternative directory
2369
# but afterwards the current working dir shouldn't be changed
2370
self.run_bzr(['foo', 'bar'], working_dir='one')
2371
self.assertNotEqual(cwd, self.working_dir)
2372
self.assertEndsWith(self.working_dir, 'one')
2373
self.assertEqual(cwd, osutils.getcwd())
2375
self.run_bzr(['foo', 'bar'], working_dir='two')
2376
self.assertNotEqual(cwd, self.working_dir)
2377
self.assertEndsWith(self.working_dir, 'two')
2378
self.assertEqual(cwd, osutils.getcwd())
2381
class StubProcess(object):
2382
"""A stub process for testing run_bzr_subprocess."""
2384
def __init__(self, out="", err="", retcode=0):
2387
self.returncode = retcode
2389
def communicate(self):
2390
return self.out, self.err
2393
class TestWithFakedStartBzrSubprocess(tests.TestCaseWithTransport):
2394
"""Base class for tests testing how we might run bzr."""
2397
tests.TestCaseWithTransport.setUp(self)
2398
self.subprocess_calls = []
2400
def start_bzr_subprocess(self, process_args, env_changes=None,
2401
skip_if_plan_to_signal=False,
2403
allow_plugins=False):
2404
"""capture what run_bzr_subprocess tries to do."""
2405
self.subprocess_calls.append({'process_args':process_args,
2406
'env_changes':env_changes,
2407
'skip_if_plan_to_signal':skip_if_plan_to_signal,
2408
'working_dir':working_dir, 'allow_plugins':allow_plugins})
2409
return self.next_subprocess
2412
class TestRunBzrSubprocess(TestWithFakedStartBzrSubprocess):
2414
def assertRunBzrSubprocess(self, expected_args, process, *args, **kwargs):
2415
"""Run run_bzr_subprocess with args and kwargs using a stubbed process.
2417
Inside TestRunBzrSubprocessCommands we use a stub start_bzr_subprocess
2418
that will return static results. This assertion method populates those
2419
results and also checks the arguments run_bzr_subprocess generates.
2421
self.next_subprocess = process
2423
result = self.run_bzr_subprocess(*args, **kwargs)
2425
self.next_subprocess = None
2426
for key, expected in expected_args.iteritems():
2427
self.assertEqual(expected, self.subprocess_calls[-1][key])
2430
self.next_subprocess = None
2431
for key, expected in expected_args.iteritems():
2432
self.assertEqual(expected, self.subprocess_calls[-1][key])
2435
def test_run_bzr_subprocess(self):
2436
"""The run_bzr_helper_external command behaves nicely."""
2437
self.assertRunBzrSubprocess({'process_args':['--version']},
2438
StubProcess(), '--version')
2439
self.assertRunBzrSubprocess({'process_args':['--version']},
2440
StubProcess(), ['--version'])
2441
# retcode=None disables retcode checking
2442
result = self.assertRunBzrSubprocess({},
2443
StubProcess(retcode=3), '--version', retcode=None)
2444
result = self.assertRunBzrSubprocess({},
2445
StubProcess(out="is free software"), '--version')
2446
self.assertContainsRe(result[0], 'is free software')
2447
# Running a subcommand that is missing errors
2448
self.assertRaises(AssertionError, self.assertRunBzrSubprocess,
2449
{'process_args':['--versionn']}, StubProcess(retcode=3),
2451
# Unless it is told to expect the error from the subprocess
2452
result = self.assertRunBzrSubprocess({},
2453
StubProcess(retcode=3), '--versionn', retcode=3)
2454
# Or to ignore retcode checking
2455
result = self.assertRunBzrSubprocess({},
2456
StubProcess(err="unknown command", retcode=3), '--versionn',
2458
self.assertContainsRe(result[1], 'unknown command')
2460
def test_env_change_passes_through(self):
2461
self.assertRunBzrSubprocess(
2462
{'env_changes':{'new':'value', 'changed':'newvalue', 'deleted':None}},
2464
env_changes={'new':'value', 'changed':'newvalue', 'deleted':None})
2466
def test_no_working_dir_passed_as_None(self):
2467
self.assertRunBzrSubprocess({'working_dir': None}, StubProcess(), '')
2469
def test_no_working_dir_passed_through(self):
2470
self.assertRunBzrSubprocess({'working_dir': 'dir'}, StubProcess(), '',
2473
def test_run_bzr_subprocess_no_plugins(self):
2474
self.assertRunBzrSubprocess({'allow_plugins': False},
2477
def test_allow_plugins(self):
2478
self.assertRunBzrSubprocess({'allow_plugins': True},
2479
StubProcess(), '', allow_plugins=True)
2482
class TestFinishBzrSubprocess(TestWithFakedStartBzrSubprocess):
2484
def test_finish_bzr_subprocess_with_error(self):
2485
"""finish_bzr_subprocess allows specification of the desired exit code.
2487
process = StubProcess(err="unknown command", retcode=3)
2488
result = self.finish_bzr_subprocess(process, retcode=3)
2489
self.assertEqual('', result[0])
2490
self.assertContainsRe(result[1], 'unknown command')
2492
def test_finish_bzr_subprocess_ignoring_retcode(self):
2493
"""finish_bzr_subprocess allows the exit code to be ignored."""
2494
process = StubProcess(err="unknown command", retcode=3)
2495
result = self.finish_bzr_subprocess(process, retcode=None)
2496
self.assertEqual('', result[0])
2497
self.assertContainsRe(result[1], 'unknown command')
2499
def test_finish_subprocess_with_unexpected_retcode(self):
2500
"""finish_bzr_subprocess raises self.failureException if the retcode is
2501
not the expected one.
2503
process = StubProcess(err="unknown command", retcode=3)
2504
self.assertRaises(self.failureException, self.finish_bzr_subprocess,
2508
class _DontSpawnProcess(Exception):
2509
"""A simple exception which just allows us to skip unnecessary steps"""
2512
class TestStartBzrSubProcess(tests.TestCase):
2514
def check_popen_state(self):
2515
"""Replace to make assertions when popen is called."""
2517
def _popen(self, *args, **kwargs):
2518
"""Record the command that is run, so that we can ensure it is correct"""
2519
self.check_popen_state()
2520
self._popen_args = args
2521
self._popen_kwargs = kwargs
2522
raise _DontSpawnProcess()
2524
def test_run_bzr_subprocess_no_plugins(self):
2525
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
2526
command = self._popen_args[0]
2527
self.assertEqual(sys.executable, command[0])
2528
self.assertEqual(self.get_bzr_path(), command[1])
2529
self.assertEqual(['--no-plugins'], command[2:])
2531
def test_allow_plugins(self):
2532
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2534
command = self._popen_args[0]
2535
self.assertEqual([], command[2:])
2537
def test_set_env(self):
2538
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2540
def check_environment():
2541
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2542
self.check_popen_state = check_environment
2543
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2544
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2545
# not set in theparent
2546
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2548
def test_run_bzr_subprocess_env_del(self):
2549
"""run_bzr_subprocess can remove environment variables too."""
2550
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2551
def check_environment():
2552
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2553
os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2554
self.check_popen_state = check_environment
2555
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2556
env_changes={'EXISTANT_ENV_VAR':None})
2557
# Still set in parent
2558
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2559
del os.environ['EXISTANT_ENV_VAR']
2561
def test_env_del_missing(self):
2562
self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
2563
def check_environment():
2564
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2565
self.check_popen_state = check_environment
2566
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2567
env_changes={'NON_EXISTANT_ENV_VAR':None})
2569
def test_working_dir(self):
2570
"""Test that we can specify the working dir for the child"""
2571
orig_getcwd = osutils.getcwd
2572
orig_chdir = os.chdir
2580
osutils.getcwd = getcwd
2582
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2585
osutils.getcwd = orig_getcwd
2587
os.chdir = orig_chdir
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 TestFeature(tests.TestCase):
2615
def test_caching(self):
2616
"""Feature._probe is called by the feature at most once."""
2617
class InstrumentedFeature(tests.Feature):
2619
super(InstrumentedFeature, self).__init__()
2622
self.calls.append('_probe')
2624
feature = InstrumentedFeature()
2626
self.assertEqual(['_probe'], feature.calls)
2628
self.assertEqual(['_probe'], feature.calls)
2630
def test_named_str(self):
2631
"""Feature.__str__ should thunk to feature_name()."""
2632
class NamedFeature(tests.Feature):
2633
def feature_name(self):
2635
feature = NamedFeature()
2636
self.assertEqual('symlinks', str(feature))
2638
def test_default_str(self):
2639
"""Feature.__str__ should default to __class__.__name__."""
2640
class NamedFeature(tests.Feature):
2642
feature = NamedFeature()
2643
self.assertEqual('NamedFeature', str(feature))
2646
class TestUnavailableFeature(tests.TestCase):
2648
def test_access_feature(self):
2649
feature = tests.Feature()
2650
exception = tests.UnavailableFeature(feature)
2651
self.assertIs(feature, exception.args[0])
2654
simple_thunk_feature = tests._CompatabilityThunkFeature(
2655
deprecated_in((2, 1, 0)),
2656
'bzrlib.tests.test_selftest',
2657
'simple_thunk_feature','UnicodeFilename',
2658
replacement_module='bzrlib.tests'
2661
class Test_CompatibilityFeature(tests.TestCase):
2663
def test_does_thunk(self):
2664
res = self.callDeprecated(
2665
['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
2666
' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
2667
simple_thunk_feature.available)
2668
self.assertEqual(tests.UnicodeFilename.available(), res)
2671
class TestModuleAvailableFeature(tests.TestCase):
2673
def test_available_module(self):
2674
feature = tests.ModuleAvailableFeature('bzrlib.tests')
2675
self.assertEqual('bzrlib.tests', feature.module_name)
2676
self.assertEqual('bzrlib.tests', str(feature))
2677
self.assertTrue(feature.available())
2678
self.assertIs(tests, feature.module)
2680
def test_unavailable_module(self):
2681
feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
2682
self.assertEqual('bzrlib.no_such_module_exists', str(feature))
2683
self.assertFalse(feature.available())
2684
self.assertIs(None, feature.module)
2687
class TestSelftestFiltering(tests.TestCase):
2690
tests.TestCase.setUp(self)
2691
self.suite = TestUtil.TestSuite()
2692
self.loader = TestUtil.TestLoader()
2693
self.suite.addTest(self.loader.loadTestsFromModule(
2694
sys.modules['bzrlib.tests.test_selftest']))
2695
self.all_names = _test_ids(self.suite)
2697
def test_condition_id_re(self):
2698
test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2699
'test_condition_id_re')
2700
filtered_suite = tests.filter_suite_by_condition(
2701
self.suite, tests.condition_id_re('test_condition_id_re'))
2702
self.assertEqual([test_name], _test_ids(filtered_suite))
2704
def test_condition_id_in_list(self):
2705
test_names = ['bzrlib.tests.test_selftest.TestSelftestFiltering.'
2706
'test_condition_id_in_list']
2707
id_list = tests.TestIdList(test_names)
2708
filtered_suite = tests.filter_suite_by_condition(
2709
self.suite, tests.condition_id_in_list(id_list))
2710
my_pattern = 'TestSelftestFiltering.*test_condition_id_in_list'
2711
re_filtered = tests.filter_suite_by_re(self.suite, my_pattern)
2712
self.assertEqual(_test_ids(re_filtered), _test_ids(filtered_suite))
2714
def test_condition_id_startswith(self):
2715
klass = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2716
start1 = klass + 'test_condition_id_starts'
2717
start2 = klass + 'test_condition_id_in'
2718
test_names = [ klass + 'test_condition_id_in_list',
2719
klass + 'test_condition_id_startswith',
2721
filtered_suite = tests.filter_suite_by_condition(
2722
self.suite, tests.condition_id_startswith([start1, start2]))
2723
self.assertEqual(test_names, _test_ids(filtered_suite))
2725
def test_condition_isinstance(self):
2726
filtered_suite = tests.filter_suite_by_condition(
2727
self.suite, tests.condition_isinstance(self.__class__))
2728
class_pattern = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2729
re_filtered = tests.filter_suite_by_re(self.suite, class_pattern)
2730
self.assertEqual(_test_ids(re_filtered), _test_ids(filtered_suite))
2732
def test_exclude_tests_by_condition(self):
2733
excluded_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2734
'test_exclude_tests_by_condition')
2735
filtered_suite = tests.exclude_tests_by_condition(self.suite,
2736
lambda x:x.id() == excluded_name)
2737
self.assertEqual(len(self.all_names) - 1,
2738
filtered_suite.countTestCases())
2739
self.assertFalse(excluded_name in _test_ids(filtered_suite))
2740
remaining_names = list(self.all_names)
2741
remaining_names.remove(excluded_name)
2742
self.assertEqual(remaining_names, _test_ids(filtered_suite))
2744
def test_exclude_tests_by_re(self):
2745
self.all_names = _test_ids(self.suite)
2746
filtered_suite = tests.exclude_tests_by_re(self.suite,
2747
'exclude_tests_by_re')
2748
excluded_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2749
'test_exclude_tests_by_re')
2750
self.assertEqual(len(self.all_names) - 1,
2751
filtered_suite.countTestCases())
2752
self.assertFalse(excluded_name in _test_ids(filtered_suite))
2753
remaining_names = list(self.all_names)
2754
remaining_names.remove(excluded_name)
2755
self.assertEqual(remaining_names, _test_ids(filtered_suite))
2757
def test_filter_suite_by_condition(self):
2758
test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2759
'test_filter_suite_by_condition')
2760
filtered_suite = tests.filter_suite_by_condition(self.suite,
2761
lambda x:x.id() == test_name)
2762
self.assertEqual([test_name], _test_ids(filtered_suite))
2764
def test_filter_suite_by_re(self):
2765
filtered_suite = tests.filter_suite_by_re(self.suite,
2766
'test_filter_suite_by_r')
2767
filtered_names = _test_ids(filtered_suite)
2768
self.assertEqual(filtered_names, ['bzrlib.tests.test_selftest.'
2769
'TestSelftestFiltering.test_filter_suite_by_re'])
2771
def test_filter_suite_by_id_list(self):
2772
test_list = ['bzrlib.tests.test_selftest.'
2773
'TestSelftestFiltering.test_filter_suite_by_id_list']
2774
filtered_suite = tests.filter_suite_by_id_list(
2775
self.suite, tests.TestIdList(test_list))
2776
filtered_names = _test_ids(filtered_suite)
2779
['bzrlib.tests.test_selftest.'
2780
'TestSelftestFiltering.test_filter_suite_by_id_list'])
2782
def test_filter_suite_by_id_startswith(self):
2783
# By design this test may fail if another test is added whose name also
2784
# begins with one of the start value used.
2785
klass = 'bzrlib.tests.test_selftest.TestSelftestFiltering.'
2786
start1 = klass + 'test_filter_suite_by_id_starts'
2787
start2 = klass + 'test_filter_suite_by_id_li'
2788
test_list = [klass + 'test_filter_suite_by_id_list',
2789
klass + 'test_filter_suite_by_id_startswith',
2791
filtered_suite = tests.filter_suite_by_id_startswith(
2792
self.suite, [start1, start2])
2795
_test_ids(filtered_suite),
2798
def test_preserve_input(self):
2799
# NB: Surely this is something in the stdlib to do this?
2800
self.assertTrue(self.suite is tests.preserve_input(self.suite))
2801
self.assertTrue("@#$" is tests.preserve_input("@#$"))
2803
def test_randomize_suite(self):
2804
randomized_suite = tests.randomize_suite(self.suite)
2805
# randomizing should not add or remove test names.
2806
self.assertEqual(set(_test_ids(self.suite)),
2807
set(_test_ids(randomized_suite)))
2808
# Technically, this *can* fail, because random.shuffle(list) can be
2809
# equal to list. Trying multiple times just pushes the frequency back.
2810
# As its len(self.all_names)!:1, the failure frequency should be low
2811
# enough to ignore. RBC 20071021.
2812
# It should change the order.
2813
self.assertNotEqual(self.all_names, _test_ids(randomized_suite))
2814
# But not the length. (Possibly redundant with the set test, but not
2816
self.assertEqual(len(self.all_names), len(_test_ids(randomized_suite)))
2818
def test_split_suit_by_condition(self):
2819
self.all_names = _test_ids(self.suite)
2820
condition = tests.condition_id_re('test_filter_suite_by_r')
2821
split_suite = tests.split_suite_by_condition(self.suite, condition)
2822
filtered_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2823
'test_filter_suite_by_re')
2824
self.assertEqual([filtered_name], _test_ids(split_suite[0]))
2825
self.assertFalse(filtered_name in _test_ids(split_suite[1]))
2826
remaining_names = list(self.all_names)
2827
remaining_names.remove(filtered_name)
2828
self.assertEqual(remaining_names, _test_ids(split_suite[1]))
2830
def test_split_suit_by_re(self):
2831
self.all_names = _test_ids(self.suite)
2832
split_suite = tests.split_suite_by_re(self.suite,
2833
'test_filter_suite_by_r')
2834
filtered_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2835
'test_filter_suite_by_re')
2836
self.assertEqual([filtered_name], _test_ids(split_suite[0]))
2837
self.assertFalse(filtered_name in _test_ids(split_suite[1]))
2838
remaining_names = list(self.all_names)
2839
remaining_names.remove(filtered_name)
2840
self.assertEqual(remaining_names, _test_ids(split_suite[1]))
2843
class TestCheckInventoryShape(tests.TestCaseWithTransport):
2845
def test_check_inventory_shape(self):
2846
files = ['a', 'b/', 'b/c']
2847
tree = self.make_branch_and_tree('.')
2848
self.build_tree(files)
2852
self.check_inventory_shape(tree.inventory, files)
2857
class TestBlackboxSupport(tests.TestCase):
2858
"""Tests for testsuite blackbox features."""
2860
def test_run_bzr_failure_not_caught(self):
2861
# When we run bzr in blackbox mode, we want any unexpected errors to
2862
# propagate up to the test suite so that it can show the error in the
2863
# usual way, and we won't get a double traceback.
2864
e = self.assertRaises(
2866
self.run_bzr, ['assert-fail'])
2867
# make sure we got the real thing, not an error from somewhere else in
2868
# the test framework
2869
self.assertEquals('always fails', str(e))
2870
# check that there's no traceback in the test log
2871
self.assertNotContainsRe(self.get_log(), r'Traceback')
2873
def test_run_bzr_user_error_caught(self):
2874
# Running bzr in blackbox mode, normal/expected/user errors should be
2875
# caught in the regular way and turned into an error message plus exit
2877
transport_server = memory.MemoryServer()
2878
transport_server.start_server()
2879
self.addCleanup(transport_server.stop_server)
2880
url = transport_server.get_url()
2881
self.permit_url(url)
2882
out, err = self.run_bzr(["log", "%s/nonexistantpath" % url], retcode=3)
2883
self.assertEqual(out, '')
2884
self.assertContainsRe(err,
2885
'bzr: ERROR: Not a branch: ".*nonexistantpath/".\n')
2888
class TestTestLoader(tests.TestCase):
2889
"""Tests for the test loader."""
2891
def _get_loader_and_module(self):
2892
"""Gets a TestLoader and a module with one test in it."""
2893
loader = TestUtil.TestLoader()
2895
class Stub(tests.TestCase):
2898
class MyModule(object):
2900
MyModule.a_class = Stub
2902
return loader, module
2904
def test_module_no_load_tests_attribute_loads_classes(self):
2905
loader, module = self._get_loader_and_module()
2906
self.assertEqual(1, loader.loadTestsFromModule(module).countTestCases())
2908
def test_module_load_tests_attribute_gets_called(self):
2909
loader, module = self._get_loader_and_module()
2910
# 'self' is here because we're faking the module with a class. Regular
2911
# load_tests do not need that :)
2912
def load_tests(self, standard_tests, module, loader):
2913
result = loader.suiteClass()
2914
for test in tests.iter_suite_tests(standard_tests):
2915
result.addTests([test, test])
2917
# add a load_tests() method which multiplies the tests from the module.
2918
module.__class__.load_tests = load_tests
2919
self.assertEqual(2, loader.loadTestsFromModule(module).countTestCases())
2921
def test_load_tests_from_module_name_smoke_test(self):
2922
loader = TestUtil.TestLoader()
2923
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
2924
self.assertEquals(['bzrlib.tests.test_sampler.DemoTest.test_nothing'],
2927
def test_load_tests_from_module_name_with_bogus_module_name(self):
2928
loader = TestUtil.TestLoader()
2929
self.assertRaises(ImportError, loader.loadTestsFromModuleName, 'bogus')
2932
class TestTestIdList(tests.TestCase):
2934
def _create_id_list(self, test_list):
2935
return tests.TestIdList(test_list)
2937
def _create_suite(self, test_id_list):
2939
class Stub(tests.TestCase):
2943
def _create_test_id(id):
2946
suite = TestUtil.TestSuite()
2947
for id in test_id_list:
2948
t = Stub('test_foo')
2949
t.id = _create_test_id(id)
2953
def _test_ids(self, test_suite):
2954
"""Get the ids for the tests in a test suite."""
2955
return [t.id() for t in tests.iter_suite_tests(test_suite)]
2957
def test_empty_list(self):
2958
id_list = self._create_id_list([])
2959
self.assertEquals({}, id_list.tests)
2960
self.assertEquals({}, id_list.modules)
2962
def test_valid_list(self):
2963
id_list = self._create_id_list(
2964
['mod1.cl1.meth1', 'mod1.cl1.meth2',
2965
'mod1.func1', 'mod1.cl2.meth2',
2967
'mod1.submod2.cl1.meth1', 'mod1.submod2.cl2.meth2',
2969
self.assertTrue(id_list.refers_to('mod1'))
2970
self.assertTrue(id_list.refers_to('mod1.submod1'))
2971
self.assertTrue(id_list.refers_to('mod1.submod2'))
2972
self.assertTrue(id_list.includes('mod1.cl1.meth1'))
2973
self.assertTrue(id_list.includes('mod1.submod1'))
2974
self.assertTrue(id_list.includes('mod1.func1'))
2976
def test_bad_chars_in_params(self):
2977
id_list = self._create_id_list(['mod1.cl1.meth1(xx.yy)'])
2978
self.assertTrue(id_list.refers_to('mod1'))
2979
self.assertTrue(id_list.includes('mod1.cl1.meth1(xx.yy)'))
2981
def test_module_used(self):
2982
id_list = self._create_id_list(['mod.class.meth'])
2983
self.assertTrue(id_list.refers_to('mod'))
2984
self.assertTrue(id_list.refers_to('mod.class'))
2985
self.assertTrue(id_list.refers_to('mod.class.meth'))
2987
def test_test_suite_matches_id_list_with_unknown(self):
2988
loader = TestUtil.TestLoader()
2989
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
2990
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing',
2992
not_found, duplicates = tests.suite_matches_id_list(suite, test_list)
2993
self.assertEquals(['bogus'], not_found)
2994
self.assertEquals([], duplicates)
2996
def test_suite_matches_id_list_with_duplicates(self):
2997
loader = TestUtil.TestLoader()
2998
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
2999
dupes = loader.suiteClass()
3000
for test in tests.iter_suite_tests(suite):
3002
dupes.addTest(test) # Add it again
3004
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing',]
3005
not_found, duplicates = tests.suite_matches_id_list(
3007
self.assertEquals([], not_found)
3008
self.assertEquals(['bzrlib.tests.test_sampler.DemoTest.test_nothing'],
3012
class TestTestSuite(tests.TestCase):
3014
def test__test_suite_testmod_names(self):
3015
# Test that a plausible list of test module names are returned
3016
# by _test_suite_testmod_names.
3017
test_list = tests._test_suite_testmod_names()
3019
'bzrlib.tests.blackbox',
3020
'bzrlib.tests.per_transport',
3021
'bzrlib.tests.test_selftest',
3025
def test__test_suite_modules_to_doctest(self):
3026
# Test that a plausible list of modules to doctest is returned
3027
# by _test_suite_modules_to_doctest.
3028
test_list = tests._test_suite_modules_to_doctest()
3030
# When docstrings are stripped, there are no modules to doctest
3031
self.assertEqual([], test_list)
3038
def test_test_suite(self):
3039
# test_suite() loads the entire test suite to operate. To avoid this
3040
# overhead, and yet still be confident that things are happening,
3041
# we temporarily replace two functions used by test_suite with
3042
# test doubles that supply a few sample tests to load, and check they
3045
def testmod_names():
3046
calls.append("testmod_names")
3048
'bzrlib.tests.blackbox.test_branch',
3049
'bzrlib.tests.per_transport',
3050
'bzrlib.tests.test_selftest',
3052
self.overrideAttr(tests, '_test_suite_testmod_names', testmod_names)
3054
calls.append("modules_to_doctest")
3057
return ['bzrlib.timestamp']
3058
self.overrideAttr(tests, '_test_suite_modules_to_doctest', doctests)
3059
expected_test_list = [
3061
'bzrlib.tests.blackbox.test_branch.TestBranch.test_branch',
3062
('bzrlib.tests.per_transport.TransportTests'
3063
'.test_abspath(LocalTransport,LocalURLServer)'),
3064
'bzrlib.tests.test_selftest.TestTestSuite.test_test_suite',
3065
# plugins can't be tested that way since selftest may be run with
3068
if __doc__ is not None:
3069
expected_test_list.extend([
3070
# modules_to_doctest
3071
'bzrlib.timestamp.format_highres_date',
3073
suite = tests.test_suite()
3074
self.assertEqual(set(["testmod_names", "modules_to_doctest"]),
3076
self.assertSubset(expected_test_list, _test_ids(suite))
3078
def test_test_suite_list_and_start(self):
3079
# We cannot test this at the same time as the main load, because we want
3080
# to know that starting_with == None works. So a second load is
3081
# incurred - note that the starting_with parameter causes a partial load
3082
# rather than a full load so this test should be pretty quick.
3083
test_list = ['bzrlib.tests.test_selftest.TestTestSuite.test_test_suite']
3084
suite = tests.test_suite(test_list,
3085
['bzrlib.tests.test_selftest.TestTestSuite'])
3086
# test_test_suite_list_and_start is not included
3087
self.assertEquals(test_list, _test_ids(suite))
3090
class TestLoadTestIdList(tests.TestCaseInTempDir):
3092
def _create_test_list_file(self, file_name, content):
3093
fl = open(file_name, 'wt')
3097
def test_load_unknown(self):
3098
self.assertRaises(errors.NoSuchFile,
3099
tests.load_test_id_list, 'i_do_not_exist')
3101
def test_load_test_list(self):
3102
test_list_fname = 'test.list'
3103
self._create_test_list_file(test_list_fname,
3104
'mod1.cl1.meth1\nmod2.cl2.meth2\n')
3105
tlist = tests.load_test_id_list(test_list_fname)
3106
self.assertEquals(2, len(tlist))
3107
self.assertEquals('mod1.cl1.meth1', tlist[0])
3108
self.assertEquals('mod2.cl2.meth2', tlist[1])
3110
def test_load_dirty_file(self):
3111
test_list_fname = 'test.list'
3112
self._create_test_list_file(test_list_fname,
3113
' mod1.cl1.meth1\n\nmod2.cl2.meth2 \n'
3115
tlist = tests.load_test_id_list(test_list_fname)
3116
self.assertEquals(4, len(tlist))
3117
self.assertEquals('mod1.cl1.meth1', tlist[0])
3118
self.assertEquals('', tlist[1])
3119
self.assertEquals('mod2.cl2.meth2', tlist[2])
3120
self.assertEquals('bar baz', tlist[3])
3123
class TestFilteredByModuleTestLoader(tests.TestCase):
3125
def _create_loader(self, test_list):
3126
id_filter = tests.TestIdList(test_list)
3127
loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
3130
def test_load_tests(self):
3131
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3132
loader = self._create_loader(test_list)
3133
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3134
self.assertEquals(test_list, _test_ids(suite))
3136
def test_exclude_tests(self):
3137
test_list = ['bogus']
3138
loader = self._create_loader(test_list)
3139
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3140
self.assertEquals([], _test_ids(suite))
3143
class TestFilteredByNameStartTestLoader(tests.TestCase):
3145
def _create_loader(self, name_start):
3146
def needs_module(name):
3147
return name.startswith(name_start) or name_start.startswith(name)
3148
loader = TestUtil.FilteredByModuleTestLoader(needs_module)
3151
def test_load_tests(self):
3152
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3153
loader = self._create_loader('bzrlib.tests.test_samp')
3155
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3156
self.assertEquals(test_list, _test_ids(suite))
3158
def test_load_tests_inside_module(self):
3159
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3160
loader = self._create_loader('bzrlib.tests.test_sampler.Demo')
3162
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3163
self.assertEquals(test_list, _test_ids(suite))
3165
def test_exclude_tests(self):
3166
test_list = ['bogus']
3167
loader = self._create_loader('bogus')
3169
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3170
self.assertEquals([], _test_ids(suite))
3173
class TestTestPrefixRegistry(tests.TestCase):
3175
def _get_registry(self):
3176
tp_registry = tests.TestPrefixAliasRegistry()
3179
def test_register_new_prefix(self):
3180
tpr = self._get_registry()
3181
tpr.register('foo', 'fff.ooo.ooo')
3182
self.assertEquals('fff.ooo.ooo', tpr.get('foo'))
3184
def test_register_existing_prefix(self):
3185
tpr = self._get_registry()
3186
tpr.register('bar', 'bbb.aaa.rrr')
3187
tpr.register('bar', 'bBB.aAA.rRR')
3188
self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
3189
self.assertThat(self.get_log(),
3190
DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR", ELLIPSIS))
3192
def test_get_unknown_prefix(self):
3193
tpr = self._get_registry()
3194
self.assertRaises(KeyError, tpr.get, 'I am not a prefix')
3196
def test_resolve_prefix(self):
3197
tpr = self._get_registry()
3198
tpr.register('bar', 'bb.aa.rr')
3199
self.assertEquals('bb.aa.rr', tpr.resolve_alias('bar'))
3201
def test_resolve_unknown_alias(self):
3202
tpr = self._get_registry()
3203
self.assertRaises(errors.BzrCommandError,
3204
tpr.resolve_alias, 'I am not a prefix')
3206
def test_predefined_prefixes(self):
3207
tpr = tests.test_prefix_alias_registry
3208
self.assertEquals('bzrlib', tpr.resolve_alias('bzrlib'))
3209
self.assertEquals('bzrlib.doc', tpr.resolve_alias('bd'))
3210
self.assertEquals('bzrlib.utils', tpr.resolve_alias('bu'))
3211
self.assertEquals('bzrlib.tests', tpr.resolve_alias('bt'))
3212
self.assertEquals('bzrlib.tests.blackbox', tpr.resolve_alias('bb'))
3213
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3216
class TestThreadLeakDetection(tests.TestCase):
3217
"""Ensure when tests leak threads we detect and report it"""
3219
class LeakRecordingResult(tests.ExtendedTestResult):
3221
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3223
def _report_thread_leak(self, test, leaks, alive):
3224
self.leaks.append((test, leaks))
3226
def test_testcase_without_addCleanups(self):
3227
"""Check old TestCase instances don't break with leak detection"""
3228
class Test(unittest.TestCase):
3231
addCleanup = None # for when on Python 2.7 with native addCleanup
3232
result = self.LeakRecordingResult()
3234
self.assertIs(getattr(test, "addCleanup", None), None)
3235
result.startTestRun()
3237
result.stopTestRun()
3238
self.assertEqual(result._tests_leaking_threads_count, 0)
3239
self.assertEqual(result.leaks, [])
3241
def test_thread_leak(self):
3242
"""Ensure a thread that outlives the running of a test is reported
3244
Uses a thread that blocks on an event, and is started by the inner
3245
test case. As the thread outlives the inner case's run, it should be
3246
detected as a leak, but the event is then set so that the thread can
3247
be safely joined in cleanup so it's not leaked for real.
3249
event = threading.Event()
3250
thread = threading.Thread(name="Leaker", target=event.wait)
3251
class Test(tests.TestCase):
3252
def test_leak(self):
3254
result = self.LeakRecordingResult()
3255
test = Test("test_leak")
3256
self.addCleanup(thread.join)
3257
self.addCleanup(event.set)
3258
result.startTestRun()
3260
result.stopTestRun()
3261
self.assertEqual(result._tests_leaking_threads_count, 1)
3262
self.assertEqual(result._first_thread_leaker_id, test.id())
3263
self.assertEqual(result.leaks, [(test, set([thread]))])
3264
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3266
def test_multiple_leaks(self):
3267
"""Check multiple leaks are blamed on the test cases at fault
3269
Same concept as the previous test, but has one inner test method that
3270
leaks two threads, and one that doesn't leak at all.
3272
event = threading.Event()
3273
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3274
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3275
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3276
class Test(tests.TestCase):
3277
def test_first_leak(self):
3279
def test_second_no_leak(self):
3281
def test_third_leak(self):
3284
result = self.LeakRecordingResult()
3285
first_test = Test("test_first_leak")
3286
third_test = Test("test_third_leak")
3287
self.addCleanup(thread_a.join)
3288
self.addCleanup(thread_b.join)
3289
self.addCleanup(thread_c.join)
3290
self.addCleanup(event.set)
3291
result.startTestRun()
3293
[first_test, Test("test_second_no_leak"), third_test]
3295
result.stopTestRun()
3296
self.assertEqual(result._tests_leaking_threads_count, 2)
3297
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3298
self.assertEqual(result.leaks, [
3299
(first_test, set([thread_b])),
3300
(third_test, set([thread_a, thread_c]))])
3301
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3304
class TestRunSuite(tests.TestCase):
3306
def test_runner_class(self):
3307
"""run_suite accepts and uses a runner_class keyword argument."""
3308
class Stub(tests.TestCase):
3311
suite = Stub("test_foo")
3313
class MyRunner(tests.TextTestRunner):
3314
def run(self, test):
3316
return tests.ExtendedTestResult(self.stream, self.descriptions,
3318
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3319
self.assertLength(1, calls)