/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
1
# Copyright (C) 2007 Canonical Ltd
2
#
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.
7
#
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.
12
#
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
2245.1.2 by Robert Collins
Remove the static DefaultHooks method from Branch, replacing it with a derived dict BranchHooks object, which is easier to use and provides a place to put the policy-checking add method discussed on list.
17
"""Tests that branch classes implement hook callouts correctly."""
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
18
3681.1.3 by Robert Collins
Update branch open tests to accomodate stacking.
19
from bzrlib.branch import Branch, ChangeBranchTipParams
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
20
from bzrlib.errors import HookFailed, TipChangeRejected
3681.1.3 by Robert Collins
Update branch open tests to accomodate stacking.
21
from bzrlib.remote import RemoteBranch
3331.1.2 by James Henstridge
Add calls to set_last_revision_info hook to both BzrBranch and
22
from bzrlib.revision import NULL_REVISION
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
23
from bzrlib.smart import server
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
24
from bzrlib.tests import TestCaseWithMemoryTransport
25
26
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
27
class ChangeBranchTipTestCase(TestCaseWithMemoryTransport):
28
    """Base TestCase for testing pre/post_change_branch_tip hooks."""
29
30
    def install_logging_hook(self, prefix):
31
        """Add a hook that logs calls made to it.
32
33
        :returns: the list that the calls will be appended to.
34
        """
35
        hook_calls = []
36
        Branch.hooks.install_named_hook(
37
            prefix + '_change_branch_tip', hook_calls.append, None)
38
        return hook_calls
39
40
    def make_branch_with_revision_ids(self, *revision_ids):
41
        """Makes a branch with the given commits."""
42
        tree = self.make_branch_and_memory_tree('source')
43
        tree.lock_write()
44
        tree.add('')
45
        for revision_id in revision_ids:
46
            tree.commit(u'Message of ' + revision_id.decode('utf8'),
47
                        rev_id=revision_id)
48
        tree.unlock()
49
        branch = tree.branch
50
        return branch
51
52
    def assertHookCalls(self, expected_params, branch, hook_calls=None,
53
        pre=False):
54
        if hook_calls is None:
55
            hook_calls = self.hook_calls
56
        if isinstance(branch, RemoteBranch):
57
            # For a remote branch, both the server and the client will raise
58
            # this hook, and we see both in the test environment. The remote
59
            # instance comes in between the clients - the client doe pre, the
60
            # server does pre, the server does post, the client does post.
61
            if pre:
62
                offset = 0
63
            else:
64
                offset = 1
65
            self.assertEqual(expected_params, hook_calls[offset])
66
            self.assertEqual(2, len(hook_calls))
67
        else:
68
            self.assertEqual([expected_params], hook_calls)
69
70
71
class TestSetRevisionHistoryHook(ChangeBranchTipTestCase):
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
72
73
    def setUp(self):
74
        self.hook_calls = []
75
        TestCaseWithMemoryTransport.setUp(self)
76
77
    def capture_set_rh_hook(self, branch, rev_history):
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
78
        """Capture post set-rh hook calls to self.hook_calls.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
79
2246.1.3 by Robert Collins
New branch hooks: post_push, post_pull, post_commit, post_uncommit. These
80
        The call is logged, as is some state of the branch.
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
81
        """
82
        self.hook_calls.append(
83
            ('set_rh', branch, rev_history, branch.is_locked()))
84
85
    def test_set_rh_empty_history(self):
86
        branch = self.make_branch('source')
3256.2.15 by Daniel Watkins
Updated uses of Hooks.install_hook to Hooks.install_named_hook in tests.branch_implementation.test_hooks.
87
        Branch.hooks.install_named_hook('set_rh', self.capture_set_rh_hook,
88
                                        None)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
89
        branch.set_revision_history([])
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
90
        expected_params = ('set_rh', branch, [], True)
91
        self.assertHookCalls(expected_params, branch)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
92
93
    def test_set_rh_nonempty_history(self):
2230.3.20 by Aaron Bentley
Add hooking for set_revision_history
94
        tree = self.make_branch_and_memory_tree('source')
95
        tree.lock_write()
96
        tree.add('')
2696.3.7 by Martin Pool
Update hook test to cope with branches that can't set their last revision to one that's not present
97
        tree.commit('another commit', rev_id='f\xc2\xb5')
2230.3.20 by Aaron Bentley
Add hooking for set_revision_history
98
        tree.commit('empty commit', rev_id='foo')
99
        tree.unlock()
