~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_hooks.py

  • Committer: Vincent Ladeuil
  • Date: 2012-01-18 14:09:19 UTC
  • mto: This revision was merged to the branch mainline in revision 6468.
  • Revision ID: v.ladeuil+lp@free.fr-20120118140919-rlvdrhpc0nq1lbwi
Change set/remove to require a lock for the branch config files.

This means that tests (or any plugin for that matter) do not requires an
explicit lock on the branch anymore to change a single option. This also
means the optimisation becomes "opt-in" and as such won't be as
spectacular as it may be and/or harder to get right (nothing fails
anymore).

This reduces the diff by ~300 lines.

Code/tests that were updating more than one config option is still taking
a lock to at least avoid some IOs and demonstrate the benefits through
the decreased number of hpss calls.

The duplication between BranchStack and BranchOnlyStack will be removed
once the same sharing is in place for local config files, at which point
the Stack class itself may be able to host the changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
from bzrlib import (
20
20
    branch,
21
21
    errors,
 
22
    hooks as _mod_hooks,
 
23
    pyutils,
22
24
    tests,
23
25
    )
24
26
from bzrlib.hooks import (
25
27
    HookPoint,
26
28
    Hooks,
 
29
    install_lazy_named_hook,
27
30
    known_hooks,
28
31
    known_hooks_key_to_object,
29
32
    known_hooks_key_to_parent_and_attribute,
30
33
    )
 
34
from bzrlib.symbol_versioning import (
 
35
    deprecated_in,
 
36
    )
31
37
 
32
38
 
33
39
class TestHooks(tests.TestCase):
34
40
 
35
41
    def test_create_hook_first(self):
36
 
        hooks = Hooks()
 
42
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
37
43
        doc = ("Invoked after changing the tip of a branch object. Called with"
38
44
            "a bzrlib.branch.PostChangeBranchTipParams object")
39
45
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
40
 
        hooks.create_hook(hook)
 
46
        self.applyDeprecated(deprecated_in((2, 4)), hooks.create_hook, hook)
41
47
        self.assertEqual(hook, hooks['post_tip_change'])
42
48
 
43
49
    def test_create_hook_name_collision_errors(self):
44
 
        hooks = Hooks()
 
50
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
45
51
        doc = ("Invoked after changing the tip of a branch object. Called with"
46
52
            "a bzrlib.branch.PostChangeBranchTipParams object")
47
53
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
48
54
        hook2 = HookPoint("post_tip_change", None, None, None)
49
 
        hooks.create_hook(hook)
50
 
        self.assertRaises(errors.DuplicateKey, hooks.create_hook, hook2)
 
55
        self.applyDeprecated(deprecated_in((2, 4)), hooks.create_hook, hook)
 
56
        self.assertRaises(errors.DuplicateKey, self.applyDeprecated,
 
57
            deprecated_in((2, 4, 0)), hooks.create_hook, hook2)
51
58
        self.assertEqual(hook, hooks['post_tip_change'])
52
59
 
53
60
    def test_docs(self):
54
61
        """docs() should return something reasonable about the Hooks."""
55
62
        class MyHooks(Hooks):
56
63
            pass
57
 
        hooks = MyHooks()
 
64
        hooks = MyHooks("bzrlib.tests.test_hooks", "some_hooks")
58
65
        hooks['legacy'] = []
