Skip Menu |

This queue is for tickets about the Test-Unit CPAN distribution.

Report information
The Basics
Id: 16130
Status: resolved
Priority: 0/
Queue: Test-Unit

People
Owner: mca1001 [...] users.sourceforge.net
Requestors: wyon+perlunit [...] pobox.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.25
Fixed in: 0.25_0922



Subject: Test-Unit 0.25 fails "make test"
Problem: On one of our Linux/Intel boxes, Test-Unit fails its "make test" tests. On another box, which runs Solaris/Sparc, the tests succceed. (System details and full output are at the end of this report.) The specific test which is failing (on the Linux box) is this one: not ok ERROR test_numericness tlib/AssertTest.pm:48 - test_numericness(Class::Inner::__A28) For string '0xF00', expect f but got t Analysis: That particular test caselet (at t/tlib/AssertTest.pm line 37) looks like: '0xF00' => 'f', # controversial? but if you +=10 then it's == 10 So it would seem that the developers are unsure what the result is *supposed* to be ... with good reason, as it turns out :-/ On the Linux machine, this Perl program: $s = '0xF00'; $s += 10; print "\$s = $s\n"; $i = 0xF00 + 10; print "\$i = $i\n"; prints: $s = 3850 $i = 3850 On this box, the assertion in the comment is wrong. The "0x" prefix is recognized in the value of a string scalar, the same as it is in a numeric literal. On the Solaris box, by contrast, that same program does indeed print: $s = 10 $i = 3850 suggesting that the "0x" is *not* recognized in $s's value, and instead the "x" terminates the parsing of the string. Interestingly, this variant (note the "3x"): $s = '3xF00'; $s += 10; print "\$s = $s\n"; prints: $s = 13 on *both* boxes. One could argue that is_numeric() should return TRUE iff Perl itself thinks the string is numeric -- and if different Perls disagree with each other on that point, is_numeric() should agree with the Perl binary it's running under. In this case, the "0xF00" test case is simply meaningless, and should be deleted. But to me, a more compelling argument is that is_numeric() should return the same result on all systems. Presumably, only one of the above string->numeric conversions is correct (though I won't hazard a guess as to which one), and the other one is a bug in the corresponding Perl binary. Such a bug can cause system-dependent problems in my application, and unit testing should help detect those problems, even if the underlying bug isn't in my own code. Feel free to send me private email if you have a candidate fix that you want me to test on both of these systems. Thanks. ========== Listings start here ================= On the Linux box, the "make test "output looks like: $ make test PERL_DL_NONLAZY=1 /usr/local/bin/perl -Iblib/arch -Iblib/lib -I/usr/lib/perl/5.6.1 -I/usr/share/perl/5.6.1 -e 'use Test::Harness qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t t/all_tests.......ok t/assert..........FAILED test 29 Failed 1/40 tests, 97.50% okay t/try_examples....ok Failed Test Stat Wstat Total Fail Failed List of Failed ------------------------------------------------------------------------------- t/assert.t 40 1 2.50% 29 Failed 1/3 test scripts, 66.67% okay. 1/89 subtests failed, 98.88% okay. make: *** [test_dynamic] Error 11 $ Digging one level deeper, again on the Linux box: $ cd t; prove -lbv assert.t assert....STARTING TEST RUN 1..40 ok PASS 0 == 'foo' ok PASS 1 == '1.0' ok PASS '1.0' == 1 ok PASS foo eq foo ok PASS 0E0 == 0 ok PASS 0 == 'foo' ok PASS both undef ok PASS 0 == 0 ok PASS 0 == 0.0 ok PASS 0.0 == 0 ok PASS 0.0 == 0.0 ok PASS '' == '' ok PASS 1 != 'foo' ok PASS 'foo' ne 0 ok PASS 'foo' ne 1 ok PASS 0 != 1 ok PASS 'foo' ne 'bar' ok PASS 'foo' ne undef ok PASS undef ne 'foo' ok PASS test_succeed_assert_not_null ok PASS test_assert_raises ok PASS test_ok_not_equals ok PASS test_fail ok PASS test_ok_equals ok PASS test_assert_equals ok PASS test_multi_assert ok PASS test_success_assert_not_equals ok PASS test_assert_deep_equals not ok ERROR test_numericness tlib/AssertTest.pm:48 - test_numericness(Class::Inner::__A28) For string '0xF00', expect f but got t ok PASS test_assert ok PASS test_assert_matches ok PASS test_fail_assert_not_equals ok PASS test_ok_bad_args ok PASS test_ok_boolean ok PASS test_fail_assert_null ok PASS test_assert_str_equals ok PASS test_fail_assert_not_null ok PASS test_assert_equals_null ok PASS test_assert_does_not_match ok PASS test_succeed_assert_null FAILED test 29 Failed 1/40 tests, 97.50% okay Failed Test Stat Wstat Total Fail Failed List of Failed ------------------------------------------------------------------------------- assert.t 40 1 2.50% 29 Failed 1/1 test scripts, 0.00% okay. 1/40 subtests failed, 97.50% okay. $ Most of the Solaris output is boring, so I haven't included it. The only interesting line is: ok PASS test_numericness System Info for the Linux box, on which the tests FAIL: System: Linux Debian 3.0 Kernel: Linux somehostname 2.4.18 #1 SMP Wed May 15 13:46:32 EST 2002 i686 unknown Test-Unit: 0.25 "perl -v" says: This is perl, v5.6.1 built for i386-linux Copyright 1987-2001, Larry Wall [licensing terms snipped] "perl -V" says: Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration: Platform: osname=linux, osvers=2.4.13, archname=i386-linux uname='linux duende 2.4.13 #1 wed oct 31 19:18:07 est 2001 i686 unknown ' config_args='-Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.6.1 -Darchlib=/usr/lib/perl/5.6.1 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.6.1 -Dsitearch=/usr/local/lib/perl/5.6.1 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Duseshrplib -Dlibperl=libperl.so.5.6.1 -Dd_dosuid -des' hint=recommended, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef Compiler: cc='cc', ccflags ='-DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-DDEBIAN -fno-strict-aliasing -I/usr/local/include' ccversion='', gccversion='2.95.4 (Debian prerelease)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=4, usemymalloc=n, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lgdbm -ldb -ldl -lm -lc -lcrypt perllibs=-ldl -lm -lc -lcrypt libc=/lib/libc-2.2.4.so, so=so, useshrplib=true, libperl=libperl.so.5.6.1 Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' Characteristics of this binary (from libperl): Compile-time options: USE_LARGE_FILES Built under linux Compiled at Jan 11 2002 04:09:18 %ENV: PERL_HOME="/usr/local" @INC: /usr/local/lib/perl/5.6.1 /usr/local/share/perl/5.6.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.6.1 /usr/share/perl/5.6.1 /usr/local/lib/site_perl . System Info for the Solaris box, on which the tests SUCCEED: System: Solaris 8 Sparc Kernel: SunOS anotherhostname 5.8 Generic_108528-12 sun4u sparc SUNW,Ultra-4 Solaris Test-Unit: 0.25 "perl -v" says: This is perl, v5.6.1 built for sun4-solaris-thread-multi (with 1 registered patch, see perl -V for more detail) Copyright 1987-2001, Larry Wall Binary build 631 provided by ActiveState Tool Corp. http://www.ActiveState.com Built 20:33:12 Jan 3 2002 [licensing terms snipped] "perl -V" says: Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration: Platform: osname=solaris, osvers=2.6, archname=sun4-solaris-thread-multi uname='sunos sparky 5.6 generic_105181-26 sun4u sparc sunw,ultra-5_10 ' config_args='-des -Dcc=gcc -Dcf_by=ActiveState -Dcf_email=ActivePerl@ActiveState.com -Uinstallusrbinperl -Ud_sigsetjmp -Dusethreads -Duseithreads -Dinc_version_list=5.6.0/$archname 5.6.0 -Dprefix=/usr/local/ActivePerl-5.6' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemultiplicity=define useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef Compiler: cc='gcc', ccflags ='-DUSE_REENTRANT_API -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O', cppflags='-DUSE_REENTRANT_API -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT -fno-strict-aliasing -I/usr/local/include' ccversion='', gccversion='2.95.2 19991024 (release)', gccosandvers='solaris2.6' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=8, usemymalloc=n, prototype=define Linker and Libraries: ld='gcc', ldflags =' -L/usr/local/lib ' libpth=/usr/local/lib /usr/lib /usr/ccs/lib libs=-lsocket -lnsl -ldl -lm -lposix4 -lpthread -lc perllibs=-lsocket -lnsl -ldl -lm -lposix4 -lpthread -lc libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' ' cccdlflags='-fPIC', lddlflags='-G -L/usr/local/lib' Characteristics of this binary (from libperl): Compile-time options: MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL_IMPLICIT_CONTEXT Locally applied patches: ActivePerl Build 631 Built under solaris Compiled at Jan 3 2002 20:33:12 %ENV: PERL_HOME="/usr/local/ActivePerl-5.6" @INC: /usr/local/ActivePerl-5.6/lib/5.6.1/sun4-solaris-thread-multi /usr/local/ActivePerl-5.6/lib/5.6.1 /usr/local/ActivePerl-5.6/lib/site_perl/5.6.1/sun4-solaris-thread-multi /usr/local/ActivePerl-5.6/lib/site_perl/5.6.1 /usr/local/ActivePerl-5.6/lib/site_perl .
Subject: 2 + 2 = banana
This is a scary thing, Show quoted text
> prints: > $s = 3850 > $i = 3850
Show quoted text
> On the Solaris box, by contrast, that same program does indeed > print: > $s = 10 > $i = 3850
so clearly I need to get myself a variety of perls to test on - it seems that the CPAN Testers don't use 5.6 anymore? On the bright side, at least we now have failures to indicate a problem. Previously versions had this problem, (but worse because the is_numeric regexp was not left-anchored) but cheerfully passed... the result of is_numeric affects the operation of assert_(not_)equals. Question is how to fix it. I think it should be aired on the perlunit-devel list. Are you subscribed to that?
After brief investigations, I'm having trouble reproducing the problem. It might make things a little easier if you could help me get a Perl that does the same as the one you have fails under. [Linux local install of 5.6.1] Show quoted text
> > prints: > > $s = 3850 > > $i = 3850
>
> > On the Solaris box, by contrast, that same program does indeed > > print: > > $s = 10 > > $i = 3850
I tried these sums on a 5.004, 5.6.1 and 5.8.0 (all Tru64), and 5.8.7 (Debian testing 5.8.7-4, i386) and $s is always 10. Can you send me a pointer to the source you used, please? Was it just http://cpan.org/src/5.0/maint/perl-5.6.1.tar.gz ? A Debianised version? Or something more exciting? Was your test script in a file or did you run it with "perl -e"? Is it possible that your shell is doing something strange to the quotes? It might help if you attach a copy of the $s and $i script in a simple file. Thanks,
From: wyon+perlunit [...] pobox.com
[MCAST - Mon Nov 28 19:26:43 2005]: Show quoted text
> so clearly I need to get myself a variety of perls to test on
And a variety of platforms; see below. Show quoted text
> Previously versions had this problem, (but worse because the is_numeric > regexp was not left-anchored) but cheerfully passed...
Yah, the 0.24 is_numeric() was simply broken... Show quoted text
> Question is how to fix it. I think it should be aired on the > perlunit-devel list. Are you subscribed to that?
I'm not, actually. Show quoted text
> I tried these sums on a 5.004, 5.6.1 and 5.8.0 (all Tru64), and 5.8.7 > (Debian testing 5.8.7-4, i386) and $s is always 10.
You're just lucky, I guess. These are all combinations on which the problem doesn't happen to occur :-/ Try it on 5.6.1 on a Linux box. Show quoted text
> Was your test script in a file or did you run it with "perl -e"?
Well, actually I typed "perl" at the shell and typed the program straight into its stdin, then cut'n'pasted from there :-) Show quoted text
> [Numerous other questions about sources, quotes, shells]
I think I've pinned it down tightly enough that this stuff is no longer relevant. If you disagree, please ask again. But I've attached the scripts as you asked. I've been doing some more investigation. Things I've learned: - On the Linux boxes in question (I tried it on one of my home machines too), running that test program with "perl -w" prints: Argument "0xF00" isn't numeric in addition (+) at typeconv line 2. s = 3850 i = 3850 In other words, it complains that the string isn't numeric -- and then converts it to a number! - Largely because of that warning, I have come to believe that the correct behaviour is to consider "0xF00" -- and of course any other string of the form "0x<hex-digits>" -- *not* to be numeric. - The root problem is that Perl depends (after many levels of indirection :-/) on the system's atof() to do the string-to-numeric conversion. (See Perl_sv_2nv() in sv.c.) On at least a couple of versions of Linux, atof() hex-converts "0x" strings, but on Solaris 8, it doesn't. (In fact, at least some versions of Perl will use strtold() if it's available, but since atof() is itself usually implemented in terms of strtod() or strtold(), the difference is immaterial for our purposes. The following refers to the two functions interchangably.) - Recognizing hex is the documented behaviour of Linux's atof()/strtod(). Not surprisingly, the Solaris man page makes no mention of it. - Here's a C test program, to take Perl completely out of the picture: #include <stdio.h> #include <stdlib.h> main() { double d = atof("0xF00"); printf("%f\n", d); } It prints "0" on the Solaris box in question, and "3840" on the Linux boxes. That matches what I expected based on what Perl is doing. - This ugly hex conversion is *not* strictly a Linuxism, however. Apparently, it's mandated by ANSI C99 (though not by C89). I don't have the standard available, but see: http://sources.redhat.com/ml/bug-glibc/2000-09/msg00003.html This discussion came up several years ago in the context of GNU awk (the above-mentioned message is from that thread). Someone (presumably the gawk maintainer) then replied: I will have to do something special within gawk, since those semantics don't match what gawk needs. So in terms of looking for a better way to do is_numeric(), that might be a good place to start. (Probably way more readable than the Perl source!) - Other versions I've tried it on: - Mandrake 10.x: - Perl 5.6.2 treated "0xF00" as hex - Perl 5.8.(um, 5 I think) did not - Perl 5.8.0, on the Debian box from my original bug report, correctly treats "0xF00" as non-numeric; when I run the test program with "-w", it prints: Argument "0xF00" isn't numeric in addition (+) at typeconv line 2. $s = 10 $i = 3850 as it should do. - I also tried it on my ancient 486 Slackware box that I keep around for nostalgic reasons. Perl 5.000 [sic] from 1994 [sic] correctly treats "0xF00" as non-numeric. - I tried to build Perl 5.004, but the build failed due to a missing library. I didn't bother trying to resolve that; let me know if it'd be useful. - To summarize: System Perl Result Linux #1 5.000 non-numeric ($s = 10) Solaris 5.6.1 non-numeric ($s = 10) Linux #2 5.6.1 hex-converted ($s = 3850) Linux #3 5.6.2 hex-converted ($s = 3850) Linux #2 5.8.0 non-numeric ($s = 10) Linux #3 5.8.5? non-numeric ($s = 10) (Linux #1 is the ancient Slackware box; Linux #2 is the Debian box from my original bug report; Linux #3 is the Mandrake box, and the only one running a reasonably modern distro) - All those experiments lend weight to my belief that "non-numeric" is the correct response. Recognizing hex in string-valued variables seems to have appeared somewhere between Perl 5.000 and Perl 5.6.1 (or, possibly, Perl itself didn't change, but the bug appeared once Perl started being linked with C99-compliant libc's.) The bug seems to have been fixed in Perl 5.8.0 (empirically anyway; that version of Perl_sv_2nv() is even more baroque than 5.6.2's, and I gave up trying to read it...) - As an aside, there is *not* a similar problem with octal strings. An inconsistency here wouldn't affect is_numeric() of course, but would affect the results from numeric conversions. But octal is fine, as it turns out. No version of strtod() that I've seen recognizes octal, only hex. This variant of the test program: $s = "0100"; $s += 10; $i = 0100 + 10; print "\$s = $s\n"; print "\$i = $i\n"; prints this bizarre and broken-looking, but I believe correct, result on all systems I've tried it on: $s = 110 $i = 74 (As expected, no warning even under "-w".) - Here's another reference to strtod() recognizing hex, this time on HP-UX: http://docs.hp.com/en/B3921-90010/strtod.3C.html A Google search turned up other scattered bug reports related to this problem -- including, amusingly enough, this changelog entry complaining about the reverse problem: Fixed trio_to_double by not using strtod() on Tru64/DECC because it does not support hex-floats. I guess that'd be why you're not seeing the problem :-/ That quote is from here, btw: http://cvs.sourceforge.net/viewcvs.py/ctrio/trio/CHANGES?rev=1.78 Thanks much. - Eric Siegerman
Download test-hex
application/octet-stream 81b

Message body not shown because it is not plain text.

[guest - Mon Nov 28 22:01:48 2005]: Darn; I can't attach two files to one reply. So here's the octal version of the test program.
Download test-oct
application/octet-stream 79b

Message body not shown because it is not plain text.

[guest - Mon Nov 28 22:01:48 2005]: Two more data points (couldn't resist :-): System Perl Result Linux #2 5.004 hex-converted ($s = 3850) Linux #2 5.005_03 hex-converted ($s = 3850) Both of them print the same result from "perl -w test-hex" as does Perl 5.6.1 on that box, i.e.: Argument "0xF00" isn't numeric in add at ../typeconv line 2. $s = 3850 $i = 3850 - Eric
Hi Eric, I fixed this back in 2007, http://perlunit.git.sourceforge.net/git/gitweb.cgi?p=perlunit/perlunit;a=commit;h=aef684ecd2a617b77a72b5ad4ee14744f98a4575 and recently made a dev release which has fared well with with cpantesters. I will make a full release shortly. The fix is conservative, in the sense that it will reject anything ambiguous. The programmer must then decide - at least it won't be a quiet problem. Thank you for your careful investigations, -- Matthew