100
        branch = tree.branch
3256.2.15 by Daniel Watkins
Updated uses of Hooks.install_hook to Hooks.install_named_hook in tests.branch_implementation.test_hooks.
101
        Branch.hooks.install_named_hook('set_rh', self.capture_set_rh_hook,
102
                                        None)
2696.3.7 by Martin Pool
Update hook test to cope with branches that can't set their last revision to one that's not present
103
        # some branches require that their history be set to a revision in the
104
        # repository
2309.4.10 by John Arbash Meinel
(fixed) Fix the last few tests that were explicitly passing around unicode ids
105
        branch.set_revision_history(['f\xc2\xb5'])
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
106
        expected_params =('set_rh', branch, ['f\xc2\xb5'], True)
107
        self.assertHookCalls(expected_params, branch)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
108
109
    def test_set_rh_branch_is_locked(self):
110
        branch = self.make_branch('source')
3256.2.15 by Daniel Watkins
Updated uses of Hooks.install_hook to Hooks.install_named_hook in tests.branch_implementation.test_hooks.
111
        Branch.hooks.install_named_hook('set_rh', self.capture_set_rh_hook,
112
                                        None)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
113
        branch.set_revision_history([])
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
114
        expected_params = ('set_rh', branch, [], True)
115
        self.assertHookCalls(expected_params, branch)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
116
117
    def test_set_rh_calls_all_hooks_no_errors(self):
118
        branch = self.make_branch('source')
3256.2.15 by Daniel Watkins
Updated uses of Hooks.install_hook to Hooks.install_named_hook in tests.branch_implementation.test_hooks.
119
        Branch.hooks.install_named_hook('set_rh', self.capture_set_rh_hook,
120
                                        None)
121
        Branch.hooks.install_named_hook('set_rh', self.capture_set_rh_hook,
122
                                        None)
2245.1.1 by Robert Collins
New Branch hooks facility, with one initial hook 'set_rh' which triggers
123
        branch.set_revision_history([])
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
124
        expected_calls = [('set_rh', branch, [], True),
125
            ('set_rh', branch, [], True),
126
            ]
127
        if isinstance(branch, RemoteBranch):
128
            # For a remote branch, both the server and the client will raise
129
            # set_rh, and the server will do so first because that is where
130
            # the change takes place.
131
            self.assertEqual(expected_calls, self.hook_calls[2:])
132
            self.assertEqual(4, len(self.hook_calls))
133
        else:
134
            self.assertEqual(expected_calls, self.hook_calls)
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
135
136
3681.1.1 by Robert Collins
Create a new hook Branch.open. (Robert Collins)
137
class TestOpen(TestCaseWithMemoryTransport):
138
139
    def capture_hook(self, branch):
140
        self.hook_calls.append(branch)
141
142
    def install_hook(self):
143
        self.hook_calls = []
144
        Branch.hooks.install_named_hook('open', self.capture_hook, None)
145
146
    def test_create(self):
147
        self.install_hook()
148
        b = self.make_branch('.')
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
149
        if isinstance(b, RemoteBranch):
150
            # RemoteBranch creation:
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
151
            # - creates the branch via the VFS (for older servers)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
152
            # - does a branch open (by creating a RemoteBranch object)
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
153
            # - this has the nearly the same behaviour as simple branch opening
154
            if (self.transport_readonly_server ==
155
                server.ReadonlySmartTCPServer_for_testing_v2_only):
156
                # Older servers:
157
                self.assertEqual(b._real_branch, self.hook_calls[0])
158
                self.assertOpenedRemoteBranch(self.hook_calls[1:], b)
159
            else:
160
                self.assertOpenedRemoteBranch(self.hook_calls, b,
161
                    remote_first=True)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
162
        else:
163
            self.assertEqual([b], self.hook_calls)
3681.1.1 by Robert Collins
Create a new hook Branch.open. (Robert Collins)
164
165
    def test_open(self):
166
        branch_url = self.make_branch('.').bzrdir.root_transport.base
167
        self.install_hook()
168
        b = Branch.open(branch_url)
3681.1.3 by Robert Collins
Update branch open tests to accomodate stacking.
169
        if isinstance(b, RemoteBranch):
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
170
            self.assertOpenedRemoteBranch(self.hook_calls, b)
3681.1.3 by Robert Collins
Update branch open tests to accomodate stacking.
171
        else:
172
            self.assertEqual([b], self.hook_calls)
