~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_hooks.py

  • Committer: Vincent Ladeuil
  • Date: 2017-01-30 14:30:10 UTC
  • mfrom: (6615.3.7 merges)
  • mto: This revision was merged to the branch mainline in revision 6621.
  • Revision ID: v.ladeuil+lp@free.fr-20170130143010-p31t1ranfeqbaeki
Merge  2.7 into trunk including fix for bug #1657238

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2009 Canonical Ltd
 
1
# Copyright (C) 2007-2012, 2016 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""Tests for the core Hooks logic."""
18
18
 
19
 
from bzrlib import branch, errors
 
19
from bzrlib import (
 
20
    branch,
 
21
    errors,
 
22
    hooks as _mod_hooks,
 
23
    pyutils,
 
24
    tests,
 
25
    )
20
26
from bzrlib.hooks import (
21
27
    HookPoint,
22
28
    Hooks,
 
29
    install_lazy_named_hook,
23
30
    known_hooks,
24
31
    known_hooks_key_to_object,
25
 
    known_hooks_key_to_parent_and_attribute,
26
 
    )
27
 
from bzrlib.errors import (
28
 
    UnknownHook,
29
 
    )
30
 
 
31
 
from bzrlib.tests import TestCase
32
 
 
33
 
 
34
 
class TestHooks(TestCase):
35
 
 
36
 
    def test_create_hook_first(self):
37
 
        hooks = Hooks()
38
 
        doc = ("Invoked after changing the tip of a branch object. Called with"
39
 
            "a bzrlib.branch.PostChangeBranchTipParams object")
40
 
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
41
 
        hooks.create_hook(hook)
42
 
        self.assertEqual(hook, hooks['post_tip_change'])
43
 
 
44
 
    def test_create_hook_name_collision_errors(self):
45
 
        hooks = Hooks()
46
 
        doc = ("Invoked after changing the tip of a branch object. Called with"
47
 
            "a bzrlib.branch.PostChangeBranchTipParams object")
48
 
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
49
 
        hook2 = HookPoint("post_tip_change", None, None, None)
50
 
        hooks.create_hook(hook)
51
 
        self.assertRaises(errors.DuplicateKey, hooks.create_hook, hook2)
52
 
        self.assertEqual(hook, hooks['post_tip_change'])
 
32
    )
 
33
from bzrlib.symbol_versioning import (
 
34
    deprecated_in,
 
35
    )
 
36
 
 
37
 
 
38
class TestHooks(tests.TestCase):
53
39
 
54
40
    def test_docs(self):
55
41
        """docs() should return something reasonable about the Hooks."""
56
42
        class MyHooks(Hooks):
57
43
            pass
58
 
        hooks = MyHooks()
 
44
        hooks = MyHooks("bzrlib.tests.test_hooks", "some_hooks")
59
45
        hooks['legacy'] = []
