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