add tests
[tiramisu.git] / test / test_parsing_group.py
1 # coding: utf-8
2 import autopath
3 from tiramisu.setting import groups, owners
4 from tiramisu.config import Config
5 from tiramisu.option import ChoiceOption, BoolOption, IntOption, \
6     StrOption, OptionDescription
7 from tiramisu.error import SlaveError
8
9 from py.test import raises
10
11
12 def make_description():
13     numero_etab = StrOption('numero_etab', "identifiant de l'établissement")
14     nom_machine = StrOption('nom_machine', "nom de la machine", default="eoleng")
15     nombre_interfaces = IntOption('nombre_interfaces', "nombre d'interfaces à activer",
16                                   default=1)
17     activer_proxy_client = BoolOption('activer_proxy_client', "utiliser un proxy",
18                                       default=False)
19     mode_conteneur_actif = BoolOption('mode_conteneur_actif', "le serveur est en mode conteneur",
20                                       default=False)
21     adresse_serveur_ntp = StrOption('serveur_ntp', "adresse serveur ntp", multi=True)
22     time_zone = ChoiceOption('time_zone', 'fuseau horaire du serveur',
23                              ('Paris', 'Londres'), 'Paris')
24
25     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé")
26     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
27
28     master = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
29     interface1 = OptionDescription('interface1', '', [master])
30     interface1.impl_set_group_type(groups.family)
31
32     general = OptionDescription('general', '', [numero_etab, nom_machine,
33                                 nombre_interfaces, activer_proxy_client,
34                                 mode_conteneur_actif, adresse_serveur_ntp,
35                                 time_zone])
36     general.impl_set_group_type(groups.family)
37     creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1])
38     descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole])
39     return descr
40
41
42 def test_base_config():
43     descr = make_description()
44     config = Config(descr)
45     config.read_write()
46     assert config.creole.general.activer_proxy_client is False
47     assert config.creole.general.nom_machine == "eoleng"
48     assert config.find_first(byname='nom_machine', type_='value') == "eoleng"
49     result = {'general.numero_etab': None, 'general.nombre_interfaces': 1,
50               'general.serveur_ntp': [], 'interface1.ip_admin_eth0.ip_admin_eth0': None,
51               'general.mode_conteneur_actif': False, 'general.time_zone': 'Paris',
52               'interface1.ip_admin_eth0.netmask_admin_eth0': None, 'general.nom_machine':
53               'eoleng', 'general.activer_proxy_client': False}
54     assert config.creole.make_dict() == result
55     result = {'serveur_ntp': [], 'mode_conteneur_actif': False,
56               'ip_admin_eth0': None, 'time_zone': 'Paris', 'numero_etab': None,
57               'netmask_admin_eth0': None, 'nom_machine': 'eoleng', 'activer_proxy_client':
58               False, 'nombre_interfaces': 1}
59     assert config.creole.make_dict(flatten=True) == result
60
61
62 def test_make_dict_filter():
63     descr = make_description()
64     config = Config(descr)
65     config.read_write()
66     subresult = {'numero_etab': None, 'nombre_interfaces': 1,
67                  'serveur_ntp': [], 'mode_conteneur_actif': False,
68                  'time_zone': 'Paris', 'nom_machine': 'eoleng',
69                  'activer_proxy_client': False}
70     result = {}
71     for key, value in subresult.items():
72         result['general.' + key] = value
73     assert config.creole.make_dict(withoption='numero_etab') == result
74     raises(AttributeError, "config.creole.make_dict(withoption='numero_etab', withvalue='toto')")
75     assert config.creole.make_dict(withoption='numero_etab', withvalue=None) == result
76     assert config.creole.general.make_dict(withoption='numero_etab') == subresult
77
78
79 def test_get_group_type():
80     descr = make_description()
81     config = Config(descr)
82     config.read_write()
83     grp = config.unwrap_from_path('creole.general')
84     assert grp.impl_get_group_type() == groups.family
85     assert grp.impl_get_group_type() == 'family'
86     assert isinstance(grp.impl_get_group_type(), groups.GroupType)
87     raises(TypeError, 'grp.impl_set_group_type(groups.default)')
88
89
90 def test_iter_on_groups():
91     descr = make_description()
92     config = Config(descr)
93     config.read_write()
94     result = list(config.creole.iter_groups(group_type=groups.family))
95     group_names = [res[0] for res in result]
96     assert group_names == ['general', 'interface1']
97     for i in config.creole.iter_groups(group_type=groups.family):
98         #test StopIteration
99         break
100
101
102 def test_iter_on_groups_props():
103     descr = make_description()
104     config = Config(descr)
105     config.read_write()
106     config.cfgimpl_get_settings()[descr.creole.interface1].append('disabled')
107     result = list(config.creole.iter_groups(group_type=groups.family))
108     group_names = [res[0] for res in result]
109     assert group_names == ['general']
110
111
112 def test_iter_on_empty_group():
113     config = Config(OptionDescription("name", "descr", []))
114     config.read_write()
115     result = list(config.iter_groups())
116     assert result == []
117     for i in config.iter_groups():
118         pass
119     for i in config:
120         pass
121     assert [] == list(config)
122
123
124 def test_iter_not_group():
125     config = Config(OptionDescription("name", "descr", []))
126     config.read_write()
127     raises(TypeError, "list(config.iter_groups(group_type='family'))")
128
129
130 def test_groups_with_master():
131     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
132     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
133     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
134     interface1.impl_set_group_type(groups.master)
135     assert interface1.impl_get_group_type() == groups.master
136
137
138 def test_groups_with_master_in_config():
139     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
140     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
141     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
142     interface1.impl_set_group_type(groups.master)
143     Config(interface1)
144     assert interface1.impl_get_group_type() == groups.master
145
146
147 def test_allowed_groups():
148     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
149     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
150     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
151     raises(ValueError, "interface1.impl_set_group_type('toto')")
152
153
154 def test_master_not_valid_name():
155     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
156     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
157     invalid_group = OptionDescription('interface1', '', [ip_admin_eth0, netmask_admin_eth0])
158     raises(ValueError, "invalid_group.impl_set_group_type(groups.master)")
159
160
161 def test_sub_group_in_master_group():
162     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
163     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
164     subgroup = OptionDescription("subgroup", '', [])
165     invalid_group = OptionDescription('ip_admin_eth0', '', [subgroup, ip_admin_eth0, netmask_admin_eth0])
166     raises(ValueError, "invalid_group.impl_set_group_type(groups.master)")
167
168
169 def test_group_always_has_multis():
170     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
171     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
172     group = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
173     raises(ValueError, "group.impl_set_group_type(groups.master)")
174
175
176 #____________________________________________________________
177 def test_values_with_master_and_slaves():
178     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
179     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
180     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
181     interface1.impl_set_group_type(groups.master)
182     maconfig = OptionDescription('toto', '', [interface1])
183     cfg = Config(maconfig)
184     cfg.read_write()
185     owner = cfg.cfgimpl_get_settings().getowner()
186     assert interface1.impl_get_group_type() == groups.master
187     assert cfg.getowner(ip_admin_eth0) == owners.default
188     assert cfg.getowner(netmask_admin_eth0) == owners.default
189     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
190     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
191     assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"]
192     assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None]
193     assert cfg.getowner(ip_admin_eth0) == owner
194     assert cfg.getowner(netmask_admin_eth0) == owners.default
195     cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.147"]
196     raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.append(None)')
197     raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.pop(0)')
198
199
200 def test_reset_values_with_master_and_slaves():
201     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
202     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
203     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
204     interface1.impl_set_group_type(groups.master)
205     maconfig = OptionDescription('toto', '', [interface1])
206     cfg = Config(maconfig)
207     cfg.read_write()
208     owner = cfg.cfgimpl_get_settings().getowner()
209     assert interface1.impl_get_group_type() == groups.master
210     assert cfg.getowner(ip_admin_eth0) == owners.default
211     assert cfg.getowner(netmask_admin_eth0) == owners.default
212     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
213     assert cfg.getowner(ip_admin_eth0) == owner
214     assert cfg.getowner(netmask_admin_eth0) == owners.default
215     del(cfg.ip_admin_eth0.ip_admin_eth0)
216     assert cfg.getowner(ip_admin_eth0) == owners.default
217     assert cfg.getowner(netmask_admin_eth0) == owners.default
218     assert cfg.ip_admin_eth0.ip_admin_eth0 == []
219     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
220
221
222 def test_values_with_master_and_slaves_slave():
223     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
224     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
225     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
226     interface1.impl_set_group_type(groups.master)
227     maconfig = OptionDescription('toto', '', [interface1])
228     cfg = Config(maconfig)
229     cfg.read_write()
230     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
231     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']")
232     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
233     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']
234     cfg.ip_admin_eth0.netmask_admin_eth0[0] = '255.255.255.0'
235     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']")
236     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = []")
237     del(cfg.ip_admin_eth0.netmask_admin_eth0)
238     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']
239     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
240     assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.255.0', None]
241     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']
242     raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.pop(1)')
243
244
245 def test_values_with_master_and_slaves_master():
246     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
247     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
248     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
249     interface1.impl_set_group_type(groups.master)
250     maconfig = OptionDescription('toto', '', [interface1])
251     cfg = Config(maconfig)
252     cfg.read_write()
253     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
254     cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145"]
255     cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.145"]
256     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']
257     raises(SlaveError, 'cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145"]')
258     assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.255.0', '255.255.255.0']
259     cfg.ip_admin_eth0.ip_admin_eth0.pop(1)
260     assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"]
261     assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.255.0']
262     del(cfg.ip_admin_eth0.ip_admin_eth0)
263     assert cfg.ip_admin_eth0.ip_admin_eth0 == []
264     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
265
266
267 def test_values_with_master_and_slaves_master_error():
268     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
269     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
270     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
271     interface1.impl_set_group_type(groups.master)
272     maconfig = OptionDescription('toto', '', [interface1])
273     cfg = Config(maconfig)
274     cfg.read_write()
275     cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.145"]
276     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']")
277     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0', '255.255.255.0']")
278     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']
279     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']")
280     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0', '255.255.255.0']")
281
282
283 def test_values_with_master_owner():
284     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
285     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
286     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
287     interface1.impl_set_group_type(groups.master)
288     maconfig = OptionDescription('toto', '', [interface1])
289     cfg = Config(maconfig)
290     cfg.read_write()
291     owner = cfg.cfgimpl_get_settings().getowner()
292     assert cfg.getowner(ip_admin_eth0) == owners.default
293     assert cfg.getowner(netmask_admin_eth0) == owners.default
294     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
295     assert cfg.getowner(ip_admin_eth0) == owner
296     assert cfg.getowner(netmask_admin_eth0) == owners.default
297     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
298     assert cfg.getowner(ip_admin_eth0) == owner
299     assert cfg.getowner(netmask_admin_eth0) == owners.default
300
301
302 def test_values_with_master_disabled():
303     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
304     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
305     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
306     interface1.impl_set_group_type(groups.master)
307     maconfig = OptionDescription('toto', '', [interface1])
308     cfg = Config(maconfig)
309     cfg.read_write()
310     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
311     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
312     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
313     cfg.ip_admin_eth0.netmask_admin_eth0 = ["192.168.230.145"]
314     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
315     del(cfg.ip_admin_eth0.netmask_admin_eth0)
316     cfg.cfgimpl_get_settings()[netmask_admin_eth0].append('disabled')
317     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
318     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
319
320     #delete with value in disabled var
321     cfg.cfgimpl_get_settings()[netmask_admin_eth0].remove('disabled')
322     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
323     cfg.ip_admin_eth0.netmask_admin_eth0 = ["192.168.230.145"]
324     cfg.cfgimpl_get_settings()[netmask_admin_eth0].append('disabled')
325     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
326
327     #append with value in disabled var
328     cfg.cfgimpl_get_settings()[netmask_admin_eth0].remove('disabled')
329     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
330     cfg.ip_admin_eth0.netmask_admin_eth0 = ["192.168.230.145"]
331     cfg.cfgimpl_get_settings()[netmask_admin_eth0].append('disabled')
332     cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.230.43')
333
334
335 def test_multi_insert():
336     var = StrOption('var', '', ['ok'], multi=True)
337     od = OptionDescription('od', '', [var])
338     c = Config(od)
339     c.read_write()
340     assert c.var == ['ok']
341     assert c.getowner(var) == owners.default
342     c.var.insert(0, 'nok')
343     assert c.var == ['nok', 'ok']
344     assert c.getowner(var) != owners.default
345
346
347 def test_multi_insert_master():
348     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
349     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
350     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
351     interface1.impl_set_group_type(groups.master)
352     maconfig = OptionDescription('toto', '', [interface1])
353     cfg = Config(maconfig)
354     cfg.read_write()
355     raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.insert(0, 'nok')")
356     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.insert(0, 'nok')")
357
358
359 def test_multi_sort():
360     var = StrOption('var', '', ['ok', 'nok'], multi=True)
361     od = OptionDescription('od', '', [var])
362     c = Config(od)
363     c.read_write()
364     assert c.var == ['ok', 'nok']
365     assert c.getowner(var) == owners.default
366     c.var.sort()
367     assert c.var == ['nok', 'ok']
368     assert c.getowner(var) != owners.default
369
370
371 def test_multi_sort_master():
372     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
373     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
374     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
375     interface1.impl_set_group_type(groups.master)
376     maconfig = OptionDescription('toto', '', [interface1])
377     cfg = Config(maconfig)
378     cfg.read_write()
379     raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.sort()")
380     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.sort()")
381
382
383 def test_multi_reverse():
384     var = StrOption('var', '', ['ok', 'nok'], multi=True)
385     od = OptionDescription('od', '', [var])
386     c = Config(od)
387     c.read_write()
388     assert c.var == ['ok', 'nok']
389     assert c.getowner(var) == owners.default
390     c.var.reverse()
391     assert c.var == ['nok', 'ok']
392     assert c.getowner(var) != owners.default
393
394
395 def test_multi_reverse_master():
396     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
397     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
398     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
399     interface1.impl_set_group_type(groups.master)
400     maconfig = OptionDescription('toto', '', [interface1])
401     cfg = Config(maconfig)
402     cfg.read_write()
403     raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.reverse()")
404     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.reverse()")
405
406
407 def test_multi_extend():
408     var = StrOption('var', '', ['ok', 'nok'], multi=True)
409     od = OptionDescription('od', '', [var])
410     c = Config(od)
411     c.read_write()
412     assert c.var == ['ok', 'nok']
413     assert c.getowner(var) == owners.default
414     c.var.extend(['pok'])
415     assert c.var == ['ok', 'nok', 'pok']
416     assert c.getowner(var) != owners.default
417
418
419 def test_multi_extend_master():
420     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
421     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
422     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
423     interface1.impl_set_group_type(groups.master)
424     maconfig = OptionDescription('toto', '', [interface1])
425     cfg = Config(maconfig)
426     cfg.read_write()
427     raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.extend(['ok'])")
428     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.extend(['ok'])")
429
430
431 def test_multi_non_valid_value():
432     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
433     maconfig = OptionDescription('toto', '', [ip_admin_eth0])
434     cfg = Config(maconfig)
435     cfg.read_write()
436     cfg.ip_admin_eth0 = ['a']
437     raises(ValueError, 'cfg.ip_admin_eth0[0] = 1')