bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bugs in test


From: Eric Blake
Subject: bugs in test
Date: Mon, 09 Jan 2006 07:13:08 -0700
User-agent: Mozilla Thunderbird 1.0.2 (Windows/20050317)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

test currently treats -a, -o, and -N as undocumented unary ops in
test_unop(), but in unary_operator(), -a maps to -e, but -o and -N are
ignored as invalid.  This leads to some strange behavior:

$ /bin/test -e ChangeLog ; echo $?
0
$ /bin/test -q ChangeLog ; echo $?
/bin/test: -q: unary operator expected
2
$ /bin/test -a ChangeLog ; echo $?
0
$ /bin/test -o ChangeLog ; echo $?
/bin/test: extra argument `-o'2
$ /bin/test -N ChangeLog ; echo $?
/bin/test: extra argument `-N'2
$ /bin/test a ChangeLog ; echo $?
/bin/test: missing argument after `ChangeLog'2

First, the 'extra argument' and 'missing argument' error messages are
missing a trailing newline.

Second, it is confusing that -a is silently accepted, but that non-unary
operators that look like an operator, such as -q, get a different error
message than non-unary operators that are completely random, which are yet
different from the special cases of -o and -N.  I think -a was added to
match bash's unary -a as a synonym for -e, and -N intends to match bash's
- -N which returns true if a file has been modified since it was last read;
bash's unary -o is unimplementable in /bin/test since there is no way to
determine if a shell option is set when test is not a shell builtin.

However, none of these behaviors violate POSIX, since test is allowed to
produce unspecified results when there are 2 arguments, the first is not
'!', and the first is not a unary primary.

The POSIX violation comes in when you now try to negate these tests:

$ /bin/test ! -a ChangeLog ; echo $?
1
$ /bin/test ! -o ChangeLog ; echo $?
/bin/test: extra argument `-o'2
$ /bin/test ! = ! ; echo $?
0

My reading of POSIX is that when there are three arguments, binary
operators take precedence over ! (although this is probably worth an
aardvark, since when there are more than 3 arguments, there is no explicit
requirement of precedence between ! vs. binary -a).  Note that "/bin/test
! = !" correctly parsed the same as "/bin/test x! = x!", by recognizing
that = is a binary operator.  I argue that "/bin/test ! -a ChangeLog"
should also parse as "/bin/test \( ! \) -a ChangeLog", which performs a
1-argument test on both ! and ChangeLog (both are non-empty), and results
in true (exit status 0); rather than parsing as "/bin/test ! \( -a
ChangeLog \)", performing the unary -a, then negating it, resulting in
false (exit status 1).  Likewise, "/bin/test ! -o ChangeLog" should
perform two 1-argument tests, and return true, since binary -o should have
higher precendence than a negation of a (non-existant) unary -o.

- --
Life is short - so eat dessert first!

Eric Blake             address@hidden

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFDwm9z84KuGfSFAYARAre4AJ0eo4/IsTqvpOH/kQEruark3MoUCQCeMtEV
JBkrzBLcSWKu4MZBN4cSW/I=
=repS
-----END PGP SIGNATURE-----




reply via email to

[Prev in Thread] Current Thread [Next in Thread]