awk.tests 11 KB

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