update test for metaconfig serialization
[tiramisu.git] / test / test_state.py
1 from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \
2     IntOption, OptionDescription
3 from tiramisu.config import Config, GroupConfig, MetaConfig
4 from tiramisu.setting import owners
5 from tiramisu.storage import delete_session
6 from tiramisu.error import ConfigError
7 from pickle import dumps, loads
8 from py.test import raises
9
10
11 def return_value(value=None):
12         return value
13
14
15 def _get_slots(opt):
16     slots = set()
17     for subclass in opt.__class__.__mro__:
18         if subclass is not object:
19             slots.update(subclass.__slots__)
20     return slots
21
22
23 def _no_state(opt):
24     for attr in _get_slots(opt):
25         if 'state' in attr:
26             try:
27                 getattr(opt, attr)
28             except:
29                 pass
30             else:
31                 raise Exception('opt should have already attribute {0}'.format(attr))
32
33
34 def _diff_opt(opt1, opt2):
35     attr1 = set(_get_slots(opt1))
36     attr2 = set(_get_slots(opt2))
37     diff1 = attr1 - attr2
38     diff2 = attr2 - attr1
39     if diff1 != set():
40         raise Exception('more attribute in opt1 {0}'.format(list(diff1)))
41     if diff2 != set():
42         raise Exception('more attribute in opt2 {0}'.format(list(diff2)))
43     for attr in attr1:
44         if attr in ['_cache_paths', '_cache_consistencies']:
45             continue
46         err1 = False
47         err2 = False
48         val1 = None
49         val2 = None
50         try:
51             val1 = getattr(opt1, attr)
52         except:
53             err1 = True
54
55         try:
56             val2 = getattr(opt2, attr)
57         except:
58             err2 = True
59         assert err1 == err2
60         if val1 is None:
61             assert val1 == val2
62         elif attr == '_children':
63             assert val1[0] == val2[0]
64             for index, _opt in enumerate(val1[1]):
65                 assert _opt._name == val2[1][index]._name
66         elif attr == '_requires':
67             assert val1[0][0][0]._name == val2[0][0][0]._name
68             assert val1[0][0][1:] == val2[0][0][1:]
69         elif attr == '_opt':
70             assert val1._name == val2._name
71         elif attr == '_consistencies':
72             # dict is only a cache
73             if isinstance(val1, list):
74                 for index, consistency in enumerate(val1):
75                     assert consistency[0] == val2[index][0]
76                     for idx, opt in enumerate(consistency[1]):
77                         assert opt._name == val2[index][1][idx]._name
78         elif attr == '_callback':
79             assert val1[0] == val2[0]
80             if val1[1] is not None:
81                 for key, values in val1[1].items():
82                     for idx, value in enumerate(values):
83                         if isinstance(value, tuple):
84                             assert val1[1][key][idx][0]._name == val2[1][key][idx][0]._name
85                             assert val1[1][key][idx][1] == val2[1][key][idx][1]
86                         else:
87                             assert val1[1][key][idx] == val2[1][key][idx]
88             else:
89                 assert val1[1] == val2[1]
90         else:
91             assert val1 == val2
92
93
94 def _diff_conf(cfg1, cfg2):
95     attr1 = set(_get_slots(cfg1))
96     attr2 = set(_get_slots(cfg2))
97     diff1 = attr1 - attr2
98     diff2 = attr2 - attr1
99     if diff1 != set():
100         raise Exception('more attribute in cfg1 {0}'.format(list(diff1)))
101     if diff2 != set():
102         raise Exception('more attribute in cfg2 {0}'.format(list(diff2)))
103     for attr in attr1:
104         if attr in ('_impl_context', '__weakref__'):
105             continue
106         err1 = False
107         err2 = False
108         val1 = None
109         val2 = None
110         try:
111             val1 = getattr(cfg1, attr)
112         except:
113             err1 = True
114
115         try:
116             val2 = getattr(cfg2, attr)
117         except:
118             err2 = True
119         assert err1 == err2
120         if val1 is None:
121             assert val1 == val2
122         elif attr == '_impl_values':
123             assert cfg1.cfgimpl_get_values().get_modified_values() == cfg2.cfgimpl_get_values().get_modified_values()
124         elif attr == '_impl_settings':
125             assert cfg1.cfgimpl_get_settings().get_modified_properties() == cfg2.cfgimpl_get_settings().get_modified_properties()
126             assert cfg1.cfgimpl_get_settings().get_modified_permissives() == cfg2.cfgimpl_get_settings().get_modified_permissives()
127         elif attr == '_impl_descr':
128             _diff_opt(cfg1.cfgimpl_get_description(), cfg2.cfgimpl_get_description())
129         else:
130             assert val1 == val2
131
132
133 def test_diff_opt():
134     b = BoolOption('b', '')
135     u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
136     #u.impl_add_consistency('not_equal', b)
137     s = SymLinkOption('s', u)
138     o = OptionDescription('o', '', [b, u, s])
139     o1 = OptionDescription('o1', '', [o])
140
141     a = dumps(o1)
142     q = loads(a)
143     _diff_opt(o1, q)
144     _diff_opt(o1.o, q.o)
145     _diff_opt(o1.o.b, q.o.b)
146     _diff_opt(o1.o.u, q.o.u)
147     _diff_opt(o1.o.s, q.o.s)
148
149
150 def test_diff_opt_cache():
151     b = BoolOption('b', '')
152     u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
153     u.impl_add_consistency('not_equal', b)
154     s = SymLinkOption('s', u)
155     o = OptionDescription('o', '', [b, u, s])
156     o1 = OptionDescription('o1', '', [o])
157     o1.impl_build_cache()
158
159     a = dumps(o1)
160     q = loads(a)
161     _diff_opt(o1, q)
162     _diff_opt(o1.o, q.o)
163     _diff_opt(o1.o.b, q.o.b)
164     _diff_opt(o1.o.u, q.o.u)
165     _diff_opt(o1.o.s, q.o.s)
166
167
168 def test_diff_opt_callback():
169     b = BoolOption('b', '', callback=return_value)
170     b2 = BoolOption('b2', '', callback=return_value, callback_params={'': ('yes',)})
171     b3 = BoolOption('b3', '', callback=return_value, callback_params={'': ('yes', (b, False)), 'value': ('no',)})
172     o = OptionDescription('o', '', [b, b2, b3])
173     o1 = OptionDescription('o1', '', [o])
174     o1.impl_build_cache()
175
176     a = dumps(o1)
177     q = loads(a)
178     _diff_opt(o1, q)
179     _diff_opt(o1.o, q.o)
180     _diff_opt(o1.o.b, q.o.b)
181     _diff_opt(o1.o.b2, q.o.b2)
182     _diff_opt(o1.o.b3, q.o.b3)
183
184
185 def test_no_state_attr():
186     # all _state_xxx attributes should be deleted
187     b = BoolOption('b', '')
188     u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
189     s = SymLinkOption('s', u)
190     o = OptionDescription('o', '', [b, u, s])
191     o1 = OptionDescription('o1', '', [o])
192
193     a = dumps(o1)
194     q = loads(a)
195     _no_state(q)
196     _no_state(q.o)
197     _no_state(q.o.b)
198     _no_state(q.o.u)
199     _no_state(q.o.s)
200
201
202 def test_state_config():
203     val1 = BoolOption('val1', "")
204     maconfig = OptionDescription('rootconfig', '', [val1])
205     try:
206         cfg = Config(maconfig, persistent=True, session_id='29090931')
207     except ValueError:
208         cfg = Config(maconfig, session_id='29090931')
209         cfg._impl_test = True
210     a = dumps(cfg)
211     q = loads(a)
212     _diff_conf(cfg, q)
213     try:
214         delete_session('29090931')
215     except ConfigError:
216         pass
217
218
219 def test_state_properties():
220     val1 = BoolOption('val1', "")
221     maconfig = OptionDescription('rootconfig', '', [val1])
222     try:
223         cfg = Config(maconfig, persistent=True, session_id='29090932')
224     except ValueError:
225         cfg = Config(maconfig, session_id='29090932')
226         cfg._impl_test = True
227     cfg.read_write()
228     cfg.cfgimpl_get_settings()[val1].append('test')
229     a = dumps(cfg)
230     q = loads(a)
231     _diff_conf(cfg, q)
232     try:
233         delete_session('29090932')
234     except ConfigError:
235         pass
236
237
238 def test_state_values():
239     val1 = BoolOption('val1', "")
240     maconfig = OptionDescription('rootconfig', '', [val1])
241     try:
242         cfg = Config(maconfig, persistent=True, session_id='29090933')
243     except ValueError:
244         cfg = Config(maconfig, session_id='29090933')
245         cfg._impl_test = True
246     cfg.val1 = True
247     a = dumps(cfg)
248     q = loads(a)
249     _diff_conf(cfg, q)
250     q.val1 = False
251     #assert cfg.val1 is True
252     assert q.val1 is False
253     try:
254         delete_session('29090933')
255     except ConfigError:
256         pass
257
258
259 def test_state_values_owner():
260     val1 = BoolOption('val1', "")
261     maconfig = OptionDescription('rootconfig', '', [val1])
262     try:
263         cfg = Config(maconfig, persistent=True, session_id='29090934')
264     except ValueError:
265         cfg = Config(maconfig, session_id='29090934')
266         cfg._impl_test = True
267     owners.addowner('newowner')
268     cfg.cfgimpl_get_settings().setowner(owners.newowner)
269     cfg.val1 = True
270     a = dumps(cfg)
271     q = loads(a)
272     _diff_conf(cfg, q)
273     q.val1 = False
274     nval1 = q.cfgimpl_get_description().val1
275     assert q.getowner(nval1) == owners.newowner
276     try:
277         delete_session('29090934')
278     except ConfigError:
279         pass
280
281
282 def test_state_metaconfig():
283     i1 = IntOption('i1', '')
284     od1 = OptionDescription('od1', '', [i1])
285     od2 = OptionDescription('od2', '', [od1])
286     conf1 = Config(od2, session_id='29090935')
287     conf1._impl_test = True
288     conf2 = Config(od2, session_id='29090936')
289     conf2._impl_test = True
290     meta = MetaConfig([conf1, conf2], session_id='29090937')
291     meta._impl_test = True
292     raises(ConfigError, "dumps(meta)")
293     try:
294         delete_session('29090935')
295         delete_session('29090936')
296         delete_session('29090937')
297     except ConfigError:
298         pass
299
300
301 def test_state_groupconfig():
302     i1 = IntOption('i1', '')
303     od1 = OptionDescription('od1', '', [i1])
304     od2 = OptionDescription('od2', '', [od1])
305     conf1 = Config(od2, session_id='29090935')
306     conf1._impl_test = True
307     conf2 = Config(od2, session_id='29090936')
308     conf2._impl_test = True
309     meta = GroupConfig([conf1, conf2], session_id='29090937')
310     meta._impl_test = True
311     a = dumps(meta)
312     q = loads(a)
313     _diff_conf(meta, q)
314     try:
315         delete_session('29090935')
316         delete_session('29090936')
317         delete_session('29090937')
318     except ConfigError:
319         pass
320
321
322 def test_state_unkown_setting_owner():
323     """load an unknow _owner, should create it"""
324     assert not 'supernewuser' in owners.__dict__
325     loads("""ccopy_reg
326 _reconstructor
327 p0
328 (ctiramisu.setting
329 Settings
330 p1
331 c__builtin__
332 object
333 p2
334 Ntp3
335 Rp4
336 (dp5
337 S'_owner'
338 p6
339 S'supernewuser'
340 p7
341 sS'_p_'
342 p8
343 g0
344 (ctiramisu.storage.dictionary.setting
345 Settings
346 p9
347 g2
348 Ntp10
349 Rp11
350 (dp12
351 S'_cache'
352 p13
353 (dp14
354 sS'_permissives'
355 p15
356 (dp16
357 sS'_properties'
358 p17
359 (dp18
360 sbsb.
361 .""")
362     assert 'supernewuser' in owners.__dict__