60
 
        hook1 = HookPoint('post_tip_change',
 
46
        hooks.add_hook('post_tip_change',
61
47
            "Invoked after the tip of a branch changes. Called with "
62
 
            "a ChangeBranchTipParams object.", (1, 4), None)
63
 
        hook2 = HookPoint('pre_tip_change',
 
48
            "a ChangeBranchTipParams object.", (1, 4))
 
49
        hooks.add_hook('pre_tip_change',
64
50
            "Invoked before the tip of a branch changes. Called with "
65
51
            "a ChangeBranchTipParams object. Hooks should raise "
66
52
            "TipChangeRejected to signal that a tip change is not permitted.",
67
53
            (1, 6), None)
68
 
        hooks.create_hook(hook1)
69
 
        hooks.create_hook(hook2)
70
54
        self.assertEqualDiff(
71
55
            "MyHooks\n"
72
56
            "-------\n"
80
64
            "~~~~~~~~~~~~~~~\n"
81
65
            "\n"
82
66
            "Introduced in: 1.4\n"
83
 
            "Deprecated in: Not deprecated\n"
84
67
            "\n"
85
68
            "Invoked after the tip of a branch changes. Called with a\n"
86
69
            "ChangeBranchTipParams object.\n"
89
72
            "~~~~~~~~~~~~~~\n"
90
73
            "\n"
91
74
            "Introduced in: 1.6\n"
92
 
            "Deprecated in: Not deprecated\n"
93
75
            "\n"
94
76
            "Invoked before the tip of a branch changes. Called with a\n"
95
77
            "ChangeBranchTipParams object. Hooks should raise TipChangeRejected to\n"
96
78
            "signal that a tip change is not permitted.\n", hooks.docs())
97
79
 
98
80
    def test_install_named_hook_raises_unknown_hook(self):
99
 
        hooks = Hooks()
100
 
        self.assertRaises(UnknownHook, hooks.install_named_hook, 'silly',
 
81
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
82
        self.assertRaises(errors.UnknownHook, hooks.install_named_hook, 'silly',
101
83
                          None, "")
102
84
 
103
85
    def test_install_named_hook_appends_known_hook(self):
104
 
        hooks = Hooks()
 
86
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
105
87
        hooks['set_rh'] = []
106
88
        hooks.install_named_hook('set_rh', None, "demo")
107
89
        self.assertEqual(hooks['set_rh'], [None])
108
90
 
109
91
    def test_install_named_hook_and_retrieve_name(self):
110
 
        hooks = Hooks()
 
92
        hooks = Hooks("bzrlib.tests.test_hooks", "somehooks")
111
93
        hooks['set_rh'] = []
112
94
        hooks.install_named_hook('set_rh', None, "demo")
113
95
        self.assertEqual("demo", hooks.get_hook_name(None))
114
96
 
115
 
 
116
 
class TestHook(TestCase):
 
97
    def test_uninstall_named_hook(self):
 
98
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
99
        hooks.add_hook('set_rh', "Set revision history", (2, 0))
 
100
        hooks.install_named_hook('set_rh', None, "demo")
 
101
        self.assertEqual(1, len(hooks["set_rh"]))
 
102
        hooks.uninstall_named_hook("set_rh", "demo")
 
103
        self.assertEqual(0, len(hooks["set_rh"]))
 
104
 
 
105
    def test_uninstall_multiple_named_hooks(self):
 
106
        # Multiple callbacks with the same label all get removed
 
107
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
108
        hooks.add_hook('set_rh', "Set revision history", (2, 0))
 
109
        hooks.install_named_hook('set_rh', 1, "demo")
 
110
        hooks.install_named_hook('set_rh', 2, "demo")
 
111
        hooks.install_named_hook('set_rh', 3, "othername")
 
112
        self.assertEqual(3, len(hooks["set_rh"]))
 
113
        hooks.uninstall_named_hook("set_rh", "demo")
 
114
        self.assertEqual(1, len(hooks["set_rh"]))
 
115
 
 
116
    def test_uninstall_named_hook_unknown_callable(self):
 
117
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
118
        hooks.add_hook('set_rh', "Set revision hsitory", (2, 0))
 
119
        self.assertRaises(KeyError, hooks.uninstall_named_hook, "set_rh",
 
120
            "demo")
 
121
 
 
122
    def test_uninstall_named_hook_raises_unknown_hook(self):
 
123
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
124
        self.assertRaises(errors.UnknownHook, hooks.uninstall_named_hook,
 
125
            'silly', "")
 
126
 
 
127
    def test_uninstall_named_hook_old_style(self):
 
128
        hooks = Hooks("bzrlib.tests.test_hooks", "some_hooks")
 
129
        hooks["set_rh"] = []
 
130
        hooks.install_named_hook('set_rh', None, "demo")
 
131
        self.assertRaises(errors.UnsupportedOperation,
 
132
            hooks.uninstall_named_hook, "set_rh", "demo")
 
133
 
 
134
    hooks = Hooks("bzrlib.tests.test_hooks", "TestHooks.hooks")
 
135
 
 
136
    def test_install_lazy_named_hook(self):
 
137
        # When the hook points are not yet registered the hook is
 
138
        # added to the _lazy_hooks dictionary in bzrlib.hooks.
 
139
        self.hooks.add_hook('set_rh', "doc", (0, 15))
 
140
        set_rh = lambda: None
 
141
        install_lazy_named_hook('bzrlib.tests.test_hooks',
 
142
            'TestHooks.hooks', 'set_rh', set_rh, "demo")
 
143
        set_rh_lazy_hooks = _mod_hooks._lazy_hooks[
 
144
            ('bzrlib.tests.test_hooks', 'TestHooks.hooks', 'set_rh')]
 
145
        self.assertEqual(1, len(set_rh_lazy_hooks))
 
146
        self.assertEqual(set_rh, set_rh_lazy_hooks[0][0].get_obj())
 
147
        self.assertEqual("demo", set_rh_lazy_hooks[0][1])
 
148
        self.assertEqual(list(TestHooks.hooks['set_rh']), [set_rh])
 
149
 
 
150
    set_rh = lambda: None
 
151
 
 
152
    def test_install_named_hook_lazy(self):
 
153
        hooks = Hooks("bzrlib.tests.hooks", "some_hooks")
 
154
        hooks['set_rh'] = HookPoint("set_rh", "doc", (0, 15), None)
 
155
        hooks.install_named_hook_lazy('set_rh', 'bzrlib.tests.test_hooks',
 
156
            'TestHooks.set_rh', "demo")
 
157
        self.assertEqual(list(hooks['set_rh']), [TestHooks.set_rh])
 
158
 
 
159
    def test_install_named_hook_lazy_old(self):
 
160
        # An exception is raised if a lazy hook is raised for
 
161
        # an old style hook point.
 
162
        hooks = Hooks("bzrlib.tests.hooks", "some_hooks")
 
163
        hooks['set_rh'] = []
 
164
        self.assertRaises(errors.UnsupportedOperation,
 
165
            hooks.install_named_hook_lazy,
 
166
            'set_rh', 'bzrlib.tests.test_hooks', 'TestHooks.set_rh',
 
167
            "demo")
 
168
 
 
169
    def test_valid_lazy_hooks(self):
 
170
        # Make sure that all the registered lazy hooks are referring to existing
 
171
        # hook points which allow lazy registration.
 
172
        for key, callbacks in _mod_hooks._lazy_hooks.iteritems():
 
173
            (module_name, member_name, hook_name) = key
 
174
            obj = pyutils.get_named_object(module_name, member_name)
 
175
            self.assertEqual(obj._module, module_name)
 
176
            self.assertEqual(obj._member_name, member_name)
 
177
            self.assertTrue(hook_name in obj)
 
178
            self.assertIs(callbacks, obj[hook_name]._callbacks)
 
179
 
 
180
 
 
181
class TestHook(tests.TestCase):
117
182
 
118
183
    def test___init__(self):
119
184
        doc = ("Invoked after changing the tip of a branch object. Called with"
133
198
            "~~~~~~~~~~~~~~~\n"
134
199
            "\n"
135
200
            "Introduced in: 0.15\n"
136
 
            "Deprecated in: Not deprecated\n"
137
201
            "\n"
138
202
            "Invoked after changing the tip of a branch object. Called with a\n"
139
203
            "bzrlib.branch.PostChangeBranchTipParams object\n", hook.docs())
145
209
        hook.hook(callback, "my callback")
146
210
        self.assertEqual([callback], list(hook))
147
211
 
 
212
    def lazy_callback():
 
213
        pass
 
214
 
 
215
    def test_lazy_hook(self):
 
216
        hook = HookPoint("foo", "no docs", None, None)
 
217
        hook.hook_lazy(
 
218
            "bzrlib.tests.test_hooks", "TestHook.lazy_callback",
 
219
            "my callback")
 
220
        self.assertEqual([TestHook.lazy_callback], list(hook))
 
221
 
 
222
    def test_uninstall(self):
 
223
        hook = HookPoint("foo", "no docs", None, None)
 
224
        hook.hook_lazy(
 
225
            "bzrlib.tests.test_hooks", "TestHook.lazy_callback",
 
226
            "my callback")
 
227
        self.assertEqual([TestHook.lazy_callback], list(hook))
 
228
        hook.uninstall("my callback")
 
229
        self.assertEqual([], list(hook))
 
230
 
 
231
    def test_uninstall_unknown(self):
 
232
        hook = HookPoint("foo", "no docs", None, None)
 
233
        self.assertRaises(KeyError, hook.uninstall, "my callback")
 
234
 
148
235
    def test___repr(self):
149
236
        # The repr should list all the callbacks, with names.
150
237
        hook = HookPoint("foo", "no docs", None, None)
157
244
            callback_repr, repr(hook))
158
245
 
159
246
 
160
 
class TestHookRegistry(TestCase):
 
247
class TestHookRegistry(tests.TestCase):
161
248
 
162
249
    def test_items_are_reasonable_keys(self):
163
250
        # All the items in the known_hooks registry need to map from
173
260
            new_hooks = factory()
174
261
            self.assertIsInstance(obj, Hooks)
175
262
            self.assertEqual(type(obj), type(new_hooks))
 
263
            self.assertEqual("No hook name", new_hooks.get_hook_name(None))
176
264
 
177
265
    def test_known_hooks_key_to_object(self):
178
266
        self.assertIs(branch.Branch.hooks,
180
268
 
181
269
    def test_known_hooks_key_to_parent_and_attribute(self):
182
270
        self.assertEqual((branch.Branch, 'hooks'),
183
 
            known_hooks_key_to_parent_and_attribute(
 
271
            known_hooks.key_to_parent_and_attribute(
184
272
            ('bzrlib.branch', 'Branch.hooks')))
185
273
        self.assertEqual((branch, 'Branch'),
186
 
            known_hooks_key_to_parent_and_attribute(
 
274
            known_hooks.key_to_parent_and_attribute(
187
275
            ('bzrlib.branch', 'Branch')))