blob: 20f6c6da10dcca40d04c034349a513aa2ff7ddfa [file] [log] [blame]
Paul Vinciguerra7e0c48e2019-02-01 19:37:45 -08001#!/usr/bin/env python3
Ole Troan9d420872017-10-12 13:06:35 +02002
3import unittest
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004from vppapigen import VPPAPI, Option, ParseError, Union, foldup_crcs, global_types
Ole Troan9f84e702020-06-25 14:27:46 +02005import vppapigen
Ole Troan9d420872017-10-12 13:06:35 +02006
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -05007
Ole Troan9d420872017-10-12 13:06:35 +02008# TODO
Ole Troan9f84e702020-06-25 14:27:46 +02009# - test parsing of options, typedefs, enums, defines
Ole Troan9d420872017-10-12 13:06:35 +020010# - test JSON, C output
11
12
13class TestVersion(unittest.TestCase):
14 @classmethod
15 def setUpClass(cls):
16 cls.parser = VPPAPI()
17
18 def test_version(self):
19 version_string = 'option version = "1.0.0";'
20 r = self.parser.parse_string(version_string)
21 self.assertTrue(isinstance(r[0], Option))
22
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -050023
Ole Troand5a78a52019-09-18 12:12:47 +020024class TestUnion(unittest.TestCase):
25 @classmethod
26 def setUpClass(cls):
27 cls.parser = VPPAPI()
28
29 def test_union(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020030 test_string = """
Ole Troand5a78a52019-09-18 12:12:47 +020031 union foo_union {
32 u32 a;
33 u8 b;
34 };
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020035 """
Ole Troand5a78a52019-09-18 12:12:47 +020036 r = self.parser.parse_string(test_string)
37 self.assertTrue(isinstance(r[0], Union))
38
39 def test_union_vla(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020040 test_string = """
Ole Troand5a78a52019-09-18 12:12:47 +020041 union foo_union_vla {
42 u32 a;
43 u8 b[a];
44 };
45 autoreply define foo {
46 vl_api_foo_union_vla_t v;
47 };
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020048 """
Ole Troand5a78a52019-09-18 12:12:47 +020049 r = self.parser.parse_string(test_string)
50 self.assertTrue(isinstance(r[0], Union))
51 self.assertTrue(r[0].vla)
52 s = self.parser.process(r)
53
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020054 test_string2 = """
Ole Troand5a78a52019-09-18 12:12:47 +020055 union foo_union_vla2 {
56 u32 a;
57 u8 b[a];
58 u32 c;
59 };
60 autoreply define foo2 {
61 vl_api_foo_union_vla2_t v;
62 };
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020063 """
Ole Troand5a78a52019-09-18 12:12:47 +020064 self.assertRaises(ValueError, self.parser.parse_string, test_string2)
65
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020066 test_string3 = """
Ole Troand5a78a52019-09-18 12:12:47 +020067 union foo_union_vla3 {
68 u32 a;
69 u8 b[a];
70 };
71 autoreply define foo3 {
72 vl_api_foo_union_vla3_t v;
73 u32 x;
74 };
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020075 """
Ole Troand5a78a52019-09-18 12:12:47 +020076 self.assertRaises(ValueError, self.parser.parse_string, test_string3)
Ole Troan9d420872017-10-12 13:06:35 +020077
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -050078
Ole Troan9d420872017-10-12 13:06:35 +020079class TestTypedef(unittest.TestCase):
80 @classmethod
81 def setUpClass(cls):
82 cls.parser = VPPAPI()
83
84 def test_duplicatetype(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020085 test_string = """
Paul Vinciguerra4bf84902019-07-31 00:34:05 -040086 typedef foo1 { u8 dummy; };
87 typedef foo1 { u8 dummy; };
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020088 """
Ole Troan9d420872017-10-12 13:06:35 +020089 self.assertRaises(KeyError, self.parser.parse_string, test_string)
90
91
92class TestDefine(unittest.TestCase):
93 @classmethod
94 def setUpClass(cls):
95 cls.parser = VPPAPI()
96
97 def test_unknowntype(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020098 test_string = "define foo { foobar foo;};"
Paul Vinciguerra4bf84902019-07-31 00:34:05 -040099 with self.assertRaises(ParseError) as ctx:
100 self.parser.parse_string(test_string)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200101 self.assertIn("Undefined type: foobar", str(ctx.exception))
Paul Vinciguerra4bf84902019-07-31 00:34:05 -0400102
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200103 test_string = "define { u8 foo;};"
Paul Vinciguerra4bf84902019-07-31 00:34:05 -0400104 with self.assertRaises(ParseError) as ctx:
105 self.parser.parse_string(test_string)
Ole Troan9d420872017-10-12 13:06:35 +0200106
107 def test_flags(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200108 test_string = """
Ole Troan9d420872017-10-12 13:06:35 +0200109 manual_print dont_trace manual_endian define foo { u8 foo; };
Paul Vinciguerra4bf84902019-07-31 00:34:05 -0400110 define foo_reply {u32 context; i32 retval; };
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200111 """
Ole Troan9d420872017-10-12 13:06:35 +0200112 r = self.parser.parse_string(test_string)
113 self.assertIsNotNone(r)
114 s = self.parser.process(r)
115 self.assertIsNotNone(s)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200116 for d in s["Define"]:
117 if d.name == "foo":
Paul Vinciguerra4bf84902019-07-31 00:34:05 -0400118 self.assertTrue(d.dont_trace)
119 self.assertTrue(d.manual_endian)
120 self.assertTrue(d.manual_print)
121 self.assertFalse(d.autoreply)
Ole Troan9d420872017-10-12 13:06:35 +0200122
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200123 test_string = """
Ole Troan9d420872017-10-12 13:06:35 +0200124 nonexisting_flag define foo { u8 foo; };
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200125 """
Paul Vinciguerra7e0c48e2019-02-01 19:37:45 -0800126 with self.assertRaises(ParseError):
127 self.parser.parse_string(test_string)
Ole Troan9d420872017-10-12 13:06:35 +0200128
Ole Troan68ebcd52020-08-10 17:06:44 +0200129 def test_options(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200130 test_string = """
Ole Troan68ebcd52020-08-10 17:06:44 +0200131 define foo { option deprecated; u8 foo; };
132 define foo_reply {u32 context; i32 retval; };
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200133 """
Ole Troan68ebcd52020-08-10 17:06:44 +0200134 r = self.parser.parse_string(test_string)
135 self.assertIsNotNone(r)
136 s = self.parser.process(r)
137 self.assertIsNotNone(s)
138
Ole Troan9d420872017-10-12 13:06:35 +0200139
140class TestService(unittest.TestCase):
141 @classmethod
142 def setUpClass(cls):
143 cls.parser = VPPAPI()
144
145 def test_service(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200146 test_string = """
Paul Vinciguerra4bf84902019-07-31 00:34:05 -0400147 autoreply define show_version { u8 foo;};
148 service { rpc show_version returns show_version_reply; };
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200149 """
Ole Troan9d420872017-10-12 13:06:35 +0200150 r = self.parser.parse_string(test_string)
Paul Vinciguerra4bf84902019-07-31 00:34:05 -0400151 s = self.parser.process(r)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200152 self.assertEqual(s["Service"][0].caller, "show_version")
153 self.assertEqual(s["Service"][0].reply, "show_version_reply")
Ole Troan9d420872017-10-12 13:06:35 +0200154
155
Ole Troan9f84e702020-06-25 14:27:46 +0200156def get_crc(apistring, name):
157 vppapigen.global_types = {}
158 parser = vppapigen.VPPAPI()
159 r = parser.parse_string(apistring)
160 s = parser.process(r)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200161 foldup_crcs(s["Define"])
162 d = [f for f in s["Define"] if f.name == name]
Ole Troan9f84e702020-06-25 14:27:46 +0200163 return d[0].crc
164
165
166class TestCRC(unittest.TestCase):
167 def test_crc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200168 test_string = """
Ole Troan9f84e702020-06-25 14:27:46 +0200169 typedef list { u8 foo; };
170 autoreply define foo { u8 foo; vl_api_list_t l;};
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200171 """
172 crc = get_crc(test_string, "foo")
Ole Troan9f84e702020-06-25 14:27:46 +0200173
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -0500174 # modify underlying type
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200175 test_string = """
Ole Troan9f84e702020-06-25 14:27:46 +0200176 typedef list { u8 foo2; };
177 autoreply define foo { u8 foo; vl_api_list_t l;};
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200178 """
179 crc2 = get_crc(test_string, "foo")
Ole Troan9f84e702020-06-25 14:27:46 +0200180 self.assertNotEqual(crc, crc2)
181
182 # two user-defined types
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200183 test_string = """
Ole Troan9f84e702020-06-25 14:27:46 +0200184 typedef address { u8 foo2; };
185 typedef list { u8 foo2; vl_api_address_t add; };
186 autoreply define foo { u8 foo; vl_api_list_t l;};
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200187 """
188 crc3 = get_crc(test_string, "foo")
Ole Troan9f84e702020-06-25 14:27:46 +0200189
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200190 test_string = """
Ole Troan9f84e702020-06-25 14:27:46 +0200191 typedef address { u8 foo3; };
192 typedef list { u8 foo2; vl_api_address_t add; };
193 autoreply define foo { u8 foo; vl_api_list_t l;};
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200194 """
195 crc4 = get_crc(test_string, "foo")
Ole Troan9f84e702020-06-25 14:27:46 +0200196 self.assertNotEqual(crc3, crc4)
197
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200198 test_string = """
Ole Troan9f84e702020-06-25 14:27:46 +0200199 typedef address { u8 foo3; };
200 typedef list { u8 foo2; vl_api_address_t add; u8 foo3; };
201 autoreply define foo { u8 foo; vl_api_list_t l;};
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200202 """
203 crc5 = get_crc(test_string, "foo")
Ole Troan9f84e702020-06-25 14:27:46 +0200204 self.assertNotEqual(crc4, crc5)
205
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200206 test_string = """
Ole Troan9f84e702020-06-25 14:27:46 +0200207typedef ip6_address
208{
209 u8 foo;
210};
211typedef srv6_sid_list
212{
213 u8 num_sids;
214 u32 weight;
215 u32 sl_index;
216 vl_api_ip6_address_t sids[16];
217};
218autoreply define sr_policy_add
219{
220 u32 client_index;
221 u32 context;
222 vl_api_ip6_address_t bsid_addr;
223 u32 weight;
224 bool is_encap;
225 bool is_spray;
226 u32 fib_table;
227 vl_api_srv6_sid_list_t sids;
228};
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200229"""
Ole Troan9f84e702020-06-25 14:27:46 +0200230
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200231 crc = get_crc(test_string, "sr_policy_add")
Ole Troan9f84e702020-06-25 14:27:46 +0200232
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200233 test_string = """
Ole Troan9f84e702020-06-25 14:27:46 +0200234typedef ip6_address
235{
236 u8 foo;
237};
238typedef srv6_sid_list
239{
240 u8 num_sids;
241 u32 weight;
242 vl_api_ip6_address_t sids[16];
243};
244autoreply define sr_policy_add
245{
246 u32 client_index;
247 u32 context;
248 vl_api_ip6_address_t bsid_addr;
249 u32 weight;
250 bool is_encap;
251 bool is_spray;
252 u32 fib_table;
253 vl_api_srv6_sid_list_t sids;
254};
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200255"""
256 crc2 = get_crc(test_string, "sr_policy_add")
Ole Troan9f84e702020-06-25 14:27:46 +0200257
258 self.assertNotEqual(crc, crc2)
259
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -0500260
261class TestEnum(unittest.TestCase):
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -0500262 @classmethod
263 def setUpClass(cls):
264 cls.parser = VPPAPI()
265
266 def test_enum_as_enum(self):
267 test_string = """\
268enum tunnel_mode : u8
269{
270 /** point-to-point */
271 TUNNEL_API_MODE_P2P = 0,
272 /** multi-point */
273 TUNNEL_API_MODE_MP,
274};
275"""
276 r = self.parser.parse_string(test_string)
277 self.assertIsNotNone(r)
278 s = self.parser.process(r)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200279 for o in s["types"]:
280 if o.type == "Enum":
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -0500281 self.assertEqual(o.name, "tunnel_mode")
282 break
283 else:
284 self.fail()
285
286 def test_enumflag_as_enum(self):
287 test_string = """\
288enum virtio_flags {
289 VIRTIO_API_FLAG_GSO = 1, /* enable gso on the interface */
290 VIRTIO_API_FLAG_CSUM_OFFLOAD = 2, /* enable checksum offload without gso on the interface */
291 VIRTIO_API_FLAG_GRO_COALESCE = 4, /* enable packet coalescing on tx side, provided gso enabled */
292 VIRTIO_API_FLAG_PACKED = 8, /* enable packed ring support, provided it is available from backend */
293 VIRTIO_API_FLAG_IN_ORDER = 16, /* enable in order support, provided it is available from backend */
294 VIRTIO_API_FLAG_BUFFERING = 32 [backwards_compatible], /* enable buffering to handle backend jitter/delays */
295};"""
296 r = self.parser.parse_string(test_string)
297 self.assertIsNotNone(r)
298 s = self.parser.process(r)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200299 for o in s["types"]:
300 if o.type == "Enum":
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -0500301 self.assertEqual(o.name, "virtio_flags")
302 break
303 else:
304 self.fail()
305
306
307class TestEnumFlag(unittest.TestCase):
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -0500308 @classmethod
309 def setUpClass(cls):
310 cls.parser = VPPAPI()
311
312 def test_enum_as_enumflag(self):
313 test_string = """\
314enumflag tunnel_mode_ef : u8
315{
316 /** point-to-point */
317 TUNNEL_API_MODE_P2P = 0,
318 /** multi-point */
319 TUNNEL_API_MODE_MP,
320 TUNNEL_API_MODE_FOO,
321 TUNNEL_API_MODE_BAR,
322};"""
323 with self.assertRaises(TypeError) as ctx:
324 r = self.parser.parse_string(test_string)
325
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200326 self.assertTrue(
327 str(ctx.exception).startswith("tunnel_mode_ef is not a flag enum.")
328 )
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -0500329
330 def test_enumflag_as_enumflag(self):
331 test_string = """\
332enumflag virtio_flags_ef {
333 VIRTIO_API_FLAG_GSO = 1, /* enable gso on the interface */
334 VIRTIO_API_FLAG_CSUM_OFFLOAD = 2, /* enable checksum offload without gso on the interface */
335 VIRTIO_API_FLAG_GRO_COALESCE = 4, /* enable packet coalescing on tx side, provided gso enabled */
336 VIRTIO_API_FLAG_PACKED = 8, /* enable packed ring support, provided it is available from backend */
337 VIRTIO_API_FLAG_IN_ORDER = 16, /* enable in order support, provided it is available from backend */
338 VIRTIO_API_FLAG_BUFFERING = 32 [backwards_compatible], /* enable buffering to handle backend jitter/delays */
339};"""
340 r = self.parser.parse_string(test_string)
341 self.assertIsNotNone(r)
342 s = self.parser.process(r)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200343 for o in s["types"]:
344 if o.type == "EnumFlag":
Paul Vinciguerraa51f9b32020-11-24 23:26:06 -0500345 self.assertEqual(o.name, "virtio_flags_ef")
346 break
347 else:
348 self.fail()
349
350
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200351if __name__ == "__main__":
Paul Vinciguerra4bf84902019-07-31 00:34:05 -0400352 unittest.main(verbosity=2)