calc_value with join could crash

This commit is contained in:
Emmanuel Garette 2022-01-09 20:36:04 +01:00
parent 3fe77f7e65
commit 9e80345dd1
5 changed files with 71 additions and 10 deletions

View file

@ -988,6 +988,19 @@ async def test_follower_not_multi():
assert not await list_sessions() assert not await list_sessions()
@pytest.mark.asyncio
async def test_follower_force_store_value_none():
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('force_store_value',))
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface0])
od2 = OptionDescription('toto', '', [od1])
async with await Config(od2) as cfg:
await cfg.property.read_write()
assert await cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
assert not await list_sessions()
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_follower_force_store_value(): async def test_follower_force_store_value():
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1']) ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])

View file

@ -1529,6 +1529,34 @@ async def test_calc_value_join(config_type):
assert not await list_sessions() assert not await list_sessions()
@pytest.mark.asyncio
async def test_calc_value_join_multi(config_type):
val1 = StrOption('val1', "", multi=True)
val4 = StrOption('val4', "", Calculation(calc_value, Params((ParamOption(val1)), join=ParamValue('.'), multi=ParamValue(True))), multi=True)
od = OptionDescription('root', '', [val1, val4])
async with await Config(od) as cfg:
cfg = await get_config(cfg, config_type)
assert await cfg.value.dict() == {'val1': [], 'val4': []}
await cfg.option('val1').value.set(['val1'])
assert await cfg.value.dict() == {'val1': ['val1'], 'val4': ['val1']}
assert not await list_sessions()
@pytest.mark.asyncio
async def test_calc_value_join_multi_value(config_type):
val1 = StrOption('val1', "", ['val1'], multi=True)
val2 = StrOption('val2', "", ['val2'], multi=True)
val3 = StrOption('val3', "", [None], multi=True)
val4 = StrOption('val4', "", Calculation(calc_value, Params((ParamOption(val1), ParamOption(val2), ParamOption(val3)), join=ParamValue('.'), multi=ParamValue(True))), multi=True)
od = OptionDescription('root', '', [val1, val2, val3, val4])
async with await Config(od) as cfg:
cfg = await get_config(cfg, config_type)
assert await cfg.value.dict() == {'val1': ['val1'], 'val2': ['val2'], 'val3': [None], 'val4': []}
await cfg.option('val3').value.set(['val3'])
assert await cfg.value.dict() == {'val1': ['val1'], 'val2': ['val2'], 'val3': ['val3'], 'val4': ['val1.val2.val3']}
assert not await list_sessions()
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_calc_value_min(): async def test_calc_value_min():
val1 = StrOption('val1', "", 'val1') val1 = StrOption('val1', "", 'val1')

View file

@ -768,6 +768,19 @@ async def test_set_modified_value():
assert not await list_sessions() assert not await list_sessions()
@pytest.mark.asyncio
async def test_none_is_not_modified():
gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value',))
gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
descr = OptionDescription('tiramisu', '', [gcgroup])
async with await Config(descr) as cfg:
assert await cfg.value.exportation() == [[], [], [], []]
await cfg.property.read_write()
assert await cfg.value.exportation() == [['gc.dummy1'], [None], ['str'], ['forced']]
assert not await list_sessions()
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_pprint(): async def test_pprint():
msg_error = _("cannot access to {0} \"{1}\" because has {2} {3}") msg_error = _("cannot access to {0} \"{1}\" because has {2} {3}")

View file

@ -347,14 +347,15 @@ class CalcValue:
raise ValueError(_(f'unexpected value in calc_value with join attribute "{val}" with invalid length "{length_val}"')) raise ValueError(_(f'unexpected value in calc_value with join attribute "{val}" with invalid length "{length_val}"'))
length_val = lval length_val = lval
new_value = [] new_value = []
for idx in range(length_val): if length_val is not None:
idx_val = [] for idx in range(length_val):
for val in value: idx_val = []
if isinstance(val, list): for val in value:
idx_val.append(val[idx]) if isinstance(val, list):
else: idx_val.append(val[idx])
idx_val.append(val) else:
new_value.append(join.join(idx_val)) idx_val.append(val)
new_value.append(join.join(idx_val))
value = new_value value = new_value
else: else:
value = [] value = []

View file

@ -132,9 +132,12 @@ class CacheOptionDescription(BaseOption):
index, index,
config_bag) config_bag)
option_bag.properties = frozenset() option_bag.properties = frozenset()
value = await values.getvalue(option_bag)
if value is None:
continue
await values._p_.setvalue(config_bag.connection, await values._p_.setvalue(config_bag.connection,
subpath, subpath,
await values.getvalue(option_bag), value,
owners.forced, owners.forced,
index, index,
False) False)
@ -163,9 +166,12 @@ class CacheOptionDescription(BaseOption):
option_bags.append(option_bag) option_bags.append(option_bag)
for option_bag in option_bags: for option_bag in option_bags:
option_bag.properties = frozenset() option_bag.properties = frozenset()
value = await values.getvalue(option_bag)
if value is None:
continue
await values._p_.setvalue(config_bag.connection, await values._p_.setvalue(config_bag.connection,
option_bag.path, option_bag.path,
await values.getvalue(option_bag), value,
owners.forced, owners.forced,
None, None,
False, False,