# coding: utf-8
from .autopath import do_autopath
do_autopath()

from copy import copy
from tiramisu.i18n import _
from tiramisu.setting import groups
from tiramisu import setting
setting.expires_time = 1
from tiramisu import IPOption, OptionDescription, BoolOption, IntOption, StrOption, \
                     MasterSlaves, Config, getapi
from tiramisu.error import PropertiesOptionError, RequirementError
from py.test import raises


def test_properties():
    a = BoolOption('activate_service', '', True)
    b = IPOption('ip_address_service', '', properties=('disabled',))
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    api.unrestraint.option('ip_address_service').property.pop('disabled')
    api.option('ip_address_service').value.get()
    api.unrestraint.option('ip_address_service').property.add('disabled')
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    # pop twice
    api.unrestraint.option('ip_address_service').property.pop('disabled')
    api.unrestraint.option('ip_address_service').property.pop('disabled')


def test_requires():
    a = BoolOption('activate_service', '', True)
    b = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('ip_address_service').value.get()
    api.option('activate_service').value.set(False)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    api.option('activate_service').value.set(True)
    api.option('ip_address_service').value.get()


def test_requires_with_requires():
    a = BoolOption('activate_service', '', True)
    b = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('ip_address_service').property.add('test')
    api.option('ip_address_service').value.get()
    api.option('activate_service').value.set(False)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    api.option('activate_service').value.set(True)
    api.option('ip_address_service').value.get()


def test_requires_invalid():
    a = BoolOption('activate_service', '', True)
    a
    raises(ValueError, "IPOption('ip_address_service', '', requires='string')")
    raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'unknown': True}])")
    raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False}])")
    raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'action': 'disabled'}])")
    raises(ValueError, "IPOption('ip_address_service', '', requires=[{'expected': False, 'action': 'disabled'}])")
    raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'inverse': 'string'}])")
    raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'transitive': 'string'}])")
    raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'same_action': 'string'}])")
    raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': 'string', 'expected': False, 'action': 'disabled'}])")
    raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'string', 'action': 'disabled'}])")


def test_requires_same_action():
    activate_service = BoolOption('activate_service', '', True)
    activate_service_web = BoolOption('activate_service_web', '', True,
                                      requires=[{'option': activate_service, 'expected': False,
                                                 'action': 'new'}])

    ip_address_service_web = IPOption('ip_address_service_web', '',
                                      requires=[{'option': activate_service_web, 'expected': False,
                                                 'action': 'disabled', 'inverse': False,
                                                 'transitive': True, 'same_action': False}])
    od1 = OptionDescription('service', '', [activate_service, activate_service_web, ip_address_service_web])
    api = getapi(Config(od1))
    api.property.read_write()
    api.property.add('new')
    api.option('activate_service').value.get()
    api.option('activate_service_web').value.get()
    api.option('ip_address_service_web').value.get()
    api.option('activate_service').value.set(False)
    #
    props = []
    try:
        api.option('activate_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['new'])
    #
    props = []
    try:
        api.option('ip_address_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
        submsg = '"disabled" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')'
        assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', 'property', submsg))
        #access to cache
        assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', 'property', submsg))
    assert frozenset(props) == frozenset(['disabled'])


def test_multiple_requires():
    a = StrOption('activate_service', '')
    b = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'},
                           {'option': a, 'expected': 'ok', 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('ip_address_service').value.get()
    api.option('activate_service').value.set('yes')
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set('ok')
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set('no')
    api.option('ip_address_service').value.get()


def test_multiple_requires_cumulative():
    a = StrOption('activate_service', '')
    b = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'},
                           {'option': a, 'expected': 'yes', 'action': 'hidden'}])
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('ip_address_service').value.get()
    api.option('activate_service').value.set('yes')
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == set(['hidden', 'disabled'])

    api.option('activate_service').value.set('ok')
    api.option('ip_address_service').value.get()

    api.option('activate_service').value.set('no')
    api.option('ip_address_service').value.get()


def test_multiple_requires_cumulative_inverse():
    a = StrOption('activate_service', '')
    b = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True},
                           {'option': a, 'expected': 'yes', 'action': 'hidden', 'inverse': True}])
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == set(['hidden', 'disabled'])
    api.option('activate_service').value.set('yes')
    api.option('ip_address_service').value.get()

    api.option('activate_service').value.set('ok')
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == set(['hidden', 'disabled'])

    api.option('activate_service').value.set('no')
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == set(['hidden', 'disabled'])


