papi: add support for enumflag part 1 of 2
[vpp.git] / src / vpp-api / python / vpp_papi / tests / test_vpp_serializer.py
1 #!/usr/bin/env python3
2
3 import unittest
4 from vpp_papi.vpp_serializer import VPPType, VPPEnumType, VPPEnumFlagType
5 from vpp_papi.vpp_serializer import VPPUnionType, VPPMessage
6 from vpp_papi.vpp_serializer import VPPTypeAlias, VPPSerializerValueError
7 from vpp_papi import MACAddress
8 from socket import inet_pton, AF_INET, AF_INET6
9 import logging
10 import sys
11 from ipaddress import *
12
13
14 class TestLimits(unittest.TestCase):
15     def test_string(self):
16         fixed_string = VPPType('fixed_string',
17                                [['string', 'name', 16]])
18
19         b = fixed_string.pack({'name': 'foobar'})
20         self.assertEqual(len(b), 16)
21
22         # Ensure string is nul terminated
23         self.assertEqual(b.decode('ascii')[6], '\x00')
24
25         nt, size = fixed_string.unpack(b)
26         self.assertEqual(size, 16)
27         self.assertEqual(nt.name, 'foobar')
28
29         # Empty string
30         b = fixed_string.pack({'name': ''})
31         self.assertEqual(len(b), 16)
32         nt, size = fixed_string.unpack(b)
33         self.assertEqual(size, 16)
34         self.assertEqual(nt.name, '')
35
36         # String too long
37         with self.assertRaises(VPPSerializerValueError):
38             b = fixed_string.pack({'name': 'foobarfoobar1234'})
39
40         variable_string = VPPType('variable_string',
41                                   [['string', 'name', 0]])
42         b = variable_string.pack({'name': 'foobar'})
43         self.assertEqual(len(b), 4 + len('foobar'))
44
45         nt, size = variable_string.unpack(b)
46         self.assertEqual(size, 4 + len('foobar'))
47         self.assertEqual(nt.name, 'foobar')
48         self.assertEqual(len(nt.name), len('foobar'))
49
50     def test_limit(self):
51         limited_type = VPPType('limited_type_t',
52                                [['string', 'name', 0, {'limit': 16}]])
53         unlimited_type = VPPType('limited_type_t',
54                                  [['string', 'name', 0]])
55
56         b = limited_type.pack({'name': 'foobar'})
57         self.assertEqual(len(b), 10)
58         b = unlimited_type.pack({'name': 'foobar'})
59         self.assertEqual(len(b), 10)
60
61         with self.assertRaises(VPPSerializerValueError):
62             b = limited_type.pack({'name': 'foobar'*3})
63
64
65 class TestDefaults(unittest.TestCase):
66     def test_defaults(self):
67         default_type = VPPType('default_type_t',
68                                [['u16', 'mtu', {'default': 1500, 'limit': 0}]])
69         without_default_type = VPPType('without_default_type_t',
70                                        [['u16', 'mtu']])
71
72         b = default_type.pack({})
73         self.assertEqual(len(b), 2)
74         nt, size = default_type.unpack(b)
75         self.assertEqual(len(b), size)
76         self.assertEqual(nt.mtu, 1500)
77
78         # distinguish between parameter 0 and parameter not passed
79         b = default_type.pack({'mtu': 0})
80         self.assertEqual(len(b), 2)
81         nt, size = default_type.unpack(b)
82         self.assertEqual(len(b), size)
83         self.assertEqual(nt.mtu, 0)
84
85         # Ensure that basetypes does not inherit default
86         b = without_default_type.pack({})
87         self.assertEqual(len(b), 2)
88         nt, size = default_type.unpack(b)
89         self.assertEqual(len(b), size)
90         self.assertEqual(nt.mtu, 0)
91
92         # default enum type
93         VPPEnumType('vl_api_enum_t', [["ADDRESS_IP4", 0],
94                                       ["ADDRESS_IP6", 1],
95                                       {"enumtype": "u32"}])
96
97         default_with_enum = VPPType('default_enum_type_t',
98                                     [['u16', 'mtu'], ['vl_api_enum_t',
99                                                       'e', {'default': 1}]])
100
101         b = default_with_enum.pack({})
102         self.assertEqual(len(b), 6)
103         nt, size = default_with_enum.unpack(b)
104         self.assertEqual(len(b), size)
105         self.assertEqual(nt.e, 1)
106
107
108 class TestAddType(unittest.TestCase):
109
110     def test_union(self):
111         un = VPPUnionType('test_union',
112                           [['u8', 'is_bool'],
113                            ['u32', 'is_int']])
114
115         b = un.pack({'is_int': 0x12345678})
116         nt, size = un.unpack(b)
117         self.assertEqual(len(b), size)
118         self.assertEqual(nt.is_bool, 0x12)
119         self.assertEqual(nt.is_int, 0x12345678)
120
121     def test_address(self):
122         af = VPPEnumType('vl_api_address_family_t', [["ADDRESS_IP4", 0],
123                                                      ["ADDRESS_IP6", 1],
124                                                      {"enumtype": "u32"}])
125         aff = VPPEnumFlagType('vl_api_address_family_flag_t', [["ADDRESS_IP4", 0],
126                                                                ["ADDRESS_IP6", 1],
127                                                                {"enumtype": "u32"}])
128         ip4 = VPPTypeAlias('vl_api_ip4_address_t', {'type': 'u8',
129                                                     'length': 4})
130         ip6 = VPPTypeAlias('vl_api_ip6_address_t', {'type': 'u8',
131                                                     'length': 16})
132         VPPUnionType('vl_api_address_union_t',
133                      [["vl_api_ip4_address_t", "ip4"],
134                       ["vl_api_ip6_address_t", "ip6"]])
135
136         address = VPPType('vl_api_address_t',
137                           [['vl_api_address_family_t', 'af'],
138                            ['vl_api_address_union_t', 'un']])
139
140         prefix = VPPType('vl_api_prefix_t',
141                          [['vl_api_address_t', 'address'],
142                           ['u8', 'len']])
143
144         va_address_list = VPPType('list_addresses',
145                                   [['u8', 'count'],
146                                    ['vl_api_address_t', 'addresses',
147                                     0, 'count']])
148
149         message_with_va_address_list = VPPType('msg_with_vla',
150                                                [['list_addresses',
151                                                  'vla_address'],
152                                                 ['u8', 'is_cool']])
153
154         b = ip4.pack(inet_pton(AF_INET, '1.1.1.1'))
155         self.assertEqual(len(b), 4)
156         nt, size = ip4.unpack(b)
157         self.assertEqual(str(nt), '1.1.1.1')
158
159         b = ip6.pack(inet_pton(AF_INET6, '1::1'))
160         self.assertEqual(len(b), 16)
161
162         b = address.pack({'af': af.ADDRESS_IP4,
163                           'un':
164                           {'ip4': inet_pton(AF_INET, '2.2.2.2')}})
165         self.assertEqual(len(b), 20)
166
167         nt, size = address.unpack(b)
168         self.assertEqual(str(nt), '2.2.2.2')
169
170         # List of addresses
171         address_list = []
172         for i in range(4):
173             address_list.append({'af': af.ADDRESS_IP4,
174                                  'un':
175                                  {'ip4': inet_pton(AF_INET, '2.2.2.2')}})
176         b = va_address_list.pack({'count': len(address_list),
177                                   'addresses': address_list})
178         self.assertEqual(len(b), 81)
179
180         nt, size = va_address_list.unpack(b)
181         self.assertEqual(str(nt.addresses[0]), '2.2.2.2')
182
183         b = message_with_va_address_list.pack({'vla_address':
184                                                {'count': len(address_list),
185                                                 'addresses': address_list},
186                                                'is_cool': 100})
187         self.assertEqual(len(b), 82)
188         nt, size = message_with_va_address_list.unpack(b)
189         self.assertEqual(nt.is_cool, 100)
190
191     def test_address_with_prefix(self):
192         af = VPPEnumType('vl_api_address_family_t', [["ADDRESS_IP4", 0],
193                                                      ["ADDRESS_IP6", 1],
194                                                      {"enumtype": "u32"}])
195         ip4 = VPPTypeAlias('vl_api_ip4_address_t', {'type': 'u8',
196                                                     'length': 4})
197         ip6 = VPPTypeAlias('vl_api_ip6_address_t', {'type': 'u8',
198                                                     'length': 16})
199         VPPUnionType('vl_api_address_union_t',
200                      [["vl_api_ip4_address_t", "ip4"],
201                       ["vl_api_ip6_address_t", "ip6"]])
202
203         address = VPPType('vl_api_address_t',
204                           [['vl_api_address_family_t', 'af'],
205                            ['vl_api_address_union_t', 'un']])
206
207         prefix = VPPType('vl_api_prefix_t',
208                          [['vl_api_address_t', 'address'],
209                           ['u8', 'len']])
210         prefix4 = VPPType('vl_api_ip4_prefix_t',
211                           [['vl_api_ip4_address_t', 'address'],
212                           ['u8', 'len']])
213         prefix6 = VPPType('vl_api_ip6_prefix_t',
214                           [['vl_api_ip6_address_t', 'address'],
215                           ['u8', 'len']])
216
217         address_with_prefix = VPPTypeAlias('vl_api_address_with_prefix_t', {'type': 'vl_api_prefix_t' })
218         address4_with_prefix = VPPTypeAlias('vl_api_ip4_address_with_prefix_t',
219                                             {'type': 'vl_api_ip4_prefix_t' })
220         address6_with_prefix = VPPTypeAlias('vl_api_ip6_address_with_prefix_t',
221                                             {'type': 'vl_api_ip6_prefix_t' })
222
223         awp_type = VPPType('foobar_t',
224                            [['vl_api_address_with_prefix_t', 'address']])
225
226         # address with prefix
227         b = address_with_prefix.pack(IPv4Interface('2.2.2.2/24'))
228         self.assertEqual(len(b), 21)
229         nt, size = address_with_prefix.unpack(b)
230         self.assertTrue(isinstance(nt, IPv4Interface))
231         self.assertEqual(str(nt), '2.2.2.2/24')
232
233         b = address_with_prefix.pack(IPv6Interface('2::2/64'))
234         self.assertEqual(len(b), 21)
235         nt, size = address_with_prefix.unpack(b)
236         self.assertTrue(isinstance(nt, IPv6Interface))
237         self.assertEqual(str(nt), '2::2/64')
238
239         b = address_with_prefix.pack(IPv4Network('2.2.2.2/24', strict=False))
240         self.assertEqual(len(b), 21)
241         nt, size = address_with_prefix.unpack(b)
242         self.assertTrue(isinstance(nt, IPv4Interface))
243         self.assertEqual(str(nt), '2.2.2.0/24')
244
245         b = address4_with_prefix.pack('2.2.2.2/24')
246         self.assertEqual(len(b), 5)
247         nt, size = address4_with_prefix.unpack(b)
248         self.assertTrue(isinstance(nt, IPv4Interface))
249         self.assertEqual(str(nt), '2.2.2.2/24')
250         b = address4_with_prefix.pack(IPv4Interface('2.2.2.2/24'))
251         self.assertEqual(len(b), 5)
252
253         b = address6_with_prefix.pack('2::2/64')
254         self.assertEqual(len(b), 17)
255         nt, size = address6_with_prefix.unpack(b)
256         self.assertTrue(isinstance(nt, IPv6Interface))
257         self.assertEqual(str(nt), '2::2/64')
258         b = address6_with_prefix.pack(IPv6Interface('2::2/64'))
259         self.assertEqual(len(b), 17)
260
261         b = prefix.pack('192.168.10.0/24')
262         self.assertEqual(len(b), 21)
263         nt, size = prefix.unpack(b)
264         self.assertTrue(isinstance(nt, IPv4Network))
265         self.assertEqual(str(nt), '192.168.10.0/24')
266
267         b = awp_type.pack({'address': '1.2.3.4/24'})
268         self.assertEqual(len(b), 21)
269         nt, size = awp_type.unpack(b)
270         self.assertTrue(isinstance(nt.address, IPv4Interface))
271         self.assertEqual(str(nt.address), '1.2.3.4/24')
272
273         b = awp_type.pack({'address': IPv4Interface('1.2.3.4/24')})
274         self.assertEqual(len(b), 21)
275         nt, size = awp_type.unpack(b)
276         self.assertTrue(isinstance(nt.address, IPv4Interface))
277         self.assertEqual(str(nt.address), '1.2.3.4/24')
278
279     def test_recursive_address(self):
280         af = VPPEnumType('vl_api_address_family_t', [["ADDRESS_IP4", 0],
281                                                      ["ADDRESS_IP6", 1],
282                                                      {"enumtype": "u32"}])
283         ip4 = VPPTypeAlias('vl_api_ip4_address_t', {'type': 'u8',
284                                                     'length': 4})
285         b = ip4.pack('1.1.1.1')
286         self.assertEqual(len(b), 4)
287         nt, size = ip4.unpack(b)
288
289         self.assertEqual(str(nt), '1.1.1.1')
290
291         ip6 = VPPTypeAlias('vl_api_ip6_address_t', {'type': 'u8',
292                                                     'length': 16})
293         VPPUnionType('vl_api_address_union_t',
294                      [["vl_api_ip4_address_t", "ip4"],
295                       ["vl_api_ip6_address_t", "ip6"]])
296
297         address = VPPType('vl_api_address_t',
298                           [['vl_api_address_family_t', 'af'],
299                            ['vl_api_address_union_t', 'un']])
300
301         prefix = VPPType('vl_api_prefix_t',
302                          [['vl_api_address_t', 'address'],
303                           ['u8', 'len']])
304         message = VPPMessage('svs',
305                              [['vl_api_prefix_t', 'prefix']])
306         message_addr = VPPMessage('svs_address',
307                                   [['vl_api_address_t', 'address']])
308
309         b = message_addr.pack({'address': "1::1"})
310         self.assertEqual(len(b), 20)
311         nt, size = message_addr.unpack(b)
312         self.assertEqual("1::1", str(nt.address))
313         b = message_addr.pack({'address': "1.1.1.1"})
314         self.assertEqual(len(b), 20)
315         nt, size = message_addr.unpack(b)
316         self.assertEqual("1.1.1.1", str(nt.address))
317
318         b = message.pack({'prefix': "1.1.1.0/24"})
319         self.assertEqual(len(b), 21)
320         nt, size = message.unpack(b)
321         self.assertEqual("1.1.1.0/24", str(nt.prefix))
322
323         message_array = VPPMessage('address_array',
324                                    [['vl_api_ip6_address_t',
325                                      'addresses', 2]])
326         b = message_array.pack({'addresses': [IPv6Address(u"1::1"), "2::2"]})
327         self.assertEqual(len(b), 32)
328         message_array_vla = VPPMessage('address_array_vla',
329                                        [['u32', 'num'],
330                                         ['vl_api_ip6_address_t',
331                                          'addresses', 0, 'num']])
332         b = message_array_vla.pack({'addresses': ["1::1", "2::2"], 'num': 2})
333         self.assertEqual(len(b), 36)
334
335         message_array4 = VPPMessage('address_array4',
336                                     [['vl_api_ip4_address_t',
337                                       'addresses', 2]])
338         b = message_array4.pack({'addresses': ["1.1.1.1", "2.2.2.2"]})
339         self.assertEqual(len(b), 8)
340         b = message_array4.pack({'addresses': [IPv4Address(u"1.1.1.1"),
341                                                "2.2.2.2"]})
342         self.assertEqual(len(b), 8)
343
344         message = VPPMessage('address', [['vl_api_address_t', 'address']])
345         b = message.pack({'address': '1::1'})
346         self.assertEqual(len(b), 20)
347         b = message.pack({'address': '1.1.1.1'})
348         self.assertEqual(len(b), 20)
349         message = VPPMessage('prefix', [['vl_api_prefix_t', 'prefix']])
350         b = message.pack({'prefix': '1::1/130'})
351         self.assertEqual(len(b), 21)
352         b = message.pack({'prefix': IPv6Network(u'1::/119')})
353         self.assertEqual(len(b), 21)
354         b = message.pack({'prefix': IPv4Network(u'1.1.0.0/16')})
355         self.assertEqual(len(b), 21)
356
357     def test_zero_vla(self):
358         '''Default zero'ed out for VLAs'''
359         list = VPPType('vl_api_list_t',
360                        [['u8', 'count', 10]])
361
362         # Define an embedded VLA type
363         valist = VPPType('vl_api_valist_t',
364                          [['u8', 'count'],
365                           ['u8', 'string', 0, 'count']])
366         # Define a message
367         vamessage = VPPMessage('vamsg',
368                                [['vl_api_valist_t', 'valist'],
369                                 ['u8', 'is_something']])
370
371         message = VPPMessage('msg',
372                              [['vl_api_list_t', 'list'],
373                               ['u8', 'is_something']])
374
375         # Pack message without VLA specified
376         b = message.pack({'is_something': 1})
377         b = vamessage.pack({'is_something': 1})
378
379     def test_arrays(self):
380         # Test cases
381         # 1. Fixed list
382         # 2. Fixed list of variable length sub type
383         # 3. Variable length type
384         #
385         s = VPPType('str', [['u32', 'length'],
386                             ['u8', 'string', 0, 'length']])
387
388         ip4 = VPPType('ip4_address', [['u8', 'address', 4]])
389         listip4 = VPPType('list_ip4_t', [['ip4_address', 'addresses', 4]])
390         valistip4 = VPPType('list_ip4_t',
391                             [['u8', 'count'],
392                              ['ip4_address', 'addresses', 0, 'count']])
393
394         valistip4_legacy = VPPType('list_ip4_t',
395                                    [['u8', 'foo'],
396                                     ['ip4_address', 'addresses', 0]])
397
398         addresses = []
399         for i in range(4):
400             addresses.append({'address': inet_pton(AF_INET, '2.2.2.2')})
401         b = listip4.pack({'addresses': addresses})
402         self.assertEqual(len(b), 16)
403         nt, size = listip4.unpack(b)
404         self.assertEqual(nt.addresses[0].address,
405                          inet_pton(AF_INET, '2.2.2.2'))
406
407         b = valistip4.pack({'count': len(addresses), 'addresses': addresses})
408         self.assertEqual(len(b), 17)
409
410         nt, size = valistip4.unpack(b)
411         self.assertEqual(nt.count, 4)
412         self.assertEqual(nt.addresses[0].address,
413                          inet_pton(AF_INET, '2.2.2.2'))
414
415         b = valistip4_legacy.pack({'foo': 1, 'addresses': addresses})
416         self.assertEqual(len(b), 17)
417         nt, size = valistip4_legacy.unpack(b)
418         self.assertEqual(len(nt.addresses), 4)
419         self.assertEqual(nt.addresses[0].address,
420                          inet_pton(AF_INET, '2.2.2.2'))
421
422         string = 'foobar foobar'
423         b = s.pack({'length': len(string), 'string': string.encode('utf-8')})
424         nt, size = s.unpack(b)
425         self.assertEqual(len(b), size)
426
427     def test_string(self):
428         s = VPPType('str', [['u32', 'length'],
429                             ['u8', 'string', 0, 'length']])
430
431         string = ''
432         b = s.pack({'length': len(string), 'string': string.encode('utf-8')})
433         nt, size = s.unpack(b)
434         self.assertEqual(len(b), size)
435
436     def test_message(self):
437         foo = VPPMessage('foo', [['u16', '_vl_msg_id'],
438                                  ['u8', 'client_index'],
439                                  ['u8', 'something'],
440                                  {"crc": "0x559b9f3c"}])
441         b = foo.pack({'_vl_msg_id': 1, 'client_index': 5,
442                       'something': 200})
443         nt, size = foo.unpack(b)
444         self.assertEqual(len(b), size)
445         self.assertEqual(nt.something, 200)
446
447     def test_abf(self):
448
449         fib_mpls_label = VPPType('vl_api_fib_mpls_label_t',
450                                  [['u8', 'is_uniform'],
451                                   ['u32', 'label'],
452                                   ['u8', 'ttl'],
453                                   ['u8', 'exp']])
454
455         label_stack = {'is_uniform': 0,
456                        'label': 0,
457                        'ttl': 0,
458                        'exp': 0}
459
460         b = fib_mpls_label.pack(label_stack)
461         self.assertEqual(len(b), 7)
462
463         fib_path = VPPType('vl_api_fib_path_t',
464                            [['u32', 'sw_if_index'],
465                             ['u32', 'table_id'],
466                             ['u8', 'weight'],
467                             ['u8', 'preference'],
468                             ['u8', 'is_local'],
469                             ['u8', 'is_drop'],
470                             ['u8', 'is_udp_encap'],
471                             ['u8', 'is_unreach'],
472                             ['u8', 'is_prohibit'],
473                             ['u8', 'is_resolve_host'],
474                             ['u8', 'is_resolve_attached'],
475                             ['u8', 'is_dvr'],
476                             ['u8', 'is_source_lookup'],
477                             ['u8', 'afi'],
478                             ['u8', 'next_hop', 16],
479                             ['u32', 'next_hop_id'],
480                             ['u32', 'rpf_id'],
481                             ['u32', 'via_label'],
482                             ['u8', 'n_labels'],
483                             ['vl_api_fib_mpls_label_t', 'label_stack', 16]])
484         label_stack_list = []
485         for i in range(16):
486             label_stack_list.append(label_stack)
487
488         paths = {'is_udp_encap': 0,
489                  'next_hop': b'\x10\x02\x02\xac',
490                  'table_id': 0,
491                  'afi': 0,
492                  'weight': 1,
493                  'next_hop_id': 4294967295,
494                  'label_stack': label_stack_list,
495                  'n_labels': 0,
496                  'sw_if_index': 4294967295,
497                  'preference': 0}
498
499         b = fib_path.pack(paths)
500         self.assertEqual(len(b), (7*16) + 49)
501
502         abf_policy = VPPType('vl_api_abf_policy_t',
503                              [['u32', 'policy_id'],
504                               ['u32', 'acl_index'],
505                               ['u8', 'n_paths'],
506                               ['vl_api_fib_path_t', 'paths', 0, 'n_paths']])
507
508         policy = {
509             'n_paths': 1,
510             'paths': [paths],
511             'acl_index': 0,
512             'policy_id': 10}
513
514         b = abf_policy.pack(policy)
515         self.assertEqual(len(b), (7*16) + 49 + 9)
516
517         abf_policy_add_del = VPPMessage('abf_policy_add_del',
518                                         [['u16', '_vl_msg_id'],
519                                          ['u32', 'client_index'],
520                                          ['u32', 'context'],
521                                          ['u8', 'is_add'],
522                                          ['vl_api_abf_policy_t', 'policy']])
523
524         b = abf_policy_add_del.pack({'is_add': 1,
525                                      'context': 66,
526                                      '_vl_msg_id': 1066,
527                                      'policy': policy})
528
529         nt, size = abf_policy_add_del.unpack(b)
530         self.assertEqual(nt.policy.paths[0].next_hop,
531                          b'\x10\x02\x02\xac\x00\x00\x00\x00'
532                          b'\x00\x00\x00\x00\x00\x00\x00\x00')
533
534     def test_bier(self):
535
536         bier_table_id = VPPType('vl_api_bier_table_id_t',
537                                 [['u8', 'bt_set'],
538                                  ['u8', 'bt_sub_domain'],
539                                  ['u8', 'bt_hdr_len_id']])
540
541         bier_imp_add = VPPMessage('bier_imp_add',
542                                   [['u32', 'client_index'],
543                                    ['u32', 'context'],
544                                    ['vl_api_bier_table_id_t', 'bi_tbl_id'],
545                                    ['u16', 'bi_src'],
546                                    ['u8', 'bi_n_bytes'],
547                                    ['u8', 'bi_bytes', 0, 'bi_n_bytes']])
548
549         table_id = {'bt_set': 0,
550                     'bt_sub_domain': 0,
551                     'bt_hdr_len_id': 0}
552
553         bibytes = b'foobar'
554
555         b = bier_imp_add.pack({'bi_tbl_id': table_id,
556                                'bi_n_bytes': len(bibytes),
557                                'bi_bytes': bibytes})
558
559         self.assertEqual(len(b), 20)
560
561     def test_lisp(self):
562         VPPEnumType('vl_api_eid_type_t',
563                     [["EID_TYPE_API_PREFIX", 0],
564                      ["EID_TYPE_API_MAC", 1],
565                      ["EID_TYPE_API_NSH", 2],
566                      {"enumtype": "u32"}])
567
568         VPPTypeAlias('vl_api_mac_address_t', {'type': 'u8',
569                                               'length': 6})
570
571         VPPType('vl_api_nsh_t',
572                 [["u32", "spi"],
573                  ["u8", "si"]])
574
575         VPPEnumType('vl_api_address_family_t', [["ADDRESS_IP4", 0],
576                                                 ["ADDRESS_IP6", 1],
577                                                 {"enumtype": "u32"}])
578         VPPTypeAlias('vl_api_ip4_address_t', {'type': 'u8',
579                                               'length': 4})
580         VPPTypeAlias('vl_api_ip6_address_t', {'type': 'u8',
581                                               'length': 16})
582         VPPUnionType('vl_api_address_union_t',
583                      [["vl_api_ip4_address_t", "ip4"],
584                       ["vl_api_ip6_address_t", "ip6"]])
585
586         VPPType('vl_api_address_t',
587                 [['vl_api_address_family_t', 'af'],
588                  ['vl_api_address_union_t', 'un']])
589
590         VPPType('vl_api_prefix_t',
591                 [['vl_api_address_t', 'address'],
592                  ['u8', 'len']])
593
594         VPPUnionType('vl_api_eid_address_t',
595                      [["vl_api_prefix_t", "prefix"],
596                       ["vl_api_mac_address_t", "mac"],
597                       ["vl_api_nsh_t", "nsh"]])
598
599         eid = VPPType('vl_api_eid_t',
600                       [["vl_api_eid_type_t", "type"],
601                        ["vl_api_eid_address_t", "address"]])
602
603         b = eid.pack({'type':1,
604                       'address': {
605                           'mac': MACAddress('aa:bb:cc:dd:ee:ff')}})
606         self.assertEqual(len(b), 25)
607         nt, size = eid.unpack(b)
608         self.assertEqual(str(nt.address.mac), 'aa:bb:cc:dd:ee:ff')
609         self.assertIsNone(nt.address.prefix)
610
611
612 class TestVppSerializerLogging(unittest.TestCase):
613
614     def test_logger(self):
615         # test logger name 'vpp_papi.serializer'
616         with self.assertRaises(VPPSerializerValueError) as ctx:
617             with self.assertLogs('vpp_papi.serializer', level='DEBUG') as cm:
618                 u = VPPUnionType('vl_api_eid_address_t',
619                                  [["vl_api_prefix_t", "prefix"],
620                                   ["vl_api_mac_address_t", "mac"],
621                                   ["vl_api_nsh_t", "nsh"]])
622         self.assertEqual(cm.output, ["DEBUG:vpp_papi.serializer:Unknown union type vl_api_prefix_t"])
623
624         # test parent logger name 'vpp_papi'
625         with self.assertRaises(VPPSerializerValueError) as ctx:
626             with self.assertLogs('vpp_papi', level='DEBUG') as cm:
627                 u = VPPUnionType('vl_api_eid_address_t',
628                                  [["vl_api_prefix_t", "prefix"],
629                                   ["vl_api_mac_address_t", "mac"],
630                                   ["vl_api_nsh_t", "nsh"]])
631         self.assertEqual(cm.output, ["DEBUG:vpp_papi.serializer:Unknown union type vl_api_prefix_t"])
632
633
634 if __name__ == '__main__':
635     unittest.main()