~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Andrew Bennetts
  • Date: 2008-07-03 07:56:02 UTC
  • mto: This revision was merged to the branch mainline in revision 3520.
  • Revision ID: andrew.bennetts@canonical.com-20080703075602-8n055qsfkjijcz6i
Better tests for {pre,post}_change_branch_tip hooks.

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.branch import Branch
 
19
from bzrlib.branch import Branch, ChangeBranchTipParams
20
20
from bzrlib.revision import NULL_REVISION
21
21
from bzrlib.tests import TestCaseWithMemoryTransport
22
22
 
81
81
 
82
82
 
83
83
class TestPreChangeBranchTip(TestCaseWithMemoryTransport):
84
 
    """Tests for pre_change_branch_tip hook."""
85
 
 
86
 
    def setUp(self):
87
 
        self.hook_calls = []
88
 
        TestCaseWithMemoryTransport.setUp(self)
89
 
 
90
 
    def capture_pre_change_branch_tip_hook(self, params):
91
 
        """Capture post_change_branch_tip hook calls to self.hook_calls.
92
 
 
93
 
        The call is logged, as is some state of the branch.
 
84
    """Tests for pre_change_branch_tip hook.
 
85
    
 
86
    Most of these tests are very similar to the tests in
 
87
    TestPostChangeBranchTip.
 
88
    """
 
89
 
 
90
    def install_logging_hook(self):
 
91
        """Add a hook that logs calls made to it.
 
92
        
 
93
        :returns: the list that the calls will be appended to.
94
94
        """
95
 
        self.hook_calls.append((params, params.branch.is_locked()))
96
 
        # The branch hasn't changed -- yet.
97
 
        self.assertEquals(params.branch.last_revision_info(),
98
 
                          (params.old_revno, params.old_revid))
 
95
        hook_calls = []
 
96
        Branch.hooks.install_named_hook(
 
97
            'pre_change_branch_tip', hook_calls.append, None)
 
98
        return hook_calls
99
99
 
100
100
    def make_branch_with_revision_ids(self, *revision_ids):
101
101
        """Makes a branch with the given commits."""
108
108
        branch = tree.branch
109
109
        return branch
110
110
 
 
111
    def test_hook_runs_before_change(self):
 
112
        """The hook runs *before* the branch's last_revision_info has changed.
 
113
        """
 
114
        branch = self.make_branch_with_revision_ids('revid-one')
 
115
        def assertBranchAtRevision1(params):
 
116
            self.assertEquals(
 
117
                (1, 'revid-one'), params.branch.last_revision_info())
 
118
        Branch.hooks.install_named_hook(
 
119
            'pre_change_branch_tip', assertBranchAtRevision1, None)
 
120
        branch.set_last_revision_info(0, NULL_REVISION)
 
121
 
111
122
    def test_reject_by_hook(self):
112
 
        """If a hook raises an exception, the change take effect."""
 
123
        """If a hook raises an exception, the change does not take effect.
 
124
        
 
125
        Also, the exception will be propogated.
 