def test_multiple_requires_inverse():
    a = StrOption('activate_service', '')
    b = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True},
                           {'option': a, 'expected': 'ok', 'action': 'disabled', 'inverse': True}])
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set('yes')
    api.option('ip_address_service').value.get()

    api.option('activate_service').value.set('ok')
    api.option('ip_address_service').value.get()

    api.option('activate_service').value.set('no')
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_requires_transitive():
    a = BoolOption('activate_service', '', True)
    b = BoolOption('activate_service_web', '', True,
                   requires=[{'option': a, 'expected': False, 'action': 'disabled'}])

    d = IPOption('ip_address_service_web', '',
                 requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b, d])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('activate_service').value.get()
    api.option('activate_service_web').value.get()
    api.option('ip_address_service_web').value.get()
    api.option('activate_service').value.set(False)
    #
    props = []
    try:
        api.option('activate_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    #
    props = []
    try:
        api.option('ip_address_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_requires_transitive_owner():
    a = BoolOption('activate_service', '', True)
    b = BoolOption('activate_service_web', '', True,
                   requires=[{'option': a, 'expected': False, 'action': 'disabled'}])

    d = IPOption('ip_address_service_web', '',
                 requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b, d])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('activate_service').value.get()
    api.option('activate_service_web').value.get()
    api.option('ip_address_service_web').value.get()
    #no more default value
    api.option('ip_address_service_web').value.set('1.1.1.1')
    api.option('activate_service').value.set(False)
    props = []
    try:
        api.option('ip_address_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_requires_transitive_bis():
    a = BoolOption('activate_service', '', True)
    abis = BoolOption('activate_service_bis', '', True)
    b = BoolOption('activate_service_web', '', True,
                   requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}])

    d = IPOption('ip_address_service_web', '',
                 requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
    od = OptionDescription('service', '', [a, abis, b, d])
    api = getapi(Config(od))
    api.property.read_write()
    #
    api.option('activate_service_web').value.get()
    api.option('ip_address_service_web').value.get()
    api.option('activate_service').value.set(False)
    #
    props = []
    try:
        api.option('activate_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    #
    props = []
    try:
        api.option('ip_address_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_requires_transitive_hidden_permissive():
    a = BoolOption('activate_service', '', True)
    b = BoolOption('activate_service_web', '', True,
                   requires=[{'option': a, 'expected': False, 'action': 'hidden'}])
    d = IPOption('ip_address_service_web', '',
                 requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b, d])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('activate_service').value.get()
    api.option('ip_address_service_web').value.get()
    api.option('ip_address_service_web').value.get()
    api.option('activate_service').value.set(False)
    #
    api.option('ip_address_service_web').value.get()


def test_requires_transitive_hidden_disabled():
    a = BoolOption('activate_service', '', True)
    b = BoolOption('activate_service_web', '', True,
                   requires=[{'option': a, 'expected': False, 'action': 'hidden'}])
    d = IPOption('ip_address_service_web', '',
                 requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b, d])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('activate_service').value.get()
    api.option('activate_service_web').value.get()
    api.option('ip_address_service_web').value.get()
    api.option('activate_service').value.set(False)
    #
    props = []
    try:
        api.option('activate_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['hidden'])
    api.option('ip_address_service_web').value.get()


def test_requires_transitive_hidden_disabled_multiple():
    a = BoolOption('activate_service', '', True)
    b = BoolOption('activate_service_web', '', True,
                   requires=[{'option': a, 'expected': False, 'action': 'hidden'},
                             {'option': a, 'expected': False, 'action': 'disabled'}])
    d = IPOption('ip_address_service_web', '',
                 requires=[{'option': b, 'expected': False, 'action': 'mandatory'}])
    od = OptionDescription('service', '', [a, b, d])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('activate_service').value.get()
    api.option('activate_service_web').value.get()
    api.option('ip_address_service_web').value.get()
    api.option('activate_service').value.set(False)
    #
    props = []
    try:
        api.option('activate_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled', 'hidden'}
    req = None
    try:
        api.option('ip_address_service_web').value.get()
    except RequirementError as err:
        req = err
    assert req, "ip_address_service_web should raise RequirementError"
    assert str(req) == str(_('cannot access to option "{}" because required option "{}" has {} {}').format('ip_address_service_web', 'activate_service_web', 'property', '"disabled"'))
    api.permissive.set(frozenset())
    try:
        api.option('ip_address_service_web').value.get()
    except RequirementError as err:
        req = err
    assert req, "ip_address_service_web should raise RequirementError"
    assert str(req) == str(_('cannot access to option "{}" because required option "{}" has {} {}').format('ip_address_service_web', 'activate_service_web', 'properties', '"disabled" and "hidden"'))


def test_requires_not_transitive():
    a = BoolOption('activate_service', '', True)
    b = BoolOption('activate_service_web', '', True,
                   requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
    d = IPOption('ip_address_service_web', '',
                 requires=[{'option': b, 'expected': False,
                            'action': 'disabled', 'transitive': False}])
    od = OptionDescription('service', '', [a, b, d])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('activate_service').value.get()
    api.option('activate_service_web').value.get()
    api.option('ip_address_service_web').value.get()
    api.option('activate_service').value.set(False)
    #
    props = []
    try:
        api.option('activate_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    #
    api.option('ip_address_service_web').value.get()


def test_requires_not_transitive_not_same_action():
    a = BoolOption('activate_service', '', True)
    b = BoolOption('activate_service_web', '', True,
                   requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
    d = IPOption('ip_address_service_web', '',
                 requires=[{'option': b, 'expected': False,
                            'action': 'hidden', 'transitive': False}])
    od = OptionDescription('service', '', [a, b, d])
    api = getapi(Config(od))
    api.property.read_write()
    api.option('activate_service').value.get()
    api.option('activate_service_web').value.get()
    api.option('ip_address_service_web').value.get()
    api.option('activate_service').value.set(False)
    #
    props = []
    try:
        api.option('activate_service_web').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    #
    raises(RequirementError, "api.option('ip_address_service_web').value.get()")


def test_requires_None():
    a = BoolOption('activate_service', '')
    b = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': None, 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    api.option('activate_service').value.set(False)
    api.option('ip_address_service').value.get()


def test_requires_multi_disabled():
    a = BoolOption('activate_service', '')
    b = IntOption('num_service', '')
    c = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': True, 'action': 'disabled'},
                           {'option': b, 'expected': 1, 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b, c])
    api = getapi(Config(od))
    api.property.read_write()

    api.option('ip_address_service').value.get()

    api.option('activate_service').value.set(True)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set(False)
    api.option('ip_address_service').value.get()

    api.option('num_service').value.set(1)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set(True)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_requires_multi_disabled_new_format():
    a = BoolOption('activate_service', '')
    b = IntOption('num_service', '')
    c = IPOption('ip_address_service', '',
            requires=[{'expected': [{'option': a, 'value': True}, {'option': b, 'value': 1}], 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b, c])
    api = getapi(Config(od))
    api.property.read_write()

    api.option('ip_address_service').value.get()

    api.option('activate_service').value.set(True)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set(False)
    api.option('ip_address_service').value.get()

    api.option('num_service').value.set(1)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set(True)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_requires_unknown_operator():
    a = BoolOption('activate_service', '')
    b = IntOption('num_service', '')
    raises(ValueError, """IPOption('ip_address_service', '',
            requires=[{'expected': [{'option': a, 'value': True}, {'option': b, 'value': 1}],
            'action': 'disabled', 'operator': 'unknown'}])""")


def test_requires_keys():
    a = BoolOption('activate_service', '')
    b = IntOption('num_service', '')
    raises(ValueError, """IPOption('ip_address_service', '',
            requires=[{'expected': [{'option': a, 'value2': True}, {'option': b, 'value': 1}],
            'action': 'disabled', 'operator': 'and'}])""")


def test_requires_unvalid():
    a = BoolOption('activate_service', '')
    b = IntOption('num_service', '')
    raises(ValueError, """IPOption('ip_address_service', '',
            requires=[{'expected': [{'option': a, 'value': 'unvalid'}, {'option': b, 'value': 1}],
            'action': 'disabled', 'operator': 'and'}])""")


def test_requires_multi_disabled_new_format_and():
    a = BoolOption('activate_service', '')
    b = IntOption('num_service', '')
    c = IPOption('ip_address_service', '',
            requires=[{'expected': [{'option': a, 'value': True}, {'option': b, 'value': 1}], 'action': 'disabled', 'operator': 'and'}])
    od = OptionDescription('service', '', [a, b, c])
    api = getapi(Config(od))
    api.property.read_write()

    api.option('ip_address_service').value.get()

    api.option('activate_service').value.set(True)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert props == []

    api.option('activate_service').value.set(False)
    api.option('ip_address_service').value.get()

    api.option('num_service').value.set(1)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert props == []

    api.option('activate_service').value.set(True)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_requires_multi_disabled_new_format_and_2():
    a = BoolOption('activate_service', '')
    b = IntOption('num_service', '')
    c = IPOption('ip_address_service', '',
            requires=[{'expected': [{'option': a, 'value': True}, {'option': b, 'value': 1}], 'action': 'disabled', 'operator': 'and'},
                      {'expected': [{'option': a, 'value': False}, {'option': b, 'value': 1}], 'action': 'expert'}])
    od = OptionDescription('service', '', [a, b, c])
    api = getapi(Config(od))
    api.property.add('expert')
    api.property.read_write()
    api.option('ip_address_service').value.get()

    api.option('activate_service').value.set(True)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert props == []

    api.option('activate_service').value.set(False)
    api.option('num_service').value.set(1)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['expert'])

    api.option('activate_service').value.set(True)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled', 'expert'])


def test_requires_multi_disabled_inverse():
    a = BoolOption('activate_service', '')
    b = IntOption('num_service', '')
    c = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': True,
                            'action': 'disabled', 'inverse': True},
                           {'option': b, 'expected': 1,
                            'action': 'disabled', 'inverse': True}])
    od = OptionDescription('service', '', [a, b, c])
    api = getapi(Config(od))
    api.property.read_write()

    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set(True)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set(False)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('num_service').value.set(1)
    props = []
    try:
        api.option('ip_address_service').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])

    api.option('activate_service').value.set(True)
    api.option('ip_address_service').value.get()


