Better support for slave with callback:
[tiramisu.git] / test / test_option_calculation.py
1 import autopath
2 from py.test import raises
3
4 from tiramisu.setting import groups
5 from tiramisu.config import Config
6 from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
7     StrOption, OptionDescription
8 from tiramisu.error import PropertiesOptionError, ConflictError
9
10
11 def return_value():
12     return 'val'
13
14
15 def make_description():
16     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
17     gcdummy = BoolOption('dummy', 'dummy', default=False)
18     objspaceoption = ChoiceOption('objspace', 'Object space',
19                                   ('std', 'thunk'), 'std')
20     booloption = BoolOption('bool', 'Test boolean option', default=True)
21     intoption = IntOption('int', 'Test int option', default=0)
22     intoption2 = IntOption('int', 'Test int option', default=0)
23     floatoption = FloatOption('float', 'Test float option', default=2.3)
24     stroption = StrOption('str', 'Test string option', default="abc")
25     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
26     wantref_option = BoolOption('wantref', 'Test requires', default=False,
27                                 requires=((boolop, True, 'hidden'),))
28     wantframework_option = BoolOption('wantframework', 'Test requires',
29                                       default=False,
30                                       requires=((boolop, True, 'hidden'),))
31     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption, intoption2])
32     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
33                               wantref_option, stroption,
34                               wantframework_option,
35                               intoption, boolop])
36     return descr
37
38
39 def make_description_duplicates():
40     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
41     ## dummy 1
42     gcdummy = BoolOption('dummy', 'dummy', default=False)
43     objspaceoption = ChoiceOption('objspace', 'Object space',
44                                   ('std', 'thunk'), 'std')
45     booloption = BoolOption('bool', 'Test boolean option', default=True)
46     intoption = IntOption('int', 'Test int option', default=0)
47     floatoption = FloatOption('float', 'Test float option', default=2.3)
48     stroption = StrOption('str', 'Test string option', default="abc")
49     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
50     wantref_option = BoolOption('wantref', 'Test requires', default=False,
51                                 requires=((boolop, True, 'hidden'),))
52     wantframework_option = BoolOption('wantframework', 'Test requires',
53                                       default=False,
54                                       requires=((boolop, True, 'hidden'),))
55     # dummy2 (same path)
56     gcdummy2 = BoolOption('dummy', 'dummy2', default=True)
57     # dummy3 (same name)
58     gcdummy3 = BoolOption('dummy', 'dummy2', default=True)
59     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, gcdummy2, floatoption])
60     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
61                               wantref_option, stroption,
62                               wantframework_option,
63                               intoption, boolop, gcdummy3])
64     return descr
65
66
67 def test_identical_paths():
68     """If in the schema (the option description) there is something that
69     have the same name, an exection is raised
70     """
71     raises(ConflictError, "make_description_duplicates()")
72
73
74 def make_description2():
75     gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
76     gcdummy = BoolOption('dummy', 'dummy', default=False)
77
78     floatoption = FloatOption('float', 'Test float option', default=2.3)
79
80     objspaceoption = ChoiceOption('objspace', 'Object space',
81                                   ['std', 'thunk'], 'std')
82     booloption = BoolOption('bool', 'Test boolean option', default=True)
83     intoption = IntOption('int', 'Test int option', default=0)
84     stroption = StrOption('str', 'Test string option', default="abc")
85     # first multi
86     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
87     boolop.enable_multi()
88     wantref_option = BoolOption('wantref', 'Test requires', default=False,
89                                 requires=((boolop, True, 'hidden'),))
90     # second multi
91     wantframework_option = BoolOption('wantframework', 'Test requires',
92                                       default=False,
93                                       requires=((boolop, True, 'hidden'),))
94     wantframework_option.enable_multi()
95
96     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
97     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
98                               wantref_option, stroption,
99                               wantframework_option,
100                               intoption, boolop])
101     return descr
102
103
104 # FIXME: il faudra tester les validations sur les multis
105 #def test_multi_constraints():
106 #    "a multi in a constraint has to have the same length"
107 #    descr = make_description2()
108 #    cfg = Config(descr)
109 #    cfg.boolop = [True, True, False]
110 #    cfg.wantframework = [False, False, True]
111 #
112 #def test_multi_raise():
113 #    "a multi in a constraint has to have the same length"
114 #    # FIXME fusionner les deux tests, MAIS PROBLEME :
115 #    # il ne devrait pas etre necessaire de refaire une config
116 #    # si la valeur est modifiee une deuxieme fois ->
117 #    #raises(ConflictConfigError, "cfg.wantframework = [False, False, True]")
118 #    #   ExceptionFailure: 'DID NOT RAISE'
119 #    descr = make_description2()
120 #    cfg = Config(descr)
121 #    cfg.boolop = [True]
122 #    raises(ConflictConfigError, "cfg.wantframework = [False, False, True]")
123 # ____________________________________________________________
124 # adding dynamically new options description schema
125 #def test_newoption_add_in_descr():
126 #    descr = make_description()
127 #    newoption = BoolOption('newoption', 'dummy twoo', default=False)
128 #    descr.add_child(newoption)
129 #    config = Config(descr)
130 #    assert config.newoption == False
131
132 #def test_newoption_add_in_subdescr():
133 #    descr = make_description()
134 #    newoption = BoolOption('newoption', 'dummy twoo', default=False)
135 #    descr.gc.add_child(newoption)
136 #    config = Config(descr)
137 #    config.bool = False
138 #    assert config.gc.newoption == False
139
140 #def test_newoption_add_in_config():
141 #    descr = make_description()
142 #    config = Config(descr)
143 #    config.bool = False
144 #    newoption = BoolOption('newoption', 'dummy twoo', default=False)
145 #    descr.add_child(newoption)
146 #    config.cfgimpl_update()
147 #    assert config.newoption == False
148 # ____________________________________________________________
149
150
151 def make_description_requires():
152     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
153     gcdummy = BoolOption('dummy', 'dummy', default=False)
154
155     floatoption = FloatOption('float', 'Test float option', default=2.3)
156
157     objspaceoption = ChoiceOption('objspace', 'Object space',
158                                   ('std', 'thunk'), 'std')
159     booloption = BoolOption('bool', 'Test boolean option', default=True)
160     intoption = IntOption('int', 'Test int option', default=0)
161     stroption = StrOption('str', 'Test string option', default="abc",
162                           requires=((intoption, 1, 'hidden'),))
163
164     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
165     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
166                               stroption, intoption])
167     return descr
168
169
170 def test_hidden_if_in():
171     descr = make_description_requires()
172     cfg = Config(descr)
173     setting = cfg.cfgimpl_get_settings()
174     cfg.read_write()
175     stroption = cfg.unwrap_from_path('str')
176     assert not 'hidden' in setting[stroption]
177     cfg.int = 1
178     raises(PropertiesOptionError, "cfg.str")
179     raises(PropertiesOptionError, 'cfg.str="uvw"')
180     assert 'hidden' in setting[stroption]
181
182
183 def test_hidden_if_in_with_group():
184     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
185     gcdummy = BoolOption('dummy', 'dummy', default=False)
186
187     floatoption = FloatOption('float', 'Test float option', default=2.3)
188
189     objspaceoption = ChoiceOption('objspace', 'Object space',
190                                   ('std', 'thunk'), 'std')
191     booloption = BoolOption('bool', 'Test boolean option', default=True)
192     intoption = IntOption('int', 'Test int option', default=0)
193     stroption = StrOption('str', 'Test string option', default="abc")
194     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption],
195                                 requires=((intoption, 1, 'hidden'),))
196     descr = OptionDescription('constraints', '', [gcgroup, booloption,
197                               objspaceoption, stroption, intoption])
198     cfg = Config(descr)
199     setting = cfg.cfgimpl_get_settings()
200     cfg.read_write()
201     assert not 'hidden' in setting[stroption]
202     cfg.int = 1
203     raises(PropertiesOptionError, "cfg.gc.name")
204
205
206 def test_disabled_with_group():
207     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
208     gcdummy = BoolOption('dummy', 'dummy', default=False)
209
210     floatoption = FloatOption('float', 'Test float option', default=2.3)
211
212     objspaceoption = ChoiceOption('objspace', 'Object space',
213                                   ('std', 'thunk'), 'std')
214     booloption = BoolOption('bool', 'Test boolean option', default=True)
215     intoption = IntOption('int', 'Test int option', default=0)
216     stroption = StrOption('str', 'Test string option', default="abc")
217     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption],
218                                 requires=((intoption, 1, 'disabled'),))
219     descr = OptionDescription('constraints', '', [gcgroup, booloption,
220                               objspaceoption, stroption, intoption])
221     cfg = Config(descr)
222     cfg.read_write()
223     assert cfg.gc.name
224     cfg.int = 1
225     raises(PropertiesOptionError, "cfg.gc.name")
226 #____________________________________________________________
227
228
229 def make_description_callback():
230     gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
231     gcdummy = BoolOption('dummy', 'dummy')
232     objspaceoption = ChoiceOption('objspace', 'Object space',
233                                   ('std', 'thunk'), 'std')
234     booloption = BoolOption('bool', 'Test boolean option', default=True)
235     intoption = IntOption('int', 'Test int option', default=0)
236     floatoption = FloatOption('float', 'Test float option', default=2.3)
237     stroption = StrOption('str', 'Test string option', default="abc")
238     boolop = BoolOption('boolop', 'Test boolean option op', default=True)
239     wantref_option = BoolOption('wantref', 'Test requires', default=False,
240                                 requires=((boolop, True, 'hidden'),))
241     wantframework_option = BoolOption('wantframework', 'Test requires',
242                                       default=False,
243                                       requires=((boolop, True, 'hidden'),))
244     gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
245     descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
246                               wantref_option, stroption,
247                               wantframework_option,
248                               intoption, boolop])
249     return descr
250
251
252 def test_has_callback():
253     descr = make_description_callback()
254     # here the owner is 'default'
255     config = Config(descr)
256     setting = config.cfgimpl_get_settings()
257     config.read_write()
258     config.bool = False
259     # because dummy has a callback
260     dummy = config.unwrap_from_path('gc.dummy')
261     setting.append('freeze')
262     setting[dummy].append('frozen')
263     raises(PropertiesOptionError, "config.gc.dummy = True")
264
265
266 def test_freeze_and_has_callback():
267     descr = make_description_callback()
268     config = Config(descr)
269     setting = config.cfgimpl_get_settings()
270     config.read_write()
271     config.bool = False
272     setting = config.cfgimpl_get_settings()
273     setting.append('freeze')
274     dummy = config.unwrap_from_path('gc.dummy')
275     setting[dummy].append('frozen')
276     raises(PropertiesOptionError, "config.gc.dummy = True")
277
278
279 def test_callback_master_and_slaves():
280     val1 = StrOption('val1', "", multi=True)
281     val2 = StrOption('val2', "", multi=True, callback=return_value)
282     interface1 = OptionDescription('val1', '', [val1, val2])
283     interface1.impl_set_group_type(groups.master)
284     maconfig = OptionDescription('rootconfig', '', [interface1])
285     cfg = Config(maconfig)
286     cfg.read_write()
287     assert cfg.val1.val1 == []
288     assert cfg.val1.val2 == []
289     #
290     cfg.val1.val1 = ['val1']
291     assert cfg.val1.val1 == ['val1']
292     assert cfg.val1.val2 == ['val']
293     #
294     cfg.val1.val1.append('val2')
295     assert cfg.val1.val1 == ['val1', 'val2']
296     assert cfg.val1.val2 == ['val', 'val']
297     #
298     cfg.val1.val1 = ['val1', 'val2', 'val3']
299     assert cfg.val1.val1 == ['val1', 'val2', 'val3']
300     assert cfg.val1.val2 == ['val', 'val', 'val']
301     #
302     cfg.val1.val1.pop(2)
303     assert cfg.val1.val1 == ['val1', 'val2']
304     assert cfg.val1.val2 == ['val', 'val']
305     #
306     cfg.val1.val2 = ['val2', 'val2']
307     assert cfg.val1.val2 == ['val2', 'val2']
308     #
309     cfg.val1.val1.append('val3')
310     assert cfg.val1.val2 == ['val2', 'val2', 'val']