From bdbefb184ad372bd75be782898c0de8b61ae60cb Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 3 Jan 2018 21:22:05 +0100 Subject: [PATCH] test --- test/new_api/test_dereference.py | 334 ++++++++++++++++++++++++++ test/new_api/test_duplicate_config.py | 75 ++++++ test/new_api/test_state.py | 232 ++++++++++++++++++ 3 files changed, 641 insertions(+) create mode 100644 test/new_api/test_dereference.py create mode 100644 test/new_api/test_duplicate_config.py create mode 100644 test/new_api/test_state.py diff --git a/test/new_api/test_dereference.py b/test/new_api/test_dereference.py new file mode 100644 index 0000000..7b7e6bf --- /dev/null +++ b/test/new_api/test_dereference.py @@ -0,0 +1,334 @@ +# coding: utf-8 +from .autopath import do_autopath +do_autopath() + +from tiramisu import BoolOption, IntOption, StrOption, IPOption, NetmaskOption, \ + SymLinkOption, OptionDescription, DynOptionDescription, submulti, \ + Config, GroupConfig, MetaConfig, getapi +import weakref + + +IS_DEREFABLE = True + + +def funcname(*args, **kwargs): + return value + + +def test_deref_storage(): + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + c = Config(o) + w = weakref.ref(c.cfgimpl_get_values()._p_) + del(c) + assert w() is None + + +def test_deref_value(): + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + c = Config(o) + w = weakref.ref(c.cfgimpl_get_values()) + del(c) + assert w() is None + + +def test_deref_setting(): + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + c = Config(o) + w = weakref.ref(c.cfgimpl_get_settings()) + del(c) + assert w() is None + + +def test_deref_config(): + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + c = Config(o) + w = weakref.ref(c) + del(c) + assert w() is None + + +def test_deref_option(): + global IS_DEREFABLE + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + w = weakref.ref(b) + del(b) + try: + assert w() is not None + except AssertionError: + IS_DEREFABLE = False + return + del(o) + assert w() is None + + +def test_deref_optiondescription(): + if not IS_DEREFABLE: + return + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + w = weakref.ref(o) + del(b) + assert w() is not None + del(o) + assert w() is None + + +def test_deref_option_cache(): + if not IS_DEREFABLE: + return + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + o._build_cache_option() + w = weakref.ref(b) + del(b) + assert w() is not None + del(o) + assert w() is None + + +def test_deref_optiondescription_cache(): + if not IS_DEREFABLE: + return + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + o._build_cache_option() + w = weakref.ref(o) + del(b) + assert w() is not None + del(o) + assert w() is None + + +def test_deref_option_config(): + if not IS_DEREFABLE: + return + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + c = Config(o) + w = weakref.ref(b) + del(b) + assert w() is not None + del(o) + assert w() is not None + del(c) + assert w() is None + + +def test_deref_optiondescription_config(): + if not IS_DEREFABLE: + return + b = BoolOption('b', '') + o = OptionDescription('od', '', [b]) + c = Config(o) + w = weakref.ref(o) + del(b) + assert w() is not None + del(o) + assert w() is not None + del(c) + assert w() is None + + +def test_deref_groupconfig(): + if not IS_DEREFABLE: + return + i1 = IntOption('i1', '') + od1 = OptionDescription('od1', '', [i1]) + od2 = OptionDescription('od2', '', [od1]) + conf1 = Config(od2, 'conf1') + conf2 = Config(od2, 'conf2') + meta = GroupConfig([conf1, conf2]) + w = weakref.ref(conf1) + del(conf1) + assert w() is not None + del(meta) + assert w() is None + + +def test_deref_metaconfig(): + if not IS_DEREFABLE: + return + i1 = IntOption('i1', '') + od1 = OptionDescription('od1', '', [i1]) + od2 = OptionDescription('od2', '', [od1]) + conf1 = Config(od2, 'conf1') + conf2 = Config(od2, 'conf2') + meta = MetaConfig([conf1, conf2]) + w = weakref.ref(conf1) + del(conf1) + assert w() is not None + del(meta) + assert w() is None + + +def test_deref_consistency(): + if not IS_DEREFABLE: + return + a = IPOption('a', '') + b = NetmaskOption('b', '') + od = OptionDescription('od', '', [a, b]) + b.impl_add_consistency('ip_netmask', a) + cfg = Config(od) + w = weakref.ref(a) + x = weakref.ref(b) + y = weakref.ref(od) + z = weakref.ref(cfg) + assert w() is not None + assert x() is not None + assert y() is not None + assert z() is not None + del(a) + del(b) + assert w() is not None + assert x() is not None + assert y() is not None + assert z() is not None + del(od) + assert w() is not None + assert x() is not None + assert y() is not None + assert z() is not None + del(cfg) + assert y() is None + assert z() is None + #assert w() is None + #assert x() is None + + +def test_deref_validator(): + if not IS_DEREFABLE: + return + a = StrOption('a', '', default='yes') + b = StrOption('b', '', validator=funcname, validator_params={'': ((a, False),)}, default='val') + od = OptionDescription('root', '', [a, b]) + cfg = Config(od) + w = weakref.ref(a) + x = weakref.ref(b) + y = weakref.ref(od) + z = weakref.ref(cfg) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(a) + del(b) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(od) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(cfg) + assert y() is None + assert z() is None + #assert w() is None + #assert x() is None + + +def test_deref_callback(): + if not IS_DEREFABLE: + return + a = StrOption('a', "", 'val') + b = StrOption('b', "", callback=funcname, callback_params={'': ((a, False),)}) + od = OptionDescription('root', '', [a, b]) + cfg = Config(od) + w = weakref.ref(a) + x = weakref.ref(b) + y = weakref.ref(od) + z = weakref.ref(cfg) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(a) + del(b) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(od) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(cfg) + assert y() is None + assert z() is None + #assert w() is None + #assert x() is None + + +def test_deref_symlink(): + if not IS_DEREFABLE: + return + a = BoolOption("a", "", default=False) + b = SymLinkOption("b", a) + od = OptionDescription('root', '', [a, b]) + cfg = Config(od) + w = weakref.ref(a) + x = weakref.ref(b) + y = weakref.ref(od) + z = weakref.ref(cfg) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(a) + del(b) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(od) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(cfg) + #assert w() is None + #assert x() is None + assert y() is None + assert z() is None + + +def test_deref_dyn(): + if not IS_DEREFABLE: + return + a = StrOption('a', '', ['val1', 'val2'], multi=True) + b = StrOption('b', '') + dod = DynOptionDescription('dod', '', [b], callback=funcname, callback_params={'': ((a, False),)}) + od = OptionDescription('od', '', [dod, a]) + cfg = Config(od) + w = weakref.ref(a) + x = weakref.ref(b) + y = weakref.ref(od) + z = weakref.ref(cfg) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(a) + del(b) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(od) + del(dod) + assert w() is not None + assert x() is not None + assert w() is not None + assert x() is not None + del(cfg) + #assert w() is None + #assert x() is None + assert y() is None + assert z() is None diff --git a/test/new_api/test_duplicate_config.py b/test/new_api/test_duplicate_config.py new file mode 100644 index 0000000..69d562b --- /dev/null +++ b/test/new_api/test_duplicate_config.py @@ -0,0 +1,75 @@ +# coding: utf-8 +from .autopath import do_autopath +do_autopath() + +from tiramisu.setting import groups +from tiramisu.config import Config +from tiramisu import ChoiceOption, BoolOption, IntOption, \ + StrOption, OptionDescription, getapi +from .test_state import _diff_opts, _diff_conf +from py.test import raises + + +def make_description(): + numero_etab = StrOption('numero_etab', "identifiant de l'établissement") + nom_machine = StrOption('nom_machine', "nom de la machine", default="eoleng") + nombre_interfaces = IntOption('nombre_interfaces', "nombre d'interfaces à activer", + default=1) + activer_proxy_client = BoolOption('activer_proxy_client', "utiliser un proxy", + default=False) + mode_conteneur_actif = BoolOption('mode_conteneur_actif', "le serveur est en mode conteneur", + default=False) + mode_conteneur_actif2 = BoolOption('mode_conteneur_actif2', "le serveur est en mode conteneur2", + default=False, properties=('hidden',)) + + adresse_serveur_ntp = StrOption('serveur_ntp', "adresse serveur ntp", multi=True) + time_zone = ChoiceOption('time_zone', 'fuseau horaire du serveur', + ('Paris', 'Londres'), 'Paris') + wantref_option = BoolOption('wantref', 'Test requires', default=False, properties=('force_store_value',)) + + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé") + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau") + + master = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1 = OptionDescription('interface1', '', [master]) + interface1.impl_set_group_type(groups.family) + + general = OptionDescription('general', '', [numero_etab, nom_machine, + nombre_interfaces, activer_proxy_client, + mode_conteneur_actif, mode_conteneur_actif2, + adresse_serveur_ntp, time_zone, wantref_option]) + general.impl_set_group_type(groups.family) + new = OptionDescription('new', '', [], properties=('hidden',)) + new.impl_set_group_type(groups.family) + creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1, new]) + descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole]) + return descr + + +def test_duplicate(): + cfg = Config(make_description()) + ncfg = cfg.duplicate() + api = getapi(cfg) + api2 = getapi(ncfg) + assert api.option('creole.general.numero_etab').value.get() == None + api.option('creole.general.numero_etab').value.set('oui') + assert api.option('creole.general.numero_etab').value.get() == 'oui' + assert api2.option('creole.general.numero_etab').value.get() == None +# _diff_opts(cfg.cfgimpl_get_description(), ncfg.cfgimpl_get_description()) +# _diff_conf(cfg, ncfg) +# cfg.creole.general.numero_etab = 'oui' +# raises(AssertionError, "_diff_conf(cfg, ncfg)") +# ncfg.creole.general.numero_etab = 'oui' +# _diff_conf(cfg, ncfg) + + +def test_duplicate_force_store_value(): + descr = make_description() + conf = Config(descr) + conf2 = Config(descr) + api = getapi(conf) + assert conf.cfgimpl_get_values().get_modified_values() == {'creole.general.wantref': ('forced', False)} + assert conf2.cfgimpl_get_values().get_modified_values() == {'creole.general.wantref': ('forced', False)} + api.option('creole.general.wantref').value.set(True) + assert conf.cfgimpl_get_values().get_modified_values() == {'creole.general.wantref': ('user', True)} + assert conf2.cfgimpl_get_values().get_modified_values() == {'creole.general.wantref': ('forced', False)} diff --git a/test/new_api/test_state.py b/test/new_api/test_state.py new file mode 100644 index 0000000..0baa7e0 --- /dev/null +++ b/test/new_api/test_state.py @@ -0,0 +1,232 @@ +#from autopath import do_autopath +#do_autopath() +# +from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \ + OptionDescription, DynOptionDescription +from tiramisu.config import Config +from pickle import dumps +from py.test import raises +import sys + + +def _get_slots(opt): + slots = set() + for subclass in opt.__class__.__mro__: + if subclass is not object and '__slots__' in dir(subclass): + slots.update(subclass.__slots__) + return slots + + +def _no_state(opt): + for attr in _get_slots(opt): + if 'state' in attr: + try: + getattr(opt, attr) + except: + pass + else: + raise Exception('opt should have already attribute {0}'.format(attr)) + + +def _diff_opt(opt1, opt2): + attr1 = set(_get_slots(opt1)) + attr2 = set(_get_slots(opt2)) + diff1 = attr1 - attr2 + diff2 = attr2 - attr1 + if diff1 != set(): + raise Exception('more attribute in opt1 {0}'.format(list(diff1))) + if diff2 != set(): + raise Exception('more attribute in opt2 {0}'.format(list(diff2))) + for attr in attr1: + if attr in ['_cache_paths', '_cache_consistencies']: + continue + err1 = False + err2 = False + val1 = None + val2 = None + try: + val1 = getattr(opt1, attr) + msg1 = "exists" + tval = val1 + except: + err1 = True + msg1 = "not exists" + + try: + val2 = getattr(opt2, attr) + msg2 = "exists" + tval = val2 + except: + err2 = True + msg2 = "not exists" + + if not err1 == err2: + raise ValueError("{0} {1} before but {2} after for {3}: {4}".format(attr, msg1, msg2, opt1.impl_getname(), tval)) + if val1 is None: + assert val1 == val2 + elif attr == '_children': + assert val1[0] == val2[0] + for index, _opt in enumerate(val1[1]): + assert _opt._name == val2[1][index]._name + elif attr == '_requires': + if val1 == val2 == []: + pass + else: + for idx1, req1 in enumerate(val1): + for idx2, req2 in enumerate(val1[idx1]): + for idx3, req3 in enumerate(val1[idx1][idx2][0]): + assert val1[idx1][idx2][0][idx3][0].impl_getname() == val2[idx1][idx2][0][idx3][0].impl_getname() + assert val1[idx1][idx2][0][idx3][1] == val2[idx1][idx2][0][idx3][1] + assert val1[idx1][idx2][1:] == val2[idx1][idx2][1:], '{} - {}\n{} - {}'.format(val1, val2, val1[0][0][1:], val2[0][0][1:]) + elif attr == '_opt': + assert val1._name == val2._name + elif attr == '_consistencies': + # dict is only a cache + if isinstance(val1, list): + for index, consistency in enumerate(val1): + assert consistency[0] == val2[index][0] + for idx, opt in enumerate(consistency[1]): + assert opt._name == val2[index][1][idx]._name + elif attr == '_val_call': + for idx, v in enumerate(val1): + if v is None: + assert val2[idx] is None + else: + assert v[0] == val2[idx][0] + if len(v) == 2: + if v[1] is not None: + for key, values in v[1].items(): + for i, value in enumerate(values): + if isinstance(value, tuple) and value[0] is not None: + assert v[1][key][i][0].impl_getname() == val2[idx][1][key][i][0].impl_getname() + assert v[1][key][i][1] == val2[idx][1][key][i][1] + else: + assert v[1][key][i] == val2[idx][1][key][i] + else: + assert v[1] == val2[idx][1] + elif attr == '_master_slaves': + assert val1._p_._sm_getmaster().impl_getname() == val2._p_._sm_getmaster().impl_getname() + sval1 = [opt.impl_getname() for opt in val1._p_._sm_getslaves()] + sval2 = [opt.impl_getname() for opt in val2._p_._sm_getslaves()] + assert sval1 == sval2 + elif attr == '_subdyn': + try: + assert val1.impl_getname() == val2.impl_getname() + except AttributeError: + assert val1 == val2 + elif attr == '_dependencies': + assert len(val1) == len(val2), "_dependencies has not same len: {} - {}".format(val1, val2) + lst1 = [] + lst2 = [] + for idx, val in enumerate(val1): + if isinstance(val, MasterSlaves): + lst1.append(val._p_.master.impl_getname()) + else: + lst1.append(val.impl_getname()) + for idx, val in enumerate(val2): + if isinstance(val, MasterSlaves): + lst2.append(val._p_.master.impl_getname()) + else: + lst2.append(val.impl_getname()) + assert set(lst1) == set(lst2), '{} - {}'.format(lst1, lst2) + elif attr == '_cache_force_store_values': + for idx, tup in enumerate(val1): + assert tup[0] == val2[idx][0] + assert tup[1].impl_getname() == val2[idx][1].impl_getname() + elif attr in ['_extra', '_information']: + dico1 = {} + dico2 = {} + assert len(val1[0]) == len(val2[0]) + assert set(val1[0]) == set(val2[0]) + for idx, val in enumerate(val1[0]): + idx2 = val1[0].index(val) + assert val1[1][idx] == val1[1][idx2] + else: + #print(attr, val1, val2) + assert val1 == val2, "error for {}".format(attr) + + +def _diff_opts(opt1, opt2): + _diff_opt(opt1, opt2) + if isinstance(opt1, OptionDescription) or isinstance(opt1, DynOptionDescription): + children1 = set([opt.impl_getname() for opt in opt1.impl_getchildren(dyn=False)]) + children2 = set([opt.impl_getname() for opt in opt2.impl_getchildren(dyn=False)]) + diff1 = children1 - children2 + diff2 = children2 - children1 + if diff1 != set(): + raise Exception('more attribute in opt1 {0}'.format(list(diff1))) + if diff2 != set(): + raise Exception('more attribute in opt2 {0}'.format(list(diff2))) + for child in children1: + _diff_opts(opt1._getattr(child, dyn=False), opt2._getattr(child, dyn=False)) + + +def _diff_conf(cfg1, cfg2): + attr1 = set(_get_slots(cfg1)) + attr2 = set(_get_slots(cfg2)) + diff1 = attr1 - attr2 + diff2 = attr2 - attr1 + if diff1 != set(): + raise Exception('more attribute in cfg1 {0}'.format(list(diff1))) + if diff2 != set(): + raise Exception('more attribute in cfg2 {0}'.format(list(diff2))) + for attr in attr1: + if attr in ('_impl_context', '__weakref__'): + continue + err1 = False + err2 = False + val1 = None + val2 = None + try: + val1 = getattr(cfg1, attr) + except: + err1 = True + + try: + val2 = getattr(cfg2, attr) + except: + err2 = True + assert err1 == err2 + if val1 is None: + assert val1 == val2 + elif attr == '_impl_values': + assert cfg1.cfgimpl_get_values().get_modified_values() == cfg2.cfgimpl_get_values().get_modified_values() + elif attr == '_impl_settings': + assert cfg1.cfgimpl_get_settings().get_modified_properties() == cfg2.cfgimpl_get_settings().get_modified_properties() + assert cfg1.cfgimpl_get_settings().get_modified_permissives() == cfg2.cfgimpl_get_settings().get_modified_permissives() + elif attr == '_impl_descr': + _diff_opt(cfg1.cfgimpl_get_description(), cfg2.cfgimpl_get_description()) + elif attr == '_impl_children': + for index, _opt in enumerate(val1): + _diff_conf(_opt, val2[index]) + elif attr == '_impl_name': + #FIXME + pass + else: + assert val1 == val2 + + +def test_diff_opt(): + b = BoolOption('b', '') + u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}]) + s = SymLinkOption('s', u) + o = OptionDescription('o', '', [b, u, s]) + o1 = OptionDescription('o1', '', [o]) + + raises(NotImplementedError, "dumps(o1)") + + +def test_diff_information_config(): + b = BoolOption('b', '') + b.impl_set_information('info', 'oh') + b.impl_set_information('info1', 'oh') + b.impl_set_information('info2', 'oh') + o = OptionDescription('o', '', [b]) + o1 = OptionDescription('o1', '', [o]) + raises(NotImplementedError, "dumps(Config(o1))") + + +def test_only_optiondescription(): + b = BoolOption('b', '') + b + raises(NotImplementedError, "a = dumps(b)")