b2f1aaf26195788a1cf2c488e3295db7d9c2be8b
[freeradius.git] / src / tests / unit / condition.txt
1 #
2 #  Tests for parsing conditional expressions.
3 #
4 #  $Id$
5 #
6
7 #
8 #  A bunch of errors, in the order that the error strings
9 #  appear in parser.c
10 #
11 condition ("foo\
12 data ERROR offset 6 End of string after escape
13
14 condition ("foo
15 data ERROR offset 2 Unterminated string
16
17 condition ()
18 data ERROR offset 1 Empty string is invalid
19
20 condition (!)
21 data ERROR offset 2 Empty string is invalid
22
23 condition (foo == bar
24 data ERROR offset 11 No closing brace at end of string
25
26 condition (|| b)
27 data ERROR offset 1 Empty string is invalid
28
29 condition ((ok || handled) foo)
30 data ERROR offset 17 Unexpected text after condition
31
32 # escapes in names are illegal
33 condition (ok\ foo || handled)
34 data ERROR offset 3 Unexpected escape
35
36 condition (ok FOO handled)
37 data ERROR offset 4 Invalid text. Expected comparison operator
38
39 condition (ok !x handled)
40 data ERROR offset 4 Invalid operator
41
42 condition (ok =x handled)
43 data ERROR offset 4 Invalid operator
44
45 condition (ok =~ handled)
46 data ERROR offset 7 Expected regular expression
47
48 condition (ok == /foo/)
49 data ERROR offset 7 Unexpected regular expression
50
51 condition (ok == handled"foo")
52 data ERROR offset 14 Unexpected start of string
53
54 # And now we have a bunch of VALID conditions we want to parse.
55
56 # sillyness is OK
57 condition ((((((ok))))))
58 data ok
59
60 #
61 #  Extra braces get squashed
62 #
63 condition (&User-Name == &User-Password)
64 data &User-Name == &User-Password
65
66 condition (!ok)
67 data !ok
68
69 condition !(ok)
70 data !ok
71
72 condition !!ok
73 data ERROR offset 1 Double negation is invalid
74
75 condition !(!ok)
76 data ok
77
78 #
79 #  These next two are identical after normalization
80 #
81 condition (&User-Name == &User-Password || &Filter-Id == &Reply-Message)
82 data &User-Name == &User-Password || &Filter-Id == &Reply-Message
83
84 condition ((&User-Name == &User-Password) || (&Filter-Id == &Reply-Message))
85 data &User-Name == &User-Password || &Filter-Id == &Reply-Message
86
87 condition (!(&User-Name == &User-Password) || (&Filter-Id == &Reply-Message))
88 data !&User-Name == &User-Password || &Filter-Id == &Reply-Message
89
90 #  different from the previous ones.
91 condition (!((&User-Name == &User-Password) || (&Filter-Id == &Reply-Message)))
92 data !(&User-Name == &User-Password || &Filter-Id == &Reply-Message)
93
94 condition (!(&User-Name == &User-Password) || (&Filter-Id == &Reply-Message))
95 data !&User-Name == &User-Password || &Filter-Id == &Reply-Message
96
97 condition ((a == b) || (c == d)))
98 data ERROR offset 22 Unexpected closing brace
99
100 condition (handled && (Response-Packet-Type == Access-Challenge))
101 data handled && &Response-Packet-Type == Access-Challenge
102
103 # This is OK, without the braces
104 condition handled && &Response-Packet-Type == Access-Challenge
105 data handled && &Response-Packet-Type == Access-Challenge
106
107 # and this, though it's not a good idea.
108 condition handled &&&Response-Packet-Type == Access-Challenge
109 data handled && &Response-Packet-Type == Access-Challenge
110
111 condition /foo/ =~ bar
112 data ERROR offset 0 Conditional check cannot begin with a regular expression
113
114 condition reply == request
115 data ERROR offset 0 Cannot use list references in condition
116
117 condition reply == "hello"
118 data ERROR offset 0 Cannot use list references in condition
119
120 condition "hello" == reply
121 data ERROR offset 0 Cannot use list references in condition
122
123 condition request:User-Name == reply:User-Name
124 data &User-Name == &reply:User-Name
125
126 #
127 #  Convert !~ to !(COND) for regex
128 #
129 condition foo =~ /bar/
130 data foo =~ /bar/
131
132 condition foo !~ /bar/
133 data !foo =~ /bar/
134
135 condition !foo !~ /bar/
136 data foo =~ /bar/
137
138 #
139 #  Convert != to !(COND) for normal checks
140 #
141 condition &User-Name == &User-Password
142 data &User-Name == &User-Password
143
144 condition &User-Name != &User-Password
145 data !&User-Name == &User-Password
146
147 condition !&User-Name != &User-Password
148 data &User-Name == &User-Password
149
150 condition <ipv6addr>foo
151 data ERROR offset 0 Cannot do cast for existence check
152
153 condition <ipaddr>Filter-Id == &Framed-IP-Address
154 data <ipaddr>&Filter-Id == &Framed-IP-Address
155
156 condition <ipaddr>Filter-Id == <ipaddr>&Framed-IP-Address
157 data ERROR offset 21 Unnecessary cast
158
159 condition <ipaddr>Filter-Id == <integer>&Framed-IP-Address
160 data ERROR offset 21 Cannot cast to a different data type
161
162 condition <ipaddr>Filter-Id == <blerg>&Framed-IP-Address
163 data ERROR offset 22 Invalid data type in cast
164
165 #
166 #  Normalize things
167 #
168 condition <ipaddr>Filter-Id == "127.0.0.1"
169 data <ipaddr>&Filter-Id == '127.0.0.1'
170
171 condition <ipaddr>127.0.0.1 < &Framed-IP-Address
172 data &Framed-IP-Address > 127.0.0.1
173
174 # =* and !* are only for attrs / lists
175 condition "foo" !* bar
176 data ERROR offset 6 Cannot use !* on a string
177
178 condition "foo" =* bar
179 data ERROR offset 6 Cannot use =* on a string
180
181 # existence checks don't need the RHS
182 condition User-Name =* bar
183 data &User-Name
184
185 condition User-Name !* bar
186 data !&User-Name
187
188 condition !User-Name =* bar
189 data !&User-Name
190
191 condition !User-Name !* bar
192 data &User-Name
193
194 # redundant casts get squashed
195 condition <ipaddr>Framed-IP-Address == 127.0.0.1
196 data &Framed-IP-Address == 127.0.0.1
197
198 condition <cidr>Framed-IP-Address <= 192.168/16
199 data <ipv4prefix>&Framed-IP-Address <= 192.168/16
200
201 # string attributes must be string
202 condition User-Name == "bob"
203 data &User-Name == "bob"
204
205 condition User-Name == `bob`
206 data &User-Name == `bob`
207
208 condition User-Name == 'bob'
209 data &User-Name == "bob"
210
211 condition User-Name == bob
212 data ERROR offset 13 Must have string as value for attribute
213
214 # Integer (etc.) types must be "bare"
215 condition Session-Timeout == 10
216 data &Session-Timeout == 10
217
218 condition Session-Timeout == '10'
219 data ERROR offset 19 Value must be an unquoted string
220
221 # Except for dates, which can be humanly readable!
222 # This one is be an expansion, so it's left as-is.
223 condition Event-Timestamp == "January 1, 2012 %{blah}"
224 data &Event-Timestamp == "January 1, 2012 %{blah}"
225
226 # This one is NOT an expansion, so it's parsed into normal form
227 condition Event-Timestamp == 'January 1, 2012'
228 #data &Event-Timestamp == 'Jan  1 2012 00:00:00 EST'
229
230 # literals are parsed when the conditions are parsed
231 condition <integer>X == 1
232 data ERROR offset 9 Failed to parse field
233
234 condition NAS-Port == X
235 data ERROR offset 12 Failed to parse value for attribute
236
237 #
238 #  The RHS is a static string, so this gets mashed to a literal,
239 #  and then statically evaluated.
240 #
241 condition <ipaddr>127.0.0.1 == "127.0.0.1"
242 data true
243
244 condition <ipaddr>127.0.0.1 == "%{sql: 127.0.0.1}"
245 data <ipaddr>127.0.0.1 == "%{sql: 127.0.0.1}"
246
247 condition <ether> 00:11:22:33:44:55 == "00:11:22:33:44:55"
248 data true
249
250 condition <ether> 00:11:22:33:44:55 == "ff:11:22:33:44:55"
251 data false
252
253 condition <ether> 00:11:22:33:44:55 == "%{sql:00:11:22:33:44:55}"
254 data <ether>00:11:22:33:44:55 == "%{sql:00:11:22:33:44:55}"
255
256 condition <ether> 00:XX:22:33:44:55 == 00:11:22:33:44:55
257 data ERROR offset 8 Failed to parse field
258
259 #
260 #  Tests for boolean data types.
261 #
262 condition true
263 data true
264
265 condition 1
266 data true
267
268 condition false
269 data false
270
271 condition 0
272 data false
273
274 condition true && (User-Name == "bob")
275 data &User-Name == "bob"
276
277 condition false && (User-Name == "bob")
278 data false
279
280 condition false || (User-Name == "bob")
281 data &User-Name == "bob"
282
283 condition true || (User-Name == "bob")
284 data true
285
286 #
287 #  Both sides static data with a cast: evaluate at parse time.
288 #
289 condition <integer>20 < 100
290 data true
291
292 #
293 #  Both sides literal: evaluate at parse time
294 #
295 condition ('foo' == 'bar')
296 data false
297
298 condition ('foo' < 'bar')
299 data false
300
301 condition ('foo' > 'bar')
302 data true
303
304 condition ('foo' == 'foo')
305 data true
306
307 #
308 #  Double-quotes strings without expansions are literals
309 #
310 condition ("foo" == "%{sql: foo}")
311 data foo == "%{sql: foo}"
312
313 condition ("foo bar" == "%{sql: foo}")
314 data 'foo bar' == "%{sql: foo}"
315
316 condition ("foo" == "bar")
317 data false
318
319 condition ("foo" == 'bar')
320 data false
321
322 #
323 #  The RHS gets parsed as a VPT_TYPE_DATA, which is
324 #  a double-quoted string
325 #
326 condition (&User-Name == "bob")
327 data &User-Name == "bob"
328
329 condition (&User-Name == "%{sql: blah}")
330 data &User-Name == "%{sql: blah}"
331
332 condition <ipaddr>127.0.0.1 == 2130706433
333 data true
334
335 # /32 suffix should be trimmed for this type
336 condition <ipaddr>127.0.0.1/32 == 127.0.0.1
337 data true
338
339 condition <ipaddr>127.0.0.1/327 == 127.0.0.1
340 data ERROR offset 8 Failed to parse field
341
342 condition <ipaddr>127.0.0.1/32 == 127.0.0.1
343 data true
344
345 condition (/foo/)
346 data ERROR offset 1 Conditional check cannot begin with a regular expression
347
348 #
349 #  Tests for (FOO).
350 #
351 condition (1)
352 data true
353
354 condition (0)
355 data false
356
357 condition (true)
358 data true
359
360 condition (false)
361 data false
362
363 condition ('')
364 data false
365
366 condition ("")
367 data false
368
369 #
370 #  Integers are true, as are non-zero strings
371 #
372 condition (4)
373 data true
374
375 condition ('a')
376 data true
377
378 condition (a)
379 data ERROR offset 1 Expected a module return code
380
381 #
382 #  Module return codes are OK
383 #
384 condition (ok)
385 data ok
386
387 condition (handled)
388 data handled
389
390 condition (fail)
391 data fail
392
393 condition ("a")
394 data true
395
396 condition (`a`)
397 data `a`
398
399 condition (User-name)
400 data &User-Name
401
402 #
403 #  Forbidden data types in cast
404 #
405 condition (<vsa>"foo" == &User-Name)
406 data ERROR offset 2 Forbidden data type in cast
407
408 #
409 #  Must have attribute references on the LHS of a condition.
410 #
411 condition ("foo" == &User-Name)
412 data ERROR offset 1 Cannot use attribute reference on right side of condition
413
414 #
415 #  If the LHS is a cast to a type, and the RHS is an attribute
416 #  of the same type, then re-write it so that the attribute
417 #  is on the LHS of the condition.
418 #
419 condition <string>"foo" == &User-Name
420 data &User-Name == "foo"
421
422 condition <integer>"%{expr: 1 + 1}" < &NAS-Port
423 data &NAS-Port > "%{expr: 1 + 1}"
424
425 condition &Filter-Id == &Framed-IP-Address
426 data ERROR offset 0 Attribute comparisons must be of the same data type
427
428 condition <ipaddr>127.0.0.1 == &Filter-Id
429 data ERROR offset 0 Attribute comparisons must be of the same data type
430
431 condition <ipaddr>&Tmp-Integer64-0 == &Foo-Stuff-Bar
432 data ERROR offset 0 Unknown attribute
433
434 #
435 #  Casting attributes of different size
436 #
437 condition <ipaddr>&Tmp-Integer64-0 == &Framed-IP-Address
438 data ERROR offset 0 Cannot cast to attribute of incompatible size
439
440 condition <ipaddr>&PMIP6-Home-IPv4-HoA == &Framed-IP-Address
441 data ERROR offset 0 Cannot cast to attribute of incompatible size
442
443 # but these are allowed
444 condition <ether>&Tmp-Integer64-0 == "%{module: foo}"
445 data <ether>&Tmp-Integer64-0 == "%{module: foo}"
446
447 condition <ipaddr>&Filter-Id == &Framed-IP-Address
448 data <ipaddr>&Filter-Id == &Framed-IP-Address
449
450 condition <ipaddr>&Class == &Framed-IP-Address
451 data <ipaddr>&Class == &Framed-IP-Address
452
453 #
454 #  Tags of zero mean restrict to attributes with no tag
455 #
456 condition &Tunnel-Password:0 == "Hello"
457 data &Tunnel-Password:0 == "Hello"
458
459 condition &Tunnel-Password:1 == "Hello"
460 data &Tunnel-Password:1 == "Hello"
461
462 #
463 #  zero offset into arrays get parsed and ignored
464 #
465 condition &User-Name[0] == "bob"
466 data &User-Name[0] == "bob"
467
468 condition &User-Name[1] == "bob"
469 data &User-Name[1] == "bob"
470
471 condition &Tunnel-Password:1[0] == "Hello"
472 data &Tunnel-Password:1[0] == "Hello"
473
474 condition &Tunnel-Password:1[3] == "Hello"
475 data &Tunnel-Password:1[3] == "Hello"