diff --git a/selftest/config_test.ok b/selftest/config_test.ok index 80b5a065..e1fb87dc 100644 --- a/selftest/config_test.ok +++ b/selftest/config_test.ok @@ -93,3 +93,20 @@ Validation: Error Validation: Error --- imsi[]: ERR: ValueError: Invalid IMSI: None Validation: Error +- Combine dicts: +- Combine dicts 2: +- Combine lists: +- Combine lists 2: +- Combine lists 3: +ValueError expected +- Combine lists 4: +ValueError expected +- Combine lists 5: +ValueError expected +- Combine lists 6: +- Combine lists 7: +- Combine lists 8: +- Combine lists 9: +- Combine lists 10: +- Combine lists 13: +- Combine lists 14: diff --git a/selftest/config_test.py b/selftest/config_test.py index 61ec73aa..fa86adce 100755 --- a/selftest/config_test.py +++ b/selftest/config_test.py @@ -112,4 +112,105 @@ val(c) c['imsi'][2] = None val(c) +print('- Combine dicts:') +a = {'times': '2'} +b = {'type': 'osmo-bts-trx'} +res = {'times': '2', 'type': 'osmo-bts-trx'} +config.combine(a, b) +assert a == res + +print('- Combine dicts 2:') +a = {'times': '1', 'label': 'foo', 'type': 'osmo-bts-trx'} +b = {'type': 'osmo-bts-trx'} +res = {'times': '1', 'label': 'foo', 'type': 'osmo-bts-trx'} +config.combine(a, b) +assert a == res + +print('- Combine lists:') +a = { 'a_list': ['x', 'y', 'z'] } +b = { 'a_list': ['y'] } +res = {'a_list': ['x', 'y', 'z']} +config.combine(a, b) +assert a == res + +print('- Combine lists 2:') +a = { 'a_list': ['x'] } +b = { 'a_list': ['w', 'u', 'x', 'y', 'z'] } +res = {'a_list': ['x', 'w', 'u', 'y', 'z']} +config.combine(a, b) +assert a == res + +print('- Combine lists 3:') +a = { 'a_list': ['x', 3] } +b = { 'a_list': ['y', 'z'] } +try: + config.combine(a, b) +except ValueError: + print("ValueError expected") + +print('- Combine lists 4:') +a = { 'a_list': [2, 3] } +b = { 'a_list': ['y', 'z'] } +try: + config.combine(a, b) +except ValueError: + print("ValueError expected") + +print('- Combine lists 5:') +a = { 'a_list': [{}, {}] } +b = { 'a_list': ['y', 'z'] } +try: + config.combine(a, b) +except ValueError: + print("ValueError expected") + +print('- Combine lists 6:') +a = { 'a_list': [{}, {}] } +b = { 'a_list': [{}] } +res = {'a_list': [{}, {}]} +config.combine(a, b) +assert a == res + +print('- Combine lists 7:') +a = { 'times': '1', 'label': 'foo', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}] } +b = { 'type': 'osmo-bts-trx', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}] } +res = {'times': '1', 'label': 'foo', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}], 'type': 'osmo-bts-trx'} +config.combine(a, b) +assert a == res + +print('- Combine lists 8:') +a = { 'times': '1', 'label': 'foo', 'trx': [{'nominal power': '10'}] } +b = { 'type': 'osmo-bts-trx', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}] } +res = {'times': '1', 'label': 'foo', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}], 'type': 'osmo-bts-trx'} +config.combine(a, b) +assert a == res + +print('- Combine lists 9:') +a = { 'times': '1', 'label': 'foo', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}] } +b = { 'type': 'osmo-bts-trx', 'trx': [{'nominal power': '10'}] } +res = {'times': '1', 'label': 'foo', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}], 'type': 'osmo-bts-trx'} +config.combine(a, b) +assert a == res + +print('- Combine lists 10:') +a = { 'times': '1', 'label': 'foo', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}] } +b = { 'type': 'osmo-bts-trx', 'trx': [{}, {'nominal power': '12'}] } +res = {'times': '1', 'label': 'foo', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}], 'type': 'osmo-bts-trx'} +config.combine(a, b) +assert a == res + +print('- Combine lists 13:') +a = { 'times': '1', 'label': 'foo', 'trx': [{}, {'nominal power': '12'}] } +b = { 'type': 'osmo-bts-trx', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}] } +res = {'times': '1', 'label': 'foo', 'trx': [{'nominal power': '10'}, {'nominal power': '12'}], 'type': 'osmo-bts-trx'} +config.combine(a, b) +assert a == res + +print('- Combine lists 14:') +a = { 'times': '1', 'label': 'foo', 'trx': [] } +b = { 'type': 'osmo-bts-trx', 'trx': [] } +res = {'times': '1', 'label': 'foo', 'trx': [], 'type': 'osmo-bts-trx'} +config.combine(a, b) +assert a == res + # vim: expandtab tabstop=4 shiftwidth=4 diff --git a/src/osmo_gsm_tester/config.py b/src/osmo_gsm_tester/config.py index 27ce428b..0721c308 100644 --- a/src/osmo_gsm_tester/config.py +++ b/src/osmo_gsm_tester/config.py @@ -245,9 +245,23 @@ def combine(dest, src): if is_list(dest): if not is_list(src): raise ValueError('cannot combine list with a value of type: %r' % type(src)) - for i in range(len(src)): - log.ctx(idx=i) - combine(dest[i], src[i]) + # Validate that all elements in both lists are of the same type: + t = util.list_validate_same_elem_type(src + dest) + if t is None: + return # both lists are empty, return + # For lists of complex objects, we expect them to be sorted lists: + if t in (dict, list, tuple): + for i in range(len(dest)): + log.ctx(idx=i) + src_it = src[i] if i < len(src) else util.empty_instance_type(t) + combine(dest[i], src_it) + for i in range(len(dest), len(src)): + log.ctx(idx=i) + dest.append(src[i]) + else: # for lists of basic elements, we handle them as unsorted sets: + for elem in src: + if elem not in dest: + dest.append(elem) return if dest == src: return diff --git a/src/osmo_gsm_tester/util.py b/src/osmo_gsm_tester/util.py index 197dc97b..bb4c5245 100644 --- a/src/osmo_gsm_tester/util.py +++ b/src/osmo_gsm_tester/util.py @@ -314,4 +314,27 @@ def str2bool(val): return True raise ValueError('Invalid BOOL field: %r' % val) +def list_validate_same_elem_type(li): + ''' + Checks that all elements in the list are of the same type and returns that type. + If the list is empty, returns None + If one of the elements is not of the same type, it throws a ValueError exception. + ''' + if len(li) == 0: + return None + t = type(li[0]) + for elem in li: + if type(elem) != t: + raise ValueError('List contains elements of different types: %r vs %r' % (t, type(elem))) + return t + +def empty_instance_type(t): + if t == dict: + return {} + elif t == list: + return [] + elif t == tuple: + return () + raise ValueError('type %r not supported!' % t) + # vim: expandtab tabstop=4 shiftwidth=4