#!/usr/bin/env python3 import unittest from vppapigen import VPPAPI, Option, ParseError, Union, foldup_crcs, global_types import vppapigen # TODO # - test parsing of options, typedefs, enums, defines # - test JSON, C output class TestVersion(unittest.TestCase): @classmethod def setUpClass(cls): cls.parser = VPPAPI() def test_version(self): version_string = 'option version = "1.0.0";' r = self.parser.parse_string(version_string) self.assertTrue(isinstance(r[0], Option)) class TestUnion(unittest.TestCase): @classmethod def setUpClass(cls): cls.parser = VPPAPI() def test_union(self): test_string = ''' union foo_union { u32 a; u8 b; }; ''' r = self.parser.parse_string(test_string) self.assertTrue(isinstance(r[0], Union)) def test_union_vla(self): test_string = ''' union foo_union_vla { u32 a; u8 b[a]; }; autoreply define foo { vl_api_foo_union_vla_t v; }; ''' r = self.parser.parse_string(test_string) self.assertTrue(isinstance(r[0], Union)) self.assertTrue(r[0].vla) s = self.parser.process(r) test_string2 = ''' union foo_union_vla2 { u32 a; u8 b[a]; u32 c; }; autoreply define foo2 { vl_api_foo_union_vla2_t v; }; ''' self.assertRaises(ValueError, self.parser.parse_string, test_string2) test_string3 = ''' union foo_union_vla3 { u32 a; u8 b[a]; }; autoreply define foo3 { vl_api_foo_union_vla3_t v; u32 x; }; ''' self.assertRaises(ValueError, self.parser.parse_string, test_string3) class TestTypedef(unittest.TestCase): @classmethod def setUpClass(cls): cls.parser = VPPAPI() def test_duplicatetype(self): test_string = ''' typedef foo1 { u8 dummy; }; typedef foo1 { u8 dummy; }; ''' self.assertRaises(KeyError, self.parser.parse_string, test_string) class TestDefine(unittest.TestCase): @classmethod def setUpClass(cls): cls.parser = VPPAPI() def test_unknowntype(self): test_string = 'define foo { foobar foo;};' with self.assertRaises(ParseError) as ctx: self.parser.parse_string(test_string) self.assertIn('Undefined type: foobar', str(ctx.exception)) test_string = 'define { u8 foo;};' with self.assertRaises(ParseError) as ctx: self.parser.parse_string(test_string) def test_flags(self): test_string = ''' manual_print dont_trace manual_endian define foo { u8 foo; }; define foo_reply {u32 context; i32 retval; }; ''' r = self.parser.parse_string(test_string) self.assertIsNotNone(r) s = self.parser.process(r) self.assertIsNotNone(s) for d in s['Define']: if d.name == 'foo': self.assertTrue(d.dont_trace) self.assertTrue(d.manual_endian) self.assertTrue(d.manual_print) self.assertFalse(d.autoreply) test_string = ''' nonexisting_flag define foo { u8 foo; }; ''' with self.assertRaises(ParseError): self.parser.parse_string(test_string) class TestService(unittest.TestCase): @classmethod def setUpClass(cls): cls.parser = VPPAPI() def test_service(self): test_string = ''' autoreply define show_version { u8 foo;}; service { rpc show_version returns show_version_reply; }; ''' r = self.parser.parse_string(test_string) s = self.parser.process(r) self.assertEqual(s['Service'][0].caller, 'show_version') self.assertEqual(s['Service'][0].reply, 'show_version_reply') def get_crc(apistring, name): vppapigen.global_types = {} parser = vppapigen.VPPAPI() r = parser.parse_string(apistring) s = parser.process(r) foldup_crcs(s['Define']) d = [f for f in s['Define'] if f.name == name] return d[0].crc class TestCRC(unittest.TestCase): def test_crc(self): test_string = ''' typedef list { u8 foo; }; autoreply define foo { u8 foo; vl_api_list_t l;}; ''' crc = get_crc(test_string, 'foo') # modify underlaying type test_string = ''' typedef list { u8 foo2; }; autoreply define foo { u8 foo; vl_api_list_t l;}; ''' crc2 = get_crc(test_string, 'foo') self.assertNotEqual(crc, crc2) # two user-defined types test_string = ''' typedef address { u8 foo2; }; typedef list { u8 foo2; vl_api_address_t add; }; autoreply define foo { u8 foo; vl_api_list_t l;}; ''' crc3 = get_crc(test_string, 'foo') test_string = ''' typedef address { u8 foo3; }; typedef list { u8 foo2; vl_api_address_t add; }; autoreply define foo { u8 foo; vl_api_list_t l;}; ''' crc4 = get_crc(test_string, 'foo') self.assertNotEqual(crc3, crc4) test_string = ''' typedef address { u8 foo3; }; typedef list { u8 foo2; vl_api_address_t add; u8 foo3; }; autoreply define foo { u8 foo; vl_api_list_t l;}; ''' crc5 = get_crc(test_string, 'foo') self.assertNotEqual(crc4, crc5) test_string = ''' typedef ip6_address { u8 foo; }; typedef srv6_sid_list { u8 num_sids; u32 weight; u32 sl_index; vl_api_ip6_address_t sids[16]; }; autoreply define sr_policy_add { u32 client_index; u32 context; vl_api_ip6_address_t bsid_addr; u32 weight; bool is_encap; bool is_spray; u32 fib_table; vl_api_srv6_sid_list_t sids; }; ''' crc = get_crc(test_string, 'sr_policy_add') test_string = ''' typedef ip6_address { u8 foo; }; typedef srv6_sid_list { u8 num_sids; u32 weight; vl_api_ip6_address_t sids[16]; }; autoreply define sr_policy_add { u32 client_index; u32 context; vl_api_ip6_address_t bsid_addr; u32 weight; bool is_encap; bool is_spray; u32 fib_table; vl_api_srv6_sid_list_t sids; }; ''' crc2 = get_crc(test_string, 'sr_policy_add') self.assertNotEqual(crc, crc2) if __name__ == '__main__': unittest.main(verbosity=2)