~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/branch_implementations/test_hooks.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-07-25 15:19:45 UTC
  • mfrom: (3577.1.3 tip-change-rejected-error)
  • Revision ID: pqm@pqm.ubuntu.com-20080725151945-kdaru30ix1m8k0h6
Add TipChangeRejected error so that pre_change_branch_tip hook
        functions can cleanly reject a change. (Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Tests that branch classes implement hook callouts correctly."""
18
18
 
 
19
from bzrlib.errors import HookFailed, TipChangeRejected
19
20
from bzrlib.branch import Branch, ChangeBranchTipParams
20
21
from bzrlib.revision import NULL_REVISION
21
22
from bzrlib.tests import TestCaseWithMemoryTransport
90
91
        """
91
92
        hook_calls = []
92
93
        Branch.hooks.install_named_hook(
93
 
            'pre_change_branch_tip', hook_calls.append, None)
 
94
            prefix + '_change_branch_tip', hook_calls.append, None)
94
95
        return hook_calls
95
96
 
96
97
    def make_branch_with_revision_ids(self, *revision_ids):
124
125
            'pre_change_branch_tip', assertBranchAtRevision1, None)
125
126
        branch.set_last_revision_info(0, NULL_REVISION)
126
127
 
127
 
    def test_reject_by_hook(self):
 
128
    def test_hook_failure_prevents_change(self):
128
129
        """If a hook raises an exception, the change does not take effect.
129
130
        
130
 
        Also, the exception will be propogated.
 
131
        Also, a HookFailed exception will be raised.
131
132
        """
132
133
        branch = self.make_branch_with_revision_ids(
133
134
            'one-\xc2\xb5', 'two-\xc2\xb5')
137
138
            raise PearShapedError()
138
139
        Branch.hooks.install_named_hook(
139
140
            'pre_change_branch_tip', hook_that_raises, None)
140
 
        self.assertRaises(
141
 
            PearShapedError, branch.set_last_revision_info, 0, NULL_REVISION)
 
141
        hook_failed_exc = self.assertRaises(
 
142
            HookFailed, branch.set_last_revision_info, 0, NULL_REVISION)
 
143
        self.assertIsInstance(hook_failed_exc.exc_value, PearShapedError)
142
144
        # The revision info is unchanged.
143
145
        self.assertEqual((2, 'two-\xc2\xb5'), branch.last_revision_info())
144
146
        
183
185
        self.assertEqual(len(hook_calls_1), 1)
184
186
        self.assertEqual(len(hook_calls_2), 1)
185
187
 
 
188
    def test_explicit_reject_by_hook(self):
 
189
        """If a hook raises TipChangeRejected, the change does not take effect.
 
190
        
 
191
        TipChangeRejected exceptions are propagated, not wrapped in HookFailed.
 
192
        """
 
193
        branch = self.make_branch_with_revision_ids(
 
194
            'one-\xc2\xb5', 'two-\xc2\xb5')
 
195
        def hook_that_rejects(params):
 
196
            raise TipChangeRejected('rejection message')
 
197
        Branch.hooks.install_named_hook(
 
198
            'pre_change_branch_tip', hook_that_rejects, None)
 
199
        self.assertRaises(
 
200
            TipChangeRejected, branch.set_last_revision_info, 0, NULL_REVISION)
 
201
        # The revision info is unchanged.
 
202
        self.assertEqual((2, 'two-\xc2\xb5'), branch.last_revision_info())
 
203
        
186
204
 
187
205
class TestPostChangeBranchTip(ChangeBranchTipTestCase):
188
206
    """Tests for post_change_branch_tip hook.
243
261
        # Both hooks are called.
244
262
        self.assertEqual(len(hook_calls_1), 1)
245
263
        self.assertEqual(len(hook_calls_2), 1)
 
264
 
 
265
 
 
266
class TestAllMethodsThatChangeTipWillRunHooks(ChangeBranchTipTestCase):
 
267
    """Every method of Branch that changes a branch tip will invoke the
 
268
    pre/post_change_branch_tip hooks.
 
269
    """
 
270
 
 
271
    def setUp(self):
 
272
        ChangeBranchTipTestCase.setUp(self)
 
273
        self.installPreAndPostHooks()
 
274
        
 
275
    def installPreAndPostHooks(self):
 
276
        self.pre_hook_calls = self.install_logging_hook('pre')
 
277
        self.post_hook_calls = self.install_logging_hook('post')
 
278
 
 
279
    def resetHookCalls(self):
 
280
        del self.pre_hook_calls[:], self.post_hook_calls[:]
 
281
 
 
282
    def assertPreAndPostHooksWereInvoked(self):
 
283
        # Check for len == 1, because the hooks should only be be invoked once
 
284
        # by an operation.
 
285
        self.assertEqual(1, len(self.pre_hook_calls))
 
286
        self.assertEqual(1, len(self.post_hook_calls))
 
287
 
 
288
    def test_set_revision_history(self):
 
289
        branch = self.make_branch('')
 
290
        branch.set_revision_history([])
 
291
        self.assertPreAndPostHooksWereInvoked()
 
292
 
 
293
    def test_set_last_revision_info(self):
 
294
        branch = self.make_branch('')
 
295
        branch.set_last_revision_info(0, NULL_REVISION)
 
296
        self.assertPreAndPostHooksWereInvoked()
 
297
 
 
298
    def test_generate_revision_history(self):
 
299
        branch = self.make_branch('')
 
300
        branch.generate_revision_history(NULL_REVISION)
 
301
        self.assertPreAndPostHooksWereInvoked()
 
302
 
 
303
    def test_pull(self):
 
304
        source_branch = self.make_branch_with_revision_ids('rev-1', 'rev-2')
 
305
        self.resetHookCalls()
 
306
        destination_branch = self.make_branch('destination')
 
307
        destination_branch.pull(source_branch)
 
308
        self.assertPreAndPostHooksWereInvoked()
 
309
 
 
310
    def test_push(self):
 
311
        source_branch = self.make_branch_with_revision_ids('rev-1', 'rev-2')
 
312
        self.resetHookCalls()
 
313
        destination_branch = self.make_branch('destination')
 
314
        source_branch.push(destination_branch)
 
315
        self.assertPreAndPostHooksWereInvoked()
 
316
 
 
317