aboutsummaryrefslogtreecommitdiff
path: root/tools/regression/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'tools/regression/usr.bin')
-rw-r--r--tools/regression/usr.bin/cc/Makefile10
-rw-r--r--tools/regression/usr.bin/cc/float.c269
-rw-r--r--tools/regression/usr.bin/cc/float.t9
-rw-r--r--tools/regression/usr.bin/env/Makefile15
-rw-r--r--tools/regression/usr.bin/env/regress-env.rgdata416
-rw-r--r--tools/regression/usr.bin/env/regress-sb.rb540
6 files changed, 1259 insertions, 0 deletions
diff --git a/tools/regression/usr.bin/cc/Makefile b/tools/regression/usr.bin/cc/Makefile
new file mode 100644
index 000000000000..1f8b5d8f03fd
--- /dev/null
+++ b/tools/regression/usr.bin/cc/Makefile
@@ -0,0 +1,10 @@
+TESTS= float
+CFLAGS+=-lm
+
+.PHONY: tests
+tests: ${TESTS}
+ for p in ${TESTS}; do ${.OBJDIR}/$$p; done
+
+.PHONY: clean
+clean:
+ -rm -f ${TESTS}
diff --git a/tools/regression/usr.bin/cc/float.c b/tools/regression/usr.bin/cc/float.c
new file mode 100644
index 000000000000..e08e0f5a6174
--- /dev/null
+++ b/tools/regression/usr.bin/cc/float.c
@@ -0,0 +1,269 @@
+/*-
+ * Copyright (c) 2012 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Test that floating-point arithmetic works as specified by the C standard.
+ */
+
+#include <sys/cdefs.h>
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
+ FE_OVERFLOW | FE_UNDERFLOW)
+
+#define TWICE(x) ((x) + (x))
+#define test(desc, pass) test1((desc), (pass), 0)
+#define skiptest(desc, pass) test1((desc), (pass), 1)
+
+#pragma STDC FENV_ACCESS ON
+
+static const float one_f = 1.0 + FLT_EPSILON / 2;
+static const double one_d = 1.0 + DBL_EPSILON / 2;
+static const long double one_ld = 1.0L + LDBL_EPSILON / 2;
+
+static int testnum, failures;
+
+static void
+test1(const char *testdesc, int pass, int skip)
+{
+
+ testnum++;
+ printf("%sok %d - %s%s\n", pass || skip ? "" : "not ", testnum,
+ skip ? "(SKIPPED) " : "", testdesc);
+ if (!pass && !skip)
+ failures++;
+}
+
+/*
+ * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0.
+ */
+static int
+fpequal(long double d1, long double d2)
+{
+
+ if (d1 != d2)
+ return (isnan(d1) && isnan(d2));
+ return (copysignl(1.0, d1) == copysignl(1.0, d2));
+}
+
+void
+run_zero_opt_test(double d1, double d2)
+{
+
+ test("optimizations don't break the sign of 0",
+ fpequal(d1 - d2, 0.0)
+ && fpequal(-d1 + 0.0, 0.0)
+ && fpequal(-d1 - d2, -0.0)
+ && fpequal(-(d1 - d2), -0.0)
+ && fpequal(-d1 - (-d2), 0.0));
+}
+
+void
+run_inf_opt_test(double d)
+{
+
+ test("optimizations don't break infinities",
+ fpequal(d / d, NAN) && fpequal(0.0 * d, NAN));
+}
+
+static inline double
+todouble(long double ld)
+{
+
+ return (ld);
+}
+
+static inline float
+tofloat(double d)
+{
+
+ return (d);
+}
+
+void
+run_tests(void)
+{
+ volatile long double vld;
+ long double ld;
+ volatile double vd;
+ double d;
+ volatile float vf;
+ float f;
+ int x;
+
+ test("sign bits", fpequal(-0.0, -0.0) && !fpequal(0.0, -0.0));
+
+ vd = NAN;
+ test("NaN equality", fpequal(NAN, NAN) && NAN != NAN && vd != vd);
+
+ feclearexcept(ALL_STD_EXCEPT);
+ test("NaN comparison returns false", !(vd <= vd));
+ /*
+ * XXX disabled; gcc/amd64 botches this IEEE 754 requirement by
+ * emitting ucomisd instead of comisd.
+ */
+ skiptest("FENV_ACCESS: NaN comparison raises invalid exception",
+ fetestexcept(ALL_STD_EXCEPT) == FE_INVALID);
+
+ vd = 0.0;
+ run_zero_opt_test(vd, vd);
+
+ vd = INFINITY;
+ run_inf_opt_test(vd);
+
+ feclearexcept(ALL_STD_EXCEPT);
+ vd = INFINITY;
+ x = (int)vd;
+ /* XXX disabled (works with -O0); gcc doesn't support FENV_ACCESS */
+ skiptest("FENV_ACCESS: Inf->int conversion raises invalid exception",
+ fetestexcept(ALL_STD_EXCEPT) == FE_INVALID);
+
+ /* Raising an inexact exception here is an IEEE-854 requirement. */
+ feclearexcept(ALL_STD_EXCEPT);
+ vd = 0.75;
+ x = (int)vd;
+ test("0.75->int conversion rounds toward 0, raises inexact exception",
+ x == 0 && fetestexcept(ALL_STD_EXCEPT) == FE_INEXACT);
+
+ feclearexcept(ALL_STD_EXCEPT);
+ vd = -42.0;
+ x = (int)vd;
+ test("-42.0->int conversion is exact, raises no exception",
+ x == -42 && fetestexcept(ALL_STD_EXCEPT) == 0);
+
+ feclearexcept(ALL_STD_EXCEPT);
+ x = (int)INFINITY;
+ /* XXX disabled; gcc doesn't support FENV_ACCESS */
+ skiptest("FENV_ACCESS: const Inf->int conversion raises invalid",
+ fetestexcept(ALL_STD_EXCEPT) == FE_INVALID);
+
+ feclearexcept(ALL_STD_EXCEPT);
+ x = (int)0.5;
+ /* XXX disabled; gcc doesn't support FENV_ACCESS */
+ skiptest("FENV_ACCESS: const double->int conversion raises inexact",
+ x == 0 && fetestexcept(ALL_STD_EXCEPT) == FE_INEXACT);
+
+ test("compile-time constants don't have too much precision",
+ one_f == 1.0L && one_d == 1.0L && one_ld == 1.0L);
+
+ test("const minimum rounding precision",
+ 1.0F + FLT_EPSILON != 1.0F &&
+ 1.0 + DBL_EPSILON != 1.0 &&
+ 1.0L + LDBL_EPSILON != 1.0L);
+
+ /* It isn't the compiler's fault if this fails on FreeBSD/i386. */
+ vf = FLT_EPSILON;
+ vd = DBL_EPSILON;
+ vld = LDBL_EPSILON;
+ test("runtime minimum rounding precision",
+ 1.0F + vf != 1.0F && 1.0 + vd != 1.0 && 1.0L + vld != 1.0L);
+
+ test("explicit float to float conversion discards extra precision",
+ (float)(1.0F + FLT_EPSILON * 0.5F) == 1.0F &&
+ (float)(1.0F + vf * 0.5F) == 1.0F);
+ test("explicit double to float conversion discards extra precision",
+ (float)(1.0 + FLT_EPSILON * 0.5) == 1.0F &&
+ (float)(1.0 + vf * 0.5) == 1.0F);
+ test("explicit ldouble to float conversion discards extra precision",
+ (float)(1.0L + FLT_EPSILON * 0.5L) == 1.0F &&
+ (float)(1.0L + vf * 0.5L) == 1.0F);
+
+ test("explicit double to double conversion discards extra precision",
+ (double)(1.0 + DBL_EPSILON * 0.5) == 1.0 &&
+ (double)(1.0 + vd * 0.5) == 1.0);
+ test("explicit ldouble to double conversion discards extra precision",
+ (double)(1.0L + DBL_EPSILON * 0.5L) == 1.0 &&
+ (double)(1.0L + vd * 0.5L) == 1.0);
+
+ /*
+ * FLT_EVAL_METHOD > 1 implies that float expressions are always
+ * evaluated in double precision or higher, but some compilers get
+ * this wrong when registers spill to memory. The following expression
+ * forces a spill when there are at most 8 FP registers.
+ */
+ test("implicit promption to double or higher precision is consistent",
+#if FLT_EVAL_METHOD == 1 || FLT_EVAL_METHOD == 2 || defined(__i386__)
+ TWICE(TWICE(TWICE(TWICE(TWICE(
+ TWICE(TWICE(TWICE(TWICE(1.0F + vf * 0.5F)))))))))
+ == (1.0 + FLT_EPSILON * 0.5) * 512.0
+#else
+ 1
+#endif
+ );
+
+ f = 1.0 + FLT_EPSILON * 0.5;
+ d = 1.0L + DBL_EPSILON * 0.5L;
+ test("const assignment discards extra precision", f == 1.0F && d == 1.0);
+
+ f = 1.0 + vf * 0.5;
+ d = 1.0L + vd * 0.5L;
+ test("variable assignment discards explicit extra precision",
+ f == 1.0F && d == 1.0);
+ f = 1.0F + vf * 0.5F;
+ d = 1.0 + vd * 0.5;
+ test("variable assignment discards implicit extra precision",
+ f == 1.0F && d == 1.0);
+
+ test("return discards extra precision",
+ tofloat(1.0 + vf * 0.5) == 1.0F &&
+ todouble(1.0L + vd * 0.5L) == 1.0);
+
+ fesetround(FE_UPWARD);
+ /* XXX disabled (works with -frounding-math) */
+ skiptest("FENV_ACCESS: constant arithmetic respects rounding mode",
+ 1.0F + FLT_MIN == 1.0F + FLT_EPSILON &&
+ 1.0 + DBL_MIN == 1.0 + DBL_EPSILON &&
+ 1.0L + LDBL_MIN == 1.0L + LDBL_EPSILON);
+ fesetround(FE_TONEAREST);
+
+ ld = vld * 0.5;
+ test("associativity is respected",
+ 1.0L + ld + (LDBL_EPSILON * 0.5) == 1.0L &&
+ 1.0L + (LDBL_EPSILON * 0.5) + ld == 1.0L &&
+ ld + 1.0 + (LDBL_EPSILON * 0.5) == 1.0L &&
+ ld + (LDBL_EPSILON * 0.5) + 1.0 == 1.0L + LDBL_EPSILON);
+}
+
+int
+main(int argc, char *argv[])
+{
+
+ printf("1..26\n");
+
+#ifdef __i386__
+ fpsetprec(FP_PE);
+#endif
+ run_tests();
+
+ return (failures);
+}
diff --git a/tools/regression/usr.bin/cc/float.t b/tools/regression/usr.bin/cc/float.t
new file mode 100644
index 000000000000..74eb8c9c581d
--- /dev/null
+++ b/tools/regression/usr.bin/cc/float.t
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+cd `dirname $0`
+
+executable=`basename $0 .t`
+
+make $executable 2>&1 > /dev/null
+
+exec ./$executable
diff --git a/tools/regression/usr.bin/env/Makefile b/tools/regression/usr.bin/env/Makefile
new file mode 100644
index 000000000000..06f1fbe82e23
--- /dev/null
+++ b/tools/regression/usr.bin/env/Makefile
@@ -0,0 +1,15 @@
+TESTPGM?=TestProgramNotSpecifed
+
+all:
+ @echo "Note that the 'env' command uses its own regression suite,"
+ @echo "which uses a single data file and a script written in ruby."
+ @echo "By default it will test /usr/bin/env"
+ @echo
+ @ruby regress-sb.rb --rgdata=${.CURDIR}/regress-env.rgdata
+
+# A version which allows the user to specify which executable of `env'
+# should be tested, e.g.: make testenv TESTPROG=/usr/bin/env-rel6
+# This will probably need a bit more thought...
+testenv:
+ @ruby regress-sb.rb --rgdata=${.CURDIR}/regress-env.rgdata \
+ --testpgm=${TESTPGM}
diff --git a/tools/regression/usr.bin/env/regress-env.rgdata b/tools/regression/usr.bin/env/regress-env.rgdata
new file mode 100644
index 000000000000..490ae1c84089
--- /dev/null
+++ b/tools/regression/usr.bin/env/regress-env.rgdata
@@ -0,0 +1,416 @@
+#-
+# Copyright (c) 2005 - Garance Alistair Drosehn <gad@FreeBSD.org>.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+
+testpgm=/usr/bin/env
+gblenv=PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+gblenv=TESTVAR=Global-TV-Value
+gblenv=OUTSIDEVAR=OutsideValue
+
+# These first two tests are testing how well the regression-script itself is
+# handling environment-variables, as much as testing the `env' program.
+[test]
+ sb_args:/bin/sh
+ setenv:TESTVAR=a1a
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-a1a-Z
+[run]
+[test]
+ sb_args:-S /bin/sh
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-Global-TV-Value-Z
+[run]
+
+[test]
+ sb_args:-S TESTVAR=bb22bb /bin/sh
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-bb22bb-Z
+[run]
+[test]
+ sb_args:-S\_TESTVAR=ab22ab\_/bin/sh
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-ab22ab-Z
+[run]
+[test]
+ sb_args:-S\_TESTVAR="abc\_33\_abc"\_/bin/sh
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-abc 33 abc-Z
+[run]
+
+# First we see that 'sh' can not be found in /usr/sbin, and then
+# we show that it can be found without changing PATH by using -P
+# And then show that it can be NOT found by using -P...
+[test]
+ sb_args:-S sh
+ setenv:PATH=/usr/sbin
+ script:/bin/echo A-${PATH}-Z
+ $?:127
+ stderr:[%-testpgm.basename-%]: sh: No such file or directory
+[run]
+[test]
+ sb_args:-S -P/bin sh
+ setenv:PATH=/usr/sbin
+ script:/bin/echo A-${PATH}-Z
+ stdout:A-/usr/sbin-Z
+[run]
+[test]
+ sb_args:-S -P/sbin:/usr/sbin sh
+ script:/bin/echo A-${PATH}-Z
+ $?:127
+ stderr:[%-testpgm.basename-%]: sh: No such file or directory
+[run]
+
+# Hmm. I wonder if -P should always set an 'ENV_PATH' variable?
+[test]
+ sb_args:-S -P/bin:/usr/bin:${PATH} ENV_PATH=/bin:/usr/bin:${PATH} sh
+ setenv:PATH=/usr/sbin
+ script:/bin/echo A-${PATH}-Z
+ script:/bin/echo B-${ENV_PATH}-Y
+ stdout:A-/usr/sbin-Z
+ stdout:B-/bin:/usr/bin:/usr/sbin-Y
+[run]
+
+# Show that the comment-characters are working, both for where they are
+# recognized and where they are ignored.
+[test]
+ sb_args:-STESTVAR="abc44abc" /bin/sh # This is some arbitrary text
+ user_args:us11er us22er
+ script:/bin/echo A-${TESTVAR}-Z B-$1-Y
+ stdout:A-abc44abc-Z B-us11er-Y
+[run]
+[test]
+ sb_args:-STESTVAR="abc55abc" /bin/sh \c This is some arbitrary text
+ user_args:us11er us22er
+ script:/bin/echo A-${TESTVAR}-Z B-$1-Y
+ stdout:A-abc55abc-Z B-us11er-Y
+[run]
+[test]
+ sb_args:-STESTVAR=abc#44#abc /bin/sh
+ user_args:us11er us22er
+ script:/bin/echo A-${TESTVAR}-Z B-$1-Y
+ stdout:A-abc#44#abc-Z B-us11er-Y
+[run]
+[test]
+ sb_args:-STESTVAR='abc\c55\cabc' /bin/sh
+ user_args:us11er us22er
+ script:/bin/echo A-${TESTVAR}-Z B-$1-Y
+ stdout:A-abc\c55\cabc-Z B-us11er-Y
+[run]
+
+# Test various aspects of quoted strings
+[test]
+ sb_args:-STESTVAR="abc'def" /bin/sh
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-abc'def-Z
+[run]
+[test]
+ sb_args:-STESTVAR='abc"def' /bin/sh
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-abc"def-Z
+[run]
+[test]
+ sb_args:-STESTVAR='ab\'cd\'ef' /bin/sh
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-ab'cd'ef-Z
+[run]
+[test]
+ sb_args:-STESTVAR='abc\"def\'ghi' /bin/sh
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-abc\"def'ghi-Z
+[run]
+[test]
+ sb_args:-STESTVAR='abc''def''ghi' /bin/sh
+ script:/bin/echo A-${TESTVAR}-Z
+ stdout:A-abcdefghi-Z
+[run]
+[test]
+ sb_args:-STESTVAR='abc\ndef\nghi' /bin/sh
+ script:/bin/echo "A-${TESTVAR}-Z"
+ stdout:A-abc\ndef\nghi-Z
+[run]
+[test]
+ sb_args:-STESTVAR="abc\ndef\nghi" /bin/sh
+ script:/bin/echo "A-${TESTVAR}-Z"
+ stdout:A-abc
+ stdout:def
+ stdout:ghi-Z
+[run]
+[test]
+ sb_args:-STESTVAR=""\_OTHERVAR=""\_/bin/sh
+ script:/bin/echo A-${TESTVAR}-M-${OTHERVAR}-Z
+ stdout:A--M--Z
+[run]
+[test]
+ sb_args:-STESTVAR=no-term-"-dq... /bin/sh
+ script:/bin/echo "A-${TESTVAR}-Z"
+ $?:1
+ stderr:[%-testpgm.basename-%]: No terminating quote for string: TESTVAR=no-term-"-dq... /bin/sh
+[run]
+[test]
+ sb_args:-STESTVAR=no-term-'-sq... /bin/sh
+ script:/bin/echo "A-${TESTVAR}-Z"
+ $?:1
+ stderr:[%-testpgm.basename-%]: No terminating quote for string: TESTVAR=no-term-'-sq... /bin/sh
+[run]
+
+# Some tests of variable-substitution.
+[test]
+ sb_args:-S TESTVAR=${TEST7} /bin/sh
+ setenv:TEST7=a23456a
+ script:/bin/echo "A-${TESTVAR}-Z"
+ stdout:A-a23456a-Z
+[run]
+[test]
+ sb_args:-S TESTVAR=${TEST8} /bin/sh
+ setenv:TEST8=b234567b
+ script:/bin/echo "A-${TESTVAR}-Z"
+ stdout:A-b234567b-Z
+[run]
+[test]
+ sb_args:-S TESTVAR=${TEST9} /bin/sh
+ setenv:TEST9=c2345678c
+ script:/bin/echo "A-${TESTVAR}-Z"
+ stdout:A-c2345678c-Z
+[run]
+[test]
+ sb_args:-S TESTVAR=${TEST8}+${TEST9}+${TEST10} /bin/sh
+ setenv:TEST8=a234567z
+ setenv:TEST9=a2345678z
+ setenv:TEST10=a23456789z
+ script:/bin/echo "A-${TESTVAR}-Z"
+ stdout:A-a234567z+a2345678z+a23456789z-Z
+[run]
+[test]
+ sb_args:-S TESTVAR=$* /bin/sh
+ script:/bin/echo "A-${TESTVAR}-Z"
+ $?:1
+ stderr:[%-testpgm.basename-%]: Only ${VARNAME} expansion is supported, error at: $* /bin/sh
+[run]
+[test]
+ sb_args:-S TESTVAR=/usr/bin:$PATH /bin/sh
+ script:/bin/echo "A-${TESTVAR}-Z"
+ $?:1
+ stderr:[%-testpgm.basename-%]: Only ${VARNAME} expansion is supported, error at: $PATH /bin/sh
+[run]
+
+# For a short time `env' was changed to recognize 'something=value' as a
+# valid utility name if 'something' begins with a '/'. However, that was
+# a bad idea, since variable-names with a '/' -- while rare -- are still
+# more blessed by standards than a filename with an '=' in it. So, this
+# test goes back to expecting an error...
+[test]
+ symlink:/bin/echo /tmp/envtest=echo
+ sb_args:-S/tmp/envtest=echo false
+ $?:1
+[run]
+
+# Show interactions between -i (clear environment), and ${VAR} substitution,
+# and that -i will clear the environment at the right point in processing...
+[test]
+ sb_args:-iS PATH=/bin:/usr/bin:/Not WASPATH=${PATH} WASOUT=${OUTSIDEVAR} TESTVAR=SbValue WASTEST=${TESTVAR} /bin/sh
+ script:/bin/echo "=== set ==="
+ script:# drop some environment variables that 'sh' itself sets, and
+ script:# then have 'set' print out all remaining environment variables.
+ script:# (can't unset OPTIND/PWD, so we use grep to get rid of those)
+ script:unset -v IFS PS1 PS2 PS4 PPID
+ script:set | grep -Ev '^(OPTIND|PWD)=' | sort
+ stdout:=== set ===
+ stdout:PATH=/bin:/usr/bin:/Not
+ stdout:TESTVAR=SbValue
+ stdout:WASOUT=OutsideValue
+ stdout:WASPATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
+ stdout:WASTEST=Global-TV-Value
+[run]
+
+# Had a bug with ${VAR} expansion if the character before the $ was
+# one of the argument-separator characters. So the first of the
+# following worked, but the second one failed:
+[test]
+ sb_args:-Secho Testv:${TESTV} Scriptname:
+ setenv:TESTV=ab/ba
+ stdout:Testv:ab/ba Scriptname: [%-script.pathname-%]
+[run]
+[test]
+ sb_args:-Secho testV: ${TESTV} scriptname:
+ setenv:TESTV=cd/dc
+ stdout:testV: cd/dc scriptname: [%-script.pathname-%]
+[run]
+
+# A "nothing variable" inside a quoted string should produce a zero-length
+# argument, but if it's outside of quotes then it should result in, well,
+# nothing. Note the tricks we play with [%-script.pathname-%] so that we
+# can supply parameters *to* the script, even though the kernel is always
+# going to stick the script name on as ARG[2] when invoking `env'.
+[test]
+ sb_args:-S/bin/sh [%-script.pathname-%] userDQ: "" SQ: '' scriptname:
+ setenv:TNADA=
+ script:printf "list_args.sh with \$# = $#\n"
+ script:# Process all parameters.
+ script:N=0
+ script:while test $# != 0 ; do
+ script: N=$(($N+1))
+ script: printf "....\$$N = [%3d] '$1'\n" ${#1}
+ script: shift
+ script:done
+ stdout:list_args.sh with $# = 6
+ stdout:....$1 = [ 7] 'userDQ:'
+ stdout:....$2 = [ 0] ''
+ stdout:....$3 = [ 3] 'SQ:'
+ stdout:....$4 = [ 0] ''
+ stdout:....$5 = [ 11] 'scriptname:'
+ stdout:....$6 = [ 16] '/tmp/env-regress'
+[run]
+[test]
+ sb_args:-S/bin/sh [%-script.pathname-%] userB "${TNADA}" scriptname:
+ setenv:TNADA=
+ script:printf "list_args.sh with \$# = $#\n"
+ script:# Process all parameters.
+ script:N=0
+ script:while test $# != 0 ; do
+ script: N=$(($N+1))
+ script: printf "....\$$N = [%3d] '$1'\n" ${#1}
+ script: shift
+ script:done
+ stdout:list_args.sh with $# = 4
+ stdout:....$1 = [ 5] 'userB'
+ stdout:....$2 = [ 0] ''
+ stdout:....$3 = [ 11] 'scriptname:'
+ stdout:....$4 = [ 16] '/tmp/env-regress'
+[run]
+[test]
+ sb_args:-S/bin/sh [%-script.pathname-%] userA ${TNADA} scriptname:
+ setenv:TNADA=
+ script:printf "list_args.sh with \$# = $#\n"
+ script:# Process all parameters.
+ script:N=0
+ script:while test $# != 0 ; do
+ script: N=$(($N+1))
+ script: printf "....\$$N = [%3d] '$1'\n" ${#1}
+ script: shift
+ script:done
+ stdout:list_args.sh with $# = 3
+ stdout:....$1 = [ 5] 'userA'
+ stdout:....$2 = [ 11] 'scriptname:'
+ stdout:....$3 = [ 16] '[%-script.pathname-%]'
+[run]
+[test]
+ sb_args:-S/bin/sh [%-script.pathname-%] ${A} ${NB} ${C} ${ND} ${NE} ${F} S:
+ setenv:A=A_ThisisAlongstring_A1
+ setenv:NB=
+ setenv:C=C_ThisisAlongstring_C1
+ setenv:ND=
+ setenv:NE=
+ setenv:F=F_ThisisAlongstring_F1
+ script:printf "list_args.sh with \$# = $#\n"
+ script:# Process all parameters.
+ script:N=0
+ script:while test $# != 0 ; do
+ script: N=$(($N+1))
+ script: printf "....\$$N = [%3d] '$1'\n" ${#1}
+ script: shift
+ script:done
+ stdout:list_args.sh with $# = 5
+ stdout:....$1 = [ 22] 'A_ThisisAlongstring_A1'
+ stdout:....$2 = [ 22] 'C_ThisisAlongstring_C1'
+ stdout:....$3 = [ 22] 'F_ThisisAlongstring_F1'
+ stdout:....$4 = [ 2] 'S:'
+ stdout:....$5 = [ 16] '/tmp/env-regress'
+[run]
+[test]
+ sb_args:-S/bin/sh [%-script.pathname-%] ${A} ${NB} "${NB}" ${NB} ${C} "${ND}" ${NE} ${F} S:
+ setenv:A=A_ThisisAlongstring_A1
+ setenv:NB=
+ setenv:C=C_ThisisAlongstring_C1
+ setenv:ND=
+ setenv:NE=
+ setenv:F=F_ThisisAlongstring_F1
+ script:printf "list_args.sh with \$# = $#\n"
+ script:# Process all parameters.
+ script:N=0
+ script:while test $# != 0 ; do
+ script: N=$(($N+1))
+ script: printf "....\$$N = [%3d] '$1'\n" ${#1}
+ script: shift
+ script:done
+ stdout:list_args.sh with $# = 7
+ stdout:....$1 = [ 22] 'A_ThisisAlongstring_A1'
+ stdout:....$2 = [ 0] ''
+ stdout:....$3 = [ 22] 'C_ThisisAlongstring_C1'
+ stdout:....$4 = [ 0] ''
+ stdout:....$5 = [ 22] 'F_ThisisAlongstring_F1'
+ stdout:....$6 = [ 2] 'S:'
+ stdout:....$7 = [ 16] '/tmp/env-regress'
+[run]
+
+[test]
+ sb_args:-S/bin/echo ${A} ${B} ${C} ${D} ScriptName:
+ setenv:A=A_ThisisAlongstring_A1
+ setenv:B=B_ThisisAlongstring_B1
+ setenv:C=C_ThisisAlongstring_C1
+ setenv:D=D_ThisisAlongstring_D1
+ stdout:A_ThisisAlongstring_A1 B_ThisisAlongstring_B1 C_ThisisAlongstring_C1 D_ThisisAlongstring_D1 ScriptName: [%-script.pathname-%]
+[run]
+[test]
+ sb_args:-S/bin/echo ${A} "${B}" ${C} "${D}" ScriptName:
+ setenv:A=A_ThisisAlongstring_A1
+ setenv:B=B_ThisisAlongstring_B1
+ setenv:C=C_ThisisAlongstring_C1
+ setenv:D=D_ThisisAlongstring_D1
+ stdout:A_ThisisAlongstring_A1 B_ThisisAlongstring_B1 C_ThisisAlongstring_C1 D_ThisisAlongstring_D1 ScriptName: [%-script.pathname-%]
+[run]
+
+[test]
+ sb_args:sh
+ script:[%-testpgm.pathname-%] -S '\c' >/dev/null
+[run]
+[test]
+ sb_args:sh
+ script:[%-testpgm.pathname-%] -S'\c' >/dev/null
+[run]
+[test]
+ sb_args:sh
+ script:[%-testpgm.pathname-%] -u foo -S '\c' >/dev/null
+[run]
+[test]
+ sb_args:sh
+ script:[%-testpgm.pathname-%] -u foo -S'\c' >/dev/null
+[run]
+[test]
+ sb_args:sh
+ script:[%-testpgm.pathname-%] -S '-u bar \c' >/dev/null
+[run]
+[test]
+ sb_args:sh
+ script:[%-testpgm.pathname-%] -S'-u bar \c' >/dev/null
+[run]
+[test]
+ sb_args:sh
+ script:[%-testpgm.pathname-%] -u foo -S '-u bar \c' >/dev/null
+[run]
+[test]
+ sb_args:sh
+ script:[%-testpgm.pathname-%] -u foo -S'-u bar \c' >/dev/null
+[run]
diff --git a/tools/regression/usr.bin/env/regress-sb.rb b/tools/regression/usr.bin/env/regress-sb.rb
new file mode 100644
index 000000000000..b784dcec3e50
--- /dev/null
+++ b/tools/regression/usr.bin/env/regress-sb.rb
@@ -0,0 +1,540 @@
+#!/usr/local/bin/ruby
+# -------+---------+---------+-------- + --------+---------+---------+---------+
+# Copyright (c) 2005 - Garance Alistair Drosehn <gad@FreeBSD.org>.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+# -------+---------+---------+-------- + --------+---------+---------+---------+
+# -------+---------+---------+-------- + --------+---------+---------+---------+
+# This script was written to provide a battery of regression-tests for some
+# changes I am making to the `env' command. I wrote a new script for this
+# for several reasons. 1) I needed to test all kinds of special-character
+# combinations, and I wanted to be able to type those in exactly as they would
+# would be in real-life situations. 2) I wanted to set environment variables
+# before executing a test, 3) I had many different details to test, so I wanted
+# to write up dozens of tests, without needing to create a hundred separate
+# little tiny files, 4) I wanted to test *failure* conditions, where I expected
+# the test would fail but I wanted to be sure that it failed the way I intended
+# it to fail.
+# This script was written for the special "shebang-line" testing that I
+# wanted for my changes to `env', but I expect it could be turned into a
+# general-purpose test-suite with a little more work.
+# Garance/June 12/2005
+# -------+---------+---------+-------- + --------+---------+---------+---------+
+
+
+# -------+---------+---------+-------- + --------+---------+---------+---------+
+class ExpectedResult
+ attr_writer :cmdvalue, :shebang_args, :user_args
+ @@gbl_envs = Hash.new
+
+ def ExpectedResult.add_gblenv(avar, avalue)
+ @@gbl_envs[avar] = avalue
+ end
+
+ def initialize
+ @shebang_args = ""
+ @cmdvalue = 0
+ @clear_envs = Hash.new
+ @new_envs = Hash.new
+ @old_envs = Hash.new
+ @script_lines = ""
+ @expect_err = Array.new
+ @expect_out = Array.new
+ @symlinks = Array.new
+ @user_args = nil
+ end
+
+ def add_expecterr(aline)
+ @expect_err << aline
+ end
+
+ def add_expectout(aline)
+ @expect_out << aline
+ end
+
+ def add_script(aline)
+ @script_lines += aline
+ @script_lines += "\n" if aline[-1] != "\n"
+ end
+
+ def add_clearenv(avar)
+ @clear_envs[avar] = true
+ end
+
+ def add_setenv(avar, avalue)
+ @new_envs[avar] = avalue
+ end
+
+ def add_symlink(srcf, newf)
+ @symlinks << Array.[](srcf, newf)
+ end
+
+ def check_out(name, fname, expect_arr)
+ idx = -1
+ all_matched = true
+ extra_lines = 0
+ rdata = File.open(fname)
+ rdata.each_line { |rline|
+ rline.chomp!
+ idx += 1
+ if idx > expect_arr.length - 1
+ if extra_lines == 0 and $verbose >= 1
+ printf "-- Extra line(s) on %s:\n", name
+ end
+ printf "-- [%d] > %s\n", idx, rline if $verbose >= 1
+ extra_lines += 1
+ elsif rline != expect_arr[idx]
+ if all_matched and $verbose >= 1
+ printf "-- Mismatched line(s) on %s:\n", name
+ end
+ printf "-- [%d] < %s\n", idx, expect_arr[idx] if $verbose >= 2
+ printf "-- > %s\n", rline if $verbose >= 1
+ all_matched = false
+ else
+ printf "-- %s[%d] = %s\n", name, idx, rline if $verbose >= 5
+ end
+ }
+ rdata.close
+ if extra_lines > 0
+ printf "-- %d extra line(s) found on %s\n", extra_lines,
+ name if $verbose == 0
+ return false
+ end
+ if not all_matched
+ printf "-- Mismatched line(s) found on %s\n",
+ name if $verbose == 0
+ return false
+ end
+ return true
+ end
+
+ def create_links
+ @symlinks.each { |fnames|
+ if $verbose >= 2
+ printf "-- Creating: symlink %s %s\n", fnames[0], fnames[1]
+ end
+ symres = File.symlink(fnames[0], fnames[1])
+ return false if symres == nil
+ return false unless File.symlink?(fnames[1])
+ }
+ return true
+ end
+
+ def destroy_links
+ @symlinks.each { |fnames|
+ if $verbose >= 2
+ printf "-- Removing: %s (symlink)\n", fnames[1]
+ end
+ if File.symlink?(fnames[1])
+ if File.delete(fnames[1]) != 1
+ $stderr.printf "Warning: problem removing symlink '%s'\n",
+ fnames[1]
+ end
+ else
+ $stderr.printf "Warning: Symlink '%s' does not exist?!?\n",
+ fnames[1]
+ end
+ }
+ return true
+ end
+
+ def init_io_files
+ @stderr = $scriptfile + ".stderr"
+ @stdout = $scriptfile + ".stdout"
+ File.delete(@stderr) if File.exists?(@stderr)
+ File.delete(@stdout) if File.exists?(@stdout)
+ @stdin = "/dev/null"
+
+ @redirs = " <" + @stdin
+ @redirs += " >" + @stdout
+ @redirs += " 2>" + @stderr
+
+ end
+
+ def pop_envs
+ @new_envs.each_key { |evar|
+ if @old_envs.has_key?(evar)
+ ENV[evar] = @old_envs[evar]
+ else
+ ENV.delete(evar)
+ end
+ }
+ end
+
+ def push_envs
+ @@gbl_envs.each_pair { |evar, eval|
+ ENV[evar] = eval
+ }
+ @new_envs.each_pair { |evar, eval|
+ if ENV.has_key?(evar)
+ @old_envs[evar] = ENV[evar]
+ end
+ ENV[evar] = eval
+ }
+ end
+
+ def run_test
+ tscript = File.open($scriptfile, "w")
+ tscript.printf "#!%s", $testpgm
+ tscript.printf " %s", @shebang_args if @shebang_args != ""
+ tscript.printf "\n"
+ tscript.printf "%s", @script_lines if @script_lines != ""
+ tscript.close
+ File.chmod(0755, $scriptfile)
+
+ usercmd = $scriptfile
+ usercmd += " " + @user_args if @user_args != nil
+ init_io_files
+
+ push_envs
+ return 0 unless create_links
+ printf "- Executing: %s\n", usercmd if $verbose >= 1
+ printf "----- with: %s\n", @redirs if $verbose >= 6
+ sys_ok = system(usercmd + @redirs)
+ if sys_ok
+ @sav_cmdvalue = 0
+ elsif $?.exited?
+ @sav_cmdvalue = $?.exitstatus
+ else
+ @sav_cmdvalue = 125
+ end
+ destroy_links
+ pop_envs
+ sys_ok = true
+ if @sav_cmdvalue != @cmdvalue
+ printf "-- Expecting cmdvalue of %d, but $? == %d\n", @cmdvalue,
+ @sav_cmdvalue
+ sys_ok = false
+ end
+ sys_ok = false unless check_out("stdout", @stdout, @expect_out)
+ sys_ok = false unless check_out("stderr", @stderr, @expect_err)
+ return 1 if sys_ok
+ return 0
+ end
+end
+
+# -------+---------+---------+-------- + --------+---------+---------+---------+
+# Processing of the command-line options given to the regress-sb.rb script.
+#
+class CommandOptions
+ def CommandOptions.parse(command_args)
+ parse_ok = true
+ command_args.each { |userarg|
+ case userarg
+ when /^--rgdata=(\S+)$/
+ parse_ok = false unless set_rgdatafile($1)
+ when /^--testpgm=(\S+)$/
+ parse_ok = false unless set_testpgm($1)
+ $cmdopt_testpgm = $testpgm
+ when "--stop-on-error", "--stop_on_error"
+ $stop_on_error = true
+ when /^--/
+ $stderr.printf "Error: Invalid long option: %s\n", userarg
+ parse_ok = false
+ when /^-/
+ userarg = userarg[1...userarg.length]
+ userarg.each_byte { |byte|
+ char = byte.chr
+ case char
+ when "v"
+ $verbose += 1
+ else
+ $stderr.printf "Error: Invalid short option: -%s\n", char
+ parse_ok = false
+ end
+ }
+ else
+ $stderr.printf "Error: Invalid request: %s\n", userarg
+ parse_ok = false
+ end
+ }
+ if $rgdatafile == nil
+ rgmatch = Dir.glob("regress*.rgdata")
+ if rgmatch.length == 1
+ $rgdatafile = rgmatch[0]
+ printf "Assuming --rgdata=%s\n", $rgdatafile
+ else
+ $stderr.printf "Error: The --rgdata file was not specified\n"
+ parse_ok = false
+ end
+ end
+ return parse_ok
+ end
+
+ def CommandOptions.set_rgdatafile(fname)
+ if not File.exists?(fname)
+ $stderr.printf "Error: Rgdata file '%s' does not exist\n", fname
+ return false
+ elsif not File.readable?(fname)
+ $stderr.printf "Error: Rgdata file '%s' is not readable\n", fname
+ return false
+ end
+ $rgdatafile = File.expand_path(fname)
+ return true
+ end
+
+ def CommandOptions.set_testpgm(fname)
+ if not File.exists?(fname)
+ $stderr.printf "Error: Testpgm file '%s' does not exist\n", fname
+ return false
+ elsif not File.executable?(fname)
+ $stderr.printf "Error: Testpgm file '%s' is not executable\n", fname
+ return false
+ end
+ $testpgm = File.expand_path(fname)
+ return true
+ end
+end
+
+# -------+---------+---------+-------- + --------+---------+---------+---------+
+# Processing of the test-specific options specifed in each [test]/[run]
+# section of the regression-data file. This will set values in the
+# global $testdata object.
+#
+class RGTestOptions
+ @@rgtest_opts = nil;
+
+ def RGTestOptions.init_rgtopts
+ @@rgtest_opts = Hash.new
+ @@rgtest_opts["$?"] = true
+ @@rgtest_opts["clearenv"] = true
+ @@rgtest_opts["sb_args"] = true
+ @@rgtest_opts["script"] = true
+ @@rgtest_opts["setenv"] = true
+ @@rgtest_opts["stderr"] = true
+ @@rgtest_opts["stdout"] = true
+ @@rgtest_opts["symlink"] = true
+ @@rgtest_opts["user_args"] = true
+ end
+
+ def RGTestOptions.parse(optname, optval)
+ init_rgtopts unless @@rgtest_opts
+
+ if not @@rgtest_opts.has_key?(optname)
+ $stderr.printf "Error: Invalid test-option in rgdata file: %s\n",
+ optname
+ return false
+ end
+
+ # Support a few very specific substitutions in values specified
+ # for test data. Format of all recognized values should be:
+ # [%-object.value-%]
+ # which is hopefully distinctive-enough that they will never
+ # conflict with any naturally-occurring string. Also note that
+ # we only match the specific values that we recognize, and not
+ # "just anything" that matches the general pattern. There are
+ # no blanks in the recognized values, but I use an x-tended
+ # regexp and then add blanks to make it more readable.
+ optval.gsub!(/\[%- testpgm\.pathname -%\]/x, $testpgm)
+ optval.gsub!(/\[%- testpgm\.basename -%\]/x, File.basename($testpgm))
+ optval.gsub!(/\[%- script\.pathname -%\]/x, $scriptfile)
+
+ invalid_value = false
+ case optname
+ when "$?"
+ if optval =~ /^\d+$/
+ $testdata.cmdvalue = optval.to_i
+ else
+ invalid_value = true
+ end
+ when "clearenv"
+ if optval =~ /^\s*([A-Za-z]\w*)\s*$/
+ $testdata.add_clearenv($1)
+ else
+ invalid_value = true
+ end
+ when "sb_args"
+ $testdata.shebang_args = optval
+ when "script"
+ $testdata.add_script(optval)
+ when "setenv"
+ if optval =~ /^\s*([A-Za-z]\w*)=(.*)$/
+ $testdata.add_setenv($1, $2)
+ else
+ invalid_value = true
+ end
+ when "stderr"
+ $testdata.add_expecterr(optval)
+ when "stdout"
+ $testdata.add_expectout(optval)
+ when "symlink"
+ if optval =~ /^\s*(\S+)\s+(\S+)\s*$/
+ srcfile = $1
+ newfile = $2
+ if not File.exists?(srcfile)
+ $stderr.printf "Error: source file '%s' does not exist.\n",
+ srcfile
+ invalid_value = true
+ elsif File.exists?(newfile)
+ $stderr.printf "Error: new file '%s' already exists.\n",
+ newfile
+ invalid_value = true
+ else
+ $testdata.add_symlink(srcfile, newfile)
+ end
+ else
+ invalid_value = true
+ end
+ when "user_args"
+ $testdata.user_args = optval
+ else
+ $stderr.printf "InternalError: Invalid test-option in rgdata file: %s\n",
+ optname
+ return false
+ end
+
+ if invalid_value
+ $stderr.printf "Error: Invalid value(s) for %s: %s\n",
+ optname, optval
+ return false
+ end
+ return true
+ end
+end
+
+# -------+---------+---------+-------- + --------+---------+---------+---------+
+# Here's where the "main" routine begins...
+#
+
+$cmdopt_testpgm = nil
+$testpgm = nil
+$rgdatafile = nil
+$scriptfile = "/tmp/env-regress"
+$stop_on_error = false
+$verbose = 0
+
+exit 1 unless CommandOptions.parse(ARGV)
+
+errline = nil
+test_count = 0
+testok_count = 0
+test_lineno = -1
+max_test = -1
+regress_data = File.open($rgdatafile)
+regress_data.each_line { |dline|
+ case dline
+ when /^\s*#/, /^\s*$/
+ # Just a comment line, ignore it.
+ when /^\s*gblenv=\s*(.+)$/
+ if test_lineno > 0
+ $stderr.printf "Error: Cannot define a global-value in the middle of a test (#5d)\n", test_lineno
+ errline = regress_data.lineno
+ break;
+ end
+ tempval = $1
+ if tempval !~ /^([A-Za-z]\w*)=(.*)$/
+ $stderr.printf "Error: Invalid value for 'gblenv=' request: %s\n",
+ tempval
+ errline = regress_data.lineno
+ break;
+ end
+ ExpectedResult.add_gblenv($1, $2)
+ when /^testpgm=\s*(\S+)\s*/
+ # Set the location of the program to be tested, if it wasn't set
+ # on the command-line processing.
+ if $cmdopt_testpgm == nil
+ if not CommandOptions.set_testpgm($1)
+ errline = regress_data.lineno
+ break;
+ end
+ end
+ when /^\[test\]$/
+ if test_lineno > 0
+ $stderr.printf "Error: Request to define a [test], but we are still defining\n"
+ $stderr.printf " the [test] at line #%s\n", test_lineno
+ errline = regress_data.lineno
+ break;
+ end
+ test_lineno = regress_data.lineno
+ max_test = test_lineno
+ printf "- Defining test at line #%s\n", test_lineno if $verbose >= 6
+ $testdata = ExpectedResult.new
+ when /^\[end\]$/
+ # User wants us to ignore the remainder of the rgdata file...
+ break;
+ when /^\[run\]$/
+ if test_lineno < 0
+ $stderr.printf "Error: Request to [run] a test, but no test is presently defined\n"
+ errline = regress_data.lineno
+ break;
+ end
+ printf "- Running test at line #%s\n", test_lineno if $verbose >= 1
+ run_result = $testdata.run_test
+ test_count += 1
+ printf "[Test #%3d: ", test_count
+ case run_result
+ when 0
+ # Test failed
+ printf "Failed! (line %4d)]\n", test_lineno
+ break if $stop_on_error
+ when 1
+ # Test ran as expected
+ testok_count += 1
+ printf "OK]\n"
+ else
+ # Internal error of some sort
+ printf "InternalError! (line %4d)]\n", test_lineno
+ errline = regress_data.lineno
+ break;
+ end
+ test_lineno = -1
+
+ when /^(\s*)([^\s:]+)\s*:(.+)$/
+ blankpfx = $1
+ test_lhs = $2
+ test_rhs = $3
+ if test_lineno < 0
+ $stderr.printf "Error: No test is presently being defined\n"
+ errline = regress_data.lineno
+ break;
+ end
+ # All the real work happens in RGTestOptions.parse
+ if not RGTestOptions.parse(test_lhs, test_rhs)
+ errline = regress_data.lineno
+ break;
+ end
+ if blankpfx.length == 0
+ $stderr.printf "Note: You should at least one blank before:%s\n",
+ dline.chomp
+ $stderr.printf " at line %d of rgdata file %s\n",
+ regress_data.lineno, $rgdatafile
+ end
+
+ else
+ $stderr.printf "Error: Invalid line: %s\n", dline.chomp
+ errline = regress_data.lineno
+ break;
+ end
+}
+regress_data.close
+if errline != nil
+ $stderr.printf " at line %d of rgdata file %s\n", errline, $rgdatafile
+ exit 2
+end
+if testok_count != test_count
+ printf "%d of %d tests were successful.\n", testok_count, test_count
+ exit 1
+end
+
+printf "All %d tests were successful!\n", testok_count
+exit 0