126
        """
113
127
        branch = self.make_branch_with_revision_ids(
114
128
            'one-\xc2\xb5', 'two-\xc2\xb5')
115
129
        class PearShapedError(Exception):
123
137
        # The revision info is unchanged.
124
138
        self.assertEqual((2, 'two-\xc2\xb5'), branch.last_revision_info())
125
139
        
126
 
    # Tests from TestPostChangeBranchTip:
127
140
    def test_pre_change_branch_tip_empty_history(self):
128
141
        branch = self.make_branch('source')
129
 
        Branch.hooks.install_named_hook(
130
 
            'pre_change_branch_tip',
131
 
            self.capture_pre_change_branch_tip_hook,
132
 
            None)
 
142
        hook_calls = self.install_logging_hook()
133
143
        branch.set_last_revision_info(0, NULL_REVISION)
134
 
        self.assertEqual(len(self.hook_calls), 1)
135
 
        self.assertEqual(self.hook_calls[0][0].branch, branch)
136
 
        self.assertEqual(self.hook_calls[0][0].old_revid, NULL_REVISION)
137
 
        self.assertEqual(self.hook_calls[0][0].old_revno, 0)
138
 
        self.assertEqual(self.hook_calls[0][0].new_revid, NULL_REVISION)
139
 
        self.assertEqual(self.hook_calls[0][0].new_revno, 0)
 
144
        expected_params = ChangeBranchTipParams(
 
145
            branch, 0, 0, NULL_REVISION, NULL_REVISION)
 
146
        self.assertEqual([expected_params], hook_calls)
140
147
 
141
148
    def test_pre_change_branch_tip_nonempty_history(self):
 
149
        # some branches require that their history be set to a revision in the
 
150
        # repository, so we need to make a branch with non-empty history for
 
151
        # this test.
142
152
        branch = self.make_branch_with_revision_ids(
143
153
            'one-\xc2\xb5', 'two-\xc2\xb5')
144
 
        Branch.hooks.install_named_hook(
145
 
            'pre_change_branch_tip',
146
 
            self.capture_pre_change_branch_tip_hook,
147
 
            None)
148
 
        # some branches require that their history be set to a revision in the
149
 
        # repository
 
154
        hook_calls = self.install_logging_hook()
150
155
        branch.set_last_revision_info(1, 'one-\xc2\xb5')
151
 
        self.assertEqual(len(self.hook_calls), 1)
152
 
        self.assertEqual(self.hook_calls[0][0].branch, branch)
153
 
        self.assertEqual(self.hook_calls[0][0].old_revid, 'two-\xc2\xb5')
154
 
        self.assertEqual(self.hook_calls[0][0].old_revno, 2)
155
 
        self.assertEqual(self.hook_calls[0][0].new_revid, 'one-\xc2\xb5')
156
 
        self.assertEqual(self.hook_calls[0][0].new_revno, 1)
 
156
        expected_params = ChangeBranchTipParams(
 
157
            branch, 2, 1, 'two-\xc2\xb5', 'one-\xc2\xb5')
 
158
        self.assertEqual([expected_params], hook_calls)
157
159
 
158
160
    def test_pre_change_branch_tip_branch_is_locked(self):
159
161
        branch = self.make_branch('source')
 
162
        def assertBranchIsLocked(params):
 
163
            self.assertTrue(params.branch.is_locked())
160
164
        Branch.hooks.install_named_hook(
161
 
            'pre_change_branch_tip',
162
 
            self.capture_pre_change_branch_tip_hook,
163
 
            None)
 
165
            'pre_change_branch_tip', assertBranchIsLocked, None)
164
166
        branch.set_last_revision_info(0, NULL_REVISION)
165
 
        self.assertEqual(len(self.hook_calls), 1)
166
 
        self.assertEqual(self.hook_calls[0][0].branch, branch)
167
 
        self.assertEqual(self.hook_calls[0][1], True)
168
167
 
169
168
    def test_pre_change_branch_tip_calls_all_hooks_no_errors(self):
170
169
        branch = self.make_branch('source')
171
 
        Branch.hooks.install_named_hook(
172
 
            'pre_change_branch_tip',
173
 
            self.capture_pre_change_branch_tip_hook,
174
 
            None)
175
 
        Branch.hooks.install_named_hook(
176
 
            'pre_change_branch_tip',
177
 
            self.capture_pre_change_branch_tip_hook,
178
 
            None)
 
170
        hook_calls_1 = self.install_logging_hook()
 
171
        hook_calls_2 = self.install_logging_hook()
 
172
        self.assertIsNot(hook_calls_1, hook_calls_2)
179
173
        branch.set_last_revision_info(0, NULL_REVISION)
180
 
        self.assertEqual(len(self.hook_calls), 2)
181
 
        self.assertEqual(self.hook_calls[0][0].branch, branch)
182
 
        self.assertEqual(self.hook_calls[1][0].branch, branch)
 
174
        # Both hooks are called.
 
175
        self.assertEqual(len(hook_calls_1), 1)
 
176
        self.assertEqual(len(hook_calls_2), 1)
183
177
 
184
178
 
185
179
class TestPostChangeBranchTip(TestCaseWithMemoryTransport):
186
 
    """Tests for post_change_branch_tip hook."""
187
 
 
188
 
    def setUp(self):
189
 
        self.hook_calls = []
190
 
        TestCaseWithMemoryTransport.setUp(self)
191
 
 
192
 
    def capture_post_change_branch_tip_hook(self, params):
193
 
        """Capture post_change_branch_tip hook calls to self.hook_calls.
