diff options
author | Ole Troan <ot@cisco.com> | 2019-10-22 14:01:53 +0200 |
---|---|---|
committer | Andrew Yourtchenko <ayourtch@gmail.com> | 2020-08-07 21:45:43 +0000 |
commit | 3584f0936c81df663c1cd5171d5d2c277da8bf78 (patch) | |
tree | 0ef1cae7bcffe8dce3d835c0d97c065d5ddd9b29 /src | |
parent | 48ec77e84ec4ed0ff38c0c772084381be4d960af (diff) |
papi: fix default handling
The BaseTypers object were reused, so a default for anyother mesage
would be inherited in new messages.
Type: fix
Fixes: 85465588b18fef9c4712f864f512e00741e2d4f2
Change-Id: Ie1efb85a76b088653eb9ea4b88540c98b6b0aad0
Signed-off-by: Ole Troan <ot@cisco.com>
(cherry picked from commit 40dc4b35e3d946efbc5c2b8b0af5e52d67b7fe6c)
Diffstat (limited to 'src')
-rwxr-xr-x | src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py | 31 | ||||
-rw-r--r-- | src/vpp-api/python/vpp_papi/vpp_serializer.py | 56 |
2 files changed, 51 insertions, 36 deletions
diff --git a/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py b/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py index 9ac3e78224c..5221034da6c 100755 --- a/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py +++ b/src/vpp-api/python/vpp_papi/tests/test_vpp_serializer.py @@ -66,14 +66,43 @@ class TestDefaults(unittest.TestCase): def test_defaults(self): default_type = VPPType('default_type_t', [['u16', 'mtu', {'default': 1500, 'limit': 0}]]) + without_default_type = VPPType('without_default_type_t', + [['u16', 'mtu']]) b = default_type.pack({}) self.assertEqual(len(b), 2) - nt, size = default_type.unpack(b) self.assertEqual(len(b), size) self.assertEqual(nt.mtu, 1500) + # distinguish between parameter 0 and parameter not passed + b = default_type.pack({'mtu': 0}) + self.assertEqual(len(b), 2) + nt, size = default_type.unpack(b) + self.assertEqual(len(b), size) + self.assertEqual(nt.mtu, 0) + + # Ensure that basetypes does not inherit default + b = without_default_type.pack({}) + self.assertEqual(len(b), 2) + nt, size = default_type.unpack(b) + self.assertEqual(len(b), size) + self.assertEqual(nt.mtu, 0) + + # default enum type + VPPEnumType('vl_api_enum_t', [["ADDRESS_IP4", 0], + ["ADDRESS_IP6", 1], + {"enumtype": "u32"}]) + + default_with_enum = VPPType('default_enum_type_t', + [['u16', 'mtu'], ['vl_api_enum_t', + 'e', {'default': 1}]]) + + b = default_with_enum.pack({}) + self.assertEqual(len(b), 6) + nt, size = default_with_enum.unpack(b) + self.assertEqual(len(b), size) + self.assertEqual(nt.e, 1) class TestAddType(unittest.TestCase): diff --git a/src/vpp-api/python/vpp_papi/vpp_serializer.py b/src/vpp-api/python/vpp_papi/vpp_serializer.py index 00ed8632916..be5c74c150a 100644 --- a/src/vpp-api/python/vpp_papi/vpp_serializer.py +++ b/src/vpp-api/python/vpp_papi/vpp_serializer.py @@ -88,12 +88,8 @@ class BaseTypes(object): self.size = self.packer.size self.options = options - def __call__(self, args): - self.options = args - return self - def pack(self, data, kwargs=None): - if not data: # Default to zero if not specified + if data is None: # Default to zero if not specified if self.options and 'default' in self.options: data = self.options['default'] else: @@ -152,6 +148,7 @@ types = {'u8': BaseTypes('u8'), 'u16': BaseTypes('u16'), 'u64': BaseTypes('u64'), 'f64': BaseTypes('f64'), 'bool': BaseTypes('bool'), 'string': String} +class_types = {} def vpp_get_type(name): try: @@ -172,10 +169,6 @@ class FixedList_u8(object): self.size = self.packer.size self.field_type = field_type - def __call__(self, args): - self.options = args - return self - def pack(self, data, kwargs=None): """Packs a fixed length bytestring. Left-pads with zeros if input data is too short.""" @@ -207,10 +200,6 @@ class FixedList(object): self.name = name self.field_type = field_type - def __call__(self, args): - self.options = args - return self - def pack(self, list, kwargs): if len(list) != self.num: raise VPPSerializerValueError( @@ -289,10 +278,6 @@ class VLAList_legacy(): self.packer = types[field_type] self.size = self.packer.size - def __call__(self, args): - self.options = args - return self - def pack(self, list, kwargs=None): if self.packer.size == 1: return bytes(list) @@ -319,9 +304,11 @@ class VLAList_legacy(): class VPPEnumType(object): - def __init__(self, name, msgdef): + def __init__(self, name, msgdef, options=None): self.size = types['u32'].size + self.name = name self.enumtype = 'u32' + self.msgdef = msgdef e_hash = {} for f in msgdef: if type(f) is dict and 'enumtype' in f: @@ -333,10 +320,8 @@ class VPPEnumType(object): e_hash[ename] = evalue self.enum = IntFlag(name, e_hash) types[name] = self - - def __call__(self, args): - self.options = args - return self + class_types[name] = VPPEnumType + self.options = options def __getattr__(self, name): return self.enum[name] @@ -348,6 +333,12 @@ class VPPEnumType(object): __nonzero__ = __bool__ def pack(self, data, kwargs=None): + if data is None: # Default to zero if not specified + if self.options and 'default' in self.options: + data = self.options['default'] + else: + data = 0 + return types[self.enumtype].pack(data) def unpack(self, data, offset=0, result=None, ntc=False): @@ -381,10 +372,6 @@ class VPPUnionType(object): types[name] = self self.tuple = collections.namedtuple(name, fields, rename=True) - def __call__(self, args): - self.options = args - return self - # Union of variable length? def pack(self, data, kwargs=None): if not data: @@ -431,10 +418,6 @@ class VPPTypeAlias(object): types[name] = self self.toplevelconversion = False - def __call__(self, args): - self.options = args - return self - def pack(self, data, kwargs=None): if data and conversion_required(data, self.name): try: @@ -512,7 +495,14 @@ class VPPType(object): p = VLAList(f_name, f_type, f[3], length_index) self.packers.append(p) else: - p = types[f_type](self.options) + # Support default for basetypes and enums + if 'default' in self.options: + try: + p = BaseTypes(f_type, 0, self.options) + except KeyError: + p = class_types[f_type](f_name, types[f_type].msgdef, self.options) + else: + p = types[f_type] self.packers.append(p) size += p.size @@ -521,10 +511,6 @@ class VPPType(object): types[name] = self self.toplevelconversion = False - def __call__(self, args): - self.options = args - return self - def pack(self, data, kwargs=None): if not kwargs: kwargs = data |