def test_requires_multi_disabled_2():
    a = BoolOption('a', '')
    b = BoolOption('b', '')
    c = BoolOption('c', '')
    d = BoolOption('d', '')
    e = BoolOption('e', '')
    f = BoolOption('f', '')
    g = BoolOption('g', '')
    h = BoolOption('h', '')
    i = BoolOption('i', '')
    j = BoolOption('j', '')
    k = BoolOption('k', '')
    l = BoolOption('l', '')
    m = BoolOption('m', '')
    list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m]
    requires = []
    for boo in list_bools:
        requires.append({'option': boo, 'expected': True, 'action': 'disabled'})
    z = IPOption('z', '', requires=requires)
    y = copy(list_bools)
    y.append(z)
    od = OptionDescription('service', '', y)
    api = getapi(Config(od))
    api.property.read_write()

    api.option('z').value.get()
    for boo in list_bools:
        api.option(boo.impl_getname()).value.set(True)
        props = []
        try:
            api.option('z').value.get()
        except PropertiesOptionError as err:
            props = err.proptype
        assert frozenset(props) == frozenset(['disabled'])
    for boo in list_bools:
        api.option(boo.impl_getname()).value.set(False)
        if boo == m:
            api.option('z').value.get()
        else:
            props = []
            try:
                api.option('z').value.get()
            except PropertiesOptionError as err:
                props = err.proptype
            assert frozenset(props) == frozenset(['disabled'])


