Re: wget 1.11.1 make test fails
On Thursday, April 3, 2008 at 9:14:52 -0700, Micah Cowan wrote: > Are you certain you rebuilt cmpt.o? This seems pretty unlikely, to me. Certain: make test after touching src/sysdep.h rebuilds both cmpt.o, the normal in src/ and the one in tests/. And both those cmpt.o become 784 bytes bigger without SYSTEM_FNMATCH. Alain.
Re: wget 1.11.1 make test fails
On Thursday, April 3, 2008 at 22:37:41 +0200, Hrvoje Niksic wrote: > Or it could be that you're picking up a different fnmatch.h that sets > up a different value for FNM_PATHNAME. Do you have more than one > "fnmatch.h" installed on your system? I have only /usr/include/fnmatch.h installed, identical to the file in the libc-5.4.33 tarball, and defining the same values as wget's src/sysdep.h (even comments are identical). Just "my" fnmatch.h defines two more flags, FNM_LEADING_DIR=8 and FNM_CASEFOLD=16, and defines an FNM_FILE_NAME alias (commented as "Preferred GNU name") to FNM_PATHNAME=1 (the libc code uses only this alias). Anyway I had noticed your comment about incompatible headers, and double-checked your little test program also with explicit value 1: same results. BTW everybody should be able to reproduce the make test failure, on any system, just by #undefining SYSTEM_FNMATCH in src/sysdep.h Alain.
Re: wget 1.11.1 make test fails
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hrvoje Niksic wrote: > Alain Guibert <[EMAIL PROTECTED]> writes: > >>> Maybe you could put a breakpoint in fnmatch and see what goes wrong? >> The for loop intended to eat several characters from the string also >> advances the pattern pointer. This one reaches the end of the pattern, >> and points to a NUL. It is not a '*' anymore, so the loop exits >> prematurely. Just below, a test for NUL returns 0. > > Thanks for the analysis. Looking at the current fnmatch code in > gnulib, it seems that the fix is to change that NUL test to something > like: > > if (c == '\0') > { > /* The wildcard(s) is/are the last element of the pattern. > If the name is a file name and contains another slash > this means it cannot match. */ > int result = (flags & FNM_PATHNAME) == 0 ? 0 : FNM_NOMATCH; > if (flags & FNM_PATHNAME) > { > if (!strchr (n, '/')) > result = 0; > } > return result; > } > > But I'm not at all sure that it covers all the needed cases. I'm thinking not: the loop still shouldn't be incrementing n, since that forces each additional * to match at least one character, doesn't it? Gnulib's version seems to handle that better. > Maybe we > should simply switch to gnulib-provided fnmatch? Unfortunately that > one is quite complex and quite hard for the '**' extension Micah > envisions. There might be other fnmatch implementations out there in > GNU which are debugged but still simpler than the gnulib/glibc one. Maybe. I'm not sure ** would be too hard to add to gnulib's fnmatch, just have to toggle with the FNM_FILE_NAME tests within the '*' case, if we see an immediate second '*'. But maybe ** as part of a *?**? sequence is more complex. I don't think so, though. The main thing is that we need it to support the invalid sequence stuff. Hm; I'm not sure we'll ever want fnmatch() to be locale-aware, though. User-specified match patterns should interpret characters based on the locale; but the source strings may be in different encodings altogether. If we solve this by transcoding to the current locale, we may find that the user's locale doesn't support all of the characters that the original string's encoding does. Probably we'll need to transcode both to Unicode before comparison. In the meantime, though, I think we want a simple byte-by-byte match. Perhaps it's best to (a) use our custom matcher, ignoring the system's (so we don't get locale specialness), and (b) fix it, providing as thorough test coverage as possible. - -- Micah J. Cowan Programmer, musician, typesetting enthusiast, gamer, and GNU Wget Project Maintainer. http://micah.cowan.name/ -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFH9jWi7M8hyUobTrERAglwAKCDnpnDjr44Ovgh/oBuzkM4mu/gKACeNnN8 arvFSrCEBatNeO29fzHxuU4= =QDMp -END PGP SIGNATURE-
Re: wget 1.11.1 make test fails
Alain Guibert <[EMAIL PROTECTED]> writes: >> Maybe you could put a breakpoint in fnmatch and see what goes wrong? > > The for loop intended to eat several characters from the string also > advances the pattern pointer. This one reaches the end of the pattern, > and points to a NUL. It is not a '*' anymore, so the loop exits > prematurely. Just below, a test for NUL returns 0. Thanks for the analysis. Looking at the current fnmatch code in gnulib, it seems that the fix is to change that NUL test to something like: if (c == '\0') { /* The wildcard(s) is/are the last element of the pattern. If the name is a file name and contains another slash this means it cannot match. */ int result = (flags & FNM_PATHNAME) == 0 ? 0 : FNM_NOMATCH; if (flags & FNM_PATHNAME) { if (!strchr (n, '/')) result = 0; } return result; } But I'm not at all sure that it covers all the needed cases. Maybe we should simply switch to gnulib-provided fnmatch? Unfortunately that one is quite complex and quite hard for the '**' extension Micah envisions. There might be other fnmatch implementations out there in GNU which are debugged but still simpler than the gnulib/glibc one. It's kind of ironic that while the various system fnmatches were considered broken, the one Wget was using (for many years unconditionally!) was also broken.
Re: wget 1.11.1 make test fails
Alain Guibert <[EMAIL PROTECTED]> writes: > On Wednesday, April 2, 2008 at 23:09:52 +0200, Hrvoje Niksic wrote: > >> Micah Cowan <[EMAIL PROTECTED]> writes: >>> It's hard for me to imagine an fnmatch that ignores FNM_PATHNAME > > The libc 5.4.33 fnmatch() supports FNM_PATHNAME, and there is code > apparently intending to return FNM_NOMATCH on a slash. But this code > seems to be rather broken. Or it could be that you're picking up a different fnmatch.h that sets up a different value for FNM_PATHNAME. Do you have more than one "fnmatch.h" installed on your system?
fnmatch [Re: wget 1.11.1 make test fails]
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Alain Guibert wrote: > The for loop intended to eat several characters from the string also > advances the pattern pointer. This one reaches the end of the pattern, > and points to a NUL. It is not a '*' anymore, so the loop exits > prematurely. Just below, a test for NUL returns 0. > > The body of the loop, returning FNM_NOMATCH on a slash, is not executed > at all. That isn't moderately broken, is it? I haven't stepped through it, but it sure looks broken to my eyes too. I am tired at the moment, though, so may be missing something. GNUlib has an fnmatch, which might be worth considering for use; but AIUI it suffers from the same overly-locale-aware problem that system fnmatches can suffer from (fnmatch fails when the string isn't encoded properly for the current locale; we often don't even _know_ the original encoding, especially for FTP, and mainly want * to match any arbitrary string of byte values). They were looking for someone to address that issue: http://lists.gnu.org/archive/html/bug-gnulib/2008-02/msg00019.html Perhaps, if I'm motivated and somehow scrounge the time, I can fix the problem in their code, and then use it in ours? :) Or, if someone else with more time would like to tackle it, I'm sure that'd also be welcome. :) I responded to the message linked above with a note that Wget also had a need for such functionality, along with some questions about the approach, but hadn't received a response. Maybe I'll try again. - -- Micah J. Cowan Programmer, musician, typesetting enthusiast, gamer, and GNU Wget Project Maintainer. http://micah.cowan.name/ -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFH9XBy7M8hyUobTrERAtReAJ94Ac0ClInQOE7qq7OQxon87zj7JACeOTz3 Lfafi0U2phRDnFqQ2IPSx+s= =9yU/ -END PGP SIGNATURE-
Re: wget 1.11.1 make test fails
On Thursday, April 3, 2008 at 11:08:27 +0200, Hrvoje Niksic wrote: > Well, it would point to a problem with both the fnmatch replacement > and the older system fnmatch. "Our" fnmatch (coming from an old > release of Bash The fnmatch()es in libc 5.4.33 and in Wget are twins. They differ on some minor details like FNM_CASEFOLD support, and cosmetic things like parenthesis around return(code). The part dealing with * in pattern is functionaly identical. > Maybe you could put a breakpoint in fnmatch and see what goes wrong? The for loop intended to eat several characters from the string also advances the pattern pointer. This one reaches the end of the pattern, and points to a NUL. It is not a '*' anymore, so the loop exits prematurely. Just below, a test for NUL returns 0. The body of the loop, returning FNM_NOMATCH on a slash, is not executed at all. That isn't moderately broken, is it? Alain.
Re: wget 1.11.1 make test fails
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Alain Guibert wrote: > Hello Hrvoje, > > On Wednesday, April 2, 2008 at 12:51:20 +0200, Hrvoje Niksic wrote: > >> Alain Guibert <[EMAIL PROTECTED]> writes: >>> The only failing src/utils.c test_array[] line is: >>> | { { "*COMPLETE", NULL, NULL }, "foo/!COMPLETE", false }, >> Try #undefing SYSTEM_FNMATCH in sysdep.h and see if it works then. > > This old system does HAVE_WORKING_FNMATCH_H (and thus SYSTEM_FNMATCH). > When #undefining SYSTEM_FNMATCH, the test still fails at the very same > line. And then it also fails on modern systems. I guess this points at > the embedded src/cmpt.c:fnmatch() replacement? Are you certain you rebuilt cmpt.o? This seems pretty unlikely, to me. > That also demonstrates the major interest of testsuites. Who would have > noticed the runtime consequences of such obscure libc problem otherwise? > Well done, Micah! Heh, thanks. However, I haven't done much yet with testsuites, despite really really wanting to. In this case, I just added two or three lines to a test that Mauro had written, when I noticed that none of the tests were against slashes or strange-ish characters. Guess that was a pretty lucky addition, then! - -- Coincidence? Or proof that God exists, and wants me to find Wget bugs? :) Micah J. Cowan -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFH9QJ87M8hyUobTrERAsqQAJsFjRfUjjCo63Srs2XbuRBBMVJVQgCfTwZU /sp4Vz8QnIV3I3W3/D6Mgq8= =drfg -END PGP SIGNATURE-
Re: wget 1.11.1 make test fails
On Wednesday, April 2, 2008 at 23:09:52 +0200, Hrvoje Niksic wrote: > Micah Cowan <[EMAIL PROTECTED]> writes: >> It's hard for me to imagine an fnmatch that ignores FNM_PATHNAME The libc 5.4.33 fnmatch() supports FNM_PATHNAME, and there is code apparently intending to return FNM_NOMATCH on a slash. But this code seems to be rather broken. >| printf("%d\n", fnmatch("foo*", "foo/bar", FNM_PATHNAME)); > It should print a non-zero value. Zero on the old system, FNM_NOMATCH on a recent one. Alain.
Re: wget 1.11.1 make test fails
Alain Guibert <[EMAIL PROTECTED]> writes: > This old system does HAVE_WORKING_FNMATCH_H (and thus > SYSTEM_FNMATCH). When #undefining SYSTEM_FNMATCH, the test still > fails at the very same line. And then it also fails on modern > systems. I guess this points at the embedded src/cmpt.c:fnmatch() > replacement? Well, it would point to a problem with both the fnmatch replacement and the older system fnmatch. "Our" fnmatch (coming from an old release of Bash, but otherwise very well-tested, both in Bash and Wget) is careful to special-case '/' only if FNM_PATHNAME is specified. Maybe you could put a breakpoint in fnmatch and see what goes wrong?
Re: wget 1.11.1 make test fails
Hello Hrvoje, On Wednesday, April 2, 2008 at 12:51:20 +0200, Hrvoje Niksic wrote: > Alain Guibert <[EMAIL PROTECTED]> writes: >> The only failing src/utils.c test_array[] line is: >> | { { "*COMPLETE", NULL, NULL }, "foo/!COMPLETE", false }, > Try #undefing SYSTEM_FNMATCH in sysdep.h and see if it works then. This old system does HAVE_WORKING_FNMATCH_H (and thus SYSTEM_FNMATCH). When #undefining SYSTEM_FNMATCH, the test still fails at the very same line. And then it also fails on modern systems. I guess this points at the embedded src/cmpt.c:fnmatch() replacement? That also demonstrates the major interest of testsuites. Who would have noticed the runtime consequences of such obscure libc problem otherwise? Well done, Micah! Alain.
Re: wget 1.11.1 make test fails
Micah Cowan <[EMAIL PROTECTED]> writes: > I'm wondering whether it might make sense to go back to completely > ignoring the system-provided fnmatch? One argument against that approach is that it increases code size on systems that do correctly implement fnmatch, i.e. on most modern Unixes that we are targeting. Supporting I18N file names would require modifications to our fnmatch; but on the other hand, we still need it for Windows, so we'd have to make those changes anyway. Providing added value in our fnmatch implementation should go a long way towards preventing complaints of code bloat. > In particular, it would probably resolve the remaining issue with > that one bug you reported about fnmatch() failing on strings whose > encoding didn't match the locale. It would. > Additionally, I've been toying with the idea of adding something > like a "**" to match all characters, including slashes. That would be great. That kind of thing is known to zsh users anyway, and it's a useful feature.
Re: wget 1.11.1 make test fails
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hrvoje Niksic wrote: > Micah Cowan <[EMAIL PROTECTED]> writes: > >>> It sounds like a libc problem rather than a gcc problem. Try >>> #undefing SYSTEM_FNMATCH in sysdep.h and see if it works then. >> It's hard for me to imagine an fnmatch that ignores FNM_PATHNAME: I >> mean, don't most shells rely on this to handle file globbing and >> whatnot? > > The conventional wisdom among free software of the 90s was that > fnmatch() was too buggy to be useful. For that reason all free shells > rolled their own fnmatch, as did other programs that needed it, > including Wget. Maybe the conventional wisdom was right for the > reporter's system. > > Another possibility is that something else is installing fnmatch.h in > a directory on the compiler's search path and breaking the system > fnmatch. IIRC Apache was a known culprit that installed fnmatch.h in > /usr/local/include. That was another reason why Wget used to > completely ignore system-provided fnmatch. I'm wondering whether it might make sense to go back to completely ignoring the system-provided fnmatch? In particular, it would probably resolve the remaining issue with that one bug you reported about fnmatch() failing on strings whose encoding didn't match the locale. Additionally, I've been toying with the idea of adding something like a "**" to match all characters, including slashes. There was a user who had trouble using wildcards to match any directory whose name was (as in the problem example here), "!COMPLETE". At the time I wasn't fully certain that it wasn't a bug in Wget; as I understand it now, in order to match _any_ directory !COMPLETE, you'd have to be sure to exclude "!COMPLETE", "*/!COMPLETE", "*/*/!COMPLETE", etc. I'm not sure if it's original there, but Vim uses a ** pattern, so that you could simply write "**!COMPLETE" (or, if you wanted to be more correct I suppose, just "!COMPLETE" and "**/!COMPLETE"). What do you think? - -- Micah J. Cowan Programmer, musician, typesetting enthusiast, gamer, and GNU Wget Project Maintainer. http://micah.cowan.name/ -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD4DBQFH8/zx7M8hyUobTrERAtpoAJiQHrzVjFwKXxEjteqMGAGgBCMgAJ9rZIah k+92ivTBGpSsmHcLnlsjfQ== =JLn9 -END PGP SIGNATURE-
Re: wget 1.11.1 make test fails
Micah Cowan <[EMAIL PROTECTED]> writes: >> It sounds like a libc problem rather than a gcc problem. Try >> #undefing SYSTEM_FNMATCH in sysdep.h and see if it works then. > > It's hard for me to imagine an fnmatch that ignores FNM_PATHNAME: I > mean, don't most shells rely on this to handle file globbing and > whatnot? The conventional wisdom among free software of the 90s was that fnmatch() was too buggy to be useful. For that reason all free shells rolled their own fnmatch, as did other programs that needed it, including Wget. Maybe the conventional wisdom was right for the reporter's system. Another possibility is that something else is installing fnmatch.h in a directory on the compiler's search path and breaking the system fnmatch. IIRC Apache was a known culprit that installed fnmatch.h in /usr/local/include. That was another reason why Wget used to completely ignore system-provided fnmatch. In any case, it should be easy enough to isolate the problem: #include #include int main() { printf("%d\n", fnmatch("foo*", "foo/bar", FNM_PATHNAME)); return 0; } It should print a non-zero value.
Re: wget 1.11.1 make test fails
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hrvoje Niksic wrote: > Alain Guibert <[EMAIL PROTECTED]> writes: > >> Hello Micah, >> >> On Monday, March 31, 2008 at 11:39:43 -0700, Micah Cowan wrote: >> >>> could you try to isolate which part of test_dir_matches_p is failing? >> The only failing src/utils.c test_array[] line is: >> >> | { { "*COMPLETE", NULL, NULL }, "foo/!COMPLETE", false }, >> >> I don't understand enough of dir_matches_p() and fnmatch() to guess >> what is supposed to happen. But with false replaced by true, this >> test and following succeed. > > '*' is not supposed to match '/' in regular fnmatch. Well, that's assuming you pass it the FNM_PATHNAME flag (which, for dir_matches_p, we always do). > It sounds like a libc problem rather than a gcc problem. Try > #undefing SYSTEM_FNMATCH in sysdep.h and see if it works then. It's hard for me to imagine an fnmatch that ignores FNM_PATHNAME: I mean, don't most shells rely on this to handle file globbing and whatnot? - -- Micah J. Cowan Programmer, musician, typesetting enthusiast, gamer, and GNU Wget Project Maintainer. http://micah.cowan.name/ -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFH86+L7M8hyUobTrERApHKAJsFbO8+PtAqFhHJ2Psv1AuKSy17YwCcDsi2 9WHcJ0Pzkc4XmNbcEUCXf6U= =r8ZV -END PGP SIGNATURE-
Re: wget 1.11.1 make test fails
Alain Guibert <[EMAIL PROTECTED]> writes: > Hello Micah, > > On Monday, March 31, 2008 at 11:39:43 -0700, Micah Cowan wrote: > >> could you try to isolate which part of test_dir_matches_p is failing? > > The only failing src/utils.c test_array[] line is: > > | { { "*COMPLETE", NULL, NULL }, "foo/!COMPLETE", false }, > > I don't understand enough of dir_matches_p() and fnmatch() to guess > what is supposed to happen. But with false replaced by true, this > test and following succeed. '*' is not supposed to match '/' in regular fnmatch. It sounds like a libc problem rather than a gcc problem. Try #undefing SYSTEM_FNMATCH in sysdep.h and see if it works then.
Re: wget 1.11.1 make test fails
Hello Micah, On Monday, March 31, 2008 at 11:39:43 -0700, Micah Cowan wrote: > could you try to isolate which part of test_dir_matches_p is failing? The only failing src/utils.c test_array[] line is: | { { "*COMPLETE", NULL, NULL }, "foo/!COMPLETE", false }, I don't understand enough of dir_matches_p() and fnmatch() to guess what is supposed to happen. But with false replaced by true, this test and following succeed. | ALL TESTS PASSED | Tests run: 7 Of course this test then fails on newer systems. Alain.
Re: wget 1.11.1 make test fails
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Alain Guibert wrote: > Hello, > > With an old gcc 2.7.2.1 compiler, wget 1.11.1 make test fails: > > | gcc -I. -I. -I./../src -DHAVE_CONFIG_H > -DSYSTEM_WGETRC=\"/usr/local/etc/wgetrc\" > -DLOCALEDIR=\"/usr/local/share/locale\" -O2 -Wall -DTESTING -c ../src/test.c > | ../src/test.c: In function `all_tests': > | ../src/test.c:51: parse error before `const' > The attached make-test.patch seems to fix this. Yeah; that's invalid C90 code; declaration following statement. I'll fix that. > However later the 3rd > test fails: > > | ./unit-tests > | RUNNING TEST test_parse_content_disposition... > | PASSED > | > | RUNNING TEST test_subdir_p... > | PASSED > | > | RUNNING TEST test_dir_matches_p... > | test_dir_matches_p: wrong result > | Tests run: 3 > | make[1]: *** [run-unit-tests] Error 1 > | make[1]: Leaving directory `/tmp/wget-1.11.1/tests' > | make: *** [test] Error 2 That's an interesting failure. I wonder if it's one of the new cases I just added... In any case, it runs through fine for me. This suggests a difference in behavior between your system fnmatch function and mine (since that should be the only bit of external code that dir_matches_p relies on). Pity the tests don't give much clue as to the specifics of what failed... there are about 10 tests for test_dir_matches_p, any of which could have caused the problem. The whole testing thing needs some serious rework; which is my current top priority, when I find time for it (GSoC is eating everything, right now). "make test" isn't actually expected to work completely, right now; some of the .px tests are known to be broken/missing. They're basically provided "as-is". I thought about removing them for the official package; maybe I should have. But if I had, I'd still be blissfully unaware of this potential problem. If you know how, and don't mind, could you try to isolate which part of test_dir_matches_p is failing? Perhaps augmenting the error message to spit the match-list and string arguments... - -- Thanks, Micah J. Cowan Programmer, musician, typesetting enthusiast, gamer, and GNU Wget Project Maintainer. http://micah.cowan.name/ -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFH8S/v7M8hyUobTrERAhrPAJ9N+XqLeVP0NN9HkLxO162Zf2uJnACeMwUo kew/FkMA2GljqWiPG6IC+zs= =fQSH -END PGP SIGNATURE-
wget 1.11.1 make test fails
Hello, With an old gcc 2.7.2.1 compiler, wget 1.11.1 make test fails: | gcc -I. -I. -I./../src -DHAVE_CONFIG_H -DSYSTEM_WGETRC=\"/usr/local/etc/wgetrc\" -DLOCALEDIR=\"/usr/local/share/locale\" -O2 -Wall -DTESTING -c ../src/test.c | ../src/test.c: In function `all_tests': | ../src/test.c:51: parse error before `const' | ../src/test.c:51: `message' undeclared (first use this function) | ../src/test.c:51: (Each undeclared identifier is reported only once | ../src/test.c:51: for each function it appears in.) | ../src/test.c:52: parse error before `const' | ../src/test.c:53: parse error before `const' | ../src/test.c:54: parse error before `const' | ../src/test.c:55: parse error before `const' | ../src/test.c:56: parse error before `const' | ../src/test.c:57: parse error before `const' | make[1]: *** [test.o] Error 1 | make[1]: Leaving directory `/tmp/wget-1.11.1/tests' | make: *** [test] Error 2 The attached make-test.patch seems to fix this. However later the 3rd test fails: | ./unit-tests | RUNNING TEST test_parse_content_disposition... | PASSED | | RUNNING TEST test_subdir_p... | PASSED | | RUNNING TEST test_dir_matches_p... | test_dir_matches_p: wrong result | Tests run: 3 | make[1]: *** [run-unit-tests] Error 1 | make[1]: Leaving directory `/tmp/wget-1.11.1/tests' | make: *** [test] Error 2 Alain. diff -prud wget-1.11.1.orig/src/test.h wget-1.11.1/src/test.h --- wget-1.11.1.orig/src/test.h Mon Mar 24 22:53:58 2008 +++ wget-1.11.1/src/test.h Mon Mar 31 15:19:31 2008 @@ -34,8 +34,9 @@ as that of the covered work. */ #define mu_assert(message, test) do { if (!(test)) return message; } while (0) #define mu_run_test(test) \ do { \ + const char *message; \ puts("RUNNING TEST " #test "..."); \ - const char *message = test(); \ + message = test(); \ tests_run++; \ if (message) return message; \ puts("PASSED\n"); \