blob: 3b9ae26f07874dbfcd25a936923d609ff8c74df3 [file] [log] [blame]
Rich Lanea06d0c32013-03-25 08:52:03 -07001#!/usr/bin/env python
2# Copyright 2013, Big Switch Networks, Inc.
3#
4# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
5# the following special exception:
6#
7# LOXI Exception
8#
9# As a special exception to the terms of the EPL, you may distribute libraries
10# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
11# that copyright and licensing notices generated by LoxiGen are not altered or removed
12# from the LoxiGen Libraries and the notice provided below is (i) included in
13# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
14# documentation for the LoxiGen Libraries, if distributed in binary form.
15#
16# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
17#
18# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
19# a copy of the EPL at:
20#
21# http://www.eclipse.org/legal/epl-v10.html
22#
23# Unless required by applicable law or agreed to in writing, software
24# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
25# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
26# EPL for the specific language governing permissions and limitations
27# under the EPL.
28
Rich Lane569338c2013-06-17 15:51:24 -070029import sys
30import os
Rich Lanea06d0c32013-03-25 08:52:03 -070031import unittest
Rich Lane569338c2013-06-17 15:51:24 -070032
33root_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
34sys.path.insert(0, root_dir)
35
Rich Lanea06d0c32013-03-25 08:52:03 -070036import pyparsing
37import loxi_front_end.parser as parser
38
39class StructTests(unittest.TestCase):
40 def test_empty(self):
41 src = """\
42struct foo { };
43"""
44 ast = parser.parse(src)
Andreas Wundsam529e6c52013-08-03 13:41:48 -070045 self.assertEquals(ast, [['struct', 'foo', [], None, []]])
Rich Lanea06d0c32013-03-25 08:52:03 -070046
47 def test_one_field(self):
48 src = """\
49struct foo {
50 uint32_t bar;
51};
52"""
53 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -070054 self.assertEquals(ast,
Andreas Wundsamdfeb5942013-09-19 13:07:49 -070055 [['struct', 'foo', [], None, [['data', ['scalar', 'uint32_t'], 'bar']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -070056
Andreas Wundsam7e5b0e72013-08-03 20:23:43 -070057 def test_struct_align_arg(self):
58 src = """\
59struct foo(align=8) {
60 uint32_t bar;
61};
62"""
63 ast = parser.parse(src)
64 self.assertEquals(ast,
Andreas Wundsamdfeb5942013-09-19 13:07:49 -070065 [['struct', 'foo', [['align', '8']], None, [['data', ['scalar', 'uint32_t'], 'bar']]]])
Andreas Wundsam7e5b0e72013-08-03 20:23:43 -070066
Rich Lanea06d0c32013-03-25 08:52:03 -070067 def test_multiple_fields(self):
68 src = """\
69struct foo {
70 uint32_t bar;
71 uint8_t baz;
72 uint64_t abc;
73};
74"""
75 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -070076 self.assertEquals(ast,
Andreas Wundsam529e6c52013-08-03 13:41:48 -070077 [['struct', 'foo', [], None,
Andreas Wundsamdfeb5942013-09-19 13:07:49 -070078 [['data', ['scalar', 'uint32_t'], 'bar'],
79 ['data', ['scalar', 'uint8_t'], 'baz'],
80 ['data', ['scalar', 'uint64_t'], 'abc']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -070081
82 def test_array_type(self):
83 src = """\
84struct foo {
85 uint32_t[4] bar;
86};
87"""
88 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -070089 self.assertEquals(ast,
Andreas Wundsamdfeb5942013-09-19 13:07:49 -070090 [['struct', 'foo', [], None, [['data', ['array', 'uint32_t[4]'], 'bar']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -070091
92 def test_list_type(self):
93 src = """\
94struct foo {
95 list(of_action_t) bar;
96};
97"""
98 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -070099 self.assertEquals(ast,
Andreas Wundsamdfeb5942013-09-19 13:07:49 -0700100 [['struct', 'foo', [], None, [['data', ['list', 'list(of_action_t)'], 'bar']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -0700101
Rich Lane32142872013-05-09 21:16:47 -0700102 def test_pad_member(self):
Rich Lanee4d04ea2013-05-09 11:27:06 -0700103 src = """\
104struct foo {
105 pad(1);
106};
107"""
108 ast = parser.parse(src)
109 self.assertEquals(ast,
Andreas Wundsam529e6c52013-08-03 13:41:48 -0700110 [['struct', 'foo', [], None, [['pad', 1]]]])
Rich Lanee4d04ea2013-05-09 11:27:06 -0700111
Rich Lane32142872013-05-09 21:16:47 -0700112 def test_type_member(self):
113 src = """\
114struct foo {
115 uint16_t foo == 0x10;
116};
117"""
118 ast = parser.parse(src)
119 self.assertEquals(ast,
Andreas Wundsamdfeb5942013-09-19 13:07:49 -0700120 [['struct', 'foo', [], None, [['type', ['scalar', 'uint16_t'], 'foo', 0x10]]]])
Rich Lanebd431502013-06-21 16:30:20 -0700121
122 def test_inheritance(self):
123 src = """\
124struct foo : bar {
125 uint16_t foo == 0x10;
126};
127"""
128 ast = parser.parse(src)
129 self.assertEquals(ast,
Andreas Wundsamdfeb5942013-09-19 13:07:49 -0700130 [['struct', 'foo', [], 'bar', [['type', ['scalar', 'uint16_t'], 'foo', 0x10]]]])
Rich Lane32142872013-05-09 21:16:47 -0700131
Andreas Wundsam7e5b0e72013-08-03 20:23:43 -0700132 def test_discriminator(self):
133 src = """\
134struct foo {
135 uint16_t foo == ?;
136};
137"""
138 ast = parser.parse(src)
139 self.assertEquals(ast,
Andreas Wundsamdfeb5942013-09-19 13:07:49 -0700140 [['struct', 'foo', [], None, [['discriminator', ['scalar', 'uint16_t'], 'foo']]]])
Andreas Wundsam7e5b0e72013-08-03 20:23:43 -0700141
Murat Parlakisik34863382016-12-05 00:53:17 -0800142 def test_field_length(self):
143 src = """\
144struct foo {
145 uint16_t list_len == length(list);
146 list(of_uint32_t) list;
147};
148"""
149 ast = parser.parse(src)
150 self.assertEquals(ast,
151 [['struct', 'foo', [], None, [
152 ['field_length', ['scalar', 'uint16_t'], 'list_len', 'list'],
153 ['data', ['list', 'list(of_uint32_t)'], 'list']]]])
154
Rich Lane517506c2013-04-08 14:08:31 -0700155class EnumTests(unittest.TestCase):
156 def test_empty(self):
157 src = """\
158enum foo {
159};
160"""
161 ast = parser.parse(src)
Andreas Wundsam529e6c52013-08-03 13:41:48 -0700162 self.assertEquals(ast, [['enum', 'foo', [], []]])
Rich Lane517506c2013-04-08 14:08:31 -0700163
164 def test_one(self):
165 src = """\
166enum foo {
167 BAR = 1
168};
169"""
170 ast = parser.parse(src)
Andreas Wundsam529e6c52013-08-03 13:41:48 -0700171 self.assertEquals(ast, [['enum', 'foo', [], [['BAR', [], 1]]]])
Rich Lane517506c2013-04-08 14:08:31 -0700172
Andreas Wundsam7e5b0e72013-08-03 20:23:43 -0700173 def test_params(self):
174 src = """\
175enum foo(wire_type=uint32, bitmask=False, complete=False) {
176 BAR = 1
177};
178"""
179 ast = parser.parse(src)
180 self.assertEquals(ast, [['enum', 'foo',
181 [ ['wire_type', 'uint32'], ['bitmask','False'], ['complete', 'False']],
182 [['BAR', [], 1]]]])
183
Rich Lane517506c2013-04-08 14:08:31 -0700184 def test_multiple(self):
185 src = """\
186enum foo {
187 OFP_A = 1,
188 OFP_B = 2,
189 OFP_C = 3
190};
191"""
192 ast = parser.parse(src)
Andreas Wundsam529e6c52013-08-03 13:41:48 -0700193 self.assertEquals(ast, [['enum', 'foo', [], [['OFP_A', [], 1], ['OFP_B', [], 2], ['OFP_C', [], 3]]]])
Rich Lane517506c2013-04-08 14:08:31 -0700194
195 def test_trailing_comma(self):
196 src = """\
197enum foo {
198 OFP_A = 1,
199 OFP_B = 2,
200 OFP_C = 3,
201};
202"""
203 ast = parser.parse(src)
Andreas Wundsam529e6c52013-08-03 13:41:48 -0700204 self.assertEquals(ast, [['enum', 'foo', [], [['OFP_A', [], 1], ['OFP_B', [], 2], ['OFP_C', [], 3]]]])
Rich Lane517506c2013-04-08 14:08:31 -0700205
Rich Lanea06d0c32013-03-25 08:52:03 -0700206class TestMetadata(unittest.TestCase):
207 def test_version(self):
208 src = """\
209#version 1
210"""
211 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700212 self.assertEquals(ast, [['metadata', 'version', '1']])
Rich Lanea06d0c32013-03-25 08:52:03 -0700213
214class TestToplevel(unittest.TestCase):
215 def test_multiple_structs(self):
216 src = """\
217struct foo { };
218struct bar { };
219"""
220 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700221 self.assertEquals(ast,
Andreas Wundsam529e6c52013-08-03 13:41:48 -0700222 [['struct', 'foo', [], None, []], ['struct', 'bar', [], None, []]])
Rich Lanea06d0c32013-03-25 08:52:03 -0700223
224 def test_comments(self):
225 src = """\
226// comment 1
227struct foo { //comment 2
228// comment 3
Andreas Wundsam53256162013-05-02 14:05:53 -0700229 uint32_t a; //comment 5
Rich Lanea06d0c32013-03-25 08:52:03 -0700230// comment 6
231};
232// comment 4
233"""
234 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700235 self.assertEquals(ast,
Andreas Wundsamdfeb5942013-09-19 13:07:49 -0700236 [['struct', 'foo', [], None, [['data', ['scalar', 'uint32_t'], 'a']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -0700237
238 def test_mixed(self):
239 src = """\
240#version 1
241struct foo { };
242#version 2
243struct bar { };
244"""
245 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700246 self.assertEquals(ast,
Rich Lanea06d0c32013-03-25 08:52:03 -0700247 [['metadata', 'version', '1'],
Andreas Wundsam529e6c52013-08-03 13:41:48 -0700248 ['struct', 'foo', [], None, []],
Rich Lanea06d0c32013-03-25 08:52:03 -0700249 ['metadata', 'version', '2'],
Andreas Wundsam529e6c52013-08-03 13:41:48 -0700250 ['struct', 'bar', [], None, []]])
Rich Lanea06d0c32013-03-25 08:52:03 -0700251
252class TestErrors(unittest.TestCase):
253 def syntax_error(self, src, regex):
254 with self.assertRaisesRegexp(pyparsing.ParseSyntaxException, regex):
255 parser.parse(src)
256
257 def test_missing_struct_syntax(self):
258 self.syntax_error('struct { uint32_t bar; };',
259 'Expected identifier \(at char 7\)')
260 self.syntax_error('struct foo uint32_t bar; };',
261 'Expected "{" \(at char 11\)')
262 self.syntax_error('struct foo { uint32_t bar; ;',
263 'Expected "}" \(at char 27\)')
264 self.syntax_error('struct foo { uint32_t bar; }',
265 'Expected ";" \(at char 28\)')
266
267 def test_invalid_type_name(self):
268 self.syntax_error('struct foo { list<of_action_t> bar; }',
269 'Expected "\(" \(at char 17\)')
270 self.syntax_error('struct foo { uint32_t[10 bar; }',
271 'Expected "\]" \(at char 24\)')
272
273 def test_invalid_member_syntax(self):
274 self.syntax_error('struct foo { bar; }',
275 'Expected identifier \(at char 16\)')
276 self.syntax_error('struct foo { uint32_t bar baz; }',
277 'Expected ";" \(at char 26\)')
278
279
280if __name__ == '__main__':
281 unittest.main()