194
 
 
195
 
        The call is logged, as is some state of the branch.
 
180
    """Tests for post_change_branch_tip hook.
 
181
 
 
182
    Most of these tests are very similar to the tests in
 
183
    TestPostChangeBranchTip.
 
184
    """
 
185
 
 
186
    def install_logging_hook(self):
 
187
        """Add a hook that logs calls made to it.
 
188
        
 
189
        :returns: the list that the calls will be appended to.
196
190
        """
197
 
        self.hook_calls.append((params, params.branch.is_locked()))
198
 
        self.assertEquals(params.branch.last_revision_info(),
199
 
                          (params.new_revno, params.new_revid))
200
 
 
201
 
    def test_post_change_branch_tip_empty_history(self):
202
 
        branch = self.make_branch('source')
 
191
        hook_calls = []
203
192
        Branch.hooks.install_named_hook(
204
 
            'post_change_branch_tip',
205
 
            self.capture_post_change_branch_tip_hook,
206
 
            None)
207
 
        branch.set_last_revision_info(0, NULL_REVISION)
208
 
        self.assertEqual(len(self.hook_calls), 1)
209
 
        self.assertEqual(self.hook_calls[0][0].branch, branch)
210
 
        self.assertEqual(self.hook_calls[0][0].old_revid, NULL_REVISION)
211
 
        self.assertEqual(self.hook_calls[0][0].old_revno, 0)
212
 
        self.assertEqual(self.hook_calls[0][0].new_revid, NULL_REVISION)
213
 
        self.assertEqual(self.hook_calls[0][0].new_revno, 0)
 
193
            'post_change_branch_tip', hook_calls.append, None)
 
194
        return hook_calls
214
195
 
215
 
    def test_post_change_branch_tip_nonempty_history(self):
 
196
    def make_branch_with_revision_ids(self, *revision_ids):
 
197
        """Makes a branch with the given commits."""
216
198
        tree = self.make_branch_and_memory_tree('source')
217
199
        tree.lock_write()
218
200
        tree.add('')
219
 
        tree.commit('another commit', rev_id='f\xc2\xb5')
220
 
        tree.commit('empty commit', rev_id='foo')
 
201
        for revision_id in revision_ids:
 
202
            tree.commit('Message of ' + revision_id, rev_id=revision_id)
221
203
        tree.unlock()
222
204
        branch = tree.branch
 
205
        return branch
 
206
 
 
207
    def test_hook_runs_after_change(self):
 
208
        """The hook runs *after* the branch's last_revision_info has changed.
 
209
        """
 
210
        branch = self.make_branch_with_revision_ids('revid-one')
 
211
        def assertBranchAtRevision1(params):
 
212
            self.assertEquals(
 
213
                (0, NULL_REVISION), params.branch.last_revision_info())
223
214
        Branch.hooks.install_named_hook(
224
 
            'post_change_branch_tip',
225
 
            self.capture_post_change_branch_tip_hook,
226
 
            None)
 
215
            'post_change_branch_tip', assertBranchAtRevision1, None)
 
216
        branch.set_last_revision_info(0, NULL_REVISION)
 
217
 
 
218
    def test_change_branch_tip_empty_history(self):
 
219
        branch = self.make_branch('source')
 
220
        hook_calls = self.install_logging_hook()
 
221
        branch.set_last_revision_info(0, NULL_REVISION)
 
222
        expected_params = ChangeBranchTipParams(
 
223
            branch, 0, 0, NULL_REVISION, NULL_REVISION)
 