59
 
        hook1 = HookPoint('post_tip_change',
 
66
        hooks.add_hook('post_tip_change',
60
67
            "Invoked after the tip of a branch changes. Called with "
61
 
            "a ChangeBranchTipParams object.", (1, 4), None)
62
 
        hook2 = HookPoint('pre_tip_change',
 
68
            "a ChangeBranchTipParams object.", (1, 4))
 
69
        hooks.add_hook('pre_tip_change',
63
70
            "Invoked before the tip of a branch changes. Called with "
64
71
            "a ChangeBranchTipParams object. Hooks should raise "
65
72
            "TipChangeRejected to signal that a tip change is not permitted.",
66
73
            (1, 6), None)
67
 
        hooks.create_hook(hook1)
68
 
        hooks.create_hook(hook2)
69
74
        self.assertEqualDiff(
70
75
            "MyHooks\n"
71
76
            "-------\n"
93
98
            "signal that a tip change is not permitted.\n", hooks.docs())
94
99
 
95
100
    def test_install_named_hook_raises_unknown_hook(self):
96
 
        hooks = Hooks()
 
101
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
97
102
        self.assertRaises(errors.UnknownHook, hooks.install_named_hook, 'silly',
98
103
                          None, "")
99
104
 
100
105
    def test_install_named_hook_appends_known_hook(self):
101
 
        hooks = Hooks()
 
106
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
102
107
        hooks['set_rh'] = []
103
108
        hooks.install_named_hook('set_rh', None, "demo")
104
109
        self.assertEqual(hooks['set_rh'], [None])
105
110
 
106
111
    def test_install_named_hook_and_retrieve_name(self):
107
 
        hooks = Hooks()
 
112
        hooks = Hooks("bzrlib.tests.test_hooks", "somehooks")
108
113
        hooks['set_rh'] = []
109
114
        hooks.install_named_hook('set_rh', None, "demo")
110
115
        self.assertEqual("demo", hooks.get_hook_name(None))
111
116
 
 
117
    def test_uninstall_named_hook(self):
 
118
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
119
        hooks.add_hook('set_rh', "Set revision history", (2, 0))
 
120
        hooks.install_named_hook('set_rh', None, "demo")
 
121
        self.assertEqual(1, len(hooks["set_rh"]))
 
122
        hooks.uninstall_named_hook("set_rh", "demo")
 
123
        self.assertEqual(0, len(hooks["set_rh"]))
 
124
 
 
125
    def test_uninstall_multiple_named_hooks(self):
 
126
        # Multiple callbacks with the same label all get removed
 
127
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
128
        hooks.add_hook('set_rh', "Set revision history", (2, 0))
 
129
        hooks.install_named_hook('set_rh', 1, "demo")
 
130
        hooks.install_named_hook('set_rh', 2, "demo")
 
131
        hooks.install_named_hook('set_rh', 3, "othername")
 
132
        self.assertEqual(3, len(hooks["set_rh"]))
 
133
        hooks.uninstall_named_hook("set_rh", "demo")
 
134
        self.assertEqual(1, len(hooks["set_rh"]))
 
135
 
 
136
    def test_uninstall_named_hook_unknown_callable(self):
 
137
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
138
        hooks.add_hook('set_rh', "Set revision hsitory", (2, 0))
 
139
        self.assertRaises(KeyError, hooks.uninstall_named_hook, "set_rh",
 
140
            "demo")
 
141
 
 
142
    def test_uninstall_named_hook_raises_unknown_hook(self):
 
143
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
144
        self.assertRaises(errors.UnknownHook, hooks.uninstall_named_hook,
 
145
            'silly', "")
 
146
 
 
147
    def test_uninstall_named_hook_old_style(self):
 
148
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
149
        hooks["set_rh"] = []
 
150
        hooks.install_named_hook('set_rh', None, "demo")
 
151
        self.assertRaises(errors.UnsupportedOperation,
 
152
            hooks.uninstall_named_hook, "set_rh", "demo")
 
153
 
 
154
    hooks = Hooks("bzrlib.tests.test_hooks", "TestHooks.hooks")
 
155
 
 
156
    def test_install_lazy_named_hook(self):
 
157
        # When the hook points are not yet registered the hook is
 
158
        # added to the _lazy_hooks dictionary in bzrlib.hooks.
 
159
        self.hooks.add_hook('set_rh', "doc", (0, 15))
 
160
        set_rh = lambda: None
 
161
        install_lazy_named_hook('bzrlib.tests.test_hooks',
 
162
            'TestHooks.hooks', 'set_rh', set_rh, "demo")
 
163
        set_rh_lazy_hooks = _mod_hooks._lazy_hooks[
 
164
            ('bzrlib.tests.test_hooks', 'TestHooks.hooks', 'set_rh')]
 
165
        self.assertEquals(1, len(set_rh_lazy_hooks))
 
166
        self.assertEquals(set_rh, set_rh_lazy_hooks[0][0].get_obj())
 
167
        self.assertEquals("demo", set_rh_lazy_hooks[0][1])
 
168
        self.assertEqual(list(TestHooks.hooks['set_rh']), [set_rh])
 
169
 
 
170
    set_rh = lambda: None
 
171
 
 
172
    def test_install_named_hook_lazy(self):
 
173
        hooks = Hooks("bzrlib.tests.hooks", "some_hooks")
 
174
        hooks['set_rh'] = HookPoint("set_rh", "doc", (0, 15), None)
 
175
        hooks.install_named_hook_lazy('set_rh', 'bzrlib.tests.test_hooks',
 
176
            'TestHooks.set_rh', "demo")
 
177
        self.assertEqual(list(hooks['set_rh']), [TestHooks.set_rh])
 
178
 
 
179
    def test_install_named_hook_lazy_old(self):
 
180
        # An exception is raised if a lazy hook is raised for
 
181
        # an old style hook point.
 
182
        hooks = Hooks("bzrlib.tests.hooks", "some_hooks")
 
183
        hooks['set_rh'] = []
 
184
        self.assertRaises(errors.UnsupportedOperation,
 
185
            hooks.install_named_hook_lazy,
 
186
            'set_rh', 'bzrlib.tests.test_hooks', 'TestHooks.set_rh',
 
187
            "demo")
 
188
 
 
189
    def test_valid_lazy_hooks(self):
 
190
        # Make sure that all the registered lazy hooks are referring to existing
 
191
        # hook points which allow lazy registration.
 
192
        for key, callbacks in _mod_hooks._lazy_hooks.iteritems():
 
193
            (module_name, member_name, hook_name) = key
 
194
            obj = pyutils.get_named_object(module_name, member_name)
 
195
            self.assertEquals(obj._module, module_name)
 
196
            self.assertEquals(obj._member_name, member_name)
 
197
            self.assertTrue(hook_name in obj)
 
198
            self.assertIs(callbacks, obj[hook_name]._callbacks)
 
199
 
112
200
 
113
201
class TestHook(tests.TestCase):
114
202
 
141
229
        hook.hook(callback, "my callback")
142
230
        self.assertEqual([callback], list(hook))
143
231
 
 
232
    def lazy_callback():
 
233
        pass
 
234
 
 
235
    def test_lazy_hook(self):
 
236
        hook = HookPoint("foo", "no docs", None, None)
 
237
        hook.hook_lazy(
 
238
            "bzrlib.tests.test_hooks", "TestHook.lazy_callback",
 
239
            "my callback")
 
240
        self.assertEqual([TestHook.lazy_callback], list(hook))
 
241
 
 
242
    def test_uninstall(self):
 
243
        hook = HookPoint("foo", "no docs", None, None)
 
244
        hook.hook_lazy(
 
245
            "bzrlib.tests.test_hooks", "TestHook.lazy_callback",
 
246
            "my callback")
 
247
        self.assertEqual([TestHook.lazy_callback], list(hook))
 
248
        hook.uninstall("my callback")
 
249
        self.assertEqual([], list(hook))
 
250
 
 
251
    def test_uninstall_unknown(self):
 
252
        hook = HookPoint("foo", "no docs", None, None)
 
253
        self.assertRaises(KeyError, hook.uninstall, "my callback")
 
254
 
144
255
    def test___repr(self):
145
256
        # The repr should list all the callbacks, with names.
146
257
        hook = HookPoint("foo", "no docs", None, None)
175
286
        self.assertIs(branch.Branch.hooks,
176
287
            known_hooks_key_to_object(('bzrlib.branch', 'Branch.hooks')))
177
288
 
 
289
    def test_known_hooks_key_to_parent_and_attribute_deprecated(self):
 
290
        self.assertEqual((branch.Branch, 'hooks'),
 
291
            self.applyDeprecated(deprecated_in((2,3)),
 
292
                known_hooks_key_to_parent_and_attribute,
 
293
                ('bzrlib.branch', 'Branch.hooks')))
 
294
        self.assertEqual((branch, 'Branch'),
 
295
            self.applyDeprecated(deprecated_in((2,3)),
 
296
                known_hooks_key_to_parent_and_attribute,
 
297
                ('bzrlib.branch', 'Branch')))
 
298
 
178
299
    def test_known_hooks_key_to_parent_and_attribute(self):
179
300
        self.assertEqual((branch.Branch, 'hooks'),
180
 
            known_hooks_key_to_parent_and_attribute(
 
301
            known_hooks.key_to_parent_and_attribute(
181
302
            ('bzrlib.branch', 'Branch.hooks')))
182
303
        self.assertEqual((branch, 'Branch'),
183
 
            known_hooks_key_to_parent_and_attribute(
 
304
            known_hooks.key_to_parent_and_attribute(
184
305
            ('bzrlib.branch', 'Branch')))