randomconfig fixes
[oweals/busybox.git] / testsuite / awk.tests
1 #!/bin/sh
2
3 # Copyright 2007 by Denys Vlasenko <vda.linux@googlemail.com>
4 # Licensed under GPLv2, see file LICENSE in this source tree.
5
6 . ./testing.sh
7
8 # testing "description" "command" "result" "infile" "stdin"
9
10 testing "awk -F case 0" "awk -F '[#]' '{ print NF }'" ""    "" ""
11 testing "awk -F case 1" "awk -F '[#]' '{ print NF }'" "0\n" "" "\n"
12 testing "awk -F case 2" "awk -F '[#]' '{ print NF }'" "2\n" "" "#\n"
13 testing "awk -F case 3" "awk -F '[#]' '{ print NF }'" "3\n" "" "#abc#\n"
14 testing "awk -F case 4" "awk -F '[#]' '{ print NF }'" "3\n" "" "#abc#zz\n"
15 testing "awk -F case 5" "awk -F '[#]' '{ print NF }'" "4\n" "" "#abc##zz\n"
16 testing "awk -F case 6" "awk -F '[#]' '{ print NF }'" "4\n" "" "z#abc##zz\n"
17 testing "awk -F case 7" "awk -F '[#]' '{ print NF }'" "5\n" "" "z##abc##zz\n"
18
19 # conditions and operators
20 testing "awk if operator == "  "awk 'BEGIN{if(23==23) print \"foo\"}'" "foo\n" "" ""
21 testing "awk if operator != "  "awk 'BEGIN{if(23!=23) print \"bar\"}'" ""      "" ""
22 testing "awk if operator >= "  "awk 'BEGIN{if(23>=23) print \"foo\"}'" "foo\n" "" ""
23 testing "awk if operator < "   "awk 'BEGIN{if(2 < 13) print \"foo\"}'" "foo\n" "" ""
24 testing "awk if string == "    "awk 'BEGIN{if(\"a\"==\"ab\") print \"bar\"}'" "" "" ""
25
26 # 4294967295 = 0xffffffff
27 testing "awk bitwise op"  "awk '{ print or(4294967295,1) }'" "4294967295\n" "" "\n"
28
29 # we were testing for a non-empty body when deciding if a function was
30 # defined or not. The testcase below caused:
31 # awk: cmd. line:8: Call to undefined function
32 prg='
33 function empty_fun(count) {
34   # empty
35 }
36 END {
37   i=1
38   print "L" i "\n"
39   empty_fun(i + i + ++i)
40   print "L" i "\n"
41 }'
42 testing "awk handles empty function f(arg){}" \
43         "awk '$prg'" \
44         "L1\n\nL2\n\n" \
45         "" ""
46
47 prg='
48 function outer_fun() {
49   return 1
50 }
51 END {
52   i=1
53   print "L" i "\n"
54   i += outer_fun()
55   print "L" i "\n"
56 }'
57 testing "awk properly handles function from other scope" \
58         "awk '$prg'" \
59         "L1\n\nL2\n\n" \
60         "" ""
61
62 prg='
63 END {
64   i=1
65   print "L" i "\n"
66   i + trigger_error_fun()
67   print "L" i "\n"
68 }'
69 testing "awk properly handles undefined function" \
70         "awk '$prg' 2>&1" \
71         "L1\n\nawk: cmd. line:5: Call to undefined function\n" \
72         "" ""
73
74
75 optional DESKTOP
76 testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n"
77 testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2147483649\n" "" "\n"
78 testing "awk oct const"   "awk '{ print or(01234,1) }'"      "669\n"         "" "\n"
79 SKIP=
80
81 # check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN
82 testing "awk floating const with leading zeroes" \
83         "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \
84         "0.123000 9.123000\n" \
85         "" "\n"
86
87 # long field seps requiring regex
88 testing "awk long field sep" \
89         "awk -F-- '{ print NF, length(\$NF), \$NF }'" \
90         "2 0 \n3 0 \n4 0 \n5 0 \n" \
91         "" \
92         "a--\na--b--\na--b--c--\na--b--c--d--"
93
94 testing "awk -F handles escapes" "awk -F'\\x21' '{print \$1}'" \
95         "a\n" \
96         "" \
97         "a!b\n"
98
99 # '@(samp|code|file)\{' is an invalid extended regex (unmatched '{'),
100 # but gawk 3.1.5 does not bail out on it.
101 testing "awk gsub falls back to non-extended-regex" \
102         "awk 'gsub(\"@(samp|code|file)\{\",\"\");'; echo \$?" "0\n" "" "Hi\n"
103
104 optional TAR BUNZIP2 FEATURE_SEAMLESS_BZ2
105 test x"$SKIP" != x"1" && tar xjf awk_t1.tar.bz2
106 testing "awk 'gcc build bug'" \
107         "awk -f awk_t1_opt-functions.awk -f awk_t1_opth-gen.awk <awk_t1_input | md5sum" \
108         "f842e256461a5ab1ec60b58d16f1114f  -\n" \
109         "" ""
110 rm -rf awk_t1_* 2>/dev/null
111 SKIP=
112
113 Q='":"'
114
115 testing "awk NF in BEGIN" \
116         "awk 'BEGIN { print ${Q} NF ${Q} \$0 ${Q} \$1 ${Q} \$2 ${Q} }'" \
117         ":0::::\n" \
118         "" ""
119
120 prg='
121 function b(tmp) {
122         tmp = 0;
123         print "" tmp; #this line causes the bug
124         return tmp;
125 }
126 function c(tmpc) {
127         tmpc = b(); return tmpc;
128 }
129 BEGIN {
130         print (c() ? "string" : "number");
131 }'
132 testing "awk string cast (bug 725)" \
133         "awk '$prg'" \
134         "0\nnumber\n" \
135         "" ""
136
137 testing "awk handles whitespace before array subscript" \
138         "awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" ""
139
140 # GNU awk 3.1.5's "print ERRNO" prints "No such file or directory" instead of "2",
141 # do we need to emulate that as well?
142 testing "awk handles non-existing file correctly" \
143         "awk 'BEGIN { getline line <\"doesnt_exist\"; print ERRNO; ERRNO=0; close(\"doesnt_exist\"); print ERRNO; print \"Ok\" }'" \
144         "2\n0\nOk\n" "" ""
145
146 prg='
147 BEGIN {
148   u["a"]=1
149   u["b"]=1
150   u["c"]=1
151   v["d"]=1
152   v["e"]=1
153   v["f"]=1
154   for (l in u) {
155     print "outer1", l;
156     for (l in v) {
157       print " inner", l;
158     }
159     print "outer2", l;
160   }
161   print "end", l;
162   l="a"
163   exit;
164 }'
165 testing "awk nested loops with the same variable" \
166         "awk '$prg'" \
167         "\
168 outer1 a
169  inner d
170  inner e
171  inner f
172 outer2 f
173 outer1 b
174  inner d
175  inner e
176  inner f
177 outer2 f
178 outer1 c
179  inner d
180  inner e
181  inner f
182 outer2 f
183 end f
184 " \
185         "" ""
186
187 prg='
188 BEGIN {
189   u["a"]=1
190   u["b"]=1
191   u["c"]=1
192   v["d"]=1
193   v["e"]=1
194   v["f"]=1
195   for (l in u) {
196     print "outer1", l;
197     for (l in v) {
198       print " inner", l;
199       break;
200     }
201     print "outer2", l;
202   }
203   print "end", l;
204   l="a"
205   exit;
206 }'
207 # It's not just buggy, it enters infinite loop. Thus disabled
208 false && test x"$SKIP_KNOWN_BUGS" = x"" && testing "awk nested loops with the same variable and break" \
209         "awk '$prg'" \
210         "\
211 outer1 a
212  inner d
213 outer2 d
214 outer1 b
215  inner d
216 outer2 d
217 outer1 c
218  inner d
219 outer2 d
220 end d
221 " \
222         "" ""
223
224 prg='
225 function f() {
226   for (l in v) {
227     print " inner", l;
228     return;
229   }
230 }
231
232 BEGIN {
233   u["a"]=1
234   u["b"]=1
235   u["c"]=1
236   v["d"]=1
237   v["e"]=1
238   v["f"]=1
239   for (l in u) {
240     print "outer1", l;
241     f();
242     print "outer2", l;
243   }
244   print "end", l;
245   l="a"
246   exit;
247 }'
248 # It's not just buggy, it enters infinite loop. Thus disabled
249 false && test x"$SKIP_KNOWN_BUGS" = x"" && testing "awk nested loops with the same variable and return" \
250         "awk '$prg'" \
251         "\
252 outer1 a
253  inner d
254 outer2 d
255 outer1 b
256  inner d
257 outer2 d
258 outer1 c
259  inner d
260 outer2 d
261 end d
262 " \
263         "" ""
264
265 prg='
266 BEGIN{
267 cnt = 0
268 a[cnt] = "zeroth"
269 a[++cnt] = "first"
270 delete a[cnt--]
271 print cnt
272 print "[0]:" a[0]
273 print "[1]:" a[1]
274 }'
275 testing "awk 'delete a[v--]' evaluates v-- once" \
276         "awk '$prg'" \
277         "\
278 0
279 [0]:zeroth
280 [1]:
281 " \
282         "" ""
283
284 testing "awk func arg parsing 1" \
285         "awk 'func f(,) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
286
287 testing "awk func arg parsing 2" \
288         "awk 'func f(a,,b) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
289
290 testing "awk func arg parsing 3" \
291         "awk 'func f(a,) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
292
293 testing "awk func arg parsing 4" \
294         "awk 'func f(a b) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
295
296 testing "awk handles empty ()" \
297         "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
298
299 testing "awk FS assignment" "awk '{FS=\":\"; print \$1}'" \
300         "a:b\ne\n" \
301         "" \
302         "a:b c:d\ne:f g:h"
303
304 optional FEATURE_AWK_LIBM
305 testing "awk large integer" \
306         "awk 'BEGIN{n=(2^31)-1; print n, int(n), n%1, ++n, int(n), n%1}'" \
307         "2147483647 2147483647 0 2147483648 2147483648 0\n" \
308         "" ""
309 SKIP=
310
311 testing "awk length(array)" \
312         "awk 'BEGIN{ A[1]=2; A[\"qwe\"]=\"asd\"; print length(A)}'" \
313         "2\n" \
314         "" ""
315
316 testing "awk length()" \
317         "awk '{print length; print length(); print length(\"qwe\"); print length(99+9)}'" \
318         "3\n3\n3\n3\n" \
319         "" "qwe"
320
321 testing "awk print length, 1" \
322         "awk '{ print length, 1 }'" \
323         "0 1\n" \
324         "" "\n"
325
326 testing "awk print length 1" \
327         "awk '{ print length 1 }'" \
328         "01\n" \
329         "" "\n"
330
331 testing "awk length == 0" \
332         "awk 'length == 0 { print \"foo\" }'" \
333         "foo\n" \
334         "" "\n"
335
336 testing "awk if (length == 0)" \
337         "awk '{ if (length == 0) { print \"bar\" } }'" \
338         "bar\n" \
339         "" "\n"
340
341 testing "awk -f and ARGC" \
342         "awk -f - input" \
343         "re\n2\n" \
344         "do re mi\n" \
345         '{print $2; print ARGC;}' \
346
347 optional FEATURE_AWK_GNU_EXTENSIONS
348 testing "awk -e and ARGC" \
349         "awk -e '{print \$2; print ARGC;}' input" \
350         "re\n2\n" \
351         "do re mi\n" \
352         ""
353 SKIP=
354
355 # The examples are in fact not valid awk programs (break/continue
356 # can only be used inside loops).
357 # But we do accept them outside of loops.
358 # We had a bug with misparsing "break ; else" sequence.
359 # Test that *that* bug is fixed, using simplest possible scripts:
360 testing "awk break" \
361         "awk -f - 2>&1; echo \$?" \
362         "0\n" \
363         "" \
364         'BEGIN { if (1) break; else a = 1 }'
365 testing "awk continue" \
366         "awk -f - 2>&1; echo \$?" \
367         "0\n" \
368         "" \
369         'BEGIN { if (1) continue; else a = 1 }'
370
371 optional FEATURE_AWK_GNU_EXTENSIONS
372 testing "awk handles invalid for loop" \
373         "awk -e '{ for() }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
374 SKIP=
375
376 optional FEATURE_AWK_GNU_EXTENSIONS
377 testing "awk handles colon not preceded by ternary" \
378         "awk -e foo:bar: 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
379 SKIP=
380
381 optional FEATURE_AWK_GNU_EXTENSIONS
382 testing "awk errors on missing delete arg" \
383         "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" ""
384 SKIP=
385
386 # testing "description" "command" "result" "infile" "stdin"
387 testing 'awk negative field access' \
388         'awk 2>&1 -- '\''{ $(-1) }'\' \
389         "awk: cmd. line:1: Access to negative field\n" \
390         '' \
391         'anything'
392
393 # was misinterpreted as (("str"++) i) instead of ("str" (++i))
394 # (and was executed: "str"++ is "0", thus concatenating "0" and "1"):
395 testing 'awk do not allow "str"++' \
396         'awk -v i=1 "BEGIN {print \"str\" ++i}"' \
397         "str2\n" \
398         '' \
399         'anything'
400
401
402 exit $FAILCOUNT