]>
Commit | Line | Data |
---|---|---|
10b1662b BP |
1 | AT_BANNER([OVN]) |
2 | ||
3 | AT_SETUP([ovn -- lexer]) | |
4 | dnl For lines without =>, input and expected output are identical. | |
5 | dnl For lines with =>, input precedes => and expected output follows =>. | |
6 | AT_DATA([test-cases.txt], [dnl | |
7 | foo bar baz quuxquuxquux _abcd_ a.b.c.d a123_.456 | |
8 | "abc\u0020def" => "abc def" | |
9 | " => error("Input ends inside quoted string.")dnl " | |
10 | ||
11 | a/*b*/c => a c | |
12 | a//b c => a | |
13 | a/**/b => a b | |
14 | a/*/b => a error("`/*' without matching `*/'.") | |
15 | a/*/**/b => a b | |
16 | a/b => a error("`/' is only valid as part of `//' or `/*'.") b | |
17 | ||
18 | 0 1 12345 18446744073709551615 | |
19 | 18446744073709551616 => error("Decimal constants must be less than 2**64.") | |
20 | 9999999999999999999999 => error("Decimal constants must be less than 2**64.") | |
21 | 01 => error("Decimal constants must not have leading zeros.") | |
22 | ||
23 | 0/0 | |
24 | 0/1 | |
25 | 1/0 => error("Value contains unmasked 1-bits.") | |
26 | 1/1 | |
27 | 128/384 | |
28 | 1/3 | |
29 | 1/ => error("Integer constant expected.") | |
30 | ||
31 | 1/0x123 => error("Value and mask have incompatible formats.") | |
32 | ||
33 | 0x1234 | |
34 | 0x01234 => 0x1234 | |
35 | 0x0 => 0 | |
36 | 0x000 => 0 | |
37 | 0xfedcba9876543210 | |
38 | 0XFEDCBA9876543210 => 0xfedcba9876543210 | |
39 | 0xfedcba9876543210fedcba9876543210 | |
10b1662b BP |
40 | 0x0000fedcba9876543210fedcba9876543210 => 0xfedcba9876543210fedcba9876543210 |
41 | 0x => error("Hex digits expected following 0x.") | |
42 | 0X => error("Hex digits expected following 0X.") | |
43 | 0x0/0x0 => 0/0 | |
44 | 0x0/0x1 => 0/0x1 | |
45 | 0x1/0x0 => error("Value contains unmasked 1-bits.") | |
46 | 0xffff/0x1ffff | |
47 | 0x. => error("Invalid syntax in hexadecimal constant.") | |
48 | ||
49 | 192.168.128.1 1.2.3.4 255.255.255.255 0.0.0.0 | |
50 | 256.1.2.3 => error("Invalid numeric constant.") | |
51 | 192.168.0.0/16 | |
52 | 192.168.0.0/255.255.0.0 => 192.168.0.0/16 | |
53 | 192.168.0.0/255.255.255.0 => 192.168.0.0/24 | |
54 | 192.168.0.0/255.255.0.255 | |
55 | 192.168.0.0/255.0.0.0 => error("Value contains unmasked 1-bits.") | |
56 | 192.168.0.0/32 | |
57 | 192.168.0.0/255.255.255.255 => 192.168.0.0/32 | |
58 | ||
59 | :: | |
60 | ::1 | |
61 | ff00::1234 => ff00::1234 | |
62 | 2001:db8:85a3::8a2e:370:7334 | |
63 | 2001:db8:85a3:0:0:8a2e:370:7334 => 2001:db8:85a3::8a2e:370:7334 | |
64 | 2001:0db8:85a3:0000:0000:8a2e:0370:7334 => 2001:db8:85a3::8a2e:370:7334 | |
65 | ::ffff:192.0.2.128 | |
66 | ::ffff:c000:0280 => ::ffff:192.0.2.128 | |
67 | ::1/::1 | |
68 | ::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff => ::1/128 | |
69 | ::1/128 | |
70 | ff00::/8 | |
71 | ff00::/ff00:: => ff00::/8 | |
72 | ||
73 | 01:23:45:67:ab:cd | |
74 | 01:23:45:67:AB:CD => 01:23:45:67:ab:cd | |
75 | fe:dc:ba:98:76:54 | |
76 | FE:DC:ba:98:76:54 => fe:dc:ba:98:76:54 | |
77 | 01:00:00:00:00:00/01:00:00:00:00:00 | |
78 | ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff | |
79 | fe:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff | |
80 | ff:ff:ff:ff:ff:ff/fe:ff:ff:ff:ff:ff => error("Value contains unmasked 1-bits.") | |
81 | fe:x => error("Invalid numeric constant.") | |
82 | 00:01:02:03:04:x => error("Invalid numeric constant.") | |
83 | ||
84 | (){}[[]]==!=<<=>>=!&&||..,;= => ( ) { } [[ ]] == != < <= > >= ! && || .. , ; = | |
85 | & => error("`&' is only valid as part of `&&'.") | |
86 | | => error("`|' is only valid as part of `||'.") | |
87 | ||
88 | ^ => error("Invalid character `^' in input.") | |
89 | ]) | |
90 | AT_CAPTURE_FILE([input.txt]) | |
91 | sed 's/ =>.*//' test-cases.txt > input.txt | |
92 | sed 's/.* => //' test-cases.txt > expout | |
93 | AT_CHECK([ovstest test-ovn lex < input.txt], [0], [expout]) | |
94 | AT_CLEANUP | |
e0840f11 BP |
95 | |
96 | AT_SETUP([ovn -- expression parser]) | |
97 | dnl For lines without =>, input and expected output are identical. | |
98 | dnl For lines with =>, input precedes => and expected output follows =>. | |
99 | AT_DATA([test-cases.txt], [[ | |
100 | eth.type == 0x800 | |
101 | eth.type==0x800 => eth.type == 0x800 | |
102 | eth.type[0..15] == 0x800 => eth.type == 0x800 | |
103 | ||
104 | vlan.present | |
105 | vlan.present == 1 => vlan.present | |
106 | !(vlan.present == 0) => vlan.present | |
107 | !(vlan.present != 1) => vlan.present | |
108 | !vlan.present | |
109 | vlan.present == 0 => !vlan.present | |
110 | vlan.present != 1 => !vlan.present | |
111 | !(vlan.present == 1) => !vlan.present | |
112 | !(vlan.present != 0) => !vlan.present | |
113 | ||
114 | eth.dst[0] | |
115 | eth.dst[0] == 1 => eth.dst[0] | |
116 | eth.dst[0] != 0 => eth.dst[0] | |
117 | !(eth.dst[0] == 0) => eth.dst[0] | |
118 | !(eth.dst[0] != 1) => eth.dst[0] | |
119 | ||
120 | !eth.dst[0] | |
121 | eth.dst[0] == 0 => !eth.dst[0] | |
122 | eth.dst[0] != 1 => !eth.dst[0] | |
123 | !(eth.dst[0] == 1) => !eth.dst[0] | |
124 | !(eth.dst[0] != 0) => !eth.dst[0] | |
125 | ||
126 | vlan.tci[12..15] == 0x3 | |
127 | vlan.tci == 0x3000/0xf000 => vlan.tci[12..15] == 0x3 | |
128 | vlan.tci[12..15] != 0x3 | |
129 | vlan.tci != 0x3000/0xf000 => vlan.tci[12..15] != 0x3 | |
130 | ||
131 | !vlan.pcp => vlan.pcp == 0 | |
132 | !(vlan.pcp) => vlan.pcp == 0 | |
133 | vlan.pcp == 0x4 | |
134 | vlan.pcp != 0x4 | |
135 | vlan.pcp > 0x4 | |
136 | vlan.pcp >= 0x4 | |
137 | vlan.pcp < 0x4 | |
138 | vlan.pcp <= 0x4 | |
139 | !(vlan.pcp != 0x4) => vlan.pcp == 0x4 | |
140 | !(vlan.pcp == 0x4) => vlan.pcp != 0x4 | |
141 | !(vlan.pcp <= 0x4) => vlan.pcp > 0x4 | |
142 | !(vlan.pcp < 0x4) => vlan.pcp >= 0x4 | |
143 | !(vlan.pcp >= 0x4) => vlan.pcp < 0x4 | |
144 | !(vlan.pcp > 0x4) => vlan.pcp <= 0x4 | |
145 | 0x4 == vlan.pcp => vlan.pcp == 0x4 | |
146 | 0x4 != vlan.pcp => vlan.pcp != 0x4 | |
147 | 0x4 < vlan.pcp => vlan.pcp > 0x4 | |
148 | 0x4 <= vlan.pcp => vlan.pcp >= 0x4 | |
149 | 0x4 > vlan.pcp => vlan.pcp < 0x4 | |
150 | 0x4 >= vlan.pcp => vlan.pcp <= 0x4 | |
151 | !(0x4 != vlan.pcp) => vlan.pcp == 0x4 | |
152 | !(0x4 == vlan.pcp) => vlan.pcp != 0x4 | |
153 | !(0x4 >= vlan.pcp) => vlan.pcp > 0x4 | |
154 | !(0x4 > vlan.pcp) => vlan.pcp >= 0x4 | |
155 | !(0x4 <= vlan.pcp) => vlan.pcp < 0x4 | |
156 | !(0x4 < vlan.pcp) => vlan.pcp <= 0x4 | |
157 | ||
158 | 1 < vlan.pcp < 4 => vlan.pcp > 0x1 && vlan.pcp < 0x4 | |
159 | 1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4 | |
160 | 1 < vlan.pcp <= 4 => vlan.pcp > 0x1 && vlan.pcp <= 0x4 | |
161 | 1 <= vlan.pcp < 4 => vlan.pcp >= 0x1 && vlan.pcp < 0x4 | |
162 | 1 <= vlan.pcp <= 4 => vlan.pcp >= 0x1 && vlan.pcp <= 0x4 | |
163 | 4 > vlan.pcp > 1 => vlan.pcp < 0x4 && vlan.pcp > 0x1 | |
164 | 4 >= vlan.pcp > 1 => vlan.pcp <= 0x4 && vlan.pcp > 0x1 | |
165 | 4 > vlan.pcp >= 1 => vlan.pcp < 0x4 && vlan.pcp >= 0x1 | |
166 | 4 >= vlan.pcp >= 1 => vlan.pcp <= 0x4 && vlan.pcp >= 0x1 | |
167 | !(1 < vlan.pcp < 4) => vlan.pcp <= 0x1 || vlan.pcp >= 0x4 | |
168 | !(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4 | |
169 | !(1 < vlan.pcp <= 4) => vlan.pcp <= 0x1 || vlan.pcp > 0x4 | |
170 | !(1 <= vlan.pcp < 4) => vlan.pcp < 0x1 || vlan.pcp >= 0x4 | |
171 | !(1 <= vlan.pcp <= 4) => vlan.pcp < 0x1 || vlan.pcp > 0x4 | |
172 | !(4 > vlan.pcp > 1) => vlan.pcp >= 0x4 || vlan.pcp <= 0x1 | |
173 | !(4 >= vlan.pcp > 1) => vlan.pcp > 0x4 || vlan.pcp <= 0x1 | |
174 | !(4 > vlan.pcp >= 1) => vlan.pcp >= 0x4 || vlan.pcp < 0x1 | |
175 | !(4 >= vlan.pcp >= 1) => vlan.pcp > 0x4 || vlan.pcp < 0x1 | |
176 | ||
177 | vlan.pcp == {1, 2, 3, 4} => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 || vlan.pcp == 0x4 | |
178 | vlan.pcp == 1 || ((vlan.pcp == 2 || vlan.pcp == 3) || vlan.pcp == 4) => vlan.pcp == 0x1 || vlan.pcp == 0x2 || vlan.pcp == 0x3 || vlan.pcp == 0x4 | |
179 | ||
180 | vlan.pcp != {1, 2, 3, 4} => vlan.pcp != 0x1 && vlan.pcp != 0x2 && vlan.pcp != 0x3 && vlan.pcp != 0x4 | |
181 | vlan.pcp == 1 && ((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && vlan.pcp == 0x2 && vlan.pcp == 0x3 && vlan.pcp == 0x4 | |
182 | ||
183 | vlan.pcp == 1 && !((vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3 || vlan.pcp != 0x4) | |
184 | vlan.pcp == 1 && (!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && (vlan.pcp != 0x2 || vlan.pcp != 0x3) && vlan.pcp == 0x4 | |
185 | vlan.pcp == 1 && !(!(vlan.pcp == 2 && vlan.pcp == 3) && vlan.pcp == 4) => vlan.pcp == 0x1 && ((vlan.pcp == 0x2 && vlan.pcp == 0x3) || vlan.pcp != 0x4) | |
186 | ||
187 | ip4.src == {10.0.0.0/8, 192.168.0.0/16, 172.16.20.0/24, 8.8.8.8} => ip4.src[24..31] == 0xa || ip4.src[16..31] == 0xc0a8 || ip4.src[8..31] == 0xac1014 || ip4.src == 0x8080808 | |
188 | ip6.src == ::1 => ip6.src == 0x1 | |
189 | ||
190 | ip4.src == 1.2.3.4 => ip4.src == 0x1020304 | |
191 | ip4.src == ::1.2.3.4/::ffff:ffff => ip4.src == 0x1020304 | |
192 | ip6.src == ::1 => ip6.src == 0x1 | |
193 | ||
194 | 1 | |
195 | 0 | |
196 | !1 => 0 | |
197 | !0 => 1 | |
198 | ||
199 | inport == "eth0" | |
200 | !(inport != "eth0") => inport == "eth0" | |
201 | ||
3b7cb7e1 BP |
202 | ip4.src == "eth0" => Integer field ip4.src is not compatible with string constant. |
203 | inport == 1 => String field inport is not compatible with integer constant. | |
e0840f11 BP |
204 | |
205 | ip4.src > {1, 2, 3} => Only == and != operators may be used with value sets. | |
206 | eth.type > 0x800 => Only == and != operators may be used with nominal field eth.type. | |
207 | vlan.present > 0 => Only == and != operators may be used with Boolean field vlan.present. | |
208 | ||
209 | inport != "eth0" => Nominal field inport may only be tested for equality (taking enclosing `!' operators into account). | |
210 | !(inport == "eth0") => Nominal field inport may only be tested for equality (taking enclosing `!' operators into account). | |
211 | eth.type != 0x800 => Nominal field eth.type may only be tested for equality (taking enclosing `!' operators into account). | |
212 | !(eth.type == 0x800) => Nominal field eth.type may only be tested for equality (taking enclosing `!' operators into account). | |
213 | ||
214 | 123 == 123 => Syntax error at `123' expecting field name. | |
215 | ||
216 | 123 == xyzzy => Syntax error at `xyzzy' expecting field name. | |
217 | xyzzy == 1 => Syntax error at `xyzzy' expecting field name. | |
218 | ||
219 | inport[1] == 1 => Cannot select subfield of string field inport. | |
220 | ||
221 | eth.type[] == 1 => Syntax error at `@:>@' expecting small integer. | |
222 | eth.type[::1] == 1 => Syntax error at `::1' expecting small integer. | |
223 | eth.type[18446744073709551615] == 1 => Syntax error at `18446744073709551615' expecting small integer. | |
224 | ||
225 | eth.type[5!] => Syntax error at `!' expecting `@:>@'. | |
226 | ||
227 | eth.type[5..1] => Invalid bit range 5 to 1. | |
228 | ||
229 | eth.type[12..16] => Cannot select bits 12 to 16 of 16-bit field eth.type. | |
230 | ||
231 | eth.type[10] == 1 => Cannot select subfield of nominal field eth.type. | |
232 | ||
233 | eth.type => Explicit `!= 0' is required for inequality test of multibit field against 0. | |
234 | ||
235 | !(!(vlan.pcp)) => Explicit `!= 0' is required for inequality test of multibit field against 0. | |
236 | ||
237 | 123 => Syntax error at end of input expecting relational operator. | |
238 | ||
239 | 123 x => Syntax error at `x' expecting relational operator. | |
240 | ||
241 | {1, "eth0"} => Syntax error at `"eth0"' expecting integer. | |
242 | ||
243 | eth.type == xyzzy => Syntax error at `xyzzy' expecting constant. | |
244 | ||
245 | (1 x) => Syntax error at `x' expecting `)'. | |
246 | ||
247 | !0x800 != eth.type => Missing parentheses around operand of !. | |
248 | ||
249 | eth.type == 0x800 || eth.type == 0x86dd && ip.proto == 17 => && and || must be parenthesized when used together. | |
250 | ||
251 | eth.dst == {} => Syntax error at `}' expecting constant. | |
252 | ||
253 | eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff => Only == and != operators may be used with masked constants. Consider using subfields instead (e.g. eth.src[0..15] > 0x1111 in place of eth.src > 00:00:00:00:11:11/00:00:00:00:ff:ff). | |
254 | ||
3b7cb7e1 | 255 | ip4.src == ::1 => 128-bit constant is not compatible with 32-bit field ip4.src. |
e0840f11 BP |
256 | |
257 | 1 == eth.type == 2 => Range expressions must have the form `x < field < y' or `x > field > y', with each `<' optionally replaced by `<=' or `>' by `>='). | |
258 | ]]) | |
259 | sed 's/ =>.*//' test-cases.txt > input.txt | |
260 | sed 's/.* => //' test-cases.txt > expout | |
261 | AT_CHECK([ovstest test-ovn parse-expr < input.txt], [0], [expout]) | |
262 | AT_CLEANUP | |
263 | ||
264 | AT_SETUP([ovn -- expression annotation]) | |
265 | dnl Input precedes =>, expected output follows =>. | |
266 | AT_DATA([test-cases.txt], [[ | |
267 | ip4.src == 1.2.3.4 => ip4.src == 0x1020304 && eth.type == 0x800 | |
268 | ip4.src != 1.2.3.4 => ip4.src != 0x1020304 && eth.type == 0x800 | |
269 | ip.proto == 123 => ip.proto == 0x7b && (eth.type == 0x800 || eth.type == 0x86dd) | |
270 | ip.proto == {123, 234} => (ip.proto == 0x7b && (eth.type == 0x800 || eth.type == 0x86dd)) || (ip.proto == 0xea && (eth.type == 0x800 || eth.type == 0x86dd)) | |
271 | ip4.src == 1.2.3.4 && ip4.dst == 5.6.7.8 => ip4.src == 0x1020304 && eth.type == 0x800 && ip4.dst == 0x5060708 && eth.type == 0x800 | |
272 | ||
273 | ip => eth.type == 0x800 || eth.type == 0x86dd | |
274 | ip == 1 => eth.type == 0x800 || eth.type == 0x86dd | |
275 | ip[0] == 1 => eth.type == 0x800 || eth.type == 0x86dd | |
276 | ip > 0 => Only == and != operators may be used with nominal field ip. | |
277 | !ip => Nominal predicate ip may only be tested positively, e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'. | |
278 | ip == 0 => Nominal predicate ip may only be tested positively, e.g. `ip' or `ip == 1' but not `!ip' or `ip == 0'. | |
279 | ||
280 | vlan.present => vlan.tci[12] | |
281 | !vlan.present => !vlan.tci[12] | |
282 | ||
283 | !vlan.pcp => vlan.tci[13..15] == 0 && vlan.tci[12] | |
284 | vlan.pcp == 1 && vlan.vid == 2 => vlan.tci[13..15] == 0x1 && vlan.tci[12] && vlan.tci[0..11] == 0x2 && vlan.tci[12] | |
285 | !reg0 && !reg1 && !reg2 && !reg3 => xreg0[32..63] == 0 && xreg0[0..31] == 0 && xreg1[32..63] == 0 && xreg1[0..31] == 0 | |
286 | ||
287 | ip.first_frag => ip.frag[0] && (eth.type == 0x800 || eth.type == 0x86dd) && (!ip.frag[1] || (eth.type != 0x800 && eth.type != 0x86dd)) | |
288 | !ip.first_frag => !ip.frag[0] || (eth.type != 0x800 && eth.type != 0x86dd) || (ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd)) | |
289 | ip.later_frag => ip.frag[1] && (eth.type == 0x800 || eth.type == 0x86dd) | |
290 | ||
291 | bad_prereq != 0 => Error parsing expression `xyzzy' encountered as prerequisite or predicate of initial expression: Syntax error at `xyzzy' expecting field name. | |
292 | self_recurse != 0 => Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `self_recurse'. | |
293 | mutual_recurse_1 != 0 => Error parsing expression `mutual_recurse_2 != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `mutual_recurse_1 != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `mutual_recurse_1'. | |
294 | mutual_recurse_2 != 0 => Error parsing expression `mutual_recurse_1 != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `mutual_recurse_2 != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `mutual_recurse_2'. | |
295 | ]]) | |
296 | sed 's/ =>.*//' test-cases.txt > input.txt | |
297 | sed 's/.* => //' test-cases.txt > expout | |
298 | AT_CHECK([ovstest test-ovn annotate-expr < input.txt], [0], [expout]) | |
299 | AT_CLEANUP | |
300 | ||
301 | AT_SETUP([ovn -- expression conversion (1)]) | |
302 | AT_CHECK([ovstest test-ovn exhaustive --operation=convert 1], [0], | |
303 | [Tested converting all 1-terminal expressions with 2 vars each of 3 bits in terms of operators == != < <= > >=. | |
304 | ]) | |
305 | AT_CLEANUP | |
306 | ||
307 | AT_SETUP([ovn -- expression conversion (2)]) | |
308 | AT_CHECK([ovstest test-ovn exhaustive --operation=convert 2], [0], | |
309 | [Tested converting 562 expressions of 2 terminals with 2 vars each of 3 bits in terms of operators == != < <= > >=. | |
310 | ]) | |
311 | AT_CLEANUP | |
312 | ||
313 | AT_SETUP([ovn -- expression conversion (3)]) | |
314 | AT_CHECK([ovstest test-ovn exhaustive --operation=convert --bits=2 3], [0], | |
315 | [Tested converting 57618 expressions of 3 terminals with 2 vars each of 2 bits in terms of operators == != < <= > >=. | |
316 | ]) | |
317 | AT_CLEANUP | |
318 | ||
319 | AT_SETUP([ovn -- expression simplification]) | |
320 | AT_CHECK([ovstest test-ovn exhaustive --operation=simplify --vars=2 3], [0], | |
321 | [Tested simplifying 477138 expressions of 3 terminals with 2 vars each of 3 bits in terms of operators == != < <= > >=. | |
322 | ]) | |
323 | AT_CLEANUP | |
324 | ||
325 | AT_SETUP([ovn -- expression normalization (1)]) | |
326 | AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --vars=3 --bits=1 4], [0], | |
327 | [Tested normalizing 1207162 expressions of 4 terminals with 3 vars each of 1 bits in terms of operators == != < <= > >=. | |
328 | ]) | |
329 | AT_CLEANUP | |
330 | ||
331 | AT_SETUP([ovn -- expression normalization (1)]) | |
332 | AT_CHECK([ovstest test-ovn exhaustive --operation=normalize --vars=3 --bits=1 --relops='==' 5], [0], | |
333 | [Tested normalizing 368550 expressions of 5 terminals with 3 vars each of 1 bits in terms of operators ==. | |
334 | ]) | |
335 | AT_CLEANUP | |
336 | ||
337 | AT_SETUP([ovn -- converting expressions to flows (1)]) | |
338 | AT_CHECK([ovstest test-ovn exhaustive --operation=flow --vars=2 --bits=2 --relops='==' 4], [0], | |
339 | [Tested converting to flows 128282 expressions of 4 terminals with 2 vars each of 2 bits in terms of operators ==. | |
340 | ]) | |
341 | AT_CLEANUP | |
342 | ||
343 | AT_SETUP([ovn -- converting expressions to flows (2)]) | |
344 | AT_CHECK([ovstest test-ovn exhaustive --operation=flow --vars=3 --bits=3 --relops='==' 3], [0], | |
345 | [Tested converting to flows 38394 expressions of 3 terminals with 3 vars each of 3 bits in terms of operators ==. | |
346 | ]) | |
347 | AT_CLEANUP | |
f386a8a7 BP |
348 | |
349 | AT_SETUP([ovn -- converting expressions to flows -- string fields]) | |
350 | expr_to_flow () { | |
351 | echo "$1" | ovstest test-ovn expr-to-flows | sort | |
352 | } | |
3b7cb7e1 | 353 | AT_CHECK([expr_to_flow 'inport == "eth0"'], [0], [reg6=0x5 |
f386a8a7 | 354 | ]) |
3b7cb7e1 | 355 | AT_CHECK([expr_to_flow 'inport == "eth1"'], [0], [reg6=0x6 |
f386a8a7 BP |
356 | ]) |
357 | AT_CHECK([expr_to_flow 'inport == "eth2"'], [0], [(no flows) | |
358 | ]) | |
359 | AT_CHECK([expr_to_flow 'inport == "eth0" && ip'], [0], [dnl | |
3b7cb7e1 BP |
360 | ip,reg6=0x5 |
361 | ipv6,reg6=0x5 | |
f386a8a7 BP |
362 | ]) |
363 | AT_CHECK([expr_to_flow 'inport == "eth1" && ip'], [0], [dnl | |
3b7cb7e1 BP |
364 | ip,reg6=0x6 |
365 | ipv6,reg6=0x6 | |
f386a8a7 BP |
366 | ]) |
367 | AT_CHECK([expr_to_flow 'inport == "eth2" && ip'], [0], [(no flows) | |
368 | ]) | |
369 | AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2", "LOCAL"}'], [0], | |
3b7cb7e1 BP |
370 | [reg6=0x5 |
371 | reg6=0x6 | |
372 | reg6=0xfffe | |
f386a8a7 BP |
373 | ]) |
374 | AT_CHECK([expr_to_flow 'inport == {"eth0", "eth1", "eth2"} && ip'], [0], [dnl | |
3b7cb7e1 BP |
375 | ip,reg6=0x5 |
376 | ip,reg6=0x6 | |
377 | ipv6,reg6=0x5 | |
378 | ipv6,reg6=0x6 | |
f386a8a7 BP |
379 | ]) |
380 | AT_CLEANUP | |
3b7cb7e1 BP |
381 | |
382 | AT_SETUP([ovn -- action parsing]) | |
383 | dnl Text before => is input, text after => is expected output. | |
384 | AT_DATA([test-cases.txt], [[ | |
385 | # Positive tests. | |
386 | drop; => actions=drop, prereqs=1 | |
387 | next; => actions=resubmit(,11), prereqs=1 | |
388 | output; => actions=resubmit(,64), prereqs=1 | |
389 | outport="eth0"; next; outport="LOCAL"; next; => actions=set_field:0x5->reg7,resubmit(,11),set_field:0xfffe->reg7,resubmit(,11), prereqs=1 | |
390 | tcp.dst=80; => actions=set_field:80->tcp_dst, prereqs=ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd) | |
391 | eth.dst[40] = 1; => actions=set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst, prereqs=1 | |
392 | vlan.pcp = 2; => actions=set_field:0x4000/0xe000->vlan_tci, prereqs=vlan.tci[12] | |
393 | vlan.tci[13..15] = 2; => actions=set_field:0x4000/0xe000->vlan_tci, prereqs=1 | |
394 | ||
395 | ## Negative tests. | |
396 | ||
397 | ; => Syntax error at `;'. | |
398 | xyzzy; => Syntax error at `xyzzy' expecting action. | |
399 | next; 123; => Syntax error at `123'. | |
400 | next; xyzzy; => Syntax error at `xyzzy' expecting action. | |
401 | ||
402 | # "drop;" must be on its own: | |
403 | drop; next; => Syntax error at `next' expecting end of input. | |
404 | next; drop; => Syntax error at `drop' expecting action. | |
405 | ||
406 | # Missing ";": | |
407 | next => Syntax error at end of input expecting ';'. | |
408 | ||
409 | inport[1] = 1; => Cannot select subfield of string field inport. | |
410 | ip.proto[1] = 1; => Cannot select subfield of nominal field ip.proto. | |
411 | eth.dst[40] == 1; => Syntax error at `==' expecting `='. | |
412 | ip = 1; => Can't assign to predicate symbol ip. | |
413 | ip.proto = 6; => Field ip.proto is not modifiable. | |
414 | inport = {"a", "b"}; => Assignments require a single value. | |
415 | inport = {}; => Syntax error at `}' expecting constant. | |
416 | bad_prereq = 123; => Error parsing expression `xyzzy' encountered as prerequisite or predicate of initial expression: Syntax error at `xyzzy' expecting field name. | |
417 | self_recurse = 123; => Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Error parsing expression `self_recurse != 0' encountered as prerequisite or predicate of initial expression: Recursive expansion of symbol `self_recurse'. | |
418 | vlan.present = 0; => Can't assign to predicate symbol vlan.present. | |
419 | ]]) | |
420 | sed 's/ =>.*//' test-cases.txt > input.txt | |
421 | sed 's/.* => //' test-cases.txt > expout | |
422 | AT_CHECK([ovstest test-ovn parse-actions < input.txt], [0], [expout]) | |
423 | AT_CLEANUP |