3681.1.1 by Robert Collins
Create a new hook Branch.open. (Robert Collins)
173
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
174
    def assertOpenedRemoteBranch(self, hook_calls, b, remote_first=False):
175
        """Assert that the expected calls were recorded for opening 'b'.
176
177
        :param remote_first: If True expect the server side operation to open
178
            the branch object first.
179
        """
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
180
        # RemoteBranch open always opens the backing branch to get stacking
181
        # details. As that is done remotely we can't see the branch object
182
        # nor even compare base url's etc. So we just assert that the first
183
        # branch returned is the RemoteBranch, and that the second is a
184
        # Branch but not a RemoteBranch.
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
185
        #
186
        # RemoteBranch *creation* on the other hand creates the branch object
187
        # on the server, and then creates the local proxy object in the client,
188
        # so it sees the reverse order.
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
189
        self.assertEqual(2, len(hook_calls))
4032.3.2 by Robert Collins
Create and use a RPC call to create branches on bzr servers rather than using VFS calls.
190
        if remote_first:
191
            real_index = 0
192
            remote_index = 1
193
        else:
194
            real_index = 1
195
            remote_index = 0
196
        self.assertEqual(b, hook_calls[remote_index])
197
        self.assertIsInstance(hook_calls[real_index], Branch)
198
        self.assertFalse(isinstance(hook_calls[real_index], RemoteBranch))
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
199
3681.1.1 by Robert Collins
Create a new hook Branch.open. (Robert Collins)
200
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
201
class TestPreChangeBranchTip(ChangeBranchTipTestCase):
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
202
    """Tests for pre_change_branch_tip hook.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
203
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
204
    Most of these tests are very similar to the tests in
205
    TestPostChangeBranchTip.
206
    """
207
208
    def test_hook_runs_before_change(self):
209
        """The hook runs *before* the branch's last_revision_info has changed.
210
        """
211
        branch = self.make_branch_with_revision_ids('revid-one')
212
        def assertBranchAtRevision1(params):
213
            self.assertEquals(
214
                (1, 'revid-one'), params.branch.last_revision_info())
215
        Branch.hooks.install_named_hook(
216
            'pre_change_branch_tip', assertBranchAtRevision1, None)
217
        branch.set_last_revision_info(0, NULL_REVISION)
218
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
219
    def test_hook_failure_prevents_change(self):
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
220
        """If a hook raises an exception, the change does not take effect.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
221
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
222
        Also, a HookFailed exception will be raised.
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
223
        """
3517.2.2 by Andrew Bennetts
Add test for a pre_change_branch_tip hook rejecting a change.
224
        branch = self.make_branch_with_revision_ids(
225
            'one-\xc2\xb5', 'two-\xc2\xb5')
226
        class PearShapedError(Exception):
227
            pass
228
        def hook_that_raises(params):
229
            raise PearShapedError()
230
        Branch.hooks.install_named_hook(
231
            'pre_change_branch_tip', hook_that_raises, None)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
232
        hook_failed_exc = self.assertRaises(
233
            HookFailed, branch.set_last_revision_info, 0, NULL_REVISION)
234
        self.assertIsInstance(hook_failed_exc.exc_value, PearShapedError)
3517.2.2 by Andrew Bennetts
Add test for a pre_change_branch_tip hook rejecting a change.
235
        # The revision info is unchanged.
236
        self.assertEqual((2, 'two-\xc2\xb5'), branch.last_revision_info())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
237
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
238
    def test_empty_history(self):
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
239
        branch = self.make_branch('source')
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
240
        hook_calls = self.install_logging_hook('pre')
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
241
        branch.set_last_revision_info(0, NULL_REVISION)
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
242
        expected_params = ChangeBranchTipParams(
243
            branch, 0, 0, NULL_REVISION, NULL_REVISION)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
244
        self.assertHookCalls(expected_params, branch, hook_calls, pre=True)
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
245
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
246
    def test_nonempty_history(self):
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
247
        # some branches require that their history be set to a revision in the
248
        # repository, so we need to make a branch with non-empty history for
249
        # this test.
3517.2.2 by Andrew Bennetts
Add test for a pre_change_branch_tip hook rejecting a change.
250
        branch = self.make_branch_with_revision_ids(
251
            'one-\xc2\xb5', 'two-\xc2\xb5')
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
252
        hook_calls = self.install_logging_hook('pre')