224
        self.assertEqual([expected_params], hook_calls)
 
225
 
 
226
    def test_change_branch_tip_nonempty_history(self):
227
227
        # some branches require that their history be set to a revision in the
228
 
        # repository
229
 
        branch.set_last_revision_info(1, 'f\xc2\xb5')
230
 
        self.assertEqual(len(self.hook_calls), 1)
231
 
        self.assertEqual(self.hook_calls[0][0].branch, branch)
232
 
        self.assertEqual(self.hook_calls[0][0].old_revid, 'foo')
233
 
        self.assertEqual(self.hook_calls[0][0].old_revno, 2)
234
 
        self.assertEqual(self.hook_calls[0][0].new_revid, 'f\xc2\xb5')
235
 
        self.assertEqual(self.hook_calls[0][0].new_revno, 1)
236
 
 
237
 
    def test_post_change_branch_tip_branch_is_locked(self):
238
 
        branch = self.make_branch('source')
239
 
        Branch.hooks.install_named_hook(
240
 
            'post_change_branch_tip',
241
 
            self.capture_post_change_branch_tip_hook,
242
 
            None)
243
 
        branch.set_last_revision_info(0, NULL_REVISION)
244
 
        self.assertEqual(len(self.hook_calls), 1)
245
 
        self.assertEqual(self.hook_calls[0][0].branch, branch)
246
 
        self.assertEqual(self.hook_calls[0][1], True)
247
 
 
248
 
    def test_post_change_branch_tip_calls_all_hooks_no_errors(self):
249
 
        branch = self.make_branch('source')
250
 
        Branch.hooks.install_named_hook(
251
 
            'post_change_branch_tip',
252
 
            self.capture_post_change_branch_tip_hook,
253
 
            None)
254
 
        Branch.hooks.install_named_hook(
255
 
            'post_change_branch_tip',
256
 
            self.capture_post_change_branch_tip_hook,
257
 
            None)
258
 
        branch.set_last_revision_info(0, NULL_REVISION)
259
 
        self.assertEqual(len(self.hook_calls), 2)
260
 
        self.assertEqual(self.hook_calls[0][0].branch, branch)
261
 
        self.assertEqual(self.hook_calls[1][0].branch, branch)
 
228
        # repository, so we need to make a branch with non-empty history for
 
229
        # this test.
 
230
        branch = self.make_branch_with_revision_ids(
 
231
            'one-\xc2\xb5', 'two-\xc2\xb5')
 
232
        hook_calls = self.install_logging_hook()
 
233
        branch.set_last_revision_info(1, 'one-\xc2\xb5')
 
234
        expected_params = ChangeBranchTipParams(
 
235
            branch, 2, 1, 'two-\xc2\xb5', 'one-\xc2\xb5')
 
236
        self.assertEqual([expected_params], hook_calls)
 
237
 
 
238
    def test_tip_branch_is_locked(self):
 
239
        """The branch passed to the hook is locked."""
 
240
        branch = self.make_branch('source')
 
241
        def assertBranchIsLocked(params):
 
242
            self.assertTrue(params.branch.is_locked())
 
243
        Branch.hooks.install_named_hook(
 
244
            'pre_change_branch_tip', assertBranchIsLocked, None)
 
245
        branch.set_last_revision_info(0, NULL_REVISION)
 
246
 
 
247
    def test_change_branch_tip_calls_all_hooks_no_errors(self):
 
248
        """If multiple hooks are registered, all are called."""
 
249
        branch = self.make_branch('source')
 
250
        hook_calls_1 = self.install_logging_hook()
 
251
        hook_calls_2 = self.install_logging_hook()
 
252
        self.assertIsNot(hook_calls_1, hook_calls_2)
 
253
        branch.set_last_revision_info(0, NULL_REVISION)
 
254
        # Both hooks are called.
 
255
        self.assertEqual(len(hook_calls_1), 1)
 
256
        self.assertEqual(len(hook_calls_2), 1)