blob: bcaafe8fda777156afe5a68ef37f4cf98587a087 [file] [log] [blame]
Denis Vlasenko960eca62007-07-18 18:33:18 +00001#!/bin/sh
2
Denis Vlasenko960eca62007-07-18 18:33:18 +00003# Copyright 2007 by Denys Vlasenko <vda.linux@googlemail.com>
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02004# Licensed under GPLv2, see file LICENSE in this source tree.
Denis Vlasenko960eca62007-07-18 18:33:18 +00005
Mike Frysingercaa79402009-11-04 18:41:22 -05006. ./testing.sh
Denis Vlasenko960eca62007-07-18 18:33:18 +00007
Denis Vlasenkobb130792008-07-15 06:45:14 +00008# testing "description" "command" "result" "infile" "stdin"
Denis Vlasenko960eca62007-07-18 18:33:18 +00009
10testing "awk -F case 0" "awk -F '[#]' '{ print NF }'" "" "" ""
11testing "awk -F case 1" "awk -F '[#]' '{ print NF }'" "0\n" "" "\n"
12testing "awk -F case 2" "awk -F '[#]' '{ print NF }'" "2\n" "" "#\n"
13testing "awk -F case 3" "awk -F '[#]' '{ print NF }'" "3\n" "" "#abc#\n"
14testing "awk -F case 4" "awk -F '[#]' '{ print NF }'" "3\n" "" "#abc#zz\n"
15testing "awk -F case 5" "awk -F '[#]' '{ print NF }'" "4\n" "" "#abc##zz\n"
16testing "awk -F case 6" "awk -F '[#]' '{ print NF }'" "4\n" "" "z#abc##zz\n"
17testing "awk -F case 7" "awk -F '[#]' '{ print NF }'" "5\n" "" "z##abc##zz\n"
18
Tanguy Pruvot0a393cf2012-06-11 10:33:45 +020019# conditions and operators
20testing "awk if operator == " "awk 'BEGIN{if(23==23) print \"foo\"}'" "foo\n" "" ""
21testing "awk if operator != " "awk 'BEGIN{if(23!=23) print \"bar\"}'" "" "" ""
22testing "awk if operator >= " "awk 'BEGIN{if(23>=23) print \"foo\"}'" "foo\n" "" ""
23testing "awk if operator < " "awk 'BEGIN{if(2 < 13) print \"foo\"}'" "foo\n" "" ""
24testing "awk if string == " "awk 'BEGIN{if(\"a\"==\"ab\") print \"bar\"}'" "" "" ""
25
Denis Vlasenko66496d72008-08-29 08:37:07 +000026# 4294967295 = 0xffffffff
Denys Vlasenkob8554602013-07-22 11:49:06 +020027testing "awk bitwise op" "awk '{ print or(4294967295,1) }'" "4294967295\n" "" "\n"
Bernhard Reutner-Fischerb79a0fe2013-03-06 21:01:05 +010028
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
32prg='
33function empty_fun(count) {
34 # empty
35}
36END {
37 i=1
38 print "L" i "\n"
39 empty_fun(i + i + ++i)
40 print "L" i "\n"
41}'
42testing "awk handles empty function f(arg){}" \
43 "awk '$prg'" \
44 "L1\n\nL2\n\n" \
45 "" ""
46
Bernhard Reutner-Fischera060a1a2013-07-31 15:29:20 +020047prg='
Denys Vlasenkod1507102021-06-30 12:23:51 +020048function empty_fun(){}
49END {empty_fun()
50 print "Ok"
51}'
52testing "awk handles empty function f(){}" \
53 "awk '$prg'" \
54 "Ok\n" \
55 "" ""
56
57prg='
Bernhard Reutner-Fischera060a1a2013-07-31 15:29:20 +020058function outer_fun() {
59 return 1
60}
61END {
62 i=1
63 print "L" i "\n"
64 i += outer_fun()
65 print "L" i "\n"
66}'
67testing "awk properly handles function from other scope" \
68 "awk '$prg'" \
69 "L1\n\nL2\n\n" \
70 "" ""
71
72prg='
73END {
74 i=1
75 print "L" i "\n"
76 i + trigger_error_fun()
77 print "L" i "\n"
78}'
79testing "awk properly handles undefined function" \
80 "awk '$prg' 2>&1" \
81 "L1\n\nawk: cmd. line:5: Call to undefined function\n" \
82 "" ""
83
Denys Vlasenko6872c192021-06-29 12:16:36 +020084prg='
85BEGIN {
86 v=1
87 a=2
88 print v (a)
89}'
Denys Vlasenkod7354df2021-06-30 12:52:51 +020090testing "awk 'v (a)' is not a function call, it is a concatenation" \
Denys Vlasenko6872c192021-06-29 12:16:36 +020091 "awk '$prg' 2>&1" \
92 "12\n" \
93 "" ""
94
Denys Vlasenkod7354df2021-06-30 12:52:51 +020095prg='func f(){print"F"};func g(){print"G"};BEGIN{f(g(),g())}'
96testing "awk unused function args are evaluated" \
97 "awk '$prg' 2>&1" \
98 "G\nG\nF\n" \
99 "" ""
100
Bernhard Reutner-Fischera060a1a2013-07-31 15:29:20 +0200101
Denys Vlasenkobfa1b2e2010-05-11 03:53:57 +0200102optional DESKTOP
Denys Vlasenkob8554602013-07-22 11:49:06 +0200103testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n"
104testing "awk hex const 2" "awk '{ print or(0x80000000,1) }'" "2147483649\n" "" "\n"
Denis Vlasenkoa2e1eea2008-09-02 09:00:23 +0000105testing "awk oct const" "awk '{ print or(01234,1) }'" "669\n" "" "\n"
Denys Vlasenkobfa1b2e2010-05-11 03:53:57 +0200106SKIP=
Denis Vlasenko66496d72008-08-29 08:37:07 +0000107
Denys Vlasenkod527e0c2010-10-05 13:22:11 +0200108# check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN
109testing "awk floating const with leading zeroes" \
110 "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \
111 "0.123000 9.123000\n" \
112 "" "\n"
113
Denis Vlasenko67b5eeb2009-04-12 13:54:13 +0000114# long field seps requiring regex
Denys Vlasenkobd8b05b2020-02-02 23:28:55 +0100115testing "awk long field sep" \
116 "awk -F-- '{ print NF, length(\$NF), \$NF }'" \
Denis Vlasenko67b5eeb2009-04-12 13:54:13 +0000117 "2 0 \n3 0 \n4 0 \n5 0 \n" \
118 "" \
119 "a--\na--b--\na--b--c--\na--b--c--d--"
120
Denys Vlasenkoea664dd2012-06-22 18:41:01 +0200121testing "awk -F handles escapes" "awk -F'\\x21' '{print \$1}'" \
122 "a\n" \
123 "" \
124 "a!b\n"
125
Denis Vlasenko7a676642009-03-15 22:20:31 +0000126# '@(samp|code|file)\{' is an invalid extended regex (unmatched '{'),
127# but gawk 3.1.5 does not bail out on it.
128testing "awk gsub falls back to non-extended-regex" \
129 "awk 'gsub(\"@(samp|code|file)\{\",\"\");'; echo \$?" "0\n" "" "Hi\n"
130
Denys Vlasenko8e3aff02010-05-10 11:00:11 +0200131optional TAR BUNZIP2 FEATURE_SEAMLESS_BZ2
Denys Vlasenkoe3d90a92010-05-10 05:53:16 +0200132test x"$SKIP" != x"1" && tar xjf awk_t1.tar.bz2
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +0000133testing "awk 'gcc build bug'" \
134 "awk -f awk_t1_opt-functions.awk -f awk_t1_opth-gen.awk <awk_t1_input | md5sum" \
135 "f842e256461a5ab1ec60b58d16f1114f -\n" \
136 "" ""
Denys Vlasenkoe3d90a92010-05-10 05:53:16 +0200137rm -rf awk_t1_* 2>/dev/null
138SKIP=
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +0000139
Denis Vlasenko41d5ebe2009-01-25 01:00:15 +0000140Q='":"'
141
142testing "awk NF in BEGIN" \
143 "awk 'BEGIN { print ${Q} NF ${Q} \$0 ${Q} \$1 ${Q} \$2 ${Q} }'" \
144 ":0::::\n" \
145 "" ""
146
Denys Vlasenko12847742009-11-30 01:15:04 +0100147prg='
148function b(tmp) {
149 tmp = 0;
150 print "" tmp; #this line causes the bug
151 return tmp;
152}
153function c(tmpc) {
154 tmpc = b(); return tmpc;
155}
156BEGIN {
157 print (c() ? "string" : "number");
158}'
159testing "awk string cast (bug 725)" \
160 "awk '$prg'" \
161 "0\nnumber\n" \
162 "" ""
163
Alexander Shishkind03cd3b2010-02-25 17:55:40 +0200164testing "awk handles whitespace before array subscript" \
165 "awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" ""
166
Denys Vlasenko6a0d7492010-10-23 21:02:15 +0200167# GNU awk 3.1.5's "print ERRNO" prints "No such file or directory" instead of "2",
168# do we need to emulate that as well?
169testing "awk handles non-existing file correctly" \
170 "awk 'BEGIN { getline line <\"doesnt_exist\"; print ERRNO; ERRNO=0; close(\"doesnt_exist\"); print ERRNO; print \"Ok\" }'" \
171 "2\n0\nOk\n" "" ""
172
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100173prg='
174BEGIN {
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100175 u["a"]=1
176 u["b"]=1
177 u["c"]=1
178 v["d"]=1
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100179 v["e"]=1
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100180 v["f"]=1
181 for (l in u) {
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100182 print "outer1", l;
183 for (l in v) {
184 print " inner", l;
185 }
186 print "outer2", l;
187 }
188 print "end", l;
189 l="a"
190 exit;
191}'
192testing "awk nested loops with the same variable" \
193 "awk '$prg'" \
194 "\
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100195outer1 a
196 inner d
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100197 inner e
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100198 inner f
199outer2 f
200outer1 b
201 inner d
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100202 inner e
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100203 inner f
204outer2 f
205outer1 c
206 inner d
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100207 inner e
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100208 inner f
209outer2 f
210end f
211" \
212 "" ""
213
214prg='
215BEGIN {
216 u["a"]=1
217 u["b"]=1
218 u["c"]=1
219 v["d"]=1
220 v["e"]=1
221 v["f"]=1
222 for (l in u) {
223 print "outer1", l;
224 for (l in v) {
225 print " inner", l;
226 break;
227 }
228 print "outer2", l;
229 }
230 print "end", l;
231 l="a"
232 exit;
233}'
234# It's not just buggy, it enters infinite loop. Thus disabled
235false && test x"$SKIP_KNOWN_BUGS" = x"" && testing "awk nested loops with the same variable and break" \
236 "awk '$prg'" \
237 "\
238outer1 a
239 inner d
240outer2 d
241outer1 b
242 inner d
243outer2 d
244outer1 c
245 inner d
246outer2 d
247end d
248" \
249 "" ""
250
251prg='
252function f() {
253 for (l in v) {
254 print " inner", l;
255 return;
256 }
257}
258
259BEGIN {
260 u["a"]=1
261 u["b"]=1
262 u["c"]=1
263 v["d"]=1
264 v["e"]=1
265 v["f"]=1
266 for (l in u) {
267 print "outer1", l;
268 f();
269 print "outer2", l;
270 }
271 print "end", l;
272 l="a"
273 exit;
274}'
275# It's not just buggy, it enters infinite loop. Thus disabled
276false && test x"$SKIP_KNOWN_BUGS" = x"" && testing "awk nested loops with the same variable and return" \
277 "awk '$prg'" \
278 "\
279outer1 a
280 inner d
281outer2 d
282outer1 b
283 inner d
284outer2 d
285outer1 c
286 inner d
287outer2 d
288end d
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100289" \
290 "" ""
291
Denys Vlasenko6f4a7852018-01-07 01:19:08 +0100292prg='
293BEGIN{
294cnt = 0
295a[cnt] = "zeroth"
296a[++cnt] = "first"
297delete a[cnt--]
298print cnt
299print "[0]:" a[0]
300print "[1]:" a[1]
301}'
302testing "awk 'delete a[v--]' evaluates v-- once" \
303 "awk '$prg'" \
304 "\
3050
306[0]:zeroth
307[1]:
308" \
309 "" ""
310
Brian Foley1c42c182019-01-06 18:32:59 -0800311testing "awk func arg parsing 1" \
312 "awk 'func f(,) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
313
314testing "awk func arg parsing 2" \
315 "awk 'func f(a,,b) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
316
317testing "awk func arg parsing 3" \
318 "awk 'func f(a,) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
319
320testing "awk func arg parsing 4" \
321 "awk 'func f(a b) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
322
Denys Vlasenko7b46d112011-09-11 00:30:56 +0200323testing "awk handles empty ()" \
324 "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
325
Denys Vlasenkodf8066a2012-07-11 01:27:15 +0200326testing "awk FS assignment" "awk '{FS=\":\"; print \$1}'" \
327 "a:b\ne\n" \
328 "" \
329 "a:b c:d\ne:f g:h"
330
Denys Vlasenko198b02f2013-12-31 23:22:36 +0100331optional FEATURE_AWK_LIBM
Denys Vlasenkob8554602013-07-22 11:49:06 +0200332testing "awk large integer" \
333 "awk 'BEGIN{n=(2^31)-1; print n, int(n), n%1, ++n, int(n), n%1}'" \
334 "2147483647 2147483647 0 2147483648 2147483648 0\n" \
335 "" ""
Denys Vlasenko198b02f2013-12-31 23:22:36 +0100336SKIP=
Denys Vlasenkob8554602013-07-22 11:49:06 +0200337
Denys Vlasenko7985bc12013-10-12 04:51:54 +0200338testing "awk length(array)" \
Denys Vlasenkobd0e2212013-11-21 15:09:55 +0100339 "awk 'BEGIN{ A[1]=2; A[\"qwe\"]=\"asd\"; print length(A)}'" \
Denys Vlasenko7985bc12013-10-12 04:51:54 +0200340 "2\n" \
341 "" ""
342
Denys Vlasenko28b00ce2015-10-02 02:41:39 +0200343testing "awk length()" \
344 "awk '{print length; print length(); print length(\"qwe\"); print length(99+9)}'" \
345 "3\n3\n3\n3\n" \
346 "" "qwe"
347
Denys Vlasenkobd8b05b2020-02-02 23:28:55 +0100348testing "awk print length, 1" \
349 "awk '{ print length, 1 }'" \
350 "0 1\n" \
351 "" "\n"
352
353testing "awk print length 1" \
354 "awk '{ print length 1 }'" \
355 "01\n" \
356 "" "\n"
357
358testing "awk length == 0" \
359 "awk 'length == 0 { print \"foo\" }'" \
360 "foo\n" \
361 "" "\n"
362
363testing "awk if (length == 0)" \
364 "awk '{ if (length == 0) { print \"bar\" } }'" \
365 "bar\n" \
366 "" "\n"
367
Denys Vlasenkobd0e2212013-11-21 15:09:55 +0100368testing "awk -f and ARGC" \
369 "awk -f - input" \
370 "re\n2\n" \
371 "do re mi\n" \
372 '{print $2; print ARGC;}' \
373
Denys Vlasenko198b02f2013-12-31 23:22:36 +0100374optional FEATURE_AWK_GNU_EXTENSIONS
Denys Vlasenkobd0e2212013-11-21 15:09:55 +0100375testing "awk -e and ARGC" \
376 "awk -e '{print \$2; print ARGC;}' input" \
377 "re\n2\n" \
378 "do re mi\n" \
Denys Vlasenko198b02f2013-12-31 23:22:36 +0100379 ""
380SKIP=
Denys Vlasenkobd0e2212013-11-21 15:09:55 +0100381
Denys Vlasenko5f8daef2014-06-26 16:40:28 +0200382testing "awk break" \
383 "awk -f - 2>&1; echo \$?" \
Denys Vlasenkod3480dd2021-07-14 14:33:37 +0200384 "awk: -:1: 'break' not in a loop\n1\n" \
Denys Vlasenko5f8daef2014-06-26 16:40:28 +0200385 "" \
386 'BEGIN { if (1) break; else a = 1 }'
387testing "awk continue" \
388 "awk -f - 2>&1; echo \$?" \
Denys Vlasenkod3480dd2021-07-14 14:33:37 +0200389 "awk: -:1: 'continue' not in a loop\n1\n" \
Denys Vlasenko5f8daef2014-06-26 16:40:28 +0200390 "" \
391 'BEGIN { if (1) continue; else a = 1 }'
392
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200393optional FEATURE_AWK_GNU_EXTENSIONS
Brian Foley61d59972016-10-15 14:45:40 +0100394testing "awk handles invalid for loop" \
Brian Foley08a514c2019-01-01 13:40:59 -0800395 "awk -e '{ for() }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200396SKIP=
Brian Foley61d59972016-10-15 14:45:40 +0100397
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200398optional FEATURE_AWK_GNU_EXTENSIONS
Brian Foleydac15a12019-01-01 13:40:58 -0800399testing "awk handles colon not preceded by ternary" \
Brian Foley08a514c2019-01-01 13:40:59 -0800400 "awk -e foo:bar: 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200401SKIP=
Brian Foley08a514c2019-01-01 13:40:59 -0800402
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200403optional FEATURE_AWK_GNU_EXTENSIONS
Brian Foley08a514c2019-01-01 13:40:59 -0800404testing "awk errors on missing delete arg" \
405 "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" ""
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200406SKIP=
Brian Foleydac15a12019-01-01 13:40:58 -0800407
Ron Yorstone8fe9f92021-01-27 11:19:14 +0000408optional FEATURE_AWK_GNU_EXTENSIONS
409testing "awk printf('%c') can output NUL" \
410 "awk '{printf(\"hello%c null\n\", 0)}'" "hello\0 null\n" "" "\n"
411SKIP=
412
Denys Vlasenko8e8cea22021-08-16 07:37:22 +0200413optional FEATURE_AWK_GNU_EXTENSIONS DESKTOP
Denys Vlasenko8d269ef2021-07-12 11:27:11 +0200414testing "awk printf('%-10c') can output NUL" \
415 "awk 'BEGIN { printf \"[%-10c]\n\", 0 }' | od -tx1" "\
4160000000 5b 00 20 20 20 20 20 20 20 20 20 5d 0a
4170000015
418" "" ""
419SKIP=
420
Denys Vlasenkodf8066a2012-07-11 01:27:15 +0200421# testing "description" "command" "result" "infile" "stdin"
Denys Vlasenko2454e672018-04-23 10:53:18 +0200422testing 'awk negative field access' \
423 'awk 2>&1 -- '\''{ $(-1) }'\' \
424 "awk: cmd. line:1: Access to negative field\n" \
425 '' \
426 'anything'
427
Denys Vlasenko6f7a0092020-06-09 01:33:54 +0200428# was misinterpreted as (("str"++) i) instead of ("str" (++i))
429# (and was executed: "str"++ is "0", thus concatenating "0" and "1"):
430testing 'awk do not allow "str"++' \
431 'awk -v i=1 "BEGIN {print \"str\" ++i}"' \
432 "str2\n" \
433 '' \
434 'anything'
435
Denys Vlasenko758c2bd2020-12-04 19:00:06 +0100436# gawk compat: FS regex matches only non-empty separators:
437# with -*, the splitting is NOT f o o b a r, but foo bar:
Denys Vlasenko665a6592020-12-02 19:07:31 +0100438testing 'awk FS regex which can match empty string' \
439 "awk -F '-*' '{print \$1 \"-\" \$2 \"=\" \$3 \"*\" \$4}'" \
440 "foo-bar=*\n" \
441 '' \
442 'foo--bar'
Denys Vlasenkodf8066a2012-07-11 01:27:15 +0200443
Denys Vlasenko758c2bd2020-12-04 19:00:06 +0100444# last+1 field should be empty (had a bug where it wasn't)
445testing 'awk $NF is empty' \
446 "awk -F '=+' '{print \$NF}'" \
447 "\n" \
448 '' \
449 'a=====123='
450
Denys Vlasenko4d902ea2021-07-02 22:28:51 +0200451testing "awk exit N propagates through END's exit" \
452 "awk 'BEGIN { exit 42 } END { exit }'; echo \$?" \
453 "42\n" \
454 '' ''
455
Denys Vlasenko3d57a842021-07-11 12:00:31 +0200456testing "awk print + redirect" \
457 "awk 'BEGIN { print \"STDERR %s\" >\"/dev/stderr\" }' 2>&1" \
458 "STDERR %s\n" \
459 '' ''
460
Denys Vlasenko39aabfe2021-07-11 12:51:43 +0200461testing "awk \"cmd\" | getline" \
462 "awk 'BEGIN { \"echo HELLO\" | getline; print }'" \
463 "HELLO\n" \
464 '' ''
465
Daniel Thau7d06d6e2021-09-02 07:41:08 -0400466# printf %% should print one % (had a bug where it didn't)
467testing 'awk printf %% prints one %' \
468 "awk 'BEGIN { printf \"%%\n\" }'" \
469 "%\n" \
470 '' ''
471
Denis Vlasenko960eca62007-07-18 18:33:18 +0000472exit $FAILCOUNT