3517.2.2 by Andrew Bennetts
Add test for a pre_change_branch_tip hook rejecting a change.
253
        branch.set_last_revision_info(1, 'one-\xc2\xb5')
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
254
        expected_params = ChangeBranchTipParams(
255
            branch, 2, 1, 'two-\xc2\xb5', 'one-\xc2\xb5')
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
256
        self.assertHookCalls(expected_params, branch, hook_calls, pre=True)
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
257
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
258
    def test_branch_is_locked(self):
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
259
        branch = self.make_branch('source')
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
260
        def assertBranchIsLocked(params):
261
            self.assertTrue(params.branch.is_locked())
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
262
        Branch.hooks.install_named_hook(
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
263
            'pre_change_branch_tip', assertBranchIsLocked, None)
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
264
        branch.set_last_revision_info(0, NULL_REVISION)
265
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
266
    def test_calls_all_hooks_no_errors(self):
267
        """If multiple hooks are registered, all are called (if none raise
268
        errors).
269
        """
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
270
        branch = self.make_branch('source')
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
271
        hook_calls_1 = self.install_logging_hook('pre')
272
        hook_calls_2 = self.install_logging_hook('pre')
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
273
        self.assertIsNot(hook_calls_1, hook_calls_2)
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
274
        branch.set_last_revision_info(0, NULL_REVISION)
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
275
        # Both hooks are called.
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
276
        if isinstance(branch, RemoteBranch):
277
            count = 2
278
        else:
279
            count = 1
280
        self.assertEqual(len(hook_calls_1), count)
281
        self.assertEqual(len(hook_calls_2), count)
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
282
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
283
    def test_explicit_reject_by_hook(self):
284
        """If a hook raises TipChangeRejected, the change does not take effect.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
285
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
286
        TipChangeRejected exceptions are propagated, not wrapped in HookFailed.
287
        """
288
        branch = self.make_branch_with_revision_ids(
289
            'one-\xc2\xb5', 'two-\xc2\xb5')
290
        def hook_that_rejects(params):
291
            raise TipChangeRejected('rejection message')
292
        Branch.hooks.install_named_hook(
293
            'pre_change_branch_tip', hook_that_rejects, None)
294
        self.assertRaises(
295
            TipChangeRejected, branch.set_last_revision_info, 0, NULL_REVISION)
296
        # The revision info is unchanged.
297
        self.assertEqual((2, 'two-\xc2\xb5'), branch.last_revision_info())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
298
3517.2.1 by Andrew Bennetts
Quick draft of pre_change_branch_tip hook.
299
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
300
class TestPostChangeBranchTip(ChangeBranchTipTestCase):
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
301
    """Tests for post_change_branch_tip hook.
302
303
    Most of these tests are very similar to the tests in
304
    TestPostChangeBranchTip.
305
    """
306
307
    def test_hook_runs_after_change(self):
308
        """The hook runs *after* the branch's last_revision_info has changed.
309
        """
310
        branch = self.make_branch_with_revision_ids('revid-one')
311
        def assertBranchAtRevision1(params):
312
            self.assertEquals(
313
                (0, NULL_REVISION), params.branch.last_revision_info())
3256.2.26 by Daniel Watkins
Updated tests to use install_named_hook.
314
        Branch.hooks.install_named_hook(
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
315
            'post_change_branch_tip', assertBranchAtRevision1, None)
316
        branch.set_last_revision_info(0, NULL_REVISION)
317
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
318
    def test_empty_history(self):
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
319
        branch = self.make_branch('source')
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
320
        hook_calls = self.install_logging_hook('post')
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
321
        branch.set_last_revision_info(0, NULL_REVISION)
322
        expected_params = ChangeBranchTipParams(
323
            branch, 0, 0, NULL_REVISION, NULL_REVISION)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
324
        self.assertHookCalls(expected_params, branch, hook_calls)
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
325
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
326
    def test_nonempty_history(self):
3331.1.2 by James Henstridge
Add calls to set_last_revision_info hook to both BzrBranch and
327
        # some branches require that their history be set to a revision in the
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
328
        # repository, so we need to make a branch with non-empty history for
329
        # this test.
330
        branch = self.make_branch_with_revision_ids(
331
            'one-\xc2\xb5', 'two-\xc2\xb5')
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
332
        hook_calls = self.install_logging_hook('post')
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
333
        branch.set_last_revision_info(1, 'one-\xc2\xb5')
334
        expected_params = ChangeBranchTipParams(
335
            branch, 2, 1, 'two-\xc2\xb5', 'one-\xc2\xb5')
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
336
        self.assertHookCalls(expected_params, branch, hook_calls)
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
337
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
338
    def test_branch_is_locked(self):
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
339
        """The branch passed to the hook is locked."""