def test_requires_multi_disabled_inverse_2():
    a = BoolOption('a', '')
    b = BoolOption('b', '')
    c = BoolOption('c', '')
    d = BoolOption('d', '')
    e = BoolOption('e', '')
    f = BoolOption('f', '')
    g = BoolOption('g', '')
    h = BoolOption('h', '')
    i = BoolOption('i', '')
    j = BoolOption('j', '')
    k = BoolOption('k', '')
    l = BoolOption('l', '')
    m = BoolOption('m', '')
    list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m]
    requires = []
    for boo in list_bools:
        requires.append({'option': boo, 'expected': True, 'action': 'disabled',
                         'inverse': True})
    z = IPOption('z', '', requires=requires)
    y = copy(list_bools)
    y.append(z)
    od = OptionDescription('service', '', y)
    api = getapi(Config(od))
    api.property.read_write()

    props = []
    try:
        api.option('z').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    for boo in list_bools:
        api.option(boo.impl_getname()).value.set(True)
        if boo == m:
            api.option('z').value.get()
        else:
            props = []
            try:
                api.option('z').value.get()
            except PropertiesOptionError as err:
                props = err.proptype
            assert frozenset(props) == frozenset(['disabled'])
    for boo in list_bools:
        api.option(boo.impl_getname()).value.set(False)
        props = []
        try:
            api.option('z').value.get()
        except PropertiesOptionError as err:
            props = err.proptype
        assert frozenset(props) == frozenset(['disabled'])


