if option with requires has a property, calculated properties are store in storage
[tiramisu.git] / test / test_requires.py
1 # coding: utf-8
2 import autopath
3 from copy import copy
4 from tiramisu import setting
5 setting.expires_time = 1
6 from tiramisu.option import IPOption, OptionDescription, BoolOption, IntOption, StrOption
7 from tiramisu.config import Config
8 from tiramisu.error import PropertiesOptionError, RequirementError
9 from py.test import raises
10
11
12 def test_requires():
13     a = BoolOption('activate_service', '', True)
14     b = IPOption('ip_address_service', '',
15                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
16     od = OptionDescription('service', '', [a, b])
17     c = Config(od)
18     c.read_write()
19     c.ip_address_service
20     c.activate_service = False
21     props = []
22     try:
23         c.ip_address_service
24     except PropertiesOptionError as err:
25         props = err.proptype
26     assert props == ['disabled']
27     c.activate_service = True
28     c.ip_address_service
29
30
31 def test_requires_with_requires():
32     a = BoolOption('activate_service', '', True)
33     b = IPOption('ip_address_service', '',
34                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
35     od = OptionDescription('service', '', [a, b])
36     c = Config(od)
37     c.read_write()
38     c.cfgimpl_get_settings()[b].append('test')
39     c.ip_address_service
40     c.activate_service = False
41     props = []
42     try:
43         c.ip_address_service
44     except PropertiesOptionError as err:
45         props = err.proptype
46     assert props == ['disabled']
47     c.activate_service = True
48     c.ip_address_service
49
50
51 def test_requires_invalid():
52     a = BoolOption('activate_service', '', True)
53     raises(ValueError, "IPOption('ip_address_service', '', requires='string')")
54     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'unknown': True}])")
55     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False}])")
56     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'action': 'disabled'}])")
57     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'expected': False, 'action': 'disabled'}])")
58     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'inverse': 'string'}])")
59     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'transitive': 'string'}])")
60     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'same_action': 'string'}])")
61     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': 'string', 'expected': False, 'action': 'disabled'}])")
62     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'string', 'action': 'disabled'}])")
63
64
65 def test_requires_same_action():
66     a = BoolOption('activate_service', '', True)
67     b = BoolOption('activate_service_web', '', True,
68                    requires=[{'option': a, 'expected': False, 'action': 'new'}])
69
70     d = IPOption('ip_address_service_web', '',
71                  requires=[{'option': b, 'expected': False,
72                             'action': 'disabled', 'inverse': False,
73                             'transitive': True, 'same_action': False}])
74     od = OptionDescription('service', '', [a, b, d])
75     c = Config(od)
76     c.read_write()
77     c.cfgimpl_get_settings().append('new')
78     c.activate_service
79     c.activate_service_web
80     c.ip_address_service_web
81     c.activate_service = False
82     #
83     props = []
84     try:
85         c.activate_service_web
86     except PropertiesOptionError as err:
87         props = err.proptype
88     assert props == ['new']
89     #
90     props = []
91     try:
92         c.ip_address_service_web
93     except PropertiesOptionError as err:
94         props = err.proptype
95     assert props == ['disabled']
96
97
98 def test_multiple_requires():
99     a = StrOption('activate_service', '')
100     b = IPOption('ip_address_service', '',
101                  requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'},
102                            {'option': a, 'expected': 'ok', 'action': 'disabled'}])
103     od = OptionDescription('service', '', [a, b])
104     c = Config(od)
105     c.read_write()
106     c.ip_address_service
107     c.activate_service = 'yes'
108     props = []
109     try:
110         c.ip_address_service
111     except PropertiesOptionError as err:
112         props = err.proptype
113     assert props == ['disabled']
114
115     c.activate_service = 'ok'
116     props = []
117     try:
118         c.ip_address_service
119     except PropertiesOptionError as err:
120         props = err.proptype
121     assert props == ['disabled']
122
123     c.activate_service = 'no'
124     c.ip_address_service
125
126
127 def test_multiple_requires_cumulative():
128     a = StrOption('activate_service', '')
129     b = IPOption('ip_address_service', '',
130                  requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'},
131                            {'option': a, 'expected': 'yes', 'action': 'hidden'}])
132     od = OptionDescription('service', '', [a, b])
133     c = Config(od)
134     c.read_write()
135     c.ip_address_service
136     c.activate_service = 'yes'
137     props = []
138     try:
139         c.ip_address_service
140     except PropertiesOptionError as err:
141         props = err.proptype
142     assert set(props) == set(['hidden', 'disabled'])
143
144     c.activate_service = 'ok'
145     c.ip_address_service
146
147     c.activate_service = 'no'
148     c.ip_address_service
149
150
151 def test_multiple_requires_cumulative_inverse():
152     a = StrOption('activate_service', '')
153     b = IPOption('ip_address_service', '',
154                  requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True},
155                            {'option': a, 'expected': 'yes', 'action': 'hidden', 'inverse': True}])
156     od = OptionDescription('service', '', [a, b])
157     c = Config(od)
158     c.read_write()
159     props = []
160     try:
161         c.ip_address_service
162     except PropertiesOptionError as err:
163         props = err.proptype
164     assert set(props) == set(['hidden', 'disabled'])
165     c.activate_service = 'yes'
166     c.ip_address_service
167
168     c.activate_service = 'ok'
169     props = []
170     try:
171         c.ip_address_service
172     except PropertiesOptionError as err:
173         props = err.proptype
174     assert set(props) == set(['hidden', 'disabled'])
175
176     c.activate_service = 'no'
177     props = []
178     try:
179         c.ip_address_service
180     except PropertiesOptionError as err:
181         props = err.proptype
182     assert set(props) == set(['hidden', 'disabled'])
183
184
185 def test_multiple_requires_inverse():
186     a = StrOption('activate_service', '')
187     b = IPOption('ip_address_service', '',
188                  requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True},
189                            {'option': a, 'expected': 'ok', 'action': 'disabled', 'inverse': True}])
190     od = OptionDescription('service', '', [a, b])
191     c = Config(od)
192     c.read_write()
193     props = []
194     try:
195         c.ip_address_service
196     except PropertiesOptionError as err:
197         props = err.proptype
198     assert props == ['disabled']
199
200     c.activate_service = 'yes'
201     c.ip_address_service
202
203     c.activate_service = 'ok'
204     c.ip_address_service
205
206     c.activate_service = 'no'
207     props = []
208     try:
209         c.ip_address_service
210     except PropertiesOptionError as err:
211         props = err.proptype
212     assert props == ['disabled']
213
214
215 def test_requires_transitive():
216     a = BoolOption('activate_service', '', True)
217     b = BoolOption('activate_service_web', '', True,
218                    requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
219
220     d = IPOption('ip_address_service_web', '',
221                  requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
222     od = OptionDescription('service', '', [a, b, d])
223     c = Config(od)
224     c.read_write()
225     c.activate_service
226     c.activate_service_web
227     c.ip_address_service_web
228     c.activate_service = False
229     #
230     props = []
231     try:
232         c.activate_service_web
233     except PropertiesOptionError as err:
234         props = err.proptype
235     assert props == ['disabled']
236     #
237     props = []
238     try:
239         c.ip_address_service_web
240     except PropertiesOptionError as err:
241         props = err.proptype
242     assert props == ['disabled']
243
244
245 def test_requires_transitive_bis():
246     a = BoolOption('activate_service', '', True)
247     abis = BoolOption('activate_service_bis', '', True)
248     b = BoolOption('activate_service_web', '', True,
249                    requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}])
250
251     d = IPOption('ip_address_service_web', '',
252                  requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
253     od = OptionDescription('service', '', [a, abis, b, d])
254     c = Config(od)
255     c.read_write()
256     #
257     c.activate_service_web
258     c.ip_address_service_web
259     c.activate_service = False
260     #
261     props = []
262     try:
263         c.activate_service_web
264     except PropertiesOptionError as err:
265         props = err.proptype
266     assert props == ['disabled']
267     #
268     props = []
269     try:
270         c.ip_address_service_web
271     except PropertiesOptionError as err:
272         props = err.proptype
273     assert props == ['disabled']
274
275
276 def test_requires_transitive_hidden_disabled():
277     a = BoolOption('activate_service', '', True)
278     b = BoolOption('activate_service_web', '', True,
279                    requires=[{'option': a, 'expected': False, 'action': 'hidden'}])
280     d = IPOption('ip_address_service_web', '',
281                  requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
282     od = OptionDescription('service', '', [a, b, d])
283     c = Config(od)
284     c.read_write()
285     c.activate_service
286     c.activate_service_web
287     c.ip_address_service_web
288     c.activate_service = False
289     #
290     props = []
291     try:
292         c.activate_service_web
293     except PropertiesOptionError as err:
294         props = err.proptype
295     assert props == ['hidden']
296     raises(RequirementError, 'c.ip_address_service_web')
297
298
299 def test_requires_not_transitive():
300     a = BoolOption('activate_service', '', True)
301     b = BoolOption('activate_service_web', '', True,
302                    requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
303     d = IPOption('ip_address_service_web', '',
304                  requires=[{'option': b, 'expected': False,
305                             'action': 'disabled', 'transitive': False}])
306     od = OptionDescription('service', '', [a, b, d])
307     c = Config(od)
308     c.read_write()
309     c.activate_service
310     c.activate_service_web
311     c.ip_address_service_web
312     c.activate_service = False
313     #
314     props = []
315     try:
316         c.activate_service_web
317     except PropertiesOptionError as err:
318         props = err.proptype
319     assert props == ['disabled']
320     #
321     c.ip_address_service_web
322
323
324 def test_requires_None():
325     a = BoolOption('activate_service', '')
326     b = IPOption('ip_address_service', '',
327                  requires=[{'option': a, 'expected': None, 'action': 'disabled'}])
328     od = OptionDescription('service', '', [a, b])
329     c = Config(od)
330     c.read_write()
331     props = []
332     try:
333         c.ip_address_service
334     except PropertiesOptionError as err:
335         props = err.proptype
336     assert props == ['disabled']
337     c.activate_service = False
338     c.ip_address_service
339
340
341 def test_requires_multi_disabled():
342     a = BoolOption('activate_service', '')
343     b = IntOption('num_service', '')
344     c = IPOption('ip_address_service', '',
345                  requires=[{'option': a, 'expected': True, 'action': 'disabled'},
346                            {'option': b, 'expected': 1, 'action': 'disabled'}])
347     od = OptionDescription('service', '', [a, b, c])
348     c = Config(od)
349     c.read_write()
350
351     c.ip_address_service
352
353     c.activate_service = True
354     props = []
355     try:
356         c.ip_address_service
357     except PropertiesOptionError as err:
358         props = err.proptype
359     assert props == ['disabled']
360
361     c.activate_service = False
362     c.ip_address_service
363
364     c.num_service = 1
365     props = []
366     try:
367         c.ip_address_service
368     except PropertiesOptionError as err:
369         props = err.proptype
370     assert props == ['disabled']
371
372     c.activate_service = True
373     props = []
374     try:
375         c.ip_address_service
376     except PropertiesOptionError as err:
377         props = err.proptype
378     assert props == ['disabled']
379
380
381 def test_requires_multi_disabled_inverse():
382     a = BoolOption('activate_service', '')
383     b = IntOption('num_service', '')
384     c = IPOption('ip_address_service', '',
385                  requires=[{'option': a, 'expected': True,
386                             'action': 'disabled', 'inverse': True},
387                            {'option': b, 'expected': 1,
388                             'action': 'disabled', 'inverse': True}])
389     od = OptionDescription('service', '', [a, b, c])
390     c = Config(od)
391     c.read_write()
392
393     props = []
394     try:
395         c.ip_address_service
396     except PropertiesOptionError as err:
397         props = err.proptype
398     assert props == ['disabled']
399
400     c.activate_service = True
401     props = []
402     try:
403         c.ip_address_service
404     except PropertiesOptionError as err:
405         props = err.proptype
406     assert props == ['disabled']
407
408     c.activate_service = False
409     props = []
410     try:
411         c.ip_address_service
412     except PropertiesOptionError as err:
413         props = err.proptype
414     assert props == ['disabled']
415
416     c.num_service = 1
417     props = []
418     try:
419         c.ip_address_service
420     except PropertiesOptionError as err:
421         props = err.proptype
422     assert props == ['disabled']
423
424     c.activate_service = True
425     c.ip_address_service
426
427
428 def test_requires_multi_disabled_2():
429     a = BoolOption('a', '')
430     b = BoolOption('b', '')
431     c = BoolOption('c', '')
432     d = BoolOption('d', '')
433     e = BoolOption('e', '')
434     f = BoolOption('f', '')
435     g = BoolOption('g', '')
436     h = BoolOption('h', '')
437     i = BoolOption('i', '')
438     j = BoolOption('j', '')
439     k = BoolOption('k', '')
440     l = BoolOption('l', '')
441     m = BoolOption('m', '')
442     list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m]
443     requires = []
444     for boo in list_bools:
445         requires.append({'option': boo, 'expected': True, 'action': 'disabled'})
446     z = IPOption('z', '', requires=requires)
447     y = copy(list_bools)
448     y.append(z)
449     od = OptionDescription('service', '', y)
450     cfg = Config(od)
451     cfg.read_write()
452
453     cfg.z
454     for boo in list_bools:
455         setattr(cfg, boo._name, True)
456         props = []
457         try:
458             cfg.z
459         except PropertiesOptionError as err:
460             props = err.proptype
461         assert props == ['disabled']
462     for boo in list_bools:
463         setattr(cfg, boo._name, False)
464         if boo == m:
465             cfg.z
466         else:
467             props = []
468             try:
469                 cfg.z
470             except PropertiesOptionError as err:
471                 props = err.proptype
472             assert props == ['disabled']
473
474
475 def test_requires_multi_disabled_inverse_2():
476     a = BoolOption('a', '')
477     b = BoolOption('b', '')
478     c = BoolOption('c', '')
479     d = BoolOption('d', '')
480     e = BoolOption('e', '')
481     f = BoolOption('f', '')
482     g = BoolOption('g', '')
483     h = BoolOption('h', '')
484     i = BoolOption('i', '')
485     j = BoolOption('j', '')
486     k = BoolOption('k', '')
487     l = BoolOption('l', '')
488     m = BoolOption('m', '')
489     list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m]
490     requires = []
491     for boo in list_bools:
492         requires.append({'option': boo, 'expected': True, 'action': 'disabled',
493                          'inverse': True})
494     z = IPOption('z', '', requires=requires)
495     y = copy(list_bools)
496     y.append(z)
497     od = OptionDescription('service', '', y)
498     cfg = Config(od)
499     cfg.read_write()
500
501     props = []
502     try:
503         cfg.z
504     except PropertiesOptionError as err:
505         props = err.proptype
506     assert props == ['disabled']
507     for boo in list_bools:
508         setattr(cfg, boo._name, True)
509         if boo == m:
510             cfg.z
511         else:
512             props = []
513             try:
514                 cfg.z
515             except PropertiesOptionError as err:
516                 props = err.proptype
517             assert props == ['disabled']
518     for boo in list_bools:
519         setattr(cfg, boo._name, False)
520         props = []
521         try:
522             cfg.z
523         except PropertiesOptionError as err:
524             props = err.proptype
525         assert props == ['disabled']
526
527
528 def test_requires_requirement_append():
529     a = BoolOption('activate_service', '', True)
530     b = IPOption('ip_address_service', '',
531                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
532     od = OptionDescription('service', '', [a, b])
533     c = Config(od)
534     c.read_write()
535     str(c.cfgimpl_get_settings())
536     str(c.cfgimpl_get_settings()[b])
537     raises(ValueError, 'c.cfgimpl_get_settings()[b].append("disabled")')
538     c.activate_service = False
539     # disabled is now set, test to remove disabled before store in storage
540     c.cfgimpl_get_settings()[b].append("test")
541
542
543 def test_requires_different_inverse():
544     a = BoolOption('activate_service', '', True)
545     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': True, 'action': 'disabled', 'inverse': False}])")
546
547
548 def test_requires_recursive_path():
549     a = BoolOption('activate_service', '', True)
550     b = IPOption('ip_address_service', '',
551                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
552     od1 = OptionDescription('service', '', [a, b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
553     od = OptionDescription('base', '', [od1])
554     c = Config(od)
555     c.read_write()
556     raises(RequirementError, 'c.service.a')
557
558
559 def test_get_properties_with_None_path():
560     a = BoolOption('activate_service', '', True)
561     b = IPOption('ip_address_service', '',
562                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
563     od1 = OptionDescription('service', '', [a, b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
564     od = OptionDescription('base', '', [od1])
565     c = Config(od)
566     c.read_write()
567     raises(ValueError, "c.cfgimpl_get_settings()._getproperties(a)")
568
569
570 def test_set_item():
571     a = BoolOption('activate_service', '', True)
572     b = IPOption('ip_address_service', '')
573     od1 = OptionDescription('service', '', [a, b])
574     od = OptionDescription('base', '', [od1])
575     c = Config(od)
576     c.read_write()
577     raises(ValueError, 'c.cfgimpl_get_settings()[a] = ("test",)')
578
579
580 def test_properties_conflict():
581     a = BoolOption('activate_service', '', True)
582     raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
583     raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")