/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2007-2010 Canonical Ltd
2553.1.1 by Robert Collins
Give Hooks names.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2553.1.1 by Robert Collins
Give Hooks names.
16
17
"""Tests for the core Hooks logic."""
18
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
19
from bzrlib import (
20
    branch,
21
    errors,
22
    tests,
23
    )
2553.1.1 by Robert Collins
Give Hooks names.
24
from bzrlib.hooks import (
4098.2.2 by Robert Collins
Review feedback.
25
    HookPoint,
2553.1.1 by Robert Collins
Give Hooks names.
26
    Hooks,
5622.2.1 by Jelmer Vernooij
Some work on lazy hooks.
27
    install_lazy_named_hook,
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
28
    known_hooks,
29
    known_hooks_key_to_object,
30
    known_hooks_key_to_parent_and_attribute,
5622.2.1 by Jelmer Vernooij
Some work on lazy hooks.
31
    _lazy_hooks,
2553.1.1 by Robert Collins
Give Hooks names.
32
    )
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
33
from bzrlib.symbol_versioning import (
34
    deprecated_in,
35
    )
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
36
37
38
class TestHooks(tests.TestCase):
2553.1.1 by Robert Collins
Give Hooks names.
39
4098.2.1 by Robert Collins
Allow self documenting hooks.
40
    def test_create_hook_first(self):
41
        hooks = Hooks()
