blob: 93e25d8c1643e173c0e5ed2505c23435f41ae68d [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"
Denys Vlasenkoe2952df2022-01-08 22:42:35 +0100105testing "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 Vlasenkoe2952df2022-01-08 22:42:35 +0100108# check that "hex/oct integer" heuristic doesn't kick in on input
109# (must be done only when parsing program text)
110testing "awk input is never oct" "awk '{ print \$1, \$1+1 }'" "011 12\n" "" "011\n"
111
Denys Vlasenkod527e0c2010-10-05 13:22:11 +0200112# check that "hex/oct integer" heuristic doesn't kick in on 00NN.NNN
113testing "awk floating const with leading zeroes" \
114 "awk '{ printf \"%f %f\n\", \"000.123\", \"009.123\" }'" \
115 "0.123000 9.123000\n" \
116 "" "\n"
117
Denis Vlasenko67b5eeb2009-04-12 13:54:13 +0000118# long field seps requiring regex
Denys Vlasenkobd8b05b2020-02-02 23:28:55 +0100119testing "awk long field sep" \
120 "awk -F-- '{ print NF, length(\$NF), \$NF }'" \
Denis Vlasenko67b5eeb2009-04-12 13:54:13 +0000121 "2 0 \n3 0 \n4 0 \n5 0 \n" \
122 "" \
123 "a--\na--b--\na--b--c--\na--b--c--d--"
124
Denys Vlasenkoea664dd2012-06-22 18:41:01 +0200125testing "awk -F handles escapes" "awk -F'\\x21' '{print \$1}'" \
126 "a\n" \
127 "" \
128 "a!b\n"
129
Denis Vlasenko7a676642009-03-15 22:20:31 +0000130# '@(samp|code|file)\{' is an invalid extended regex (unmatched '{'),
131# but gawk 3.1.5 does not bail out on it.
132testing "awk gsub falls back to non-extended-regex" \
133 "awk 'gsub(\"@(samp|code|file)\{\",\"\");'; echo \$?" "0\n" "" "Hi\n"
134
Denys Vlasenko8e3aff02010-05-10 11:00:11 +0200135optional TAR BUNZIP2 FEATURE_SEAMLESS_BZ2
Denys Vlasenkoe3d90a92010-05-10 05:53:16 +0200136test x"$SKIP" != x"1" && tar xjf awk_t1.tar.bz2
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +0000137testing "awk 'gcc build bug'" \
138 "awk -f awk_t1_opt-functions.awk -f awk_t1_opth-gen.awk <awk_t1_input | md5sum" \
139 "f842e256461a5ab1ec60b58d16f1114f -\n" \
140 "" ""
Denys Vlasenkoe3d90a92010-05-10 05:53:16 +0200141rm -rf awk_t1_* 2>/dev/null
142SKIP=
Denis Vlasenko3bb2bbd2008-07-01 01:57:36 +0000143
Denis Vlasenko41d5ebe2009-01-25 01:00:15 +0000144Q='":"'
145
146testing "awk NF in BEGIN" \
147 "awk 'BEGIN { print ${Q} NF ${Q} \$0 ${Q} \$1 ${Q} \$2 ${Q} }'" \
148 ":0::::\n" \
149 "" ""
150
Denys Vlasenko12847742009-11-30 01:15:04 +0100151prg='
152function b(tmp) {
153 tmp = 0;
154 print "" tmp; #this line causes the bug
155 return tmp;
156}
157function c(tmpc) {
158 tmpc = b(); return tmpc;
159}
160BEGIN {
161 print (c() ? "string" : "number");
162}'
163testing "awk string cast (bug 725)" \
164 "awk '$prg'" \
165 "0\nnumber\n" \
166 "" ""
167
Alexander Shishkind03cd3b2010-02-25 17:55:40 +0200168testing "awk handles whitespace before array subscript" \
169 "awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" ""
170
Denys Vlasenko6a0d7492010-10-23 21:02:15 +0200171# GNU awk 3.1.5's "print ERRNO" prints "No such file or directory" instead of "2",
172# do we need to emulate that as well?
173testing "awk handles non-existing file correctly" \
174 "awk 'BEGIN { getline line <\"doesnt_exist\"; print ERRNO; ERRNO=0; close(\"doesnt_exist\"); print ERRNO; print \"Ok\" }'" \
175 "2\n0\nOk\n" "" ""
176
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100177prg='
178BEGIN {
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100179 u["a"]=1
180 u["b"]=1
181 u["c"]=1
182 v["d"]=1
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100183 v["e"]=1
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100184 v["f"]=1
185 for (l in u) {
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100186 print "outer1", l;
187 for (l in v) {
188 print " inner", l;
189 }
190 print "outer2", l;
191 }
192 print "end", l;
193 l="a"
194 exit;
195}'
196testing "awk nested loops with the same variable" \
197 "awk '$prg'" \
198 "\
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100199outer1 a
200 inner d
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100201 inner e
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100202 inner f
203outer2 f
204outer1 b
205 inner d
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100206 inner e
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100207 inner f
208outer2 f
209outer1 c
210 inner d
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100211 inner e
Denys Vlasenko90f19fa2010-03-11 08:27:53 +0100212 inner f
213outer2 f
214end f
215" \
216 "" ""
217
218prg='
219BEGIN {
220 u["a"]=1
221 u["b"]=1
222 u["c"]=1
223 v["d"]=1
224 v["e"]=1
225 v["f"]=1
226 for (l in u) {
227 print "outer1", l;
228 for (l in v) {
229 print " inner", l;
230 break;
231 }
232 print "outer2", l;
233 }
234 print "end", l;
235 l="a"
236 exit;
237}'
238# It's not just buggy, it enters infinite loop. Thus disabled
239false && test x"$SKIP_KNOWN_BUGS" = x"" && testing "awk nested loops with the same variable and break" \
240 "awk '$prg'" \
241 "\
242outer1 a
243 inner d
244outer2 d
245outer1 b
246 inner d
247outer2 d
248outer1 c
249 inner d
250outer2 d
251end d
252" \
253 "" ""
254
255prg='
256function f() {
257 for (l in v) {
258 print " inner", l;
259 return;
260 }
261}
262
263BEGIN {
264 u["a"]=1
265 u["b"]=1
266 u["c"]=1
267 v["d"]=1
268 v["e"]=1
269 v["f"]=1
270 for (l in u) {
271 print "outer1", l;
272 f();
273 print "outer2", l;
274 }
275 print "end", l;
276 l="a"
277 exit;
278}'
279# It's not just buggy, it enters infinite loop. Thus disabled
280false && test x"$SKIP_KNOWN_BUGS" = x"" && testing "awk nested loops with the same variable and return" \
281 "awk '$prg'" \
282 "\
283outer1 a
284 inner d
285outer2 d
286outer1 b
287 inner d
288outer2 d
289outer1 c
290 inner d
291outer2 d
292end d
Denys Vlasenko3cb60c32010-03-10 19:20:32 +0100293" \
294 "" ""
295
Denys Vlasenko6f4a7852018-01-07 01:19:08 +0100296prg='
297BEGIN{
298cnt = 0
299a[cnt] = "zeroth"
300a[++cnt] = "first"
301delete a[cnt--]
302print cnt
303print "[0]:" a[0]
304print "[1]:" a[1]
305}'
306testing "awk 'delete a[v--]' evaluates v-- once" \
307 "awk '$prg'" \
308 "\
3090
310[0]:zeroth
311[1]:
312" \
313 "" ""
314
Brian Foley1c42c182019-01-06 18:32:59 -0800315testing "awk func arg parsing 1" \
316 "awk 'func f(,) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
317
318testing "awk func arg parsing 2" \
319 "awk 'func f(a,,b) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
320
321testing "awk func arg parsing 3" \
322 "awk 'func f(a,) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
323
324testing "awk func arg parsing 4" \
325 "awk 'func f(a b) { }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
326
Denys Vlasenko7b46d112011-09-11 00:30:56 +0200327testing "awk handles empty ()" \
328 "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
329
Denys Vlasenkodf8066a2012-07-11 01:27:15 +0200330testing "awk FS assignment" "awk '{FS=\":\"; print \$1}'" \
331 "a:b\ne\n" \
332 "" \
333 "a:b c:d\ne:f g:h"
334
Denys Vlasenko198b02f2013-12-31 23:22:36 +0100335optional FEATURE_AWK_LIBM
Denys Vlasenkob8554602013-07-22 11:49:06 +0200336testing "awk large integer" \
337 "awk 'BEGIN{n=(2^31)-1; print n, int(n), n%1, ++n, int(n), n%1}'" \
338 "2147483647 2147483647 0 2147483648 2147483648 0\n" \
339 "" ""
Denys Vlasenko198b02f2013-12-31 23:22:36 +0100340SKIP=
Denys Vlasenkob8554602013-07-22 11:49:06 +0200341
Denys Vlasenko7985bc12013-10-12 04:51:54 +0200342testing "awk length(array)" \
Denys Vlasenkobd0e2212013-11-21 15:09:55 +0100343 "awk 'BEGIN{ A[1]=2; A[\"qwe\"]=\"asd\"; print length(A)}'" \
Denys Vlasenko7985bc12013-10-12 04:51:54 +0200344 "2\n" \
345 "" ""
346
Denys Vlasenko28b00ce2015-10-02 02:41:39 +0200347testing "awk length()" \
348 "awk '{print length; print length(); print length(\"qwe\"); print length(99+9)}'" \
349 "3\n3\n3\n3\n" \
350 "" "qwe"
351
Denys Vlasenkobd8b05b2020-02-02 23:28:55 +0100352testing "awk print length, 1" \
353 "awk '{ print length, 1 }'" \
354 "0 1\n" \
355 "" "\n"
356
357testing "awk print length 1" \
358 "awk '{ print length 1 }'" \
359 "01\n" \
360 "" "\n"
361
362testing "awk length == 0" \
363 "awk 'length == 0 { print \"foo\" }'" \
364 "foo\n" \
365 "" "\n"
366
367testing "awk if (length == 0)" \
368 "awk '{ if (length == 0) { print \"bar\" } }'" \
369 "bar\n" \
370 "" "\n"
371
Denys Vlasenkobd0e2212013-11-21 15:09:55 +0100372testing "awk -f and ARGC" \
373 "awk -f - input" \
374 "re\n2\n" \
375 "do re mi\n" \
376 '{print $2; print ARGC;}' \
377
Denys Vlasenko198b02f2013-12-31 23:22:36 +0100378optional FEATURE_AWK_GNU_EXTENSIONS
Denys Vlasenkobd0e2212013-11-21 15:09:55 +0100379testing "awk -e and ARGC" \
380 "awk -e '{print \$2; print ARGC;}' input" \
381 "re\n2\n" \
382 "do re mi\n" \
Denys Vlasenko198b02f2013-12-31 23:22:36 +0100383 ""
384SKIP=
Denys Vlasenkobd0e2212013-11-21 15:09:55 +0100385
Denys Vlasenko5f8daef2014-06-26 16:40:28 +0200386testing "awk break" \
387 "awk -f - 2>&1; echo \$?" \
Denys Vlasenkod3480dd2021-07-14 14:33:37 +0200388 "awk: -:1: 'break' not in a loop\n1\n" \
Denys Vlasenko5f8daef2014-06-26 16:40:28 +0200389 "" \
390 'BEGIN { if (1) break; else a = 1 }'
391testing "awk continue" \
392 "awk -f - 2>&1; echo \$?" \
Denys Vlasenkod3480dd2021-07-14 14:33:37 +0200393 "awk: -:1: 'continue' not in a loop\n1\n" \
Denys Vlasenko5f8daef2014-06-26 16:40:28 +0200394 "" \
395 'BEGIN { if (1) continue; else a = 1 }'
396
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200397optional FEATURE_AWK_GNU_EXTENSIONS
Brian Foley61d59972016-10-15 14:45:40 +0100398testing "awk handles invalid for loop" \
Brian Foley08a514c2019-01-01 13:40:59 -0800399 "awk -e '{ for() }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200400SKIP=
Brian Foley61d59972016-10-15 14:45:40 +0100401
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200402optional FEATURE_AWK_GNU_EXTENSIONS
Brian Foleydac15a12019-01-01 13:40:58 -0800403testing "awk handles colon not preceded by ternary" \
Brian Foley08a514c2019-01-01 13:40:59 -0800404 "awk -e foo:bar: 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200405SKIP=
Brian Foley08a514c2019-01-01 13:40:59 -0800406
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200407optional FEATURE_AWK_GNU_EXTENSIONS
Brian Foley08a514c2019-01-01 13:40:59 -0800408testing "awk errors on missing delete arg" \
409 "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" ""
Denys Vlasenko22cc9282019-06-08 13:00:46 +0200410SKIP=
Brian Foleydac15a12019-01-01 13:40:58 -0800411
Ron Yorstone8fe9f92021-01-27 11:19:14 +0000412optional FEATURE_AWK_GNU_EXTENSIONS
413testing "awk printf('%c') can output NUL" \
414 "awk '{printf(\"hello%c null\n\", 0)}'" "hello\0 null\n" "" "\n"
415SKIP=
416
Denys Vlasenko8e8cea22021-08-16 07:37:22 +0200417optional FEATURE_AWK_GNU_EXTENSIONS DESKTOP
Denys Vlasenko8d269ef2021-07-12 11:27:11 +0200418testing "awk printf('%-10c') can output NUL" \
419 "awk 'BEGIN { printf \"[%-10c]\n\", 0 }' | od -tx1" "\
4200000000 5b 00 20 20 20 20 20 20 20 20 20 5d 0a
4210000015
422" "" ""
423SKIP=
424
Denys Vlasenkodf8066a2012-07-11 01:27:15 +0200425# testing "description" "command" "result" "infile" "stdin"
Denys Vlasenko2454e672018-04-23 10:53:18 +0200426testing 'awk negative field access' \
427 'awk 2>&1 -- '\''{ $(-1) }'\' \
428 "awk: cmd. line:1: Access to negative field\n" \
429 '' \
430 'anything'
431
Denys Vlasenko6f7a0092020-06-09 01:33:54 +0200432# was misinterpreted as (("str"++) i) instead of ("str" (++i))
433# (and was executed: "str"++ is "0", thus concatenating "0" and "1"):
434testing 'awk do not allow "str"++' \
435 'awk -v i=1 "BEGIN {print \"str\" ++i}"' \
436 "str2\n" \
437 '' \
438 'anything'
439
Denys Vlasenko758c2bd2020-12-04 19:00:06 +0100440# gawk compat: FS regex matches only non-empty separators:
441# with -*, the splitting is NOT f o o b a r, but foo bar:
Denys Vlasenko665a6592020-12-02 19:07:31 +0100442testing 'awk FS regex which can match empty string' \
443 "awk -F '-*' '{print \$1 \"-\" \$2 \"=\" \$3 \"*\" \$4}'" \
444 "foo-bar=*\n" \
445 '' \
446 'foo--bar'
Denys Vlasenkodf8066a2012-07-11 01:27:15 +0200447
Denys Vlasenko758c2bd2020-12-04 19:00:06 +0100448# last+1 field should be empty (had a bug where it wasn't)
449testing 'awk $NF is empty' \
450 "awk -F '=+' '{print \$NF}'" \
451 "\n" \
452 '' \
453 'a=====123='
454
Denys Vlasenko4d902ea2021-07-02 22:28:51 +0200455testing "awk exit N propagates through END's exit" \
456 "awk 'BEGIN { exit 42 } END { exit }'; echo \$?" \
457 "42\n" \
458 '' ''
459
Denys Vlasenko3d57a842021-07-11 12:00:31 +0200460testing "awk print + redirect" \
461 "awk 'BEGIN { print \"STDERR %s\" >\"/dev/stderr\" }' 2>&1" \
462 "STDERR %s\n" \
463 '' ''
464
Denys Vlasenko39aabfe2021-07-11 12:51:43 +0200465testing "awk \"cmd\" | getline" \
466 "awk 'BEGIN { \"echo HELLO\" | getline; print }'" \
467 "HELLO\n" \
468 '' ''
469
Daniel Thau7d06d6e2021-09-02 07:41:08 -0400470# printf %% should print one % (had a bug where it didn't)
471testing 'awk printf %% prints one %' \
472 "awk 'BEGIN { printf \"%%\n\" }'" \
473 "%\n" \
474 '' ''
475
Denys Vlasenkoe2952df2022-01-08 22:42:35 +0100476testing 'awk backslash+newline eaten with no trace' \
477 "awk 'BEGIN { printf \"Hello\\
478 world\n\" }'" \
479 "Hello world\n" \
480 '' ''
481
Denis Vlasenko960eca62007-07-18 18:33:18 +0000482exit $FAILCOUNT