add SubMulti
[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 = ['val1']
442     cfg.val1.val1.append()
443     assert cfg.val1.val1 == ['val1', 'val']
444
445
446 def test_callback_master_and_slaves_master():
447     val1 = StrOption('val1', "", multi=True, callback=return_val)
448     val2 = StrOption('val2', "", multi=True)
449     interface1 = OptionDescription('val1', '', [val1, val2])
450     interface1.impl_set_group_type(groups.master)
451     maconfig = OptionDescription('rootconfig', '', [interface1])
452     cfg = Config(maconfig)
453     cfg.read_write()
454     assert cfg.val1.val1 == ['val']
455     cfg.val1.val1.append()
456     assert cfg.val1.val1 == ['val', 'val']
457     assert cfg.val1.val2 == [None, None]
458
459
460 def test_callback_master_and_slaves_master2():
461     val1 = StrOption('val1', "", multi=True)
462     val2 = StrOption('val2', "", multi=True, default_multi='val2')
463     val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
464     val4 = StrOption('val4', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
465     interface1 = OptionDescription('val1', '', [val1, val2, val3, val4])
466     interface1.impl_set_group_type(groups.master)
467     maconfig = OptionDescription('rootconfig', '', [interface1])
468     cfg = Config(maconfig)
469     cfg.read_write()
470     cfg.val1.val1.append('val')
471     assert cfg.val1.val4 == ['val2']
472     assert cfg.val1.val3 == ['val2']
473     assert cfg.val1.val2 == ['val2']
474
475
476 def test_callback_master_and_slaves_master_list():
477     val1 = StrOption('val1', "", multi=True, callback=return_list)
478     val2 = StrOption('val2', "", multi=True)
479     interface1 = OptionDescription('val1', '', [val1, val2])
480     interface1.impl_set_group_type(groups.master)
481     maconfig = OptionDescription('rootconfig', '', [interface1])
482     cfg = Config(maconfig)
483     cfg.read_write()
484     assert cfg.val1.val1 == ['val', 'val']
485     assert cfg.val1.val2 == [None, None]
486     cfg.val1.val1.append()
487     assert cfg.val1.val1 == ['val', 'val', None]
488     assert cfg.val1.val2 == [None, None, None]
489     del(cfg.val1.val1)
490     assert cfg.val1.val1 == ['val', 'val']
491     assert cfg.val1.val2 == [None, None]
492     assert cfg.val1.val1.pop(1)
493     assert cfg.val1.val1 == ['val']
494     assert cfg.val1.val2 == [None]
495
496
497 def test_callback_master_and_slaves_slave():
498     val1 = StrOption('val1', "", multi=True)
499     val2 = StrOption('val2', "", multi=True, callback=return_val)
500     interface1 = OptionDescription('val1', '', [val1, val2])
501     interface1.impl_set_group_type(groups.master)
502     maconfig = OptionDescription('rootconfig', '', [interface1])
503     cfg = Config(maconfig)
504     cfg.read_write()
505     assert cfg.val1.val1 == []
506     assert cfg.val1.val2 == []
507     #
508     cfg.val1.val1 = ['val1']
509     assert cfg.val1.val1 == ['val1']
510     assert cfg.val1.val2 == ['val']
511     #
512     cfg.val1.val1.append('val2')
513     assert cfg.val1.val1 == ['val1', 'val2']
514     assert cfg.val1.val2 == ['val', 'val']
515     #
516     cfg.val1.val1 = ['val1', 'val2', 'val3']
517     assert cfg.val1.val1 == ['val1', 'val2', 'val3']
518     assert cfg.val1.val2 == ['val', 'val', 'val']
519     #
520     cfg.val1.val1.pop(2)
521     assert cfg.val1.val1 == ['val1', 'val2']
522     assert cfg.val1.val2 == ['val', 'val']
523     #
524     cfg.val1.val2 = ['val2', 'val2']
525     assert cfg.val1.val2 == ['val2', 'val2']
526     #
527     cfg.val1.val1.append('val3')
528     assert cfg.val1.val2 == ['val2', 'val2', 'val']
529
530
531 def test_callback_master_and_slaves():
532     val1 = StrOption('val1', "", multi=True)
533     val2 = StrOption('val2', "", multi=True, callback=return_val)
534     interface1 = OptionDescription('val1', '', [val1, val2])
535     interface1.impl_set_group_type(groups.master)
536     maconfig = OptionDescription('rootconfig', '', [interface1])
537     cfg = Config(maconfig)
538     cfg.read_write()
539
540
541 def test_callback_master_and_slaves_slave_cal():
542     val3 = StrOption('val3', "", multi=True)
543     val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
544     val2 = StrOption('val2', "", multi=True, callback=return_val)
545     interface1 = OptionDescription('val1', '', [val1, val2])
546     interface1.impl_set_group_type(groups.master)
547     maconfig = OptionDescription('rootconfig', '', [interface1, val3])
548     cfg = Config(maconfig)
549     cfg.read_write()
550     assert cfg.val3 == []
551     assert cfg.val1.val1 == []
552     assert cfg.val1.val2 == []
553     cfg.val1.val1 = ['val1']
554     cfg.val3 = ['val1']
555     assert cfg.val1.val1 == ['val1']
556     assert cfg.val1.val2 == ['val']
557     del(cfg.val1.val1)
558     cfg.val1.val2 = ['val']
559     cfg.val3 = ['val1', 'val2']
560     assert cfg.val1.val2 == ['val', 'val']
561     assert cfg.val1.val1 == ['val1', 'val2']
562     cfg.val1.val2 = ['val1', 'val2']
563     cfg.val3.pop(1)
564     # cannot remove slave's value because master is calculated
565     # so raise
566     raises(SlaveError, "cfg.val1.val1")
567     raises(SlaveError, "cfg.val1.val2")
568     cfg.val3 = ['val1', 'val2', 'val3']
569     assert cfg.val1.val2 == ['val1', 'val2', 'val']
570
571
572 def test_callback_master_and_slaves_slave_cal2():
573     val3 = StrOption('val3', "", ['val', 'val'], multi=True)
574     val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
575     val2 = StrOption('val2', "", ['val2', 'val2'], multi=True)
576     interface1 = OptionDescription('val1', '', [val1, val2])
577     interface1.impl_set_group_type(groups.master)
578     maconfig = OptionDescription('rootconfig', '', [interface1, val3])
579     cfg = Config(maconfig)
580     cfg.read_write()
581     assert cfg.val3 == ['val', 'val']
582     assert cfg.val1.val1 == ['val', 'val']
583     assert cfg.val1.val2 == ['val2', 'val2']
584     cfg.val3.pop(1)
585     # cannot remove slave's value because master is calculated
586     # so raise
587     raises(SlaveError, "cfg.val1.val1")
588     raises(SlaveError, "cfg.val1.val2")
589     cfg.val3 = ['val', 'val']
590     assert cfg.val3 == ['val', 'val']
591     assert cfg.val1.val1 == ['val', 'val']
592     assert cfg.val1.val2 == ['val2', 'val2']
593     raises(SlaveError, "cfg.val1.val1 = ['val']")
594     assert cfg.val3 == ['val', 'val']
595     assert cfg.val1.val1 == ['val', 'val']
596     assert cfg.val1.val2 == ['val2', 'val2']
597
598
599 def test_callback_master_and_slaves_master_disabled():
600     #properties must be transitive
601     val1 = StrOption('val1', "", multi=True, properties=('disabled',))
602     val2 = StrOption('val2', "", multi=True)
603     interface1 = OptionDescription('val1', '', [val1, val2])
604     interface1.impl_set_group_type(groups.master)
605     maconfig = OptionDescription('rootconfig', '', [interface1])
606     cfg = Config(maconfig)
607     cfg.read_write()
608     raises(PropertiesOptionError, "cfg.val1.val1")
609     raises(PropertiesOptionError, "cfg.val1.val1.append('yes')")
610     raises(PropertiesOptionError, "cfg.val1.val2")
611
612
613 def test_callback_master_and_slaves_master_callback_disabled():
614     val0 = StrOption('val0', "", multi=True, properties=('disabled',))
615     val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val0, False),)})
616     val2 = StrOption('val2', "", multi=True)
617     interface1 = OptionDescription('val1', '', [val1, val2])
618     interface1.impl_set_group_type(groups.master)
619     maconfig = OptionDescription('rootconfig', '', [interface1, val0])
620     cfg = Config(maconfig)
621     cfg.read_write()
622     raises(ConfigError, "cfg.val1.val1")
623     raises(ConfigError, "cfg.val1.val2")
624     cfg.cfgimpl_get_settings().remove('disabled')
625     cfg.val1.val1 = []
626     cfg.cfgimpl_get_settings().append('disabled')
627     assert cfg.val1.val1 == []
628     assert cfg.val1.val2 == []
629
630
631 def test_callback_master_and_slaves_slave_disabled():
632     val1 = StrOption('val1', "", multi=True)
633     val2 = StrOption('val2', "", multi=True, properties=('disabled',))
634     interface1 = OptionDescription('val1', '', [val1, val2])
635     interface1.impl_set_group_type(groups.master)
636     maconfig = OptionDescription('rootconfig', '', [interface1])
637     cfg = Config(maconfig)
638     cfg.read_write()
639     assert cfg.val1.val1 == []
640     raises(PropertiesOptionError, "cfg.val1.val2")
641     cfg.val1.val1.append('yes')
642     assert cfg.val1.val1 == ['yes']
643     cfg.cfgimpl_get_settings().remove('disabled')
644     assert cfg.val1.val2 == [None]
645     cfg.val1.val2 = ['no']
646     cfg.val1.val1.append('yes2')
647     cfg.val1.val1.append('yes3')
648     cfg.val1.val2[2] = 'no1'
649     assert cfg.val1.val2 == ['no', None, 'no1']
650     cfg.cfgimpl_get_settings().append('disabled')
651     cfg.val1.val1.pop(0)
652     assert cfg.val1.val1 == ['yes2', 'yes3']
653     cfg.cfgimpl_get_settings().remove('disabled')
654     assert cfg.val1.val2 == [None, 'no1']
655
656
657 def test_callback_master_and_slaves_slave_callback_disabled():
658     val0 = StrOption('val0', "", multi=True, properties=('disabled',))
659     val1 = StrOption('val1', "", multi=True)
660     val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val0, False),)})
661     interface1 = OptionDescription('val1', '', [val1, val2])
662     interface1.impl_set_group_type(groups.master)
663     maconfig = OptionDescription('rootconfig', '', [interface1, val0])
664     cfg = Config(maconfig)
665     cfg.read_write()
666     assert cfg.val1.val1 == []
667     raises(ConfigError, "cfg.val1.val2")
668     cfg.val1.val1.append('yes')
669     assert cfg.val1.val1 == ['yes']
670     cfg.cfgimpl_get_settings().remove('disabled')
671     assert cfg.val1.val2 == [None]
672     cfg.val1.val2 = ['no']
673     cfg.val1.val1.append('yes1')
674     cfg.val1.val2[1] = 'no1'
675     cfg.cfgimpl_get_settings().append('disabled')
676     cfg.val1.val1.pop(0)
677     assert cfg.val1.val1 == ['yes1']
678     assert cfg.val1.val2 == ['no1']
679
680
681 def test_callback_master_and_slaves_slave_list():
682     val1 = StrOption('val1', "", multi=True)
683     val2 = StrOption('val2', "", multi=True, callback=return_list)
684     interface1 = OptionDescription('val1', '', [val1, val2])
685     interface1.impl_set_group_type(groups.master)
686     maconfig = OptionDescription('rootconfig', '', [interface1])
687     cfg = Config(maconfig)
688     cfg.read_write()
689     #len is equal to 2 for slave and 0 for master
690     raises(SlaveError, "cfg.val1.val2")
691     cfg.val1.val1 = ['val1', 'val2']
692     assert cfg.val1.val1 == ['val1', 'val2']
693     assert cfg.val1.val2 == ['val', 'val']
694     #wrong len
695     raises(SlaveError, "cfg.val1.val1 = ['val1']")
696
697
698 def test_callback_master_and_slaves_value():
699     val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
700     val1 = StrOption('val1', "", multi=True)
701     val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
702     val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ('yes',)})
703     val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val4, False),)})
704     val6 = StrOption('val6', "", multi=True, callback=return_value, callback_params={'': ((val5, False),)})
705     interface1 = OptionDescription('val1', '', [val1, val2, val3, val5, val6])
706     interface1.impl_set_group_type(groups.master)
707     maconfig = OptionDescription('rootconfig', '', [interface1, val4])
708     cfg = Config(maconfig)
709     cfg.read_write()
710     cfg.val4 == ['val10', 'val11']
711     raises(SlaveError, "cfg.val1.val1")
712     raises(SlaveError, "cfg.val1.val2")
713     raises(SlaveError, "cfg.val1.val3")
714     raises(SlaveError, "cfg.val1.val5")
715     raises(SlaveError, "cfg.val1.val6")
716     #
717     #default calculation has greater length
718     raises(SlaveError, "cfg.val1.val1 = ['val1']")
719     #
720     cfg.val1.val1 = ['val1', 'val2']
721     assert cfg.val1.val1 == ['val1', 'val2']
722     assert cfg.val1.val2 == ['val1', 'val2']
723     assert cfg.val1.val3 == ['yes', 'yes']
724     assert cfg.val1.val5 == ['val10', 'val11']
725     assert cfg.val1.val6 == ['val10', 'val11']
726     #
727     cfg.val1.val1.append('val3')
728     assert cfg.val1.val1 == ['val1', 'val2', 'val3']
729     assert cfg.val1.val2 == ['val1', 'val2', 'val3']
730     assert cfg.val1.val3 == ['yes', 'yes', 'yes']
731     assert cfg.val1.val5 == ['val10', 'val11', None]
732     assert cfg.val1.val6 == ['val10', 'val11', None]
733     #
734     cfg.val1.val1.pop(2)
735     assert cfg.val1.val1 == ['val1', 'val2']
736     assert cfg.val1.val2 == ['val1', 'val2']
737     assert cfg.val1.val3 == ['yes', 'yes']
738     assert cfg.val1.val5 == ['val10', 'val11']
739     assert cfg.val1.val6 == ['val10', 'val11']
740     #
741     cfg.val1.val2 = ['val2', 'val2']
742     cfg.val1.val3 = ['val2', 'val2']
743     cfg.val1.val5 = ['val2', 'val2']
744     assert cfg.val1.val2 == ['val2', 'val2']
745     assert cfg.val1.val3 == ['val2', 'val2']
746     assert cfg.val1.val5 == ['val2', 'val2']
747     assert cfg.val1.val6 == ['val2', 'val2']
748     #
749     cfg.val1.val1.append('val3')
750     assert cfg.val1.val2 == ['val2', 'val2', 'val3']
751     assert cfg.val1.val3 == ['val2', 'val2', 'yes']
752     assert cfg.val1.val5 == ['val2', 'val2', None]
753     assert cfg.val1.val6 == ['val2', 'val2', None]
754     cfg.cfgimpl_get_settings().remove('cache')
755     cfg.val4 = ['val10', 'val11', 'val12']
756     #if value is already set, not updated !
757     cfg.val1.val1.pop(2)
758     cfg.val1.val1.append('val3')
759     cfg.val1.val1 = ['val1', 'val2', 'val3']
760     assert cfg.val1.val5 == ['val2', 'val2', 'val12']
761     assert cfg.val1.val6 == ['val2', 'val2', 'val12']
762
763
764 def test_callback_master():
765     val2 = StrOption('val2', "", multi=True, callback=return_value)
766     val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
767     interface1 = OptionDescription('val1', '', [val1, val2])
768     raises(ValueError, "interface1.impl_set_group_type(groups.master)")
769
770
771 def test_callback_master_and_other_master_slave():
772     val1 = StrOption('val1', "", multi=True)
773     val2 = StrOption('val2', "", multi=True)
774     val3 = StrOption('val3', "", multi=True)
775     val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
776     val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
777     val6 = StrOption('val6', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
778     interface1 = OptionDescription('val1', '', [val1, val2, val3])
779     interface1.impl_set_group_type(groups.master)
780     interface2 = OptionDescription('val4', '', [val4, val5, val6])
781     interface2.impl_set_group_type(groups.master)
782     maconfig = OptionDescription('rootconfig', '', [interface1, interface2])
783     cfg = Config(maconfig)
784     cfg.read_write()
785     assert cfg.val4.val4 == ['val10', 'val11']
786     assert cfg.val4.val5 == [None, None]
787     assert cfg.val4.val6 == [None, None]
788     cfg.val1.val1 = ['yes']
789     assert cfg.val4.val4 == ['val10', 'val11']
790     assert cfg.val4.val5 == ['yes', None]
791     assert cfg.val4.val6 == [None, None]
792     cfg.val1.val2 = ['no']
793     assert cfg.val4.val4 == ['val10', 'val11']
794     assert cfg.val4.val5 == ['yes', None]
795     assert cfg.val4.val6 == ['no', None]
796     cfg.val1.val1 = ['yes', 'yes', 'yes']
797     cfg.val1.val2 = ['no', 'no', 'no']
798     raises(SlaveError, "cfg.val4.val4")
799     raises(SlaveError, "cfg.val4.val5")
800     raises(SlaveError, "cfg.val4.val6")
801     cfg.val4.getattr('val4', validate=False).append('val12')
802     assert cfg.val4.val4 == ['val10', 'val11', 'val12']
803     assert cfg.val4.val5 == ['yes', 'yes', 'yes']
804     assert cfg.val4.val6 == ['no', 'no', 'no']
805
806
807 #FIXME: slave est un symlink
808
809
810 def test_callback_different_type():
811     val = IntOption('val', "", default=2)
812     val_ = IntOption('val_', "", default=3)
813     val1 = IntOption('val1', "", multi=True)
814     val2 = IntOption('val2', "", multi=True, callback=return_calc, callback_params={'': ((val, False), (val1, False)), 'k': ((val_, False),)})
815     interface1 = OptionDescription('val1', '', [val1, val2])
816     interface1.impl_set_group_type(groups.master)
817     maconfig = OptionDescription('rootconfig', '', [interface1, val, val_])
818     cfg = Config(maconfig)
819     cfg.read_write()
820     assert cfg.val1.val1 == []
821     assert cfg.val1.val2 == []
822     cfg.val1.val1 = [1]
823     assert cfg.val1.val1 == [1]
824     assert cfg.val1.val2 == [6]
825     cfg.val1.val1 = [1, 3]
826     assert cfg.val1.val1 == [1, 3]
827     assert cfg.val1.val2 == [6, 8]
828     cfg.val1.val1 = [1, 3, 5]
829     assert cfg.val1.val1 == [1, 3, 5]
830     assert cfg.val1.val2 == [6, 8, 10]
831
832
833 def test_callback_hidden():
834     opt1 = BoolOption('opt1', '')
835     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)})
836     od1 = OptionDescription('od1', '', [opt1], properties=('hidden',))
837     od2 = OptionDescription('od2', '', [opt2])
838     maconfig = OptionDescription('rootconfig', '', [od1, od2])
839     cfg = Config(maconfig)
840     cfg.cfgimpl_get_settings().setpermissive(('hidden',))
841     cfg.read_write()
842     raises(PropertiesOptionError, 'cfg.od1.opt1')
843     cfg.od2.opt2
844
845
846 def test_callback_two_disabled():
847     opt1 = BoolOption('opt1', '', properties=('disabled',))
848     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('disabled',))
849     od1 = OptionDescription('od1', '', [opt1])
850     od2 = OptionDescription('od2', '', [opt2])
851     maconfig = OptionDescription('rootconfig', '', [od1, od2])
852     cfg = Config(maconfig)
853     cfg.read_write()
854     raises(PropertiesOptionError, 'cfg.od2.opt2')
855
856
857 def test_callback_two_disabled2():
858     opt1 = BoolOption('opt1', '', properties=('hidden',))
859     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('hidden',))
860     od1 = OptionDescription('od1', '', [opt1])
861     od2 = OptionDescription('od2', '', [opt2])
862     maconfig = OptionDescription('rootconfig', '', [od1, od2])
863     cfg = Config(maconfig)
864     cfg.read_write()
865     cfg.cfgimpl_get_settings().setpermissive(('hidden',))
866     raises(PropertiesOptionError, 'cfg.od2.opt2')
867     assert cfg.getowner(opt2, force_permissive=True) == owners.default
868
869
870 def test_callback_calculating_disabled():
871     opt1 = BoolOption('opt1', '', properties=('disabled',))
872     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)})
873     od1 = OptionDescription('od1', '', [opt1])
874     od2 = OptionDescription('od2', '', [opt2])
875     maconfig = OptionDescription('rootconfig', '', [od1, od2])
876     cfg = Config(maconfig)
877     cfg.read_write()
878     raises(ConfigError, 'cfg.od2.opt2')
879
880
881 def test_callback_calculating_mandatory():
882     opt1 = BoolOption('opt1', '', properties=('disabled',))
883     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('mandatory',))
884     od1 = OptionDescription('od1', '', [opt1])
885     od2 = OptionDescription('od2', '', [opt2])
886     maconfig = OptionDescription('rootconfig', '', [od1, od2])
887     cfg = Config(maconfig)
888     cfg.read_only()
889     raises(ConfigError, 'cfg.od2.opt2')
890
891
892 def test_callback_calculating_mandatory_multi():
893     opt1 = BoolOption('opt1', '', multi=True, properties=('disabled',))
894     opt2 = BoolOption('opt2', '', multi=True, callback=return_value, callback_params={'': ((opt1, False),)}, properties=('mandatory',))
895     od1 = OptionDescription('od1', '', [opt1])
896     od2 = OptionDescription('od2', '', [opt2])
897     maconfig = OptionDescription('rootconfig', '', [od1, od2])
898     cfg = Config(maconfig)
899     cfg.read_only()
900     raises(ConfigError, 'cfg.od2.opt2')
901
902
903 def test_callback_two_disabled_multi():
904     opt1 = BoolOption('opt1', '', properties=('disabled',))
905     opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('disabled',), multi=True)
906     od1 = OptionDescription('od1', '', [opt1])
907     od2 = OptionDescription('od2', '', [opt2])
908     maconfig = OptionDescription('rootconfig', '', [od1, od2])
909     cfg = Config(maconfig)
910     cfg.read_write()
911     raises(PropertiesOptionError, 'cfg.od2.opt2')
912
913
914 def test_callback_multi_list_params():
915     val1 = StrOption('val1', "", multi=True, default=['val1', 'val2'])
916     val2 = StrOption('val2', "", multi=True, callback=return_list, callback_params={'': ((val1, False),)})
917     oval2 = OptionDescription('val2', '', [val2])
918     maconfig = OptionDescription('rootconfig', '', [val1, oval2])
919     cfg = Config(maconfig)
920     cfg.read_write()
921     assert cfg.val2.val2 == ['val', 'val']
922
923
924 def test_callback_multi_list_params_key():
925     val1 = StrOption('val1', "", multi=True, default=['val1', 'val2'])
926     val2 = StrOption('val2', "", multi=True, callback=return_list, callback_params={'value': ((val1, False),)})
927     oval2 = OptionDescription('val2', '', [val2])
928     maconfig = OptionDescription('rootconfig', '', [val1, oval2])
929     cfg = Config(maconfig)
930     cfg.read_write()
931     assert cfg.val2.val2 == ['val', 'val']