From cd3dd42c28832da92ee0d4d3afe7cf722e38f80c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 15 Jun 2009 09:16:27 +0200 Subject: [PATCH] seq: fix testsuite failures Signed-off-by: Denys Vlasenko --- coreutils/seq.c | 71 ++++++++++++++++++++++++++++---------- docs/posix_conformance.txt | 2 +- testsuite/runtest | 10 +++--- testsuite/seq.tests | 14 ++++---- 4 files changed, 68 insertions(+), 29 deletions(-) diff --git a/coreutils/seq.c b/coreutils/seq.c index 4b853c698..bb39a5b54 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c @@ -6,12 +6,10 @@ * * Licensed under the GPL v2, see the file LICENSE in this tarball. */ - #include "libbb.h" /* This is a NOFORK applet. Be very careful! */ - int seq_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int seq_main(int argc, char **argv) { @@ -19,35 +17,72 @@ int seq_main(int argc, char **argv) OPT_w = (1 << 0), OPT_s = (1 << 1), }; - double last, increment, i; + double first, last, increment, v; + unsigned n; + unsigned width; + unsigned frac_part; const char *sep, *opt_s = "\n"; unsigned opt = getopt32(argv, "+ws:", &opt_s); - unsigned width = 0; argc -= optind; argv += optind; - i = increment = 1; + first = increment = 1; + errno = 0; switch (argc) { + char *pp; case 3: - increment = atof(argv[1]); + increment = strtod(argv[1], &pp); + errno |= *pp; case 2: - i = atof(*argv); + first = strtod(argv[0], &pp); + errno |= *pp; case 1: - last = atof(argv[argc-1]); - break; + last = strtod(argv[argc-1], &pp); + if (!errno && *pp == '\0') + break; default: bb_show_usage(); } - if (opt & OPT_w) /* Pad to length of start or last */ - width = MAX(strlen(*argv), strlen(argv[argc-1])); - /* You should note that this is pos-5.0.91 semantics, -- FK. */ - sep = ""; - while ((increment > 0 && i <= last) || (increment < 0 && i >= last)) { - printf("%s%0*g", sep, width, i); - sep = opt_s; - i += increment; + /* Last checked to be compatible with: coreutils-6.10 */ + width = 0; + frac_part = 0; + while (1) { + char *dot = strchrnul(*argv, '.'); + int w = (dot - *argv); + int f = strlen(dot); + if (width < w) + width = w; + argv++; + if (!*argv) + break; + /* Why do the above _before_ frac check below? + * Try "seq 1 2.0" and "seq 1.0 2.0": + * coreutils never pay attention to the number + * of fractional digits in last arg. */ + if (frac_part < f) + frac_part = f; } - bb_putchar('\n'); + if (frac_part) { + frac_part--; + if (frac_part) + width += frac_part + 1; + } + if (!(opt & OPT_w)) + width = 0; + + sep = ""; + v = first; + n = 0; + while (increment >= 0 ? v <= last : v >= last) { + printf("%s%0*.*f", sep, width, frac_part, v); + sep = opt_s; + /* v += increment; - would accumulate floating point errors */ + n++; + v = first + n * increment; + } + if (n) /* if while loop executed at least once */ + bb_putchar('\n'); + return fflush(stdout); } diff --git a/docs/posix_conformance.txt b/docs/posix_conformance.txt index a9176f503..5451a322d 100644 --- a/docs/posix_conformance.txt +++ b/docs/posix_conformance.txt @@ -189,7 +189,7 @@ df POSIX options df Busybox specific options: -a, -m, -B SIZE, -i, -h Remark: -- It seems that GNU df doesnt rount percents up in its output (thus its results are a bit different) +- It seems that GNU df does not round percents up in its output (thus its results are a bit different) diff POSIX options option | exists | compliant | remarks diff --git a/testsuite/runtest b/testsuite/runtest index cade871a2..2d60591fb 100755 --- a/testsuite/runtest +++ b/testsuite/runtest @@ -120,11 +120,13 @@ fi # Populate a directory with links to all busybox applets +# Note: if $LINKSDIR/applet exists, we do not overwrite it. +# Useful if one wants to run tests against a standard utility, not an applet. LINKSDIR="$bindir/runtest-tempdir-links" -rm -rf "$LINKSDIR" 2>/dev/null -mkdir "$LINKSDIR" +#rm -rf "$LINKSDIR" 2>/dev/null +mkdir "$LINKSDIR" 2>/dev/null for i in $implemented; do - ln -s "$bindir/busybox" "$LINKSDIR/$i" + ln -s "$bindir/busybox" "$LINKSDIR/$i" 2>/dev/null done # Set up option flags so tests can be selective. @@ -142,7 +144,7 @@ for applet in $applets; do # Is this a new-style test? if [ -f "$applet.tests" ]; then - if [ ! -h "$LINKSDIR/$applet" ]; then + if [ ! -e "$LINKSDIR/$applet" ]; then # (avoiding bash'ism "${applet:0:4}") if ! echo "$applet" | grep "^all_" >/dev/null; then echo "SKIPPED: $applet (not built)" diff --git a/testsuite/seq.tests b/testsuite/seq.tests index 4e43d0ee1..817e1a724 100755 --- a/testsuite/seq.tests +++ b/testsuite/seq.tests @@ -29,16 +29,18 @@ testing "seq count up by 2" "seq 4 2 8" "4\n6\n8\n" "" "" testing "seq count down by 2" "seq 8 -2 4" "8\n6\n4\n" "" "" testing "seq count wrong way #1" "seq 4 -2 8" "" "" "" testing "seq count wrong way #2" "seq 8 2 4" "" "" "" -# Fails: first item is printed as 3, not 3.0 -# note: makes sense to fix "seq 3 .30 4" case as well testing "seq count by .3" "seq 3 .3 4" "3.0\n3.3\n3.6\n3.9\n" "" "" -testing "seq count by -.9" "seq .7 -.9 -2.2" "0.7\n-0.2\n-1.1\n-2\n" "" "" -testing "seq count by zero" "seq 4 0 8 | head -n 10" "" "" "" +testing "seq count by .30" "seq 3 .30 4" "3.00\n3.30\n3.60\n3.90\n" "" "" +testing "seq count by .30 to 4.000" "seq 3 .30 4.000" "3.00\n3.30\n3.60\n3.90\n" "" "" +testing "seq count by -.9" "seq .7 -.9 -2.2" "0.7\n-0.2\n-1.1\n-2.0\n" "" "" +testing "seq count by zero" "seq 4 0 8 | head -n 10" "4\n4\n4\n4\n4\n4\n4\n4\n4\n4\n" "" "" testing "seq one argument with padding" "seq -w 003" "001\n002\n003\n" "" "" testing "seq two arguments with padding" "seq -w 005 7" "005\n006\n007\n" "" "" testing "seq count down by 3 with padding" "seq -w 8 -3 04" "08\n05\n" "" "" -# Known to fail -testing "seq count by .3 with padding" "seq -w 03 .3 0004" "003.0\n003.3\n003.6\n003.9\n" "" "" +# Looks like a bug in coreutils 6.10: it uses width one less than needed +# These tests contain the expected "fixed" output +testing "seq count by .3 with padding 1" "seq -w 09 .3 11" "09.0\n09.3\n09.6\n09.9\n10.2\n10.5\n10.8\n" "" "" +testing "seq count by .3 with padding 2" "seq -w 03 .3 0004" "0003.0\n0003.3\n0003.6\n0003.9\n" "" "" exit $FAILCOUNT