test: fix mishandling of 'test ! arg1 op arg2 more args'; add testsuite
No binary (build failed)
—
(log yok)
| @@ -555,7 +555,7 @@ int test_main(int argc, char **argv) | |
| { | |
| int res; | |
| const char *arg0; | |
| - | bool _off; |
| + | bool negate = 0; |
| arg0 = bb_basename(argv[0]); | |
| if (arg0[0] == '[') { | |
| @@ -578,9 +578,8 @@ int test_main(int argc, char **argv) | |
| INIT_S(); | |
| res = setjmp(leaving); | |
| - | if (res) { |
| + | if (res) |
| goto ret; | |
| - | } |
| /* resetting ngroups is probably unnecessary. it will | |
| * force a new call to getgroups(), which prevents using | |
| @@ -592,34 +591,40 @@ int test_main(int argc, char **argv) | |
| */ | |
| ngroups = 0; | |
| + | //argc--; |
| + | argv++; |
| + | |
| /* Implement special cases from POSIX.2, section 4.62.4 */ | |
| - | if (argc == 1) { |
| + | if (!argv[0]) { /* "test" */ |
| res = 1; | |
| goto ret; | |
| } | |
| - | if (argc == 2) { |
| - | res = (*argv[1] == '\0'); |
| + | if (LONE_CHAR(argv[0], '!') && argv[1]) { |
| + | negate = 1; |
| + | //argc--; |
| + | argv++; |
| + | } |
| + | if (!argv[1]) { /* "test [!] arg" */ |
| + | res = (*argv[0] == '\0'); |
| goto ret; | |
| } | |
| - | |
| - | /* remember if we saw argc==4 which wants *no* '!' test */ |
| - | _off = argc - 4; |
| - | if (_off ? (LONE_CHAR(argv[1], '!')) |
| - | : (argv[1][0] != '!' || argv[1][1] != '\0') |
| - | ) { |
| - | if (argc == 3) { |
| - | res = (*argv[2] != '\0'); |
| - | goto ret; |
| - | } |
| - | |
| - | t_lex(argv[2 + _off]); |
| + | if (argv[2] && !argv[3]) { |
| + | t_lex(argv[1]); |
| if (t_wp_op && t_wp_op->op_type == BINOP) { | |
| - | t_wp = &argv[1 + _off]; |
| - | res = (binop() == _off); |
| + | /* "test [!] arg1 <binary_op> arg2" */ |
| + | t_wp = &argv[0]; |
| + | res = (binop() == 0); |
| goto ret; | |
| } | |
| } | |
| - | t_wp = &argv[1]; |
| + | |
| + | /* Some complex expression. Undo '!' removal */ |
| + | if (negate) { |
| + | negate = 0; |
| + | //argc++; |
| + | argv--; |
| + | } |
| + | t_wp = &argv[0]; |
| res = !oexpr(t_lex(*t_wp)); | |
| if (*t_wp != NULL && *++t_wp != NULL) { | |
| @@ -628,5 +633,5 @@ int test_main(int argc, char **argv) | |
| } | |
| ret: | |
| DEINIT_S(); | |
| - | return res; |
| + | return negate ? !res : res; |
| } | |
| @@ -0,0 +1,26 @@ | |
| + | #!/bin/sh |
| + | |
| + | # Copyright 2007 by Denys Vlasenko <[email protected]> |
| + | # Licensed under GPL v2, see file LICENSE for details. |
| + | |
| + | . testing.sh |
| + | |
| + | # testing "test name" "options" "expected result" "file input" "stdin" |
| + | # file input will be file called "input" |
| + | # test can create a file "actual" instead of writing to stdout |
| + | |
| + | # Need to call 'busybox test', otherwise shell builtin is used |
| + | |
| + | testing "test ! a = b -a ! c = c: should be false" \ |
| + | "busybox test ! a = b -a ! c = c; echo \$?" \ |
| + | "1\n" \ |
| + | "" \ |
| + | "" \ |
| + | |
| + | testing "test ! a = b -a ! c = d: should be true" \ |
| + | "busybox test ! a = b -a ! c = d; echo \$?" \ |
| + | "0\n" \ |
| + | "" \ |
| + | "" \ |
| + | |
| + | exit $FAILCOUNT |