blob: 40d2913911bd964390da5d35c504d018b120ea86 [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)
Rich Lane43b2a902013-05-09 13:47:07 -070045 self.assertEquals(ast, [['struct', 'foo', []]])
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,
Rich Lanef424e972013-05-09 21:00:13 -070055 [['struct', 'foo', [['data', 'uint32_t', 'bar']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -070056
57 def test_multiple_fields(self):
58 src = """\
59struct foo {
60 uint32_t bar;
61 uint8_t baz;
62 uint64_t abc;
63};
64"""
65 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -070066 self.assertEquals(ast,
Rich Lanea06d0c32013-03-25 08:52:03 -070067 [['struct', 'foo',
Rich Lanef424e972013-05-09 21:00:13 -070068 [['data', 'uint32_t', 'bar'],
69 ['data', 'uint8_t', 'baz'],
70 ['data', 'uint64_t', 'abc']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -070071
72 def test_array_type(self):
73 src = """\
74struct foo {
75 uint32_t[4] bar;
76};
77"""
78 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -070079 self.assertEquals(ast,
Rich Lanef424e972013-05-09 21:00:13 -070080 [['struct', 'foo', [['data', 'uint32_t[4]', 'bar']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -070081
82 def test_list_type(self):
83 src = """\
84struct foo {
85 list(of_action_t) bar;
86};
87"""
88 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -070089 self.assertEquals(ast,
Rich Lanef424e972013-05-09 21:00:13 -070090 [['struct', 'foo', [['data', 'list(of_action_t)', 'bar']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -070091
Rich Lane32142872013-05-09 21:16:47 -070092 def test_pad_member(self):
Rich Lanee4d04ea2013-05-09 11:27:06 -070093 src = """\
94struct foo {
95 pad(1);
96};
97"""
98 ast = parser.parse(src)
99 self.assertEquals(ast,
100 [['struct', 'foo', [['pad', 1]]]])
101
Rich Lane32142872013-05-09 21:16:47 -0700102 def test_type_member(self):
103 src = """\
104struct foo {
105 uint16_t foo == 0x10;
106};
107"""
108 ast = parser.parse(src)
109 self.assertEquals(ast,
110 [['struct', 'foo', [['type', 'uint16_t', 'foo', 0x10]]]])
111
Rich Lane517506c2013-04-08 14:08:31 -0700112class EnumTests(unittest.TestCase):
113 def test_empty(self):
114 src = """\
115enum foo {
116};
117"""
118 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700119 self.assertEquals(ast, [['enum', 'foo', []]])
Rich Lane517506c2013-04-08 14:08:31 -0700120
121 def test_one(self):
122 src = """\
123enum foo {
124 BAR = 1
125};
126"""
127 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700128 self.assertEquals(ast, [['enum', 'foo', [['BAR', 1]]]])
Rich Lane517506c2013-04-08 14:08:31 -0700129
130 def test_multiple(self):
131 src = """\
132enum foo {
133 OFP_A = 1,
134 OFP_B = 2,
135 OFP_C = 3
136};
137"""
138 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700139 self.assertEquals(ast, [['enum', 'foo', [['OFP_A', 1], ['OFP_B', 2], ['OFP_C', 3]]]])
Rich Lane517506c2013-04-08 14:08:31 -0700140
141 def test_trailing_comma(self):
142 src = """\
143enum foo {
144 OFP_A = 1,
145 OFP_B = 2,
146 OFP_C = 3,
147};
148"""
149 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700150 self.assertEquals(ast, [['enum', 'foo', [['OFP_A', 1], ['OFP_B', 2], ['OFP_C', 3]]]])
Rich Lane517506c2013-04-08 14:08:31 -0700151
Rich Lanea06d0c32013-03-25 08:52:03 -0700152class TestMetadata(unittest.TestCase):
153 def test_version(self):
154 src = """\
155#version 1
156"""
157 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700158 self.assertEquals(ast, [['metadata', 'version', '1']])
Rich Lanea06d0c32013-03-25 08:52:03 -0700159
160class TestToplevel(unittest.TestCase):
161 def test_multiple_structs(self):
162 src = """\
163struct foo { };
164struct bar { };
165"""
166 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700167 self.assertEquals(ast,
Rich Lanea06d0c32013-03-25 08:52:03 -0700168 [['struct', 'foo', []], ['struct', 'bar', []]])
169
170 def test_comments(self):
171 src = """\
172// comment 1
173struct foo { //comment 2
174// comment 3
Andreas Wundsam53256162013-05-02 14:05:53 -0700175 uint32_t a; //comment 5
Rich Lanea06d0c32013-03-25 08:52:03 -0700176// comment 6
177};
178// comment 4
179"""
180 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700181 self.assertEquals(ast,
Rich Lanef424e972013-05-09 21:00:13 -0700182 [['struct', 'foo', [['data', 'uint32_t', 'a']]]])
Rich Lanea06d0c32013-03-25 08:52:03 -0700183
184 def test_mixed(self):
185 src = """\
186#version 1
187struct foo { };
188#version 2
189struct bar { };
190"""
191 ast = parser.parse(src)
Rich Lane43b2a902013-05-09 13:47:07 -0700192 self.assertEquals(ast,
Rich Lanea06d0c32013-03-25 08:52:03 -0700193 [['metadata', 'version', '1'],
194 ['struct', 'foo', []],
195 ['metadata', 'version', '2'],
196 ['struct', 'bar', []]])
197
198class TestErrors(unittest.TestCase):
199 def syntax_error(self, src, regex):
200 with self.assertRaisesRegexp(pyparsing.ParseSyntaxException, regex):
201 parser.parse(src)
202
203 def test_missing_struct_syntax(self):
204 self.syntax_error('struct { uint32_t bar; };',
205 'Expected identifier \(at char 7\)')
206 self.syntax_error('struct foo uint32_t bar; };',
207 'Expected "{" \(at char 11\)')
208 self.syntax_error('struct foo { uint32_t bar; ;',
209 'Expected "}" \(at char 27\)')
210 self.syntax_error('struct foo { uint32_t bar; }',
211 'Expected ";" \(at char 28\)')
212
213 def test_invalid_type_name(self):
214 self.syntax_error('struct foo { list<of_action_t> bar; }',
215 'Expected "\(" \(at char 17\)')
216 self.syntax_error('struct foo { uint32_t[10 bar; }',
217 'Expected "\]" \(at char 24\)')
218
219 def test_invalid_member_syntax(self):
220 self.syntax_error('struct foo { bar; }',
221 'Expected identifier \(at char 16\)')
222 self.syntax_error('struct foo { uint32_t bar baz; }',
223 'Expected ";" \(at char 26\)')
224
225
226if __name__ == '__main__':
227 unittest.main()