340
        branch = self.make_branch('source')
341
        def assertBranchIsLocked(params):
342
            self.assertTrue(params.branch.is_locked())
343
        Branch.hooks.install_named_hook(
3517.2.4 by Andrew Bennetts
Fix typo.
344
            'post_change_branch_tip', assertBranchIsLocked, None)
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
345
        branch.set_last_revision_info(0, NULL_REVISION)
346
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
347
    def test_calls_all_hooks_no_errors(self):
348
        """If multiple hooks are registered, all are called (if none raise
349
        errors).
350
        """
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
351
        branch = self.make_branch('source')
3517.2.5 by Andrew Bennetts
Reduce duplication in test_hooks a little.
352
        hook_calls_1 = self.install_logging_hook('post')
353
        hook_calls_2 = self.install_logging_hook('post')
3517.2.3 by Andrew Bennetts
Better tests for {pre,post}_change_branch_tip hooks.
354
        self.assertIsNot(hook_calls_1, hook_calls_2)
355
        branch.set_last_revision_info(0, NULL_REVISION)
356
        # Both hooks are called.
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
357
        if isinstance(branch, RemoteBranch):
358
            count = 2
359
        else:
360
            count = 1
361
        self.assertEqual(len(hook_calls_1), count)
362
        self.assertEqual(len(hook_calls_2), count)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
363
364
365
class TestAllMethodsThatChangeTipWillRunHooks(ChangeBranchTipTestCase):
366
    """Every method of Branch that changes a branch tip will invoke the
367
    pre/post_change_branch_tip hooks.
368
    """
369
370
    def setUp(self):
371
        ChangeBranchTipTestCase.setUp(self)
372
        self.installPreAndPostHooks()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
373
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
374
    def installPreAndPostHooks(self):
375
        self.pre_hook_calls = self.install_logging_hook('pre')
376
        self.post_hook_calls = self.install_logging_hook('post')
377
378
    def resetHookCalls(self):
379
        del self.pre_hook_calls[:], self.post_hook_calls[:]
380
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
381
    def assertPreAndPostHooksWereInvoked(self, branch, smart_enabled):
382
        """assert that both pre and post hooks were called
383
384
        :param smart_enabled: The method invoked is one that should be
385
            smart server ready.
386
        """
387
        # Check for the number of invocations expected. One invocation is
388
        # local, one is remote (if the branch is remote).
389
        if smart_enabled and isinstance(branch, RemoteBranch):
390
            length = 2
391
        else:
392
            length = 1
393
        self.assertEqual(length, len(self.pre_hook_calls))
394
        self.assertEqual(length, len(self.post_hook_calls))
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
395
396
    def test_set_revision_history(self):
397
        branch = self.make_branch('')
398
        branch.set_revision_history([])
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
399
        self.assertPreAndPostHooksWereInvoked(branch, True)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
400
401
    def test_set_last_revision_info(self):
402
        branch = self.make_branch('')
403
        branch.set_last_revision_info(0, NULL_REVISION)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
404
        self.assertPreAndPostHooksWereInvoked(branch, True)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
405
406
    def test_generate_revision_history(self):
407
        branch = self.make_branch('')
408
        branch.generate_revision_history(NULL_REVISION)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
409
        # NB: for HPSS protocols < v3, the server does not invoke branch tip
410
        # change events on generate_revision_history, as the change is done
411
        # directly by the client over the VFS.
412
        self.assertPreAndPostHooksWereInvoked(branch, True)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
413
414
    def test_pull(self):
415
        source_branch = self.make_branch_with_revision_ids('rev-1', 'rev-2')
416
        self.resetHookCalls()
417
        destination_branch = self.make_branch('destination')
418
        destination_branch.pull(source_branch)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
419
        self.assertPreAndPostHooksWereInvoked(destination_branch, False)
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
420
421
    def test_push(self):
422
        source_branch = self.make_branch_with_revision_ids('rev-1', 'rev-2')
423
        self.resetHookCalls()
424
        destination_branch = self.make_branch('destination')
425
        source_branch.push(destination_branch)
4005.2.1 by Robert Collins
Fix RemoteBranch to be used correctly in tests using bzr+ssh, to fire off Branch hooks correctly, and improve the branch_implementations tests to check that making a branch gets the right format under test.
426
        self.assertPreAndPostHooksWereInvoked(destination_branch, True)