42
        doc = ("Invoked after changing the tip of a branch object. Called with"
43
            "a bzrlib.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
44
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
45
        hooks.create_hook(hook)
46
        self.assertEqual(hook, hooks['post_tip_change'])
47
48
    def test_create_hook_name_collision_errors(self):
49
        hooks = Hooks()
50
        doc = ("Invoked after changing the tip of a branch object. Called with"
51
            "a bzrlib.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
52
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
53
        hook2 = HookPoint("post_tip_change", None, None, None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
54
        hooks.create_hook(hook)
55
        self.assertRaises(errors.DuplicateKey, hooks.create_hook, hook2)
56
        self.assertEqual(hook, hooks['post_tip_change'])
57
58
    def test_docs(self):
59
        """docs() should return something reasonable about the Hooks."""
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
60
        class MyHooks(Hooks):
61
            pass
62
        hooks = MyHooks()
4098.2.1 by Robert Collins
Allow self documenting hooks.
63
        hooks['legacy'] = []
4098.2.2 by Robert Collins
Review feedback.
64
        hook1 = HookPoint('post_tip_change',
4098.2.1 by Robert Collins
Allow self documenting hooks.
65
            "Invoked after the tip of a branch changes. Called with "
66
            "a ChangeBranchTipParams object.", (1, 4), None)
4098.2.2 by Robert Collins
Review feedback.
67
        hook2 = HookPoint('pre_tip_change',
4098.2.1 by Robert Collins
Allow self documenting hooks.
68
            "Invoked before the tip of a branch changes. Called with "
69
            "a ChangeBranchTipParams object. Hooks should raise "
70
            "TipChangeRejected to signal that a tip change is not permitted.",
71
            (1, 6), None)
72
        hooks.create_hook(hook1)
73
        hooks.create_hook(hook2)
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
74
        self.assertEqualDiff(
75
            "MyHooks\n"
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
76
            "-------\n"
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
77
            "\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
78
            "legacy\n"
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
79
            "~~~~~~\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
80
            "\n"
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
81
            "An old-style hook. For documentation see the __init__ method of 'MyHooks'\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
82
            "\n"
83
            "post_tip_change\n"
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
84
            "~~~~~~~~~~~~~~~\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
85
            "\n"
86
            "Introduced in: 1.4\n"
87
            "\n"
88
            "Invoked after the tip of a branch changes. Called with a\n"
89
            "ChangeBranchTipParams object.\n"
90
            "\n"
91
            "pre_tip_change\n"
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
92
            "~~~~~~~~~~~~~~\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
93
            "\n"
94
            "Introduced in: 1.6\n"
95
            "\n"
96
            "Invoked before the tip of a branch changes. Called with a\n"
97
            "ChangeBranchTipParams object. Hooks should raise TipChangeRejected to\n"
98
            "signal that a tip change is not permitted.\n", hooks.docs())
99
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
100
    def test_install_named_hook_raises_unknown_hook(self):
101
        hooks = Hooks()
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
102
        self.assertRaises(errors.UnknownHook, hooks.install_named_hook, 'silly',
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
103
                          None, "")
104
105
    def test_install_named_hook_appends_known_hook(self):
106
        hooks = Hooks()
3256.2.32 by Ian Clatworthy
tweak hook tests to init the set_rh test when needed
107
        hooks['set_rh'] = []
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
108
        hooks.install_named_hook('set_rh', None, "demo")
109
        self.assertEqual(hooks['set_rh'], [None])
110
111
    def test_install_named_hook_and_retrieve_name(self):
112
        hooks = Hooks()
3256.2.32 by Ian Clatworthy
tweak hook tests to init the set_rh test when needed
113
        hooks['set_rh'] = []
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
114
        hooks.install_named_hook('set_rh', None, "demo")
3256.2.1 by Daniel Watkins
Added tests from Hooks.install_hook with an optional name parameter.
115
        self.assertEqual("demo", hooks.get_hook_name(None))
116
5622.2.1 by Jelmer Vernooij
Some work on lazy hooks.
117
    hooks = Hooks()
118
119
    def test_install_lazy_named_hook(self):
120
        # When the hook points are not yet registered the hook is
121
        # added to the _lazy_hooks dictionary in bzrlib.hooks.
122
        self.hooks['set_rh'] = []
123
        set_rh = lambda: None
124
        install_lazy_named_hook('bzrlib.tests.test_hooks',
125
            'TestHooks.hooks', 'set_rh', set_rh, "demo")
5622.2.4 by Jelmer Vernooij
Fix tests for lazy hooks.
126
        set_rh_lazy_hooks = _lazy_hooks[
127
            ('bzrlib.tests.test_hooks', 'TestHooks.hooks', 'set_rh')]
128
        self.assertEquals(1, len(set_rh_lazy_hooks))
129
        self.assertEquals(set_rh, set_rh_lazy_hooks[0][0].get_obj())
130
        self.assertEquals("demo", set_rh_lazy_hooks[0][1])
5622.2.1 by Jelmer Vernooij
Some work on lazy hooks.
131
5622.1.1 by Jelmer Vernooij
Allow lazily loading hook callbacks.
132
    set_rh = lambda: None
133
134
    def test_install_named_hook_lazy(self):
135
        hooks = Hooks()
136
        hooks['set_rh'] = HookPoint("set_rh", "doc", (0, 15), None)
137
        hooks.install_named_hook_lazy('set_rh', 'bzrlib.tests.test_hooks',
138
            'TestHooks.set_rh', "demo")
139
        self.assertEqual(list(hooks['set_rh']), [TestHooks.set_rh])
140
141
    def test_install_named_hook_lazy_old(self):
142
        # An exception is raised if a lazy hook is raised for
143
        # an old style hook point.
144
        hooks = Hooks()
145
        hooks['set_rh'] = []
146
        self.assertRaises(errors.UnsupportedOperation,
147
            hooks.install_named_hook_lazy,
148
            'set_rh', 'bzrlib.tests.test_hooks', 'TestHooks.set_rh',
149
            "demo")
150
4098.2.1 by Robert Collins
Allow self documenting hooks.
151
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
152
class TestHook(tests.TestCase):
4098.2.1 by Robert Collins
Allow self documenting hooks.
153
154
    def test___init__(self):
155
        doc = ("Invoked after changing the tip of a branch object. Called with"
156
            "a bzrlib.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
157
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
158
        self.assertEqual(doc, hook.__doc__)
159
        self.assertEqual("post_tip_change", hook.name)
160
        self.assertEqual((0, 15), hook.introduced)
161
        self.assertEqual(None, hook.deprecated)
162
        self.assertEqual([], list(hook))
163
164
    def test_docs(self):
165
        doc = ("Invoked after changing the tip of a branch object. Called with"
166
            " a bzrlib.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
167
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
168
        self.assertEqual("post_tip_change\n"
4119.3.2 by Robert Collins
Migrate existing hooks over to the new HookPoint infrastructure.
169
            "~~~~~~~~~~~~~~~\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
170
            "\n"
171
            "Introduced in: 0.15\n"
172
            "\n"
173
            "Invoked after changing the tip of a branch object. Called with a\n"
174
            "bzrlib.branch.PostChangeBranchTipParams object\n", hook.docs())
175
176
    def test_hook(self):
4098.2.2 by Robert Collins
Review feedback.
177
        hook = HookPoint("foo", "no docs", None, None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
178
        def callback():
179
            pass
180
        hook.hook(callback, "my callback")
181
        self.assertEqual([callback], list(hook))
182
5622.1.1 by Jelmer Vernooij
Allow lazily loading hook callbacks.
183
    def lazy_callback():
184
        pass
185
186
    def test_lazy_hook(self):
187
        hook = HookPoint("foo", "no docs", None, None)
188
        hook.hook_lazy(
189
            "bzrlib.tests.test_hooks", "TestHook.lazy_callback",
190
            "my callback")
191
        self.assertEqual([TestHook.lazy_callback], list(hook))
192
4098.2.1 by Robert Collins
Allow self documenting hooks.
193
    def test___repr(self):
194
        # The repr should list all the callbacks, with names.
4098.2.2 by Robert Collins
Review feedback.
195
        hook = HookPoint("foo", "no docs", None, None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
196
        def callback():
197
            pass
198
        hook.hook(callback, "my callback")
199
        callback_repr = repr(callback)
200
        self.assertEqual(
4098.2.2 by Robert Collins
Review feedback.
201
            '<HookPoint(foo), callbacks=[%s(my callback)]>' %
4098.2.1 by Robert Collins
Allow self documenting hooks.
202
            callback_repr, repr(hook))
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
203
204
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
205
class TestHookRegistry(tests.TestCase):
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
206
207
    def test_items_are_reasonable_keys(self):
208
        # All the items in the known_hooks registry need to map from
209
        # (module_name, member_name) tuples to the callable used to get an
4230.1.2 by James Westby
Update the comments based on those in the test.
210
        # empty Hooks for that attribute. This is used to support the test
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
211
        # suite which needs to generate empty hooks (and HookPoints) to ensure
212
        # isolation and prevent tests failing spuriously.
213
        for key, factory in known_hooks.items():
214
            self.assertTrue(callable(factory),
215
                "The factory(%r) for %r is not callable" % (factory, key))
216
            obj = known_hooks_key_to_object(key)
217
            self.assertIsInstance(obj, Hooks)
218
            new_hooks = factory()
219
            self.assertIsInstance(obj, Hooks)
220
            self.assertEqual(type(obj), type(new_hooks))
4781.1.1 by Vincent Ladeuil
Hooks daughter classes should always call the base constructor
221
            self.assertEqual("No hook name", new_hooks.get_hook_name(None))
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
222
223
    def test_known_hooks_key_to_object(self):
224
        self.assertIs(branch.Branch.hooks,
225
            known_hooks_key_to_object(('bzrlib.branch', 'Branch.hooks')))
226
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
227
    def test_known_hooks_key_to_parent_and_attribute_deprecated(self):
228
        self.assertEqual((branch.Branch, 'hooks'),
229
            self.applyDeprecated(deprecated_in((2,3)),
230
                known_hooks_key_to_parent_and_attribute,
231
                ('bzrlib.branch', 'Branch.hooks')))
232
        self.assertEqual((branch, 'Branch'),
233
            self.applyDeprecated(deprecated_in((2,3)),
234
                known_hooks_key_to_parent_and_attribute,
235
                ('bzrlib.branch', 'Branch')))
236
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
237
    def test_known_hooks_key_to_parent_and_attribute(self):
238
        self.assertEqual((branch.Branch, 'hooks'),
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
239
            known_hooks.key_to_parent_and_attribute(
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
240
            ('bzrlib.branch', 'Branch.hooks')))
241
        self.assertEqual((branch, 'Branch'),
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
242
            known_hooks.key_to_parent_and_attribute(
4119.3.1 by Robert Collins
Create a single registry of all Hooks classes, removing the test suite knowledge of such hooks and allowing plugins to sensibly and safely define new hooks.
243
            ('bzrlib.branch', 'Branch')))