def test_requires_requirement_append():
    a = BoolOption('activate_service', '', True)
    b = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    api.property.get()
    api.option('ip_address_service').property.get()
    raises(ValueError, "api.option('ip_address_service').property.add('disabled')")
    api.option('activate_service').value.set(False)
    # disabled is now set, test to remove disabled before store in storage
    api.unrestraint.option('ip_address_service').property.add("test")


def test_requires_different_inverse():
    a = BoolOption('activate_service', '', True)
    b = IPOption('ip_address_service', '', requires=[
        {'option': a, 'expected': True, 'action': 'disabled', 'inverse': True},
        {'option': a, 'expected': True, 'action': 'disabled', 'inverse': False}])
    od = OptionDescription('service', '', [a, b])
    api = getapi(Config(od))
    api.property.read_write()
    raises(PropertiesOptionError, "api.option('ip_address_service').value.get()")
    api.option('activate_service').value.set(False)
    raises(PropertiesOptionError, "api.option('ip_address_service').value.get()")


def test_requires_different_inverse_unicode():
    a = BoolOption('activate_service', '', True)
    d = StrOption('activate_other_service', '', 'val2')
    b = IPOption('ip_address_service', '', requires=[
        {'option': a, 'expected': True, 'action': 'disabled', 'inverse': True},
        {'option': d, 'expected': 'val1', 'action': 'disabled', 'inverse': False}])
    od = OptionDescription('service', '', [a, d, b])
    api = getapi(Config(od))
    api.property.read_write()
    assert api.option('ip_address_service').value.get() == None
    api.option('activate_service').value.set(False)
    raises(PropertiesOptionError, "api.option('ip_address_service').value.get()")
    api.option('activate_service').value.set(True)
    assert api.option('ip_address_service').value.get() == None
    api.option('activate_other_service').value.set('val1')
    raises(PropertiesOptionError, "api.option('ip_address_service').value.get()")
    api.option('activate_service').value.set(False)
    raises(PropertiesOptionError, "api.option('ip_address_service').value.get()")


def test_requires_recursive_path():
    a = BoolOption('activate_service', '', True)
    b = IPOption('ip_address_service', '',
                 requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
    od1 = OptionDescription('service', '', [a, b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
    od = OptionDescription('base', '', [od1])
    api = getapi(Config(od))
    api.property.read_write()
    raises(RequirementError, "api.option('service.a').value.get()")


def test_optiondescription_requires():
    a = BoolOption('activate_service', '', True)
    b = BoolOption('ip_address_service', '', multi=True)
    a, b
    OptionDescription('service', '', [b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}])


def test_optiondescription_requires_multi():
    a = BoolOption('activate_service', '', True)
    b = IPOption('ip_address_service', '', multi=True)
    a, b
    raises(ValueError, "OptionDescription('service', '', [a], requires=[{'option': b, 'expected': False, 'action': 'disabled'}])")


def test_properties_conflict():
    a = BoolOption('activate_service', '', True)
    a
    raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
    raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")


def test_master_slave_requires():
    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True,
                                   requires=[{'option': ip_admin_eth0, 'expected': '192.168.1.1', 'action': 'disabled'}])
    interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
    #interface1.impl_set_group_type(groups.master)
    maconfig = OptionDescription('toto', '', [interface1])
    api = getapi(Config(maconfig))
    api.property.read_write()
    assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
    api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2'])
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
    assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2']
    #
    api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1'])
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
    raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()")
    #
    api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.2'])
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() is None
    api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.255')
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.255'
    #
    api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1'])
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
    raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()")


def test_master_slave_requires_no_master():
    activate = BoolOption('activate', "Activer l'accès au réseau", True)
    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True,
                                   requires=[{'option': activate, 'expected': False, 'action': 'disabled'}])
    interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
    #interface1.impl_set_group_type(groups.master)
    maconfig = OptionDescription('toto', '', [activate, interface1])
    api = getapi(Config(maconfig))
    api.property.read_write()
    assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
    api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2'])
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
    assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2']
    api.option('activate').value.set(False)
    api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1'])
    assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2', '192.168.1.1']
    raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()")
    raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()")
    api.option('activate').value.set(True)
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() is None
    api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.255')
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.255'
    api.option('activate').value.set(False)
    raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()")
    raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()")