5 :copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
5 :copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
6 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
6 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
7 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
7 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
8 """ |
8 """ |
9 |
9 |
10 from logilab.common.testlib import unittest_main |
10 from logilab.common.testlib import TestCase, unittest_main, mock_object |
11 |
11 |
|
12 |
|
13 from cubicweb.devtools import TestServerConfiguration |
12 from cubicweb.devtools.testlib import CubicWebTC |
14 from cubicweb.devtools.testlib import CubicWebTC |
13 from cubicweb.server.hook import LateOperation, Operation, SingleLastOperation |
15 from cubicweb.selectors import implements |
|
16 from cubicweb.server import hook |
14 from cubicweb.hooks import integrity, syncschema |
17 from cubicweb.hooks import integrity, syncschema |
15 |
18 |
16 |
19 |
17 def clean_session_ops(func): |
20 def clean_session_ops(func): |
18 def wrapper(self, *args, **kwargs): |
21 def wrapper(self, *args, **kwargs): |
20 return func(self, *args, **kwargs) |
23 return func(self, *args, **kwargs) |
21 finally: |
24 finally: |
22 self.session.pending_operations[:] = [] |
25 self.session.pending_operations[:] = [] |
23 return wrapper |
26 return wrapper |
24 |
27 |
25 class HookHelpersTC(CubicWebTC): |
28 class OperationsTC(CubicWebTC): |
26 |
29 |
27 def setUp(self): |
30 def setUp(self): |
28 CubicWebTC.setUp(self) |
31 CubicWebTC.setUp(self) |
29 self.hm = self.repo.hm |
32 self.hm = self.repo.hm |
30 |
33 |
31 @clean_session_ops |
34 @clean_session_ops |
32 def test_late_operation(self): |
35 def test_late_operation(self): |
33 session = self.session |
36 session = self.session |
34 l1 = LateOperation(session) |
37 l1 = hook.LateOperation(session) |
35 l2 = LateOperation(session) |
38 l2 = hook.LateOperation(session) |
36 l3 = Operation(session) |
39 l3 = hook.Operation(session) |
37 self.assertEquals(session.pending_operations, [l3, l1, l2]) |
40 self.assertEquals(session.pending_operations, [l3, l1, l2]) |
38 |
41 |
39 @clean_session_ops |
42 @clean_session_ops |
40 def test_single_last_operation(self): |
43 def test_single_last_operation(self): |
41 session = self.session |
44 session = self.session |
42 l0 = SingleLastOperation(session) |
45 l0 = hook.SingleLastOperation(session) |
43 l1 = LateOperation(session) |
46 l1 = hook.LateOperation(session) |
44 l2 = LateOperation(session) |
47 l2 = hook.LateOperation(session) |
45 l3 = Operation(session) |
48 l3 = hook.Operation(session) |
46 self.assertEquals(session.pending_operations, [l3, l1, l2, l0]) |
49 self.assertEquals(session.pending_operations, [l3, l1, l2, l0]) |
47 l4 = SingleLastOperation(session) |
50 l4 = hook.SingleLastOperation(session) |
48 self.assertEquals(session.pending_operations, [l3, l1, l2, l4]) |
51 self.assertEquals(session.pending_operations, [l3, l1, l2, l4]) |
49 |
52 |
50 @clean_session_ops |
53 @clean_session_ops |
51 def test_global_operation_order(self): |
54 def test_global_operation_order(self): |
52 session = self.session |
55 session = self.session |
57 op3 = syncschema.MemSchemaNotifyChanges(session) |
60 op3 = syncschema.MemSchemaNotifyChanges(session) |
58 op4 = integrity._DelayedDeleteOp(session) |
61 op4 = integrity._DelayedDeleteOp(session) |
59 op5 = integrity._CheckORelationOp(session) |
62 op5 = integrity._CheckORelationOp(session) |
60 self.assertEquals(session.pending_operations, [op1, op2, op4, op5, op3]) |
63 self.assertEquals(session.pending_operations, [op1, op2, op4, op5, op3]) |
61 |
64 |
|
65 |
|
66 class HookCalled(Exception): pass |
|
67 |
|
68 config = TestServerConfiguration('data') |
|
69 config.bootstrap_cubes() |
|
70 schema = config.load_schema() |
|
71 |
|
72 class AddAnyHook(hook.Hook): |
|
73 __regid__ = 'addany' |
|
74 category = 'cat1' |
|
75 events = ('before_add_entity',) |
|
76 def __call__(self): |
|
77 raise HookCalled() |
|
78 |
|
79 |
|
80 class HooksManagerTC(TestCase): |
|
81 |
|
82 def setUp(self): |
|
83 """ called before each test from this class """ |
|
84 self.vreg = mock_object(config=config, schema=schema) |
|
85 self.o = hook.HooksRegistry(self.vreg) |
|
86 |
|
87 def test_register_bad_hook1(self): |
|
88 class _Hook(hook.Hook): |
|
89 events = ('before_add_entiti',) |
|
90 ex = self.assertRaises(Exception, self.o.register, _Hook) |
|
91 self.assertEquals(str(ex), 'bad event before_add_entiti on unittest_hook._Hook') |
|
92 |
|
93 def test_register_bad_hook2(self): |
|
94 class _Hook(hook.Hook): |
|
95 events = None |
|
96 ex = self.assertRaises(Exception, self.o.register, _Hook) |
|
97 self.assertEquals(str(ex), 'bad .events attribute None on unittest_hook._Hook') |
|
98 |
|
99 def test_register_bad_hook3(self): |
|
100 class _Hook(hook.Hook): |
|
101 events = 'before_add_entity' |
|
102 ex = self.assertRaises(Exception, self.o.register, _Hook) |
|
103 self.assertEquals(str(ex), 'bad event b on unittest_hook._Hook') |
|
104 |
|
105 def test_call_hook(self): |
|
106 self.o.register(AddAnyHook) |
|
107 cw = mock_object(vreg=self.vreg) |
|
108 self.assertRaises(HookCalled, self.o.call_hooks, 'before_add_entity', cw) |
|
109 self.o.call_hooks('before_delete_entity', cw) # nothing to call |
|
110 config.disabled_hooks_categories.add('cat1') |
|
111 self.o.call_hooks('before_add_entity', cw) # disabled hooks category, not called |
|
112 config.disabled_hooks_categories.remove('cat1') |
|
113 self.assertRaises(HookCalled, self.o.call_hooks, 'before_add_entity', cw) |
|
114 self.o.unregister(AddAnyHook) |
|
115 self.o.call_hooks('before_add_entity', cw) # nothing to call |
|
116 |
|
117 |
|
118 class SystemHooksTC(CubicWebTC): |
|
119 |
|
120 def test_startup_shutdown(self): |
|
121 import hooks # cubicweb/server/test/data/hooks.py |
|
122 self.assertEquals(hooks.CALLED_EVENTS['server_startup'], True) |
|
123 # don't actually call repository.shutdown ! |
|
124 self.repo.hm.call_hooks('server_shutdown', repo=self.repo) |
|
125 self.assertEquals(hooks.CALLED_EVENTS['server_shutdown'], True) |
|
126 |
|
127 def test_session_open_close(self): |
|
128 import hooks # cubicweb/server/test/data/hooks.py |
|
129 cnx = self.login('anon') |
|
130 self.assertEquals(hooks.CALLED_EVENTS['session_open'], 'anon') |
|
131 cnx.close() |
|
132 self.assertEquals(hooks.CALLED_EVENTS['session_close'], 'anon') |
|
133 |
|
134 |
|
135 # class RelationHookTC(TestCase): |
|
136 # """testcase for relation hooks grouping""" |
|
137 # def setUp(self): |
|
138 # """ called before each test from this class """ |
|
139 # self.o = HooksManager(schema) |
|
140 # self.called = [] |
|
141 |
|
142 # def test_before_add_relation(self): |
|
143 # """make sure before_xxx_relation hooks are called directly""" |
|
144 # self.o.register(self._before_relation_hook, |
|
145 # 'before_add_relation', 'concerne') |
|
146 # self.assertEquals(self.called, []) |
|
147 # self.o.call_hooks('before_add_relation', 'concerne', 'USER', |
|
148 # 1, 'concerne', 2) |
|
149 # self.assertEquals(self.called, [(1, 'concerne', 2)]) |
|
150 |
|
151 # def test_after_add_relation(self): |
|
152 # """make sure after_xxx_relation hooks are deferred""" |
|
153 # self.o.register(self._after_relation_hook, |
|
154 # 'after_add_relation', 'concerne') |
|
155 # self.assertEquals(self.called, []) |
|
156 # self.o.call_hooks('after_add_relation', 'concerne', 'USER', |
|
157 # 1, 'concerne', 2) |
|
158 # self.o.call_hooks('after_add_relation', 'concerne', 'USER', |
|
159 # 3, 'concerne', 4) |
|
160 # self.assertEquals(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)]) |
|
161 |
|
162 # def test_before_delete_relation(self): |
|
163 # """make sure before_xxx_relation hooks are called directly""" |
|
164 # self.o.register(self._before_relation_hook, |
|
165 # 'before_delete_relation', 'concerne') |
|
166 # self.assertEquals(self.called, []) |
|
167 # self.o.call_hooks('before_delete_relation', 'concerne', 'USER', |
|
168 # 1, 'concerne', 2) |
|
169 # self.assertEquals(self.called, [(1, 'concerne', 2)]) |
|
170 |
|
171 # def test_after_delete_relation(self): |
|
172 # """make sure after_xxx_relation hooks are deferred""" |
|
173 # self.o.register(self._after_relation_hook, |
|
174 # 'after_delete_relation', 'concerne') |
|
175 # self.o.call_hooks('after_delete_relation', 'concerne', 'USER', |
|
176 # 1, 'concerne', 2) |
|
177 # self.o.call_hooks('after_delete_relation', 'concerne', 'USER', |
|
178 # 3, 'concerne', 4) |
|
179 # self.assertEquals(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)]) |
|
180 |
|
181 |
|
182 # def _before_relation_hook(self, pool, subject, r_type, object): |
|
183 # self.called.append((subject, r_type, object)) |
|
184 |
|
185 # def _after_relation_hook(self, pool, subject, r_type, object): |
|
186 # self.called.append((subject, r_type, object)) |
|
187 |
|
188 |
62 if __name__ == '__main__': |
189 if __name__ == '__main__': |
63 unittest_main() |
190 unittest_main() |