31993081fe997de175ed9fa15bbb9ab61f8763f3
[tiramisu.git] / test / test_option_calculation.py
1 import autopath
2 from py.test import raises
3
4 from tiramisu.config import Config
5 from tiramisu.setting import groups, owners
6 from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
7     StrOption, OptionDescription, SymLinkOption
8 from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError, ConfigError
9
10
11 def return_val():
12     return 'val'
13
14
15 def return_concat(*args):
16     return '.'.join(list(args))
17
18
19 def return_list(value=None):
20     return ['val', 'val']
21
22
23 def return_list2(*args):
24     l = []
25     for arg in args:
26         if isinstance(arg, list):
27             l.extend(arg)
28         else:
29             l.append(arg)
30     return l
31
32
33 def return_value(value=None):
34     return value
35
36
37 def return_value2(*args, **kwargs):
38     value = list(args)
39     value.extend(kwargs.values())
40     return value
41
42
43 def return_calc(i, j, k):
44     return i + j + k
45
46
47 def is_config(config, **kwargs):
48     if isinstance(config, Config):
49         return 'yes'
50     else:
51         return 'no'
52
53
54 def make_description():
55     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
56     gcdummy = BoolOption('dummy', 'dummy', default=False)
57     objspaceoption = ChoiceOption('objspace', 'Object space',
58                                   ('std', 'thunk'), 'std')
59     booloption = BoolOption('bool', 'Test boolean option', default=True)
60     intoption = IntOption('int', 'Test int option', default=0)
61     intoption2 = IntOption('int', 'Test int option', default=0)
62     floatoption = FloatOption('float', 'Test float option', default=2.3)
63     stroption = StrOption('str', 'Test string option', default="abc")
64     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
65     wantref_option = BoolOption('wantref', 'Test requires', default=False,
66                                 requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
67     wantframework_option = BoolOption('wantframework', 'Test requires',
68                                       default=False,
69                                       requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
70     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption, intoption2])
71     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
72                               wantref_option, stroption,
73                               wantframework_option,
74                               intoption, boolop])
75     return descr
76
77
78 def make_description_duplicates():
79     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
80     ## dummy 1
81     gcdummy = BoolOption('dummy', 'dummy', default=False)
82     objspaceoption = ChoiceOption('objspace', 'Object space',
83                                   ('std', 'thunk'), 'std')
84     booloption = BoolOption('bool', 'Test boolean option', default=True)
85     intoption = IntOption('int', 'Test int option', default=0)
86     floatoption = FloatOption('float', 'Test float option', default=2.3)
87     stroption = StrOption('str', 'Test string option', default="abc")
88     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
89     wantref_option = BoolOption('wantref', 'Test requires', default=False,
90                                 requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
91     wantframework_option = BoolOption('wantframework', 'Test requires',
92                                       default=False,
93                                       requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
94     # dummy2 (same path)
95     gcdummy2 = BoolOption('dummy', 'dummy2', default=True)
96     # dummy3 (same name)
97     gcdummy3 = BoolOption('dummy', 'dummy2', default=True)
98     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, gcdummy2, floatoption])
99     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
100                               wantref_option, stroption,
101                               wantframework_option,
102                               intoption, boolop, gcdummy3])
103     return descr
104
105
106 def test_identical_paths():
107     """If in the schema (the option description) there is something that
108     have the same name, an exection is raised
109     """
110     raises(ConflictError, "make_description_duplicates()")
111
112
113 def make_description_requires():
114     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
115     gcdummy = BoolOption('dummy', 'dummy', default=False)
116
117     floatoption = FloatOption('float', 'Test float option', default=2.3)
118
119     objspaceoption = ChoiceOption('objspace', 'Object space',
120                                   ('std', 'thunk'), 'std')
121     booloption = BoolOption('bool', 'Test boolean option', default=True)
122     intoption = IntOption('int', 'Test int option', default=0)
123     stroption = StrOption('str', 'Test string option', default="abc",
124                           requires=({'option': intoption, 'expected': 1, 'action': 'hidden'},))
125
126     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
127     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
128                               stroption, intoption])
129     return descr
130
131
132 def test_hidden_if_in():
133     descr = make_description_requires()
134     cfg = Config(descr)
135     setting = cfg.cfgimpl_get_settings()
136     cfg.read_write()
137     stroption = cfg.unwrap_from_path('str')
138     assert not 'hidden' in setting[stroption]
139     cfg.int = 1
140     raises(PropertiesOptionError, "cfg.str")
141     raises(PropertiesOptionError, 'cfg.str="uvw"')
142     assert 'hidden' in setting[stroption]
143
144
145 def test_hidden_if_in_with_group():
146     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
147     gcdummy = BoolOption('dummy', 'dummy', default=False)
148
149     floatoption = FloatOption('float', 'Test float option', default=2.3)
150
151     objspaceoption = ChoiceOption('objspace', 'Object space',
152                                   ('std', 'thunk'), 'std')
153     booloption = BoolOption('bool', 'Test boolean option', default=True)
154     intoption = IntOption('int', 'Test int option', default=0)
155     stroption = StrOption('str', 'Test string option', default="abc")
156     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption],
157                                 requires=({'option': intoption, 'expected': 1, 'action': 'hidden'},))
158     descr = OptionDescription('constraints', '', [gcgroup, booloption,
159                               objspaceoption, stroption, intoption])
160     cfg = Config(descr)
161     setting = cfg.cfgimpl_get_settings()
162     cfg.read_write()
163     assert not 'hidden' in setting[stroption]
164     cfg.int = 1
165     raises(PropertiesOptionError, "cfg.gc.name")
166
167
168 def test_disabled_with_group():
169     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
170     gcdummy = BoolOption('dummy', 'dummy', default=False)
171
172     floatoption = FloatOption('float', 'Test float option', default=2.3)
173
174     objspaceoption = ChoiceOption('objspace', 'Object space',
175                                   ('std', 'thunk'), 'std')
176     booloption = BoolOption('bool', 'Test boolean option', default=True)
177     intoption = IntOption('int', 'Test int option', default=0)
178     stroption = StrOption('str', 'Test string option', default="abc")
179     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption],
180                                 requires=({'option': intoption, 'expected': 1, 'action': 'disabled'},))
181     descr = OptionDescription('constraints', '', [gcgroup, booloption,
182                               objspaceoption, stroption, intoption])
183     cfg = Config(descr)
184     cfg.read_write()
185     assert cfg.gc.name
186     cfg.int = 1
187     raises(PropertiesOptionError, "cfg.gc.name")
188 #____________________________________________________________
189
190
191 def make_description_callback():
192     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
193     gcdummy = BoolOption('dummy', 'dummy')
194     objspaceoption = ChoiceOption('objspace', 'Object space',
195                                   ('std', 'thunk'), 'std')
196     booloption = BoolOption('bool', 'Test boolean option', default=True)
197     intoption = IntOption('int', 'Test int option', default=0)
198     floatoption = FloatOption('float', 'Test float option', default=2.3)
199     stroption = StrOption('str', 'Test string option', default="abc")
200     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
201     wantref_option = BoolOption('wantref', 'Test requires', default=False,
202                                 requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
203     wantframework_option = BoolOption('wantframework', 'Test requires',
204                                       default=False,
205                                       requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
206     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
207     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
208                               wantref_option, stroption,
209                               wantframework_option,
210                               intoption, boolop])
211     return descr
212
213
214 def test_has_callback():
215     descr = make_description_callback()
216     # here the owner is 'default'
217     config = Config(descr)
218     setting = config.cfgimpl_get_settings()
219     config.read_write()
220     config.bool = False
221     # because dummy has a callback
222     dummy = config.unwrap_from_path('gc.dummy')
223     setting.append('freeze')
224     setting[dummy].append('frozen')
225     raises(PropertiesOptionError, "config.gc.dummy = True")
226
227
228 def test_freeze_and_has_callback():
229     descr = make_description_callback()
230     config = Config(descr)
231     setting = config.cfgimpl_get_settings()
232     config.read_write()
233     config.bool = False
234     setting = config.cfgimpl_get_settings()
235     setting.append('freeze')
236     dummy = config.unwrap_from_path('gc.dummy')
237     setting[dummy].append('frozen')
238     raises(PropertiesOptionError, "config.gc.dummy = True")
239
240
241 def test_callback():
242     val1 = StrOption('val1', "", callback=return_val)
243     maconfig = OptionDescription('rootconfig', '', [val1])
244     cfg = Config(maconfig)
245     cfg.read_write()
246     assert cfg.val1 == 'val'
247     cfg.val1 = 'new-val'
248     assert cfg.val1 == 'new-val'
249     del(cfg.val1)
250     assert cfg.val1 == 'val'
251
252
253 def test_callback_params_without_callback():
254     raises(ValueError, "StrOption('val2', '', callback_params={'': ('yes',)})")
255
256
257 def test_callback_invalid():
258     raises(ValueError, 'val1 = StrOption("val1", "", callback="string")')
259     raises(ValueError, 'val1 = StrOption("val1", "", callback=return_val, callback_params="string")')
260     val1 = StrOption('val1', "", 'val')
261     raises(ValueError, "StrOption('val2', '', callback=return_value, callback_params={'': 'string'})")
262     raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': (('string', False),)})")
263     raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1, 'string'),)})")
264     raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1, False, 'unknown'),)})")
265     raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1,),)})")
266
267
268 def test_callback_with_context():
269     val1 = StrOption("val1", "", callback=is_config, callback_params={'': ((None,),), 'value': ('string',)})
270     maconfig = OptionDescription('rootconfig', '', [val1])
271     cfg = Config(maconfig)
272     assert cfg.val1 == 'yes'
273
274
275 def test_callback_with_context_named():
276     val1 = StrOption("val1", "", callback=is_config, callback_params={'config': ((None,),)})
277     maconfig = OptionDescription('rootconfig', '', [val1])
278     cfg = Config(maconfig)
279     assert cfg.val1 == 'yes'
280
281
282 def test_callback_with_error():
283     val1 = StrOption("val1", "", callback=is_config, callback_params={'': ('string',), 'value': ('string',)})
284     maconfig = OptionDescription('rootconfig', '', [val1])
285     cfg = Config(maconfig)
286     assert cfg.val1 == 'no'
287
288
289 def test_callback_value():
290     val1 = StrOption('val1', "", 'val')
291     val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)})
292     val3 = StrOption('val3', "", callback=return_value, callback_params={'': ('yes',)})
293     val4 = StrOption('val4', "", callback=return_value, callback_params={'value': ((val1, False),)})
294     val5 = StrOption('val5', "", callback=return_value, callback_params={'value': ('yes',)})
295     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4, val5])
296     cfg = Config(maconfig)
297     cfg.read_write()
298     assert cfg.val1 == 'val'
299     assert cfg.val2 == 'val'
300     assert cfg.val4 == 'val'
301     cfg.val1 = 'new-val'
302     assert cfg.val1 == 'new-val'
303     assert cfg.val2 == 'new-val'
304     assert cfg.val4 == 'new-val'
305     del(cfg.val1)
306     assert cfg.val1 == 'val'
307     assert cfg.val2 == 'val'
308     assert cfg.val3 == 'yes'
309     assert cfg.val4 == 'val'
310     assert cfg.val5 == 'yes'
311
312
313 def test_callback_value_tuple():
314     val1 = StrOption('val1', "", 'val1')
315     val2 = StrOption('val2', "", 'val2')
316     val3 = StrOption('val3', "", callback=return_concat, callback_params={'': ((val1, False), (val2, False))})
317     val4 = StrOption('val4', "", callback=return_concat, callback_params={'': ('yes', 'no')})
318     raises(ValueError, "StrOption('val4', '', callback=return_concat, callback_params={'value': ('yes', 'no')})")
319     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4])
320     cfg = Config(maconfig)
321     cfg.read_write()
322     assert cfg.val1 == 'val1'
323     assert cfg.val2 == 'val2'
324     assert cfg.val3 == 'val1.val2'
325     assert cfg.val4 == 'yes.no'
326     cfg.val1 = 'new-val'
327     assert cfg.val3 == 'new-val.val2'
328     del(cfg.val1)
329     assert cfg.val3 == 'val1.val2'
330
331
332 def test_callback_value_force_permissive():
333     val1 = StrOption('val1', "", 'val', properties=('disabled',))
334     val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)})
335     val3 = StrOption('val3', "", callback=return_value, callback_params={'': ((val1, True),)})
336     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3])
337     cfg = Config(maconfig)
338     cfg.read_only()
339     raises(ConfigError, "cfg.val2")
340     assert cfg.val3 is None
341
342
343 def test_callback_symlink():
344     val1 = StrOption('val1', "", 'val')
345     val2 = SymLinkOption('val2', val1)
346     val3 = StrOption('val3', "", callback=return_value, callback_params={'': ((val2, False),)})
347     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3])
348     cfg = Config(maconfig)
349     cfg.read_write()
350     assert cfg.val1 == 'val'
351     assert cfg.val2 == 'val'
352     assert cfg.val3 == 'val'
353     cfg.val1 = 'new-val'
354     assert cfg.val1 == 'new-val'
355     assert cfg.val3 == 'new-val'
356     del(cfg.val1)
357     assert cfg.val1 == 'val'
358     assert cfg.val3 == 'val'
359
360
361 def test_callback_list():
362     val1 = StrOption('val1', "", callback=return_list)
363     maconfig = OptionDescription('rootconfig', '', [val1])
364     cfg = Config(maconfig)
365     cfg.read_write()
366     raises(ValueError, "cfg.val1")
367
368
369 def test_callback_multi():
370     val1 = StrOption('val1', "", callback=return_val, multi=True)
371     maconfig = OptionDescription('rootconfig', '', [val1])
372     cfg = Config(maconfig)
373     cfg.read_write()
374     assert cfg.val1 == ['val']
375     cfg.val1 = ['new-val']
376     assert cfg.val1 == ['new-val']
377     cfg.val1.append('new-val2')
378     assert cfg.val1 == ['new-val', 'new-val2']
379     del(cfg.val1)
380     assert cfg.val1 == ['val']
381
382
383 def test_callback_multi_value():
384     val1 = StrOption('val1', "", ['val'], multi=True)
385     val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
386     val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ('yes',)})
387     val4 = StrOption('val4', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), 'yes')})
388     maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4])
389     cfg = Config(maconfig)
390     cfg.read_write()
391     assert cfg.val1 == ['val']
392     assert cfg.val2 == ['val']
393     assert cfg.val4 == ['val', 'yes']
394     cfg.val1 = ['new-val']
395     assert cfg.val1 == ['new-val']
396     assert cfg.val2 == ['new-val']
397     assert cfg.val4 == ['new-val', 'yes']
398     cfg.val1.append('new-val2')
399     assert cfg.val1 == ['new-val', 'new-val2']
400     assert cfg.val2 == ['new-val', 'new-val2']
401     assert cfg.val4 == ['new-val', 'new-val2', 'yes']
402     del(cfg.val1)
403     assert cfg.val1 == ['val']
404     assert cfg.val2 == ['val']
405     assert cfg.val3 == ['yes']
406     assert cfg.val4 == ['val', 'yes']
407     cfg.val2.append('new')
408     assert cfg.val1 == ['val']
409     assert cfg.val2 == ['val', 'new']
410
411
412 def test_callback_multi_list():
413     val1 = StrOption('val1', "", callback=return_list, multi=True)
414     maconfig = OptionDescription('rootconfig', '', [val1])
415     cfg = Config(maconfig)
416     cfg.read_write()
417     assert cfg.val1 == ['val', 'val']
418     cfg.val1 = ['new-val']
419     assert cfg.val1 == ['new-val']
420     cfg.val1.append('new-val2')
421     assert cfg.val1 == ['new-val', 'new-val2']
422     del(cfg.val1)
423     assert cfg.val1 == ['val', 'val']
424
425
426 def test_callback_multi_list_extend():
427     val1 = StrOption('val1', "", callback=return_list2, callback_params={'': (['1', '2', '3'], ['4', '5'])}, multi=True)
428     maconfig = OptionDescription('rootconfig', '', [val1])
429     cfg = Config(maconfig)
430     cfg.read_write()
431     assert cfg.val1 == ['1', '2', '3', '4', '5']
432
433
434 def test_callback_multi_callback():
435     val1 = StrOption('val1', "", multi=True, callback=return_val)
436     interface1 = OptionDescription('val1', '', [val1])
437     maconfig = OptionDescription('rootconfig', '', [interface1])
438     cfg = Config(maconfig)
439     cfg.read_write()
440     assert cfg.val1.val1 == ['val']
441     cfg.val1.val1.append()
442     assert cfg.val1.val1 == ['val', 'val']
443
444
445 def test_callback_master_and_slaves_master():
446     val1 = StrOption('val1', "", multi=True, callback=return_val)
447     val2 = StrOption('val2', "", multi=True)
448     interface1 = OptionDescription('val1', '', [val1, val2])
449     interface1.impl_set_group_type(groups.master)
450     maconfig = OptionDescription('rootconfig', '', [interface1])
451     cfg = Config(maconfig)
452     cfg.read_write()
453     assert cfg.val1.val1 == ['val']
454     cfg.val1.val1.append()
455     assert cfg.val1.val1 == ['val', 'val']
456     assert cfg.val1.val2 == [None, None]
457
458
459 def test_callback_master_and_slaves_master2():
460     val1 = StrOption('val1', "", multi=True)
461     val2 = StrOption('val2', "", multi=True, default_multi='val2')
462     val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
463     val4 = StrOption('val4', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
464     interface1 = OptionDescription('val1', '', [val1, val2, val3, val4])
465     interface1.impl_set_group_type(groups.master)
466     maconfig = OptionDescription('rootconfig', '', [interface1])
467     cfg = Config(maconfig)
468     cfg.read_write()
469     cfg.val1.val1.append('val')
470     assert cfg.val1.val4 == ['val2']
471     assert cfg.val1.val3 == ['val2']
472     assert cfg.val1.val2 == ['val2']
473
474
475 def test_callback_master_and_slaves_master_list():
476     val1 = StrOption('val1', "", multi=True, callback=return_list)
477     val2 = StrOption('val2', "", multi=True)
478     interface1 = OptionDescription('val1', '', [val1, val2])
479     interface1.impl_set_group_type(groups.master)
480     maconfig = OptionDescription('rootconfig', '', [interface1])
481     cfg = Config(maconfig)
482     cfg.read_write()
483     assert cfg.val1.val1 == ['val', 'val']
484     assert cfg.val1.val2 == [None, None]
485     cfg.val1.val1.append()
486     assert cfg.val1.val1 == ['val', 'val', None]
487     assert cfg.val1.val2 == [None, None, None]
488     del(cfg.val1.val1)
489     assert cfg.val1.val1 == ['val', 'val']
490     assert cfg.val1.val2 == [None, None]
491     assert cfg.val1.val1.pop(1)
492     assert cfg.val1.val1 == ['val']
493     assert cfg.val1.val2 == [None]
494
495
496 def test_callback_master_and_slaves_slave():
497     val1 = StrOption('val1', "", multi=True)
498     val2 = StrOption('val2', "", multi=True, callback=return_val)
499     interface1 = OptionDescription('val1', '', [val1, val2])
500     interface1.impl_set_group_type(groups.master)
501     maconfig = OptionDescription('rootconfig', '', [interface1])
502     cfg = Config(maconfig)
503     cfg.read_write()
504     assert cfg.val1.val1 == []
505     assert cfg.val1.val2 == []
506     #
507     cfg.val1.val1 = ['val1']
508     assert cfg.val1.val1 == ['val1']
509     assert cfg.val1.val2 == ['val']
510     #
511     cfg.val1.val1.append('val2')
512     assert cfg.val1.val1 == ['val1', 'val2']
513     assert cfg.val1.val2 == ['val', 'val']
514     #
515     cfg.val1.val1 = ['val1', 'val2', 'val3']
516     assert cfg.val1.val1 == ['val1', 'val2', 'val3']
517     assert cfg.val1.val2 == ['val', 'val', 'val']
518     #
519     cfg.val1.val1.pop(2)
520     assert cfg.val1.val1 == ['val1', 'val2']
521     assert cfg.val1.val2 == ['val', 'val']
522     #
523     cfg.val1.val2 = ['val2', 'val2']
524     assert cfg.val1.val2 == ['val2', 'val2']
525     #
526     cfg.val1.val1.append('val3')
527     assert cfg.val1.val2 == ['val2', 'val2', 'val']
528
529
530 def test_callback_master_and_slaves():
531     val1 = StrOption('val1', "", multi=True)
532     val2 = StrOption('val2', "", multi=True, callback=return_val)
533     interface1 = OptionDescription('val1', '', [val1, val2])
534     interface1.impl_set_group_type(groups.master)
535     maconfig = OptionDescription('rootconfig', '', [interface1])
536     cfg = Config(maconfig)
537     cfg.read_write()
538
539
540 def test_callback_master_and_slaves_slave_cal():
541     val3 = StrOption('val3', "", multi=True)
542     val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
543     val2 = StrOption('val2', "", multi=True, callback=return_val)
544     interface1 = OptionDescription('val1', '', [val1, val2])
545     interface1.impl_set_group_type(groups.master)
546     maconfig = OptionDescription('rootconfig', '', [interface1, val3])
547     cfg = Config(maconfig)
548     cfg.read_write()
549     assert cfg.val3 == []
550     assert cfg.val1.val1 == []
551     assert cfg.val1.val2 == []
552     cfg.val1.val1 = ['val1']
553     cfg.val3 = ['val1']
554     assert cfg.val1.val1 == ['val1']
555     assert cfg.val1.val2 == ['val']
556     del(cfg.val1.val1)
557     cfg.val1.val2 = ['val']
558     cfg.val3 = ['val1', 'val2']
559     assert cfg.val1.val2 == ['val', 'val']
560     assert cfg.val1.val1 == ['val1', 'val2']
561     cfg.val1.val2 = ['val1', 'val2']
562     cfg.val3.pop(1)
563     # cannot remove slave's value because master is calculated
564     # so raise
565     raises(SlaveError, "cfg.val1.val1")
566     raises(SlaveError, "cfg.val1.val2")
567     cfg.val3 = ['val1', 'val2', 'val3']
568     assert cfg.val1.val2 == ['val1', 'val2', 'val']
569
570
571 def test_callback_master_and_slaves_slave_cal2():
572     val3 = StrOption('val3', "", ['val', 'val'], multi=True)
573     val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
574     val2 = StrOption('val2', "", ['val2', 'val2'], multi=True)
575     interface1 = OptionDescription('val1', '', [val1, val2])
576     interface1.impl_set_group_type(groups.master)
577     maconfig = OptionDescription('rootconfig', '', [interface1, val3])
578     cfg = Config(maconfig)
579     cfg.read_write()
580     assert cfg.val3 == ['val', 'val']
581     assert cfg.val1.val1 == ['val', 'val']
582     assert cfg.val1.val2 == ['val2', 'val2']
583     cfg.val3.pop(1)
584     # cannot remove slave's value because master is calculated
585     # so raise
586     raises(SlaveError, "cfg.val1.val1")
587     raises(SlaveError, "cfg.val1.val2")
588     cfg.val3 = ['val', 'val']
589     assert cfg.val3 == ['val', 'val']
590     assert cfg.val1.val1 == ['val', 'val']
591     assert cfg.val1.val2 == ['val2', 'val2']
592     raises(SlaveError, "cfg.val1.val1 = ['val']")
593     assert cfg.val3 == ['val', 'val']
594     assert cfg.val1.val1 == ['val', 'val']
595     assert cfg.val1.val2 == ['val2', 'val2']
596
597
598 def test_callback_master_and_slaves_master_disabled():
599     #properties must be transitive
600     val1 = StrOption('val1', "", multi=True, properties=('disabled',))
601     val2 = StrOption('val2', "", multi=True)
602     interface1 = OptionDescription('val1', '', [val1, val2])
603     interface1.impl_set_group_type(groups.master)
604     maconfig = OptionDescription('rootconfig', '', [interface1])
605     cfg = Config(maconfig)
606     cfg.read_write()
607     raises(PropertiesOptionError, "cfg.val1.val1")
608     raises(PropertiesOptionError, "cfg.val1.val1.append('yes')")
609     raises(PropertiesOptionError, "cfg.val1.val2")
610
611
612 def test_callback_master_and_slaves_master_callback_disabled():
613     val0 = StrOption('val0', "", multi=True, properties=('disabled',))
614     val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val0, False),)})
615     val2 = StrOption('val2', "", multi=True)
616     interface1 = OptionDescription('val1', '', [val1, val2])
617     interface1.impl_set_group_type(groups.master)
618     maconfig = OptionDescription('rootconfig', '', [interface1, val0])
619     cfg = Config(maconfig)
620     cfg.read_write()
621     raises(ConfigError, "cfg.val1.val1")
622     raises(ConfigError, "cfg.val1.val2")
623     cfg.cfgimpl_get_settings().remove('disabled')
624     cfg.val1.val1 = []
625     cfg.cfgimpl_get_settings().append('disabled')
626     assert cfg.val1.val1 == []
627     assert cfg.val1.val2 == []
628
629
630 def test_callback_master_and_slaves_slave_disabled():
631     val1 = StrOption('val1', "", multi=True)
632     val2 = StrOption('val2', "", multi=True, properties=('disabled',))
633     interface1 = OptionDescription('val1', '', [val1, val2])
634     interface1.impl_set_group_type(groups.master)
635     maconfig = OptionDescription('rootconfig', '', [interface1])
636     cfg = Config(maconfig)
637     cfg.read_write()
638     assert cfg.val1.val1 == []
639     raises(PropertiesOptionError, "cfg.val1.val2")
640     cfg.val1.val1.append('yes')
641     assert cfg.val1.val1 == ['yes']
642     cfg.cfgimpl_get_settings().remove('disabled')
643     assert cfg.val1.val2 == [None]
644     cfg.val1.val2 = ['no']
645     cfg.val1.val1.append('yes2')
646     cfg.val1.val1.append('yes3')
647     cfg.val1.val2[2] = 'no1'
648     assert cfg.val1.val2 == ['no', None, 'no1']
649     cfg.cfgimpl_get_settings().append('disabled')
650     cfg.val1.val1.pop(0)
651     assert cfg.val1.val1 == ['yes2', 'yes3']
652     cfg.cfgimpl_get_settings().remove('disabled')
653     assert cfg.val1.val2 == [None, 'no1']
654
655
656 def test_callback_master_and_slaves_slave_callback_disabled():
657     val0 = StrOption('val0', "", multi=True, properties=('disabled',))
658     val1 = StrOption('val1', "", multi=True)
659     val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val0, False),)})
660     interface1 = OptionDescription('val1', '', [val1, val2])
661     interface1.impl_set_group_type(groups.master)
662     maconfig = OptionDescription('rootconfig', '', [interface1, val0])
663     cfg = Config(maconfig)
664     cfg.read_write()
665     assert cfg.val1.val1 == []
666     raises(ConfigError, "cfg.val1.val2")
667     cfg.val1.val1.append('yes')
668     assert cfg.val1.val1 == ['yes']
669     cfg.cfgimpl_get_settings().remove('disabled')
670     assert cfg.val1.val2 == [None]
671     cfg.val1.val2 = ['no']
672     cfg.val1.val1.append('yes1')
673     cfg.val1.val2[1] = 'no1'
674     cfg.cfgimpl_get_settings().append('disabled')
675     cfg.val1.val1.pop(0)
676     assert cfg.val1.val1 == ['yes1']
677     assert cfg.val1.val2 == ['no1']
678
679
680 def test_callback_master_and_slaves_slave_list():
681     val1 = StrOption('val1', "", multi=True)
682     val2 = StrOption('val2', "", multi=True, callback=return_list)
683     interface1 = OptionDescription('val1', '', [val1, val2])
684     interface1.impl_set_group_type(groups.master)
685     maconfig = OptionDescription('rootconfig', '', [interface1])
686     cfg = Config(maconfig)
687     cfg.read_write()
688     #len is equal to 2 for slave and 0 for master
689     raises(SlaveError, "cfg.val1.val2")
690     cfg.val1.val1 = ['val1', 'val2']
691     assert cfg.val1.val1 == ['val1', 'val2']
692     assert cfg.val1.val2 == ['val', 'val']
693     #wrong len
694     raises(SlaveError, "cfg.val1.val1 = ['val1']")
695
696
697 def test_callback_master_and_slaves_value():
698     val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
699     val1 = StrOption('val1', "", multi=True)
700     val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
701     val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ('yes',)})
702     val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val4, False),)})
703     val6 = StrOption('val6', "", multi=True, callback=return_value, callback_params={'': ((val5, False),)})
704     interface1 = OptionDescription('val1', '', [val1, val2, val3, val5, val6])
705     interface1.impl_set_group_type(groups.master)
706     maconfig = OptionDescription('rootconfig', '', [interface1, val4])
707     cfg = Config(maconfig)
708     cfg.read_write()
709     cfg.val4 == ['val10', 'val11']
710     raises(SlaveError, "cfg.val1.val1")
711     raises(SlaveError, "cfg.val1.val2")
712     raises(SlaveError, "cfg.val1.val3")
713     raises(SlaveError, "cfg.val1.val5")
714     raises(SlaveError, "cfg.val1.val6")
715     #
716     #default calculation has greater length
717     raises(SlaveError, "cfg.val1.val1 = ['val1']")
718     #
719     cfg.val1.val1 = ['val1', 'val2']
720     assert cfg.val1.val1 == ['val1', 'val2']
721     assert cfg.val1.val2 == ['val1', 'val2']
722     assert cfg.val1.val3 == ['yes', 'yes']
723     assert cfg.val1.val5 == ['val10', 'val11']
724     assert cfg.val1.val6 == ['val10', 'val11']
725     #
726     cfg.val1.val1.append('val3')
727     assert cfg.val1.val1 == ['val1', 'val2', 'val3']
728     assert cfg.val1.val2 == ['val1', 'val2', 'val3']
729     assert cfg.val1.val3 == ['yes', 'yes', 'yes']
730     assert cfg.val1.val5 == ['val10', 'val11', None]
731     assert cfg.val1.val6 == ['val10', 'val11', None]
732     #
733     cfg.val1.val1.pop(2)
734     assert cfg.val1.val1 == ['val1', 'val2']
735     assert cfg.val1.val2 == ['val1', 'val2']
736     assert cfg.val1.val3 == ['yes', 'yes']
737     assert cfg.val1.val5 == ['val10', 'val11']
738     assert cfg.val1.val6 == ['val10', 'val11']
739     #
740     cfg.val1.val2 = ['val2', 'val2']
741     cfg.val1.val3 = ['val2', 'val2']
742     cfg.val1.val5 = ['val2', 'val2']
743     assert cfg.val1.val2 == ['val2', 'val2']
744     assert cfg.val1.val3 == ['val2', 'val2']
745     assert cfg.val1.val5 == ['val2', 'val2']
746     assert cfg.val1.val6 == ['val2', 'val2']
747     #
748     cfg.val1.val1.append('val3')
749     assert cfg.val1.val2 == ['val2', 'val2', 'val3']
750     assert cfg.val1.val3 == ['val2', 'val2', 'yes']
751     assert cfg.val1.val5 == ['val2', 'val2', None]
752     assert cfg.val1.val6 == ['val2', 'val2', None]
753     cfg.cfgimpl_get_settings().remove('cache')
754     cfg.val4 = ['val10', 'val11', 'val12']
755     #if value is already set, not updated !
756     cfg.val1.val1.pop(2)
757     cfg.val1.val1.append('val3')
758     cfg.val1.val1 = ['val1', 'val2', 'val3']
759     assert cfg.val1.val5 == ['val2', 'val2', 'val12']
760     assert cfg.val1.val6 == ['val2', 'val2', 'val12']
761
762
763 def test_callback_master():
764     val2 = StrOption('val2', "", multi=True, callback=return_value)
765     val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
766     interface1 = OptionDescription('val1', '', [val1, val2])
767     raises(ValueError, "interface1.impl_set_group_type(groups.master)")
768
769
770 def test_callback_master_and_other_master_slave():
771     val1 = StrOption('val1', "", multi=True)
772     val2 = StrOption('val2', "", multi=True)
773     val3 = StrOption('val3', "", multi=True)
774     val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
775     val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
776     val6 = StrOption('val6', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
777     interface1 = OptionDescription('val1', '', [val1, val2, val3])
778     interface1.impl_set_group_type(groups.master)
779     interface2 = OptionDescription('val4', '', [val4, val5, val6])
780     interface2.impl_set_group_type(groups.master)
781     maconfig = OptionDescription('rootconfig', '', [interface1, interface2])
782     cfg = Config(maconfig)
783     cfg.read_write()
784     assert cfg.val4.val4 == ['val10', 'val11']
785     assert cfg.val4.val5 == [None, None]
786     assert cfg.val4.val6 == [None, None]
787     cfg.val1.val1 = ['yes']
788     assert cfg.val4.val4 == ['val10', 'val11']
789     assert cfg.val4.val5 == ['yes', None]
790     assert cfg.val4.val6 == [None, None]
791     cfg.val1.val2 = ['no']
792     assert cfg.val4.val4 == ['val10', 'val11']
793     assert cfg.val4.val5 == ['yes', None]
794     assert cfg.val4.val6 == ['no', None]
795     cfg.val1.val1 = ['yes', 'yes', 'yes']
796     cfg.val1.val2 = ['no', 'no', 'no']
797     raises(SlaveError, "cfg.val4.val4")
798     raises(SlaveError, "cfg.val4.val5")
799     raises(SlaveError, "cfg.val4.val6")
800     cfg.val4.getattr('val4', validate=False).append('val12')
801     assert cfg.val4.val4 == ['val10', 'val11', 'val12']
802     assert cfg.val4.val5 == ['yes', 'yes', 'yes']
803     assert cfg.val4.val6 == ['no', 'no', 'no']
804
805
806 #FIXME: slave est un symlink
807
808
809 def test_callback_different_type():
810     val = IntOption('val', "", default=2)
811     val_ = IntOption('val_', "", default=3)
812     val1 = IntOption('val1', "", multi=True)
813     val2 = IntOption('val2', "", multi=True, callback=return_calc, callback_params={'': ((val, False), (val1, False)), 'k': ((val_, False),)})
814     interface1 = OptionDescription('val1', '', [val1, val2])
815     interface1.impl_set_group_type(groups.master)
816     maconfig = OptionDescription('rootconfig', '', [interface1, val, val_])
817     cfg = Config(maconfig)
818     cfg.read_write()
819     assert cfg.val1.val1 == []
820     assert cfg.val1.val2 == []
821     cfg.val1.val1 = [1]
822     assert cfg.val1.val1 == [1]
823     assert cfg.val1.val2 == [6]
824     cfg.val1.val1 = [1, 3]
825     assert cfg.val1.val1 == [1, 3]
826     assert cfg.val1.val2 == [6, 8]
827     cfg.val1.val1 = [1, 3, 5]
828     assert cfg.val1.val1 == [1, 3, 5]
829     assert cfg.val1.val2 == [6, 8, 10]
830
831
832 def test_callback_hidden():
833     opt1 = BoolOption('opt1', '')
834     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)})
835     od1 = OptionDescription('od1', '', [opt1], properties=('hidden',))
836     od2 = OptionDescription('od2', '', [opt2])
837     maconfig = OptionDescription('rootconfig', '', [od1, od2])
838     cfg = Config(maconfig)
839     cfg.cfgimpl_get_settings().setpermissive(('hidden',))
840     cfg.read_write()
841     raises(PropertiesOptionError, 'cfg.od1.opt1')
842     cfg.od2.opt2
843
844
845 def test_callback_two_disabled():
846     opt1 = BoolOption('opt1', '', properties=('disabled',))
847     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('disabled',))
848     od1 = OptionDescription('od1', '', [opt1])
849     od2 = OptionDescription('od2', '', [opt2])
850     maconfig = OptionDescription('rootconfig', '', [od1, od2])
851     cfg = Config(maconfig)
852     cfg.read_write()
853     raises(PropertiesOptionError, 'cfg.od2.opt2')
854
855
856 def test_callback_two_disabled2():
857     opt1 = BoolOption('opt1', '', properties=('hidden',))
858     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('hidden',))
859     od1 = OptionDescription('od1', '', [opt1])
860     od2 = OptionDescription('od2', '', [opt2])
861     maconfig = OptionDescription('rootconfig', '', [od1, od2])
862     cfg = Config(maconfig)
863     cfg.read_write()
864     cfg.cfgimpl_get_settings().setpermissive(('hidden',))
865     raises(PropertiesOptionError, 'cfg.od2.opt2')
866     assert cfg.getowner(opt2, force_permissive=True) == owners.default
867
868
869 def test_callback_calculating_disabled():
870     opt1 = BoolOption('opt1', '', properties=('disabled',))
871     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)})
872     od1 = OptionDescription('od1', '', [opt1])
873     od2 = OptionDescription('od2', '', [opt2])
874     maconfig = OptionDescription('rootconfig', '', [od1, od2])
875     cfg = Config(maconfig)
876     cfg.read_write()
877     raises(ConfigError, 'cfg.od2.opt2')
878
879
880 def test_callback_calculating_mandatory():
881     opt1 = BoolOption('opt1', '', properties=('disabled',))
882     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('mandatory',))
883     od1 = OptionDescription('od1', '', [opt1])
884     od2 = OptionDescription('od2', '', [opt2])
885     maconfig = OptionDescription('rootconfig', '', [od1, od2])
886     cfg = Config(maconfig)
887     cfg.read_only()
888     raises(ConfigError, 'cfg.od2.opt2')
889
890
891 def test_callback_calculating_mandatory_multi():
892     opt1 = BoolOption('opt1', '', multi=True, properties=('disabled',))
893     opt2 = BoolOption('opt2', '', multi=True, callback=return_value, callback_params={'': ((opt1, False),)}, properties=('mandatory',))
894     od1 = OptionDescription('od1', '', [opt1])
895     od2 = OptionDescription('od2', '', [opt2])
896     maconfig = OptionDescription('rootconfig', '', [od1, od2])
897     cfg = Config(maconfig)
898     cfg.read_only()
899     raises(ConfigError, 'cfg.od2.opt2')
900
901
902 def test_callback_two_disabled_multi():
903     opt1 = BoolOption('opt1', '', properties=('disabled',))
904     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('disabled',), multi=True)
905     od1 = OptionDescription('od1', '', [opt1])
906     od2 = OptionDescription('od2', '', [opt2])
907     maconfig = OptionDescription('rootconfig', '', [od1, od2])
908     cfg = Config(maconfig)
909     cfg.read_write()
910     raises(PropertiesOptionError, 'cfg.od2.opt2')
911
912
913 def test_callback_multi_list_params():
914     val1 = StrOption('val1', "", multi=True, default=['val1', 'val2'])
915     val2 = StrOption('val2', "", multi=True, callback=return_list, callback_params={'': ((val1, False),)})
916     oval2 = OptionDescription('val2', '', [val2])
917     maconfig = OptionDescription('rootconfig', '', [val1, oval2])
918     cfg = Config(maconfig)
919     cfg.read_write()
920     assert cfg.val2.val2 == ['val', 'val']
921
922
923 def test_callback_multi_list_params_key():
924     val1 = StrOption('val1', "", multi=True, default=['val1', 'val2'])
925     val2 = StrOption('val2', "", multi=True, callback=return_list, callback_params={'value': ((val1, False),)})
926     oval2 = OptionDescription('val2', '', [val2])
927     maconfig = OptionDescription('rootconfig', '', [val1, oval2])
928     cfg = Config(maconfig)
929     cfg.read_write()
930     assert cfg.val2.val2 == ['val', 'val']