~bzr-pqm/bzr/bzr.dev

2553.1.1 by Robert Collins
Give Hooks names.
1
# Copyright (C) 2007 Canonical Ltd
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for the core Hooks logic."""
18
4098.2.1 by Robert Collins
Allow self documenting hooks.
19
from bzrlib import errors
2553.1.1 by Robert Collins
Give Hooks names.
20
from bzrlib.hooks import (
4098.2.2 by Robert Collins
Review feedback.
21
    HookPoint,
2553.1.1 by Robert Collins
Give Hooks names.
22
    Hooks,
23
    )
24
from bzrlib.errors import (
25
    UnknownHook,
26
    )
27
3256.2.30 by Daniel Watkins
Updated deprecation warnings and tests.
28
from bzrlib.symbol_versioning import one_five
2553.1.1 by Robert Collins
Give Hooks names.
29
from bzrlib.tests import TestCase
30
31
32
class TestHooks(TestCase):
33
4098.2.1 by Robert Collins
Allow self documenting hooks.
34
    def test_create_hook_first(self):
35
        hooks = Hooks()
36
        doc = ("Invoked after changing the tip of a branch object. Called with"
37
            "a bzrlib.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
38
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
39
        hooks.create_hook(hook)
40
        self.assertEqual(hook, hooks['post_tip_change'])
41
42
    def test_create_hook_name_collision_errors(self):
43
        hooks = Hooks()
44
        doc = ("Invoked after changing the tip of a branch object. Called with"
45
            "a bzrlib.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
46
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
47
        hook2 = HookPoint("post_tip_change", None, None, None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
48
        hooks.create_hook(hook)
49
        self.assertRaises(errors.DuplicateKey, hooks.create_hook, hook2)
50
        self.assertEqual(hook, hooks['post_tip_change'])
51
52
    def test_docs(self):
53
        """docs() should return something reasonable about the Hooks."""
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
54
        class MyHooks(Hooks):
55
            pass
56
        hooks = MyHooks()
4098.2.1 by Robert Collins
Allow self documenting hooks.
57
        hooks['legacy'] = []
4098.2.2 by Robert Collins
Review feedback.
58
        hook1 = HookPoint('post_tip_change',
4098.2.1 by Robert Collins
Allow self documenting hooks.
59
            "Invoked after the tip of a branch changes. Called with "
60
            "a ChangeBranchTipParams object.", (1, 4), None)
4098.2.2 by Robert Collins
Review feedback.
61
        hook2 = HookPoint('pre_tip_change',
4098.2.1 by Robert Collins
Allow self documenting hooks.
62
            "Invoked before the tip of a branch changes. Called with "
63
            "a ChangeBranchTipParams object. Hooks should raise "
64
            "TipChangeRejected to signal that a tip change is not permitted.",
65
            (1, 6), None)
66
        hooks.create_hook(hook1)
67
        hooks.create_hook(hook2)
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
68
        self.assertEqualDiff(
69
            "MyHooks\n"
70
            "=======\n"
71
            "\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
72
            "legacy\n"
73
            "------\n"
74
            "\n"
4108.3.1 by Robert Collins
Include the Hooks class in the Hooks docs.
75
            "An old-style hook. For documentation see the __init__ method of 'MyHooks'\n"
4098.2.1 by Robert Collins
Allow self documenting hooks.
76
            "\n"
77
            "post_tip_change\n"
78
            "---------------\n"
79
            "\n"
80
            "Introduced in: 1.4\n"
81
            "Deprecated in: Not deprecated\n"
82
            "\n"
83
            "Invoked after the tip of a branch changes. Called with a\n"
84
            "ChangeBranchTipParams object.\n"
85
            "\n"
86
            "pre_tip_change\n"
87
            "--------------\n"
88
            "\n"
89
            "Introduced in: 1.6\n"
90
            "Deprecated in: Not deprecated\n"
91
            "\n"
92
            "Invoked before the tip of a branch changes. Called with a\n"
93
            "ChangeBranchTipParams object. Hooks should raise TipChangeRejected to\n"
94
            "signal that a tip change is not permitted.\n", hooks.docs())
95
2553.1.1 by Robert Collins
Give Hooks names.
96
    def test_install_hook_raises_unknown_hook(self):
97
        """install_hook should raise UnknownHook if a hook is unknown."""
98
        hooks = Hooks()
3256.2.30 by Daniel Watkins
Updated deprecation warnings and tests.
99
        self.assertRaises(UnknownHook, self.applyDeprecated, one_five,
3256.2.20 by Daniel Watkins
Modified Hooks.install_hook tests to use applyDeprecated.
100
                          hooks.install_hook, 'silly', None)
2553.1.1 by Robert Collins
Give Hooks names.
101
102
    def test_install_hook_appends_known_hook(self):
103
        """install_hook should append the callable for known hooks."""
104
        hooks = Hooks()
3256.2.32 by Ian Clatworthy
tweak hook tests to init the set_rh test when needed
105
        hooks['set_rh'] = []
3256.2.30 by Daniel Watkins
Updated deprecation warnings and tests.
106
        self.applyDeprecated(one_five, hooks.install_hook, 'set_rh', None)
2553.1.1 by Robert Collins
Give Hooks names.
107
        self.assertEqual(hooks['set_rh'], [None])
108
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
109
    def test_install_named_hook_raises_unknown_hook(self):
110
        hooks = Hooks()
111
        self.assertRaises(UnknownHook, hooks.install_named_hook, 'silly',
112
                          None, "")
113
114
    def test_install_named_hook_appends_known_hook(self):
115
        hooks = Hooks()
3256.2.32 by Ian Clatworthy
tweak hook tests to init the set_rh test when needed
116
        hooks['set_rh'] = []
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
117
        hooks.install_named_hook('set_rh', None, "demo")
118
        self.assertEqual(hooks['set_rh'], [None])
119
120
    def test_install_named_hook_and_retrieve_name(self):
121
        hooks = Hooks()
3256.2.32 by Ian Clatworthy
tweak hook tests to init the set_rh test when needed
122
        hooks['set_rh'] = []
3256.2.4 by Daniel Watkins
Modified tests to reflect install_named_hook becoming a separate method.
123
        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.
124
        self.assertEqual("demo", hooks.get_hook_name(None))
125
2553.1.1 by Robert Collins
Give Hooks names.
126
    def test_name_hook_and_retrieve_name(self):
127
        """name_hook puts the name in the names mapping."""
128
        hooks = Hooks()
3256.2.32 by Ian Clatworthy
tweak hook tests to init the set_rh test when needed
129
        hooks['set_rh'] = []
3256.2.30 by Daniel Watkins
Updated deprecation warnings and tests.
130
        self.applyDeprecated(one_five, hooks.install_hook, 'set_rh', None)
2553.1.1 by Robert Collins
Give Hooks names.
131
        hooks.name_hook(None, 'demo')
132
        self.assertEqual("demo", hooks.get_hook_name(None))
133
134
    def test_get_unnamed_hook_name_is_unnamed(self):
135
        hooks = Hooks()
3256.2.32 by Ian Clatworthy
tweak hook tests to init the set_rh test when needed
136
        hooks['set_rh'] = []
3256.2.30 by Daniel Watkins
Updated deprecation warnings and tests.
137
        self.applyDeprecated(one_five, hooks.install_hook, 'set_rh', None)
2553.1.1 by Robert Collins
Give Hooks names.
138
        self.assertEqual("No hook name", hooks.get_hook_name(None))
4098.2.1 by Robert Collins
Allow self documenting hooks.
139
140
141
class TestHook(TestCase):
142
143
    def test___init__(self):
144
        doc = ("Invoked after changing the tip of a branch object. Called with"
145
            "a bzrlib.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
146
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
147
        self.assertEqual(doc, hook.__doc__)
148
        self.assertEqual("post_tip_change", hook.name)
149
        self.assertEqual((0, 15), hook.introduced)
150
        self.assertEqual(None, hook.deprecated)
151
        self.assertEqual([], list(hook))
152
153
    def test_docs(self):
154
        doc = ("Invoked after changing the tip of a branch object. Called with"
155
            " a bzrlib.branch.PostChangeBranchTipParams object")
4098.2.2 by Robert Collins
Review feedback.
156
        hook = HookPoint("post_tip_change", doc, (0, 15), None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
157
        self.assertEqual("post_tip_change\n"
158
            "---------------\n"
159
            "\n"
160
            "Introduced in: 0.15\n"
161
            "Deprecated in: Not deprecated\n"
162
            "\n"
163
            "Invoked after changing the tip of a branch object. Called with a\n"
164
            "bzrlib.branch.PostChangeBranchTipParams object\n", hook.docs())
165
166
    def test_hook(self):
4098.2.2 by Robert Collins
Review feedback.
167
        hook = HookPoint("foo", "no docs", None, None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
168
        def callback():
169
            pass
170
        hook.hook(callback, "my callback")
171
        self.assertEqual([callback], list(hook))
172
173
    def test___repr(self):
174
        # The repr should list all the callbacks, with names.
4098.2.2 by Robert Collins
Review feedback.
175
        hook = HookPoint("foo", "no docs", None, None)
4098.2.1 by Robert Collins
Allow self documenting hooks.
176
        def callback():
177
            pass
178
        hook.hook(callback, "my callback")
179
        callback_repr = repr(callback)
180
        self.assertEqual(
4098.2.2 by Robert Collins
Review feedback.
181
            '<HookPoint(foo), callbacks=[%s(my callback)]>' %
4098.2.1 by Robert Collins
Allow self documenting hooks.
182
            callback_repr, repr(hook))