[Top][All Lists]
[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-----
- bugs in test,
Eric Blake <=