blob: 82937bc10b41bf907573fe8d87a31212706b8d82
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" "awk -F-- '{ print NF, length(\$NF), \$NF }'" \ |
89 | "2 0 \n3 0 \n4 0 \n5 0 \n" \ |
90 | "" \ |
91 | "a--\na--b--\na--b--c--\na--b--c--d--" |
92 | |
93 | testing "awk -F handles escapes" "awk -F'\\x21' '{print \$1}'" \ |
94 | "a\n" \ |
95 | "" \ |
96 | "a!b\n" |
97 | |
98 | # '@(samp|code|file)\{' is an invalid extended regex (unmatched '{'), |
99 | # but gawk 3.1.5 does not bail out on it. |
100 | testing "awk gsub falls back to non-extended-regex" \ |
101 | "awk 'gsub(\"@(samp|code|file)\{\",\"\");'; echo \$?" "0\n" "" "Hi\n" |
102 | |
103 | optional TAR BUNZIP2 FEATURE_SEAMLESS_BZ2 |
104 | test x"$SKIP" != x"1" && tar xjf awk_t1.tar.bz2 |
105 | testing "awk 'gcc build bug'" \ |
106 | "awk -f awk_t1_opt-functions.awk -f awk_t1_opth-gen.awk <awk_t1_input | md5sum" \ |
107 | "f842e256461a5ab1ec60b58d16f1114f -\n" \ |
108 | "" "" |
109 | rm -rf awk_t1_* 2>/dev/null |
110 | SKIP= |
111 | |
112 | Q='":"' |
113 | |
114 | testing "awk NF in BEGIN" \ |
115 | "awk 'BEGIN { print ${Q} NF ${Q} \$0 ${Q} \$1 ${Q} \$2 ${Q} }'" \ |
116 | ":0::::\n" \ |
117 | "" "" |
118 | |
119 | prg=' |
120 | function b(tmp) { |
121 | tmp = 0; |
122 | print "" tmp; #this line causes the bug |
123 | return tmp; |
124 | } |
125 | function c(tmpc) { |
126 | tmpc = b(); return tmpc; |
127 | } |
128 | BEGIN { |
129 | print (c() ? "string" : "number"); |
130 | }' |
131 | testing "awk string cast (bug 725)" \ |
132 | "awk '$prg'" \ |
133 | "0\nnumber\n" \ |
134 | "" "" |
135 | |
136 | testing "awk handles whitespace before array subscript" \ |
137 | "awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" "" |
138 | |
139 | # GNU awk 3.1.5's "print ERRNO" prints "No such file or directory" instead of "2", |
140 | # do we need to emulate that as well? |
141 | testing "awk handles non-existing file correctly" \ |
142 | "awk 'BEGIN { getline line <\"doesnt_exist\"; print ERRNO; ERRNO=0; close(\"doesnt_exist\"); print ERRNO; print \"Ok\" }'" \ |
143 | "2\n0\nOk\n" "" "" |
144 | |
145 | prg=' |
146 | BEGIN { |
147 | u["a"]=1 |
148 | u["b"]=1 |
149 | u["c"]=1 |
150 | v["d"]=1 |
151 | v["e"]=1 |
152 | v["f"]=1 |
153 | for (l in u) { |
154 | print "outer1", l; |
155 | for (l in v) { |
156 | print " inner", l; |
157 | } |
158 | print "outer2", l; |
159 | } |
160 | print "end", l; |
161 | l="a" |
162 | exit; |
163 | }' |
164 | testing "awk nested loops with the same variable" \ |
165 | "awk '$prg'" \ |
166 | "\ |
167 | outer1 a |
168 | inner d |
169 | inner e |
170 | inner f |
171 | outer2 f |
172 | outer1 b |
173 | inner d |
174 | inner e |
175 | inner f |
176 | outer2 f |
177 | outer1 c |
178 | inner d |
179 | inner e |
180 | inner f |
181 | outer2 f |
182 | end f |
183 | " \ |
184 | "" "" |
185 | |
186 | prg=' |
187 | BEGIN { |
188 | u["a"]=1 |
189 | u["b"]=1 |
190 | u["c"]=1 |
191 | v["d"]=1 |
192 | v["e"]=1 |
193 | v["f"]=1 |
194 | for (l in u) { |
195 | print "outer1", l; |
196 | for (l in v) { |
197 | print " inner", l; |
198 | break; |
199 | } |
200 | print "outer2", l; |
201 | } |
202 | print "end", l; |
203 | l="a" |
204 | exit; |
205 | }' |
206 | # It's not just buggy, it enters infinite loop. Thus disabled |
207 | false && test x"$SKIP_KNOWN_BUGS" = x"" && testing "awk nested loops with the same variable and break" \ |
208 | "awk '$prg'" \ |
209 | "\ |
210 | outer1 a |
211 | inner d |
212 | outer2 d |
213 | outer1 b |
214 | inner d |
215 | outer2 d |
216 | outer1 c |
217 | inner d |
218 | outer2 d |
219 | end d |
220 | " \ |
221 | "" "" |
222 | |
223 | prg=' |
224 | function f() { |
225 | for (l in v) { |
226 | print " inner", l; |
227 | return; |
228 | } |
229 | } |
230 | |
231 | BEGIN { |
232 | u["a"]=1 |
233 | u["b"]=1 |
234 | u["c"]=1 |
235 | v["d"]=1 |
236 | v["e"]=1 |
237 | v["f"]=1 |
238 | for (l in u) { |
239 | print "outer1", l; |
240 | f(); |
241 | print "outer2", l; |
242 | } |
243 | print "end", l; |
244 | l="a" |
245 | exit; |
246 | }' |
247 | # It's not just buggy, it enters infinite loop. Thus disabled |
248 | false && test x"$SKIP_KNOWN_BUGS" = x"" && testing "awk nested loops with the same variable and return" \ |
249 | "awk '$prg'" \ |
250 | "\ |
251 | outer1 a |
252 | inner d |
253 | outer2 d |
254 | outer1 b |
255 | inner d |
256 | outer2 d |
257 | outer1 c |
258 | inner d |
259 | outer2 d |
260 | end d |
261 | " \ |
262 | "" "" |
263 | |
264 | testing "awk handles empty ()" \ |
265 | "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" "" |
266 | |
267 | testing "awk FS assignment" "awk '{FS=\":\"; print \$1}'" \ |
268 | "a:b\ne\n" \ |
269 | "" \ |
270 | "a:b c:d\ne:f g:h" |
271 | |
272 | optional FEATURE_AWK_LIBM |
273 | testing "awk large integer" \ |
274 | "awk 'BEGIN{n=(2^31)-1; print n, int(n), n%1, ++n, int(n), n%1}'" \ |
275 | "2147483647 2147483647 0 2147483648 2147483648 0\n" \ |
276 | "" "" |
277 | SKIP= |
278 | |
279 | testing "awk length(array)" \ |
280 | "awk 'BEGIN{ A[1]=2; A[\"qwe\"]=\"asd\"; print length(A)}'" \ |
281 | "2\n" \ |
282 | "" "" |
283 | |
284 | testing "awk length()" \ |
285 | "awk '{print length; print length(); print length(\"qwe\"); print length(99+9)}'" \ |
286 | "3\n3\n3\n3\n" \ |
287 | "" "qwe" |
288 | |
289 | testing "awk -f and ARGC" \ |
290 | "awk -f - input" \ |
291 | "re\n2\n" \ |
292 | "do re mi\n" \ |
293 | '{print $2; print ARGC;}' \ |
294 | |
295 | optional FEATURE_AWK_GNU_EXTENSIONS |
296 | testing "awk -e and ARGC" \ |
297 | "awk -e '{print \$2; print ARGC;}' input" \ |
298 | "re\n2\n" \ |
299 | "do re mi\n" \ |
300 | "" |
301 | SKIP= |
302 | |
303 | # The examples are in fact not valid awk programs (break/continue |
304 | # can only be used inside loops). |
305 | # But we do accept them outside of loops. |
306 | # We had a bug with misparsing "break ; else" sequence. |
307 | # Test that *that* bug is fixed, using simplest possible scripts: |
308 | testing "awk break" \ |
309 | "awk -f - 2>&1; echo \$?" \ |
310 | "0\n" \ |
311 | "" \ |
312 | 'BEGIN { if (1) break; else a = 1 }' |
313 | testing "awk continue" \ |
314 | "awk -f - 2>&1; echo \$?" \ |
315 | "0\n" \ |
316 | "" \ |
317 | 'BEGIN { if (1) continue; else a = 1 }' |
318 | |
319 | testing "awk handles invalid for loop" \ |
320 | "awk '{ for() }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" "" |
321 | |
322 | # testing "description" "command" "result" "infile" "stdin" |
323 | |
324 | exit $FAILCOUNT |
325 |