~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_branch.py

  • Committer: Vincent Ladeuil
  • Date: 2010-02-10 15:46:03 UTC
  • mfrom: (4985.3.21 update)
  • mto: This revision was merged to the branch mainline in revision 5021.
  • Revision ID: v.ladeuil+lp@free.fr-20100210154603-k4no1gvfuqpzrw7p
Update performs two merges in a more logical order but stop on conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Tests for the Branch facility that are not interface  tests.
18
18
 
19
 
For interface tests see tests/branch_implementations/*.py.
 
19
For interface tests see tests/per_branch/*.py.
20
20
 
21
21
For concrete class tests see this file, and for meta-branch tests
22
22
also see this file.
23
23
"""
24
24
 
25
 
from StringIO import StringIO
 
25
from cStringIO import StringIO
26
26
 
27
27
from bzrlib import (
28
28
    branch as _mod_branch,
29
29
    bzrdir,
30
30
    config,
31
31
    errors,
 
32
    tests,
32
33
    trace,
 
34
    transport,
33
35
    urlutils,
34
36
    )
35
 
from bzrlib.branch import (
36
 
    Branch,
37
 
    BranchHooks,
38
 
    BranchFormat,
39
 
    BranchReferenceFormat,
40
 
    BzrBranch5,
41
 
    BzrBranchFormat5,
42
 
    BzrBranchFormat6,
43
 
    PullResult,
44
 
    _run_with_write_locked_target,
45
 
    )
46
 
from bzrlib.bzrdir import (BzrDirMetaFormat1, BzrDirMeta1, 
47
 
                           BzrDir, BzrDirFormat)
48
 
from bzrlib.errors import (NotBranchError,
49
 
                           UnknownFormatError,
50
 
                           UnknownHook,
51
 
                           UnsupportedFormatError,
52
 
                           )
53
 
 
54
 
from bzrlib.tests import TestCase, TestCaseWithTransport
55
 
from bzrlib.transport import get_transport
56
 
 
57
 
 
58
 
class TestDefaultFormat(TestCase):
 
37
 
 
38
 
 
39
class TestDefaultFormat(tests.TestCase):
59
40
 
60
41
    def test_default_format(self):
61
42
        # update this if you change the default branch format
62
 
        self.assertIsInstance(BranchFormat.get_default_format(),
63
 
                BzrBranchFormat6)
 
43
        self.assertIsInstance(_mod_branch.BranchFormat.get_default_format(),
 
44
                _mod_branch.BzrBranchFormat7)
64
45
 
65
46
    def test_default_format_is_same_as_bzrdir_default(self):
66
47
        # XXX: it might be nice if there was only one place the default was
67
 
        # set, but at the moment that's not true -- mbp 20070814 -- 
 
48
        # set, but at the moment that's not true -- mbp 20070814 --
68
49
        # https://bugs.launchpad.net/bzr/+bug/132376
69
 
        self.assertEqual(BranchFormat.get_default_format(),
70
 
                BzrDirFormat.get_default_format().get_branch_format())
 
50
        self.assertEqual(
 
51
            _mod_branch.BranchFormat.get_default_format(),
 
52
            bzrdir.BzrDirFormat.get_default_format().get_branch_format())
71
53
 
72
54
    def test_get_set_default_format(self):
73
55
        # set the format and then set it back again
74
 
        old_format = BranchFormat.get_default_format()
75
 
        BranchFormat.set_default_format(SampleBranchFormat())
 
56
        old_format = _mod_branch.BranchFormat.get_default_format()
 
57
        _mod_branch.BranchFormat.set_default_format(SampleBranchFormat())
76
58
        try:
77
59
            # the default branch format is used by the meta dir format
78
60
            # which is not the default bzrdir format at this point
79
 
            dir = BzrDirMetaFormat1().initialize('memory:///')
 
61
            dir = bzrdir.BzrDirMetaFormat1().initialize('memory:///')
80
62
            result = dir.create_branch()
81
63
            self.assertEqual(result, 'A branch')
82
64
        finally:
83
 
            BranchFormat.set_default_format(old_format)
84
 
        self.assertEqual(old_format, BranchFormat.get_default_format())
85
 
 
86
 
 
87
 
class TestBranchFormat5(TestCaseWithTransport):
 
65
            _mod_branch.BranchFormat.set_default_format(old_format)
 
66
        self.assertEqual(old_format,
 
67
                         _mod_branch.BranchFormat.get_default_format())
 
68
 
 
69
 
 
70
class TestBranchFormat5(tests.TestCaseWithTransport):
88
71
    """Tests specific to branch format 5"""
89
72
 
90
73
    def test_branch_format_5_uses_lockdir(self):
91
74
        url = self.get_url()
92
 
        bzrdir = BzrDirMetaFormat1().initialize(url)
93
 
        bzrdir.create_repository()
94
 
        branch = bzrdir.create_branch()
 
75
        bdir = bzrdir.BzrDirMetaFormat1().initialize(url)
 
76
        bdir.create_repository()
 
77
        branch = bdir.create_branch()
95
78
        t = self.get_transport()
96
79
        self.log("branch instance is %r" % branch)
97
 
        self.assert_(isinstance(branch, BzrBranch5))
 
80
        self.assert_(isinstance(branch, _mod_branch.BzrBranch5))
98
81
        self.assertIsDirectory('.', t)
99
82
        self.assertIsDirectory('.bzr/branch', t)
100
83
        self.assertIsDirectory('.bzr/branch/lock', t)
101
84
        branch.lock_write()
102
 
        try:
103
 
            self.assertIsDirectory('.bzr/branch/lock/held', t)
104
 
        finally:
105
 
            branch.unlock()
 
85
        self.addCleanup(branch.unlock)
 
86
        self.assertIsDirectory('.bzr/branch/lock/held', t)
106
87
 
107
88
    def test_set_push_location(self):
108
89
        from bzrlib.config import (locations_config_filename,
131
112
    # recursive section - that is, it appends the branch name.
132
113
 
133
114
 
134
 
class SampleBranchFormat(BranchFormat):
 
115
class SampleBranchFormat(_mod_branch.BranchFormat):
135
116
    """A sample format
136
117
 
137
 
    this format is initializable, unsupported to aid in testing the 
 
118
    this format is initializable, unsupported to aid in testing the
138
119
    open and open_downlevel routines.
139
120
    """
140
121
 
151
132
    def is_supported(self):
152
133
        return False
153
134
 
154
 
    def open(self, transport, _found=False):
 
135
    def open(self, transport, _found=False, ignore_fallbacks=False):
155
136
        return "opened branch."
156
137
 
157
138
 
158
 
class TestBzrBranchFormat(TestCaseWithTransport):
 
139
class TestBzrBranchFormat(tests.TestCaseWithTransport):
159
140
    """Tests for the BzrBranchFormat facility."""
160
141
 
161
142
    def test_find_format(self):
162
143
        # is the right format object found for a branch?
163
144
        # create a branch with a few known format objects.
164
 
        # this is not quite the same as 
 
145
        # this is not quite the same as
165
146
        self.build_tree(["foo/", "bar/"])
166
147
        def check_format(format, url):
167
148
            dir = format._matchingbzrdir.initialize(url)
168
149
            dir.create_repository()
169
150
            format.initialize(dir)
170
 
            found_format = BranchFormat.find_format(dir)
 
151
            found_format = _mod_branch.BranchFormat.find_format(dir)
171
152
            self.failUnless(isinstance(found_format, format.__class__))
172
 
        check_format(BzrBranchFormat5(), "bar")
173
 
        
 
153
        check_format(_mod_branch.BzrBranchFormat5(), "bar")
 
154
 
174
155
    def test_find_format_not_branch(self):
175
156
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
176
 
        self.assertRaises(NotBranchError,
177
 
                          BranchFormat.find_format,
 
157
        self.assertRaises(errors.NotBranchError,
 
158
                          _mod_branch.BranchFormat.find_format,
178
159
                          dir)
179
160
 
180
161
    def test_find_format_unknown_format(self):
181
162
        dir = bzrdir.BzrDirMetaFormat1().initialize(self.get_url())
182
163
        SampleBranchFormat().initialize(dir)
183
 
        self.assertRaises(UnknownFormatError,
184
 
                          BranchFormat.find_format,
 
164
        self.assertRaises(errors.UnknownFormatError,
 
165
                          _mod_branch.BranchFormat.find_format,
185
166
                          dir)
186
167
 
187
168
    def test_register_unregister_format(self):
191
172
        # make a branch
192
173
        format.initialize(dir)
193
174
        # register a format for it.
194
 
        BranchFormat.register_format(format)
 
175
        _mod_branch.BranchFormat.register_format(format)
195
176
        # which branch.Open will refuse (not supported)
196
 
        self.assertRaises(UnsupportedFormatError, Branch.open, self.get_url())
 
177
        self.assertRaises(errors.UnsupportedFormatError,
 
178
                          _mod_branch.Branch.open, self.get_url())
197
179
        self.make_branch_and_tree('foo')
198
180
        # but open_downlevel will work
199
 
        self.assertEqual(format.open(dir), bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
 
181
        self.assertEqual(
 
182
            format.open(dir),
 
183
            bzrdir.BzrDir.open(self.get_url()).open_branch(unsupported=True))
200
184
        # unregister the format
201
 
        BranchFormat.unregister_format(format)
 
185
        _mod_branch.BranchFormat.unregister_format(format)
202
186
        self.make_branch_and_tree('bar')
203
187
 
204
188
 
215
199
        raise NotImplementedError(self.get_class)
216
200
 
217
201
    def test_creation(self):
218
 
        format = BzrDirMetaFormat1()
 
202
        format = bzrdir.BzrDirMetaFormat1()
219
203
        format.set_branch_format(_mod_branch.BzrBranchFormat6())
220
204
        branch = self.make_branch('a', format=format)
221
205
        self.assertIsInstance(branch, self.get_class())
228
212
        branch = self.make_branch('a', format=self.get_format_name())
229
213
        self.failUnlessExists('a/.bzr/branch/last-revision')
230
214
        self.failIfExists('a/.bzr/branch/revision-history')
 
215
        self.failIfExists('a/.bzr/branch/references')
231
216
 
232
217
    def test_config(self):
233
218
        """Ensure that all configuration data is stored in the branch"""
307
292
                         'locations.conf')
308
293
 
309
294
 
310
 
class TestBranch6(TestBranch67, TestCaseWithTransport):
 
295
class TestBranch6(TestBranch67, tests.TestCaseWithTransport):
311
296
 
312
297
    def get_class(self):
313
298
        return _mod_branch.BzrBranch6
328
313
        self.assertRaises(errors.UnstackableBranchFormat, branch.get_stacked_on_url)
329
314
 
330
315
 
331
 
class TestBranch7(TestBranch67, TestCaseWithTransport):
 
316
class TestBranch7(TestBranch67, tests.TestCaseWithTransport):
332
317
 
333
318
    def get_class(self):
334
319
        return _mod_branch.BzrBranch7
335
320
 
336
321
    def get_format_name(self):
337
 
        return "development"
 
322
        return "1.9"
338
323
 
339
324
    def get_format_name_subtree(self):
340
325
        return "development-subtree"
378
363
        self.assertTrue(branch.repository.has_revision(revid))
379
364
 
380
365
 
381
 
class TestBranchReference(TestCaseWithTransport):
 
366
class BzrBranch8(tests.TestCaseWithTransport):
 
367
 
 
368
    def make_branch(self, location, format=None):
 
369
        if format is None:
 
370
            format = bzrdir.format_registry.make_bzrdir('1.9')
 
371
            format.set_branch_format(_mod_branch.BzrBranchFormat8())
 
372
        return tests.TestCaseWithTransport.make_branch(
 
373
            self, location, format=format)
 
374
 
 
375
    def create_branch_with_reference(self):
 
376
        branch = self.make_branch('branch')
 
377
        branch._set_all_reference_info({'file-id': ('path', 'location')})
 
378
        return branch
 
379
 
 
380
    @staticmethod
 
381
    def instrument_branch(branch, gets):
 
382
        old_get = branch._transport.get
 
383
        def get(*args, **kwargs):
 
384
            gets.append((args, kwargs))
 
385
            return old_get(*args, **kwargs)
 
386
        branch._transport.get = get
 
387
 
 
388
    def test_reference_info_caching_read_locked(self):
 
389
        gets = []
 
390
        branch = self.create_branch_with_reference()
 
391
        branch.lock_read()
 
392
        self.addCleanup(branch.unlock)
 
393
        self.instrument_branch(branch, gets)
 
394
        branch.get_reference_info('file-id')
 
395
        branch.get_reference_info('file-id')
 
396
        self.assertEqual(1, len(gets))
 
397
 
 
398
    def test_reference_info_caching_read_unlocked(self):
 
399
        gets = []
 
400
        branch = self.create_branch_with_reference()
 
401
        self.instrument_branch(branch, gets)
 
402
        branch.get_reference_info('file-id')
 
403
        branch.get_reference_info('file-id')
 
404
        self.assertEqual(2, len(gets))
 
405
 
 
406
    def test_reference_info_caching_write_locked(self):
 
407
        gets = []
 
408
        branch = self.make_branch('branch')
 
409
        branch.lock_write()
 
410
        self.instrument_branch(branch, gets)
 
411
        self.addCleanup(branch.unlock)
 
412
        branch._set_all_reference_info({'file-id': ('path2', 'location2')})
 
413
        path, location = branch.get_reference_info('file-id')
 
414
        self.assertEqual(0, len(gets))
 
415
        self.assertEqual('path2', path)
 
416
        self.assertEqual('location2', location)
 
417
 
 
418
    def test_reference_info_caches_cleared(self):
 
419
        branch = self.make_branch('branch')
 
420
        branch.lock_write()
 
421
        branch.set_reference_info('file-id', 'path2', 'location2')
 
422
        branch.unlock()
 
423
        doppelganger = _mod_branch.Branch.open('branch')
 
424
        doppelganger.set_reference_info('file-id', 'path3', 'location3')
 
425
        self.assertEqual(('path3', 'location3'),
 
426
                         branch.get_reference_info('file-id'))
 
427
 
 
428
class TestBranchReference(tests.TestCaseWithTransport):
382
429
    """Tests for the branch reference facility."""
383
430
 
384
431
    def test_create_open_reference(self):
385
432
        bzrdirformat = bzrdir.BzrDirMetaFormat1()
386
 
        t = get_transport(self.get_url('.'))
 
433
        t = transport.get_transport(self.get_url('.'))
387
434
        t.mkdir('repo')
388
435
        dir = bzrdirformat.initialize(self.get_url('repo'))
389
436
        dir.create_repository()
390
437
        target_branch = dir.create_branch()
391
438
        t.mkdir('branch')
392
439
        branch_dir = bzrdirformat.initialize(self.get_url('branch'))
393
 
        made_branch = BranchReferenceFormat().initialize(branch_dir, target_branch)
 
440
        made_branch = _mod_branch.BranchReferenceFormat().initialize(
 
441
            branch_dir, target_branch)
394
442
        self.assertEqual(made_branch.base, target_branch.base)
395
443
        opened_branch = branch_dir.open_branch()
396
444
        self.assertEqual(opened_branch.base, target_branch.base)
407
455
            _mod_branch.BranchReferenceFormat().get_reference(checkout.bzrdir))
408
456
 
409
457
 
410
 
class TestHooks(TestCase):
 
458
class TestHooks(tests.TestCase):
411
459
 
412
460
    def test_constructor(self):
413
461
        """Check that creating a BranchHooks instance has the right defaults."""
414
 
        hooks = BranchHooks()
 
462
        hooks = _mod_branch.BranchHooks()
415
463
        self.assertTrue("set_rh" in hooks, "set_rh not in %s" % hooks)
416
464
        self.assertTrue("post_push" in hooks, "post_push not in %s" % hooks)
417
465
        self.assertTrue("post_commit" in hooks, "post_commit not in %s" % hooks)
418
466
        self.assertTrue("pre_commit" in hooks, "pre_commit not in %s" % hooks)
419
467
        self.assertTrue("post_pull" in hooks, "post_pull not in %s" % hooks)
420
 
        self.assertTrue("post_uncommit" in hooks, "post_uncommit not in %s" % hooks)
 
468
        self.assertTrue("post_uncommit" in hooks,
 
469
                        "post_uncommit not in %s" % hooks)
421
470
        self.assertTrue("post_change_branch_tip" in hooks,
422
471
                        "post_change_branch_tip not in %s" % hooks)
423
472
 
424
473
    def test_installed_hooks_are_BranchHooks(self):
425
474
        """The installed hooks object should be a BranchHooks."""
426
475
        # the installed hooks are saved in self._preserved_hooks.
427
 
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch], BranchHooks)
428
 
 
429
 
 
430
 
class TestPullResult(TestCase):
 
476
        self.assertIsInstance(self._preserved_hooks[_mod_branch.Branch][1],
 
477
                              _mod_branch.BranchHooks)
 
478
 
 
479
 
 
480
class TestPullResult(tests.TestCase):
431
481
 
432
482
    def test_pull_result_to_int(self):
433
483
        # to support old code, the pull result can be used as an int
434
 
        r = PullResult()
 
484
        r = _mod_branch.PullResult()
435
485
        r.old_revno = 10
436
486
        r.new_revno = 20
437
487
        # this usage of results is not recommended for new code (because it
440
490
        a = "%d revisions pulled" % r
441
491
        self.assertEqual(a, "10 revisions pulled")
442
492
 
 
493
    def test_report_changed(self):
 
494
        r = _mod_branch.PullResult()
 
495
        r.old_revid = "old-revid"
 
496
        r.old_revno = 10
 
497
        r.new_revid = "new-revid"
 
498
        r.new_revno = 20
 
499
        f = StringIO()
 
500
        r.report(f)
 
501
        self.assertEqual("Now on revision 20.\n", f.getvalue())
 
502
 
 
503
    def test_report_unchanged(self):
 
504
        r = _mod_branch.PullResult()
 
505
        r.old_revid = "same-revid"
 
506
        r.new_revid = "same-revid"
 
507
        f = StringIO()
 
508
        r.report(f)
 
509
        self.assertEqual("No revisions to pull.\n", f.getvalue())
443
510
 
444
511
 
445
512
class _StubLockable(object):
451
518
 
452
519
    def lock_write(self):
453
520
        self.calls.append('lock_write')
454
 
    
 
521
 
455
522
    def unlock(self):
456
523
        self.calls.append('unlock')
457
524
        if self.unlock_exc is not None:
466
533
    """Helper for TestRunWithWriteLockedTarget."""
467
534
 
468
535
 
469
 
class TestRunWithWriteLockedTarget(TestCase):
 
536
class TestRunWithWriteLockedTarget(tests.TestCase):
470
537
    """Tests for _run_with_write_locked_target."""
471
538
 
472
539
    def setUp(self):
 
540
        tests.TestCase.setUp(self)
473
541
        self._calls = []
474
542
 
475
543
    def func_that_returns_ok(self):
482
550
 
483
551
    def test_success_unlocks(self):
484
552
        lockable = _StubLockable(self._calls)
485
 
        result = _run_with_write_locked_target(
 
553
        result = _mod_branch._run_with_write_locked_target(
486
554
            lockable, self.func_that_returns_ok)
487
555
        self.assertEqual('ok', result)
488
556
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
490
558
    def test_exception_unlocks_and_propagates(self):
491
559
        lockable = _StubLockable(self._calls)
492
560
        self.assertRaises(_ErrorFromCallable,
493
 
            _run_with_write_locked_target, lockable, self.func_that_raises)
 
561
                          _mod_branch._run_with_write_locked_target,
 
562
                          lockable, self.func_that_raises)
494
563
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
495
564
 
496
565
    def test_callable_succeeds_but_error_during_unlock(self):
497
566
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
498
567
        self.assertRaises(_ErrorFromUnlock,
499
 
            _run_with_write_locked_target, lockable, self.func_that_returns_ok)
 
568
                          _mod_branch._run_with_write_locked_target,
 
569
                          lockable, self.func_that_returns_ok)
500
570
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
501
571
 
502
572
    def test_error_during_unlock_does_not_mask_original_error(self):
503
573
        lockable = _StubLockable(self._calls, unlock_exc=_ErrorFromUnlock())
504
574
        self.assertRaises(_ErrorFromCallable,
505
 
            _run_with_write_locked_target, lockable, self.func_that_raises)
 
575
                          _mod_branch._run_with_write_locked_target,
 
576
                          lockable, self.func_that_raises)
506
577
        self.assertEqual(['lock_write', 'func called', 'unlock'], self._calls)
507
578
 
508
579