busybox/testsuite/awk.tests
<<
>>
Prefs
   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
  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
  19# 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
  26# 4294967295 = 0xffffffff
  27testing "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
  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
  47prg='
  48function empty_fun(){}
  49END {empty_fun()
  50  print "Ok"
  51}'
  52testing "awk handles empty function f(){}" \
  53        "awk '$prg'" \
  54        "Ok\n" \
  55        "" ""
  56
  57prg='
  58function 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
  84prg='
  85BEGIN {
  86  v=1
  87  a=2
  88  print v (a)
  89}'
  90testing "awk 'v (a)' is not a function call, it is a concatenation" \
  91        "awk '$prg' 2>&1" \
  92        "12\n" \
  93        "" ""
  94
  95prg='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
 101
 102optional DESKTOP
 103testing "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"
 105testing "awk oct const"   "awk '{ print or(01234,1) }'"      "669\n"         "" "\n"
 106SKIP=
 107
 108# 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
 114# long field seps requiring regex
 115testing "awk long field sep" \
 116        "awk -F-- '{ print NF, length(\$NF), \$NF }'" \
 117        "2 0 \n3 0 \n4 0 \n5 0 \n" \
 118        "" \
 119        "a--\na--b--\na--b--c--\na--b--c--d--"
 120
 121testing "awk -F handles escapes" "awk -F'\\x21' '{print \$1}'" \
 122        "a\n" \
 123        "" \
 124        "a!b\n"
 125
 126# '@(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
 131optional TAR BUNZIP2 FEATURE_SEAMLESS_BZ2
 132test x"$SKIP" != x"1" && tar xjf awk_t1.tar.bz2
 133testing "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        "" ""
 137rm -rf awk_t1_* 2>/dev/null
 138SKIP=
 139
 140Q='":"'
 141
 142testing "awk NF in BEGIN" \
 143        "awk 'BEGIN { print ${Q} NF ${Q} \$0 ${Q} \$1 ${Q} \$2 ${Q} }'" \
 144        ":0::::\n" \
 145        "" ""
 146
 147prg='
 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
 164testing "awk handles whitespace before array subscript" \
 165        "awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" ""
 166
 167# 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
 173prg='
 174BEGIN {
 175  u["a"]=1
 176  u["b"]=1
 177  u["c"]=1
 178  v["d"]=1
 179  v["e"]=1
 180  v["f"]=1
 181  for (l in u) {
 182    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        "\
 195outer1 a
 196 inner d
 197 inner e
 198 inner f
 199outer2 f
 200outer1 b
 201 inner d
 202 inner e
 203 inner f
 204outer2 f
 205outer1 c
 206 inner d
 207 inner e
 208 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
 289" \
 290        "" ""
 291
 292prg='
 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
 311testing "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
 323testing "awk handles empty ()" \
 324        "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
 325
 326testing "awk FS assignment" "awk '{FS=\":\"; print \$1}'" \
 327        "a:b\ne\n" \
 328        "" \
 329        "a:b c:d\ne:f g:h"
 330
 331optional FEATURE_AWK_LIBM
 332testing "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        "" ""
 336SKIP=
 337
 338testing "awk length(array)" \
 339        "awk 'BEGIN{ A[1]=2; A[\"qwe\"]=\"asd\"; print length(A)}'" \
 340        "2\n" \
 341        "" ""
 342
 343testing "awk length()" \
 344        "awk '{print length; print length(); print length(\"qwe\"); print length(99+9)}'" \
 345        "3\n3\n3\n3\n" \
 346        "" "qwe"
 347
 348testing "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
 368testing "awk -f and ARGC" \
 369        "awk -f - input" \
 370        "re\n2\n" \
 371        "do re mi\n" \
 372        '{print $2; print ARGC;}' \
 373
 374optional FEATURE_AWK_GNU_EXTENSIONS
 375testing "awk -e and ARGC" \
 376        "awk -e '{print \$2; print ARGC;}' input" \
 377        "re\n2\n" \
 378        "do re mi\n" \
 379        ""
 380SKIP=
 381
 382testing "awk break" \
 383        "awk -f - 2>&1; echo \$?" \
 384        "awk: -:1: 'break' not in a loop\n1\n" \
 385        "" \
 386        'BEGIN { if (1) break; else a = 1 }'
 387testing "awk continue" \
 388        "awk -f - 2>&1; echo \$?" \
 389        "awk: -:1: 'continue' not in a loop\n1\n" \
 390        "" \
 391        'BEGIN { if (1) continue; else a = 1 }'
 392
 393optional FEATURE_AWK_GNU_EXTENSIONS
 394testing "awk handles invalid for loop" \
 395        "awk -e '{ for() }' 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
 396SKIP=
 397
 398optional FEATURE_AWK_GNU_EXTENSIONS
 399testing "awk handles colon not preceded by ternary" \
 400        "awk -e foo:bar: 2>&1" "awk: cmd. line:1: Unexpected token\n" "" ""
 401SKIP=
 402
 403optional FEATURE_AWK_GNU_EXTENSIONS
 404testing "awk errors on missing delete arg" \
 405        "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" ""
 406SKIP=
 407
 408optional 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
 413optional FEATURE_AWK_GNU_EXTENSIONS DESKTOP
 414testing "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
 421# testing "description" "command" "result" "infile" "stdin"
 422testing 'awk negative field access' \
 423        'awk 2>&1 -- '\''{ $(-1) }'\' \
 424        "awk: cmd. line:1: Access to negative field\n" \
 425        '' \
 426        'anything'
 427
 428# 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
 436# gawk compat: FS regex matches only non-empty separators:
 437# with -*, the splitting is NOT f o o b a r, but foo bar:
 438testing 'awk FS regex which can match empty string' \
 439        "awk -F '-*' '{print \$1 \"-\" \$2 \"=\" \$3 \"*\" \$4}'" \
 440        "foo-bar=*\n" \
 441        '' \
 442        'foo--bar'
 443
 444# 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
 451testing "awk exit N propagates through END's exit" \
 452        "awk 'BEGIN { exit 42 } END { exit }'; echo \$?" \
 453        "42\n" \
 454        '' ''
 455
 456testing "awk print + redirect" \
 457        "awk 'BEGIN { print \"STDERR %s\" >\"/dev/stderr\" }' 2>&1" \
 458        "STDERR %s\n" \
 459        '' ''
 460
 461testing "awk \"cmd\" | getline" \
 462        "awk 'BEGIN { \"echo HELLO\" | getline; print }'" \
 463        "HELLO\n" \
 464        '' ''
 465
 466# 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
 472exit $FAILCOUNT
 473