transitive in apply_requires should only by apply if properties are same has testing...
[tiramisu.git] / test / test_requires.py
1 # coding: utf-8
2 from autopath import do_autopath
3 do_autopath()
4
5 from copy import copy
6 from tiramisu.setting import groups
7 from tiramisu import setting
8 setting.expires_time = 1
9 from tiramisu.option import IPOption, OptionDescription, BoolOption, IntOption, StrOption
10 from tiramisu.config import Config
11 from tiramisu.error import PropertiesOptionError, RequirementError
12 from py.test import raises
13
14
15 def test_requires():
16     a = BoolOption('activate_service', '', True)
17     b = IPOption('ip_address_service', '',
18                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
19     od = OptionDescription('service', '', [a, b])
20     c = Config(od)
21     c.read_write()
22     c.ip_address_service
23     c.activate_service = False
24     props = []
25     try:
26         c.ip_address_service
27     except PropertiesOptionError as err:
28         props = err.proptype
29     assert props == ['disabled']
30     c.activate_service = True
31     c.ip_address_service
32
33
34 def test_requires_with_requires():
35     a = BoolOption('activate_service', '', True)
36     b = IPOption('ip_address_service', '',
37                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
38     od = OptionDescription('service', '', [a, b])
39     c = Config(od)
40     c.read_write()
41     c.cfgimpl_get_settings()[b].append('test')
42     c.ip_address_service
43     c.activate_service = False
44     props = []
45     try:
46         c.ip_address_service
47     except PropertiesOptionError as err:
48         props = err.proptype
49     assert props == ['disabled']
50     c.activate_service = True
51     c.ip_address_service
52
53
54 def test_requires_invalid():
55     a = BoolOption('activate_service', '', True)
56     a
57     raises(ValueError, "IPOption('ip_address_service', '', requires='string')")
58     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'unknown': True}])")
59     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False}])")
60     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'action': 'disabled'}])")
61     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'expected': False, 'action': 'disabled'}])")
62     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'inverse': 'string'}])")
63     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'transitive': 'string'}])")
64     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'same_action': 'string'}])")
65     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': 'string', 'expected': False, 'action': 'disabled'}])")
66     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'string', 'action': 'disabled'}])")
67
68
69 def test_requires_same_action():
70     a = BoolOption('activate_service', '', True)
71     b = BoolOption('activate_service_web', '', True,
72                    requires=[{'option': a, 'expected': False, 'action': 'new'}])
73
74     d = IPOption('ip_address_service_web', '',
75                  requires=[{'option': b, 'expected': False,
76                             'action': 'disabled', 'inverse': False,
77                             'transitive': True, 'same_action': False}])
78     od = OptionDescription('service', '', [a, b, d])
79     c = Config(od)
80     c.read_write()
81     c.cfgimpl_get_settings().append('new')
82     c.activate_service
83     c.activate_service_web
84     c.ip_address_service_web
85     c.activate_service = False
86     #
87     props = []
88     try:
89         c.activate_service_web
90     except PropertiesOptionError as err:
91         props = err.proptype
92     assert props == ['new']
93     #
94     props = []
95     try:
96         c.ip_address_service_web
97     except PropertiesOptionError as err:
98         props = err.proptype
99     assert props == ['disabled']
100
101
102 def test_multiple_requires():
103     a = StrOption('activate_service', '')
104     b = IPOption('ip_address_service', '',
105                  requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'},
106                            {'option': a, 'expected': 'ok', 'action': 'disabled'}])
107     od = OptionDescription('service', '', [a, b])
108     c = Config(od)
109     c.read_write()
110     c.ip_address_service
111     c.activate_service = 'yes'
112     props = []
113     try:
114         c.ip_address_service
115     except PropertiesOptionError as err:
116         props = err.proptype
117     assert props == ['disabled']
118
119     c.activate_service = 'ok'
120     props = []
121     try:
122         c.ip_address_service
123     except PropertiesOptionError as err:
124         props = err.proptype
125     assert props == ['disabled']
126
127     c.activate_service = 'no'
128     c.ip_address_service
129
130
131 def test_multiple_requires_cumulative():
132     a = StrOption('activate_service', '')
133     b = IPOption('ip_address_service', '',
134                  requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'},
135                            {'option': a, 'expected': 'yes', 'action': 'hidden'}])
136     od = OptionDescription('service', '', [a, b])
137     c = Config(od)
138     c.read_write()
139     c.ip_address_service
140     c.activate_service = 'yes'
141     props = []
142     try:
143         c.ip_address_service
144     except PropertiesOptionError as err:
145         props = err.proptype
146     assert set(props) == set(['hidden', 'disabled'])
147
148     c.activate_service = 'ok'
149     c.ip_address_service
150
151     c.activate_service = 'no'
152     c.ip_address_service
153
154
155 def test_multiple_requires_cumulative_inverse():
156     a = StrOption('activate_service', '')
157     b = IPOption('ip_address_service', '',
158                  requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True},
159                            {'option': a, 'expected': 'yes', 'action': 'hidden', 'inverse': True}])
160     od = OptionDescription('service', '', [a, b])
161     c = Config(od)
162     c.read_write()
163     props = []
164     try:
165         c.ip_address_service
166     except PropertiesOptionError as err:
167         props = err.proptype
168     assert set(props) == set(['hidden', 'disabled'])
169     c.activate_service = 'yes'
170     c.ip_address_service
171
172     c.activate_service = 'ok'
173     props = []
174     try:
175         c.ip_address_service
176     except PropertiesOptionError as err:
177         props = err.proptype
178     assert set(props) == set(['hidden', 'disabled'])
179
180     c.activate_service = 'no'
181     props = []
182     try:
183         c.ip_address_service
184     except PropertiesOptionError as err:
185         props = err.proptype
186     assert set(props) == set(['hidden', 'disabled'])
187
188
189 def test_multiple_requires_inverse():
190     a = StrOption('activate_service', '')
191     b = IPOption('ip_address_service', '',
192                  requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True},
193                            {'option': a, 'expected': 'ok', 'action': 'disabled', 'inverse': True}])
194     od = OptionDescription('service', '', [a, b])
195     c = Config(od)
196     c.read_write()
197     props = []
198     try:
199         c.ip_address_service
200     except PropertiesOptionError as err:
201         props = err.proptype
202     assert props == ['disabled']
203
204     c.activate_service = 'yes'
205     c.ip_address_service
206
207     c.activate_service = 'ok'
208     c.ip_address_service
209
210     c.activate_service = 'no'
211     props = []
212     try:
213         c.ip_address_service
214     except PropertiesOptionError as err:
215         props = err.proptype
216     assert props == ['disabled']
217
218
219 def test_requires_transitive():
220     a = BoolOption('activate_service', '', True)
221     b = BoolOption('activate_service_web', '', True,
222                    requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
223
224     d = IPOption('ip_address_service_web', '',
225                  requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
226     od = OptionDescription('service', '', [a, b, d])
227     c = Config(od)
228     c.read_write()
229     c.activate_service
230     c.activate_service_web
231     c.ip_address_service_web
232     c.activate_service = False
233     #
234     props = []
235     try:
236         c.activate_service_web
237     except PropertiesOptionError as err:
238         props = err.proptype
239     assert props == ['disabled']
240     #
241     props = []
242     try:
243         c.ip_address_service_web
244     except PropertiesOptionError as err:
245         props = err.proptype
246     assert props == ['disabled']
247
248
249 def test_requires_transitive_owner():
250     a = BoolOption('activate_service', '', True)
251     b = BoolOption('activate_service_web', '', True,
252                    requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
253
254     d = IPOption('ip_address_service_web', '',
255                  requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
256     od = OptionDescription('service', '', [a, b, d])
257     c = Config(od)
258     c.read_write()
259     c.activate_service
260     c.activate_service_web
261     c.ip_address_service_web
262     #no more default value
263     c.ip_address_service_web = '1.1.1.1'
264     c.activate_service = False
265     props = []
266     try:
267         c.ip_address_service_web
268     except PropertiesOptionError as err:
269         props = err.proptype
270     assert props == ['disabled']
271
272
273 def test_requires_transitive_bis():
274     a = BoolOption('activate_service', '', True)
275     abis = BoolOption('activate_service_bis', '', True)
276     b = BoolOption('activate_service_web', '', True,
277                    requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}])
278
279     d = IPOption('ip_address_service_web', '',
280                  requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
281     od = OptionDescription('service', '', [a, abis, b, d])
282     c = Config(od)
283     c.read_write()
284     #
285     c.activate_service_web
286     c.ip_address_service_web
287     c.activate_service = False
288     #
289     props = []
290     try:
291         c.activate_service_web
292     except PropertiesOptionError as err:
293         props = err.proptype
294     assert props == ['disabled']
295     #
296     props = []
297     try:
298         c.ip_address_service_web
299     except PropertiesOptionError as err:
300         props = err.proptype
301     assert props == ['disabled']
302
303
304 def test_requires_transitive_hidden_disabled():
305     a = BoolOption('activate_service', '', True)
306     b = BoolOption('activate_service_web', '', True,
307                    requires=[{'option': a, 'expected': False, 'action': 'hidden'}])
308     d = IPOption('ip_address_service_web', '',
309                  requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
310     od = OptionDescription('service', '', [a, b, d])
311     c = Config(od)
312     c.read_write()
313     c.activate_service
314     c.activate_service_web
315     c.ip_address_service_web
316     c.activate_service = False
317     #
318     props = []
319     try:
320         c.activate_service_web
321     except PropertiesOptionError as err:
322         props = err.proptype
323     assert props == ['hidden']
324     raises(RequirementError, 'c.ip_address_service_web')
325
326
327 def test_requires_not_transitive():
328     a = BoolOption('activate_service', '', True)
329     b = BoolOption('activate_service_web', '', True,
330                    requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
331     d = IPOption('ip_address_service_web', '',
332                  requires=[{'option': b, 'expected': False,
333                             'action': 'disabled', 'transitive': False}])
334     od = OptionDescription('service', '', [a, b, d])
335     c = Config(od)
336     c.read_write()
337     c.activate_service
338     c.activate_service_web
339     c.ip_address_service_web
340     c.activate_service = False
341     #
342     props = []
343     try:
344         c.activate_service_web
345     except PropertiesOptionError as err:
346         props = err.proptype
347     assert props == ['disabled']
348     #
349     c.ip_address_service_web
350
351
352 def test_requires_not_transitive_not_same_action():
353     a = BoolOption('activate_service', '', True)
354     b = BoolOption('activate_service_web', '', True,
355                    requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
356     d = IPOption('ip_address_service_web', '',
357                  requires=[{'option': b, 'expected': False,
358                             'action': 'hidden', 'transitive': False}])
359     od = OptionDescription('service', '', [a, b, d])
360     c = Config(od)
361     c.read_write()
362     c.activate_service
363     c.activate_service_web
364     c.ip_address_service_web
365     c.activate_service = False
366     #
367     props = []
368     try:
369         c.activate_service_web
370     except PropertiesOptionError as err:
371         props = err.proptype
372     assert props == ['disabled']
373     #
374     raises(RequirementError, "c.ip_address_service_web")
375
376
377 def test_requires_None():
378     a = BoolOption('activate_service', '')
379     b = IPOption('ip_address_service', '',
380                  requires=[{'option': a, 'expected': None, 'action': 'disabled'}])
381     od = OptionDescription('service', '', [a, b])
382     c = Config(od)
383     c.read_write()
384     props = []
385     try:
386         c.ip_address_service
387     except PropertiesOptionError as err:
388         props = err.proptype
389     assert props == ['disabled']
390     c.activate_service = False
391     c.ip_address_service
392
393
394 def test_requires_multi_disabled():
395     a = BoolOption('activate_service', '')
396     b = IntOption('num_service', '')
397     c = IPOption('ip_address_service', '',
398                  requires=[{'option': a, 'expected': True, 'action': 'disabled'},
399                            {'option': b, 'expected': 1, 'action': 'disabled'}])
400     od = OptionDescription('service', '', [a, b, c])
401     c = Config(od)
402     c.read_write()
403
404     c.ip_address_service
405
406     c.activate_service = True
407     props = []
408     try:
409         c.ip_address_service
410     except PropertiesOptionError as err:
411         props = err.proptype
412     assert props == ['disabled']
413
414     c.activate_service = False
415     c.ip_address_service
416
417     c.num_service = 1
418     props = []
419     try:
420         c.ip_address_service
421     except PropertiesOptionError as err:
422         props = err.proptype
423     assert props == ['disabled']
424
425     c.activate_service = True
426     props = []
427     try:
428         c.ip_address_service
429     except PropertiesOptionError as err:
430         props = err.proptype
431     assert props == ['disabled']
432
433
434 def test_requires_multi_disabled_inverse():
435     a = BoolOption('activate_service', '')
436     b = IntOption('num_service', '')
437     c = IPOption('ip_address_service', '',
438                  requires=[{'option': a, 'expected': True,
439                             'action': 'disabled', 'inverse': True},
440                            {'option': b, 'expected': 1,
441                             'action': 'disabled', 'inverse': True}])
442     od = OptionDescription('service', '', [a, b, c])
443     c = Config(od)
444     c.read_write()
445
446     props = []
447     try:
448         c.ip_address_service
449     except PropertiesOptionError as err:
450         props = err.proptype
451     assert props == ['disabled']
452
453     c.activate_service = True
454     props = []
455     try:
456         c.ip_address_service
457     except PropertiesOptionError as err:
458         props = err.proptype
459     assert props == ['disabled']
460
461     c.activate_service = False
462     props = []
463     try:
464         c.ip_address_service
465     except PropertiesOptionError as err:
466         props = err.proptype
467     assert props == ['disabled']
468
469     c.num_service = 1
470     props = []
471     try:
472         c.ip_address_service
473     except PropertiesOptionError as err:
474         props = err.proptype
475     assert props == ['disabled']
476
477     c.activate_service = True
478     c.ip_address_service
479
480
481 def test_requires_multi_disabled_2():
482     a = BoolOption('a', '')
483     b = BoolOption('b', '')
484     c = BoolOption('c', '')
485     d = BoolOption('d', '')
486     e = BoolOption('e', '')
487     f = BoolOption('f', '')
488     g = BoolOption('g', '')
489     h = BoolOption('h', '')
490     i = BoolOption('i', '')
491     j = BoolOption('j', '')
492     k = BoolOption('k', '')
493     l = BoolOption('l', '')
494     m = BoolOption('m', '')
495     list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m]
496     requires = []
497     for boo in list_bools:
498         requires.append({'option': boo, 'expected': True, 'action': 'disabled'})
499     z = IPOption('z', '', requires=requires)
500     y = copy(list_bools)
501     y.append(z)
502     od = OptionDescription('service', '', y)
503     cfg = Config(od)
504     cfg.read_write()
505
506     cfg.z
507     for boo in list_bools:
508         setattr(cfg, boo._name, True)
509         props = []
510         try:
511             cfg.z
512         except PropertiesOptionError as err:
513             props = err.proptype
514         assert props == ['disabled']
515     for boo in list_bools:
516         setattr(cfg, boo._name, False)
517         if boo == m:
518             cfg.z
519         else:
520             props = []
521             try:
522                 cfg.z
523             except PropertiesOptionError as err:
524                 props = err.proptype
525             assert props == ['disabled']
526
527
528 def test_requires_multi_disabled_inverse_2():
529     a = BoolOption('a', '')
530     b = BoolOption('b', '')
531     c = BoolOption('c', '')
532     d = BoolOption('d', '')
533     e = BoolOption('e', '')
534     f = BoolOption('f', '')
535     g = BoolOption('g', '')
536     h = BoolOption('h', '')
537     i = BoolOption('i', '')
538     j = BoolOption('j', '')
539     k = BoolOption('k', '')
540     l = BoolOption('l', '')
541     m = BoolOption('m', '')
542     list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m]
543     requires = []
544     for boo in list_bools:
545         requires.append({'option': boo, 'expected': True, 'action': 'disabled',
546                          'inverse': True})
547     z = IPOption('z', '', requires=requires)
548     y = copy(list_bools)
549     y.append(z)
550     od = OptionDescription('service', '', y)
551     cfg = Config(od)
552     cfg.read_write()
553
554     props = []
555     try:
556         cfg.z
557     except PropertiesOptionError as err:
558         props = err.proptype
559     assert props == ['disabled']
560     for boo in list_bools:
561         setattr(cfg, boo._name, True)
562         if boo == m:
563             cfg.z
564         else:
565             props = []
566             try:
567                 cfg.z
568             except PropertiesOptionError as err:
569                 props = err.proptype
570             assert props == ['disabled']
571     for boo in list_bools:
572         setattr(cfg, boo._name, False)
573         props = []
574         try:
575             cfg.z
576         except PropertiesOptionError as err:
577             props = err.proptype
578         assert props == ['disabled']
579
580
581 def test_requires_requirement_append():
582     a = BoolOption('activate_service', '', True)
583     b = IPOption('ip_address_service', '',
584                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
585     od = OptionDescription('service', '', [a, b])
586     c = Config(od)
587     c.read_write()
588     str(c.cfgimpl_get_settings())
589     str(c.cfgimpl_get_settings()[b])
590     raises(ValueError, 'c.cfgimpl_get_settings()[b].append("disabled")')
591     c.activate_service = False
592     # disabled is now set, test to remove disabled before store in storage
593     c.cfgimpl_get_settings()[b].append("test")
594
595
596 def test_requires_different_inverse():
597     a = BoolOption('activate_service', '', True)
598     a
599     raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': True, 'action': 'disabled', 'inverse': False}])")
600
601
602 def test_requires_recursive_path():
603     a = BoolOption('activate_service', '', True)
604     b = IPOption('ip_address_service', '',
605                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
606     od1 = OptionDescription('service', '', [a, b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
607     od = OptionDescription('base', '', [od1])
608     c = Config(od)
609     c.read_write()
610     raises(RequirementError, 'c.service.a')
611
612
613 def test_get_properties_with_None_path():
614     a = BoolOption('activate_service', '', True)
615     b = IPOption('ip_address_service', '',
616                  requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
617     od1 = OptionDescription('service', '', [a, b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
618     od = OptionDescription('base', '', [od1])
619     c = Config(od)
620     c.read_write()
621     raises(ValueError, "c.cfgimpl_get_settings()._getproperties(a)")
622
623
624 def test_set_item():
625     a = BoolOption('activate_service', '', True)
626     b = IPOption('ip_address_service', '')
627     od1 = OptionDescription('service', '', [a, b])
628     od = OptionDescription('base', '', [od1])
629     c = Config(od)
630     c.read_write()
631     raises(ValueError, 'c.cfgimpl_get_settings()[a] = ("test",)')
632
633
634 def test_optiondescription_requires():
635     a = BoolOption('activate_service', '', True)
636     b = BoolOption('ip_address_service', '', multi=True)
637     a, b
638     OptionDescription('service', '', [b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
639
640
641 def test_optiondescription_requires_multi():
642     a = BoolOption('activate_service', '', True)
643     b = IPOption('ip_address_service', '', multi=True)
644     a, b
645     raises(ValueError, "OptionDescription('service', '', [a], requires=[{'option': b, 'expected': False, 'action': 'disabled'}])")
646
647
648 def test_properties_conflict():
649     a = BoolOption('activate_service', '', True)
650     a
651     raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
652     raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
653
654
655 def test_master_slave_requires():
656     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
657     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True,
658                                    requires=[{'option': ip_admin_eth0, 'expected': '192.168.1.1', 'action': 'disabled'}])
659     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
660     interface1.impl_set_group_type(groups.master)
661     maconfig = OptionDescription('toto', '', [interface1])
662     cfg = Config(maconfig)
663     cfg.read_write()
664     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
665     assert cfg.ip_admin_eth0.ip_admin_eth0 == []
666     cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.2')
667     assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None]
668     assert cfg.ip_admin_eth0.ip_admin_eth0 == ['192.168.1.2']
669     cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
670     assert cfg.ip_admin_eth0.netmask_admin_eth0[0] is None
671     raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]")
672     cfg.ip_admin_eth0.ip_admin_eth0[1] = '192.168.1.2'
673     assert cfg.ip_admin_eth0.netmask_admin_eth0[1] is None
674     cfg.ip_admin_eth0.netmask_admin_eth0[1] = '255.255.255.255'
675     assert cfg.ip_admin_eth0.netmask_admin_eth0[1] == '255.255.255.255'
676     cfg.ip_admin_eth0.ip_admin_eth0[1] = '192.168.1.1'
677     raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]")
678
679
680 def test_master_slave_requires_no_master():
681     activate = BoolOption('activate', "Activer l'accès au réseau", True)
682     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
683     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True,
684                                    requires=[{'option': activate, 'expected': False, 'action': 'disabled'}])
685     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
686     interface1.impl_set_group_type(groups.master)
687     maconfig = OptionDescription('toto', '', [activate, interface1])
688     cfg = Config(maconfig)
689     cfg.read_write()
690     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
691     assert cfg.ip_admin_eth0.ip_admin_eth0 == []
692     cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.2')
693     assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None]
694     assert cfg.ip_admin_eth0.netmask_admin_eth0[0] is None
695     assert cfg.ip_admin_eth0.ip_admin_eth0 == ['192.168.1.2']
696     cfg.activate = False
697     cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
698     assert cfg.ip_admin_eth0.ip_admin_eth0 == ['192.168.1.2', '192.168.1.1']
699     raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0")
700     raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[0]")
701     raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]")
702     cfg.activate = True
703     assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None, None]
704     cfg.ip_admin_eth0.netmask_admin_eth0 = [None, '255.255.255.255']
705     assert cfg.ip_admin_eth0.netmask_admin_eth0[1] == '255.255.255.255'
706     cfg.activate = False
707     raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0")
708     raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[0]")
709     raises(PropertiesOptionError, "cfg.ip_admin_eth0.netmask_admin_eth0[1]")