Commit Diff


commit - 9d3bc9e22e36abc872ea2082e4bad194d395cdf4
commit + 8256f5dffdca364cde5c43fcaa001bfe255f4fcd
blob - 78fc2082dc1554a3a5beb1ad0275fe109b350328
blob + 9446a3b3d20d03a46d354f149a677ed155005458
--- exercise
+++ exercise
@@ -10,6 +10,7 @@ package require Tcl 8.4
 # config options
 set opts(-B) .                  ;# basedir
 set opts(-j) 1                  ;# number of concurrent jobs
+set opts(-n) 0                  ;# dry run
 set opts(-pd) {*}               ;# pattern for test search directories
 set opts(-ps) {*.ts}            ;# pattern for test suite executable files
 set opts(-pt) {*.t}             ;# pattern for test executable files
@@ -28,6 +29,8 @@ set opts(-v) 0                  ;# verbose mode
 # sequential operation. If set to non-blocking, an event handler should be set
 # up that resumes the coroutine whenever the channel becomes readable. When
 # the coroutine ends, the channel is closed and any event handler vanishes.
+#   In dry runs, the routine terminates before executing the test and returns
+# a bogus result of "error", to signal only that no job was started.
 proc execute_test {job basedir path} {
     global opts counters
     set args {}
@@ -51,8 +54,12 @@ proc execute_test {job basedir path} {
         # Pass stderr through when calling test suites.
         set errfile @stderr
 
-	# Pass -v(v) on to test suites.
-	if {$opts(-v) > 0} {set args "-[string repeat v $opts(-v)] $args"}
+        # Pass -v(v) and -n on to test suites.
+        if {$opts(-v) > 0} {set args "-[string repeat v $opts(-v)] $args"}
+        if {$opts(-n)} {set args "-n $args"}
+    } elseif {$opts(-n)} {
+        # Dry run requested; stop here.
+        return error    ;# dummy to signal we did not create a channel
     } else {
         # Capture stderr in a temporary file.
         # Unfortunately, 'chan pipe' only appears in Tcl 8.6. :(
@@ -441,9 +448,9 @@ proc main {argc argv} {
     if {[info exists env(EXERCISEDIR)]} {set opts(-D) $env(EXERCISEDIR)}
 
     # handle command line options
-    set u {[-qv] [-B dir] [-C dir] [-D dir] [-j n] [-p k=pattern] [path ...]}
+    set u {[-nqv] [-B dir] [-C dir] [-D dir] [-j n] [-p k=pattern] [path ...]}
     set prog [file tail $::argv0]
-    while {[getopt argv {B:C:D:j:p:qv} opt arg]} {
+    while {[getopt argv {B:C:D:j:np:qv} opt arg]} {
         if {$opt eq "?"} {
             puts stderr "usage: $prog $u"
             exit 1
@@ -523,6 +530,7 @@ proc main {argc argv} {
         exit 127
     }
 
+    if {$opts(-n)} {exit 0}                 ;# dry run
     exit [notok $counters]
 }
 
blob - 24b4a6ffedbf654c6f198a9cc8b3e051a1f9450f
blob + ec62f029162839840dd8b1b2f2416f79e5bc8650
--- exercise.1
+++ exercise.1
@@ -8,7 +8,7 @@
 .
 .Sh SYNOPSIS
 .Nm exercise
-.Op Fl qv
+.Op Fl nqv
 .Op Fl B Ar dir
 .Op Fl C Ar dir
 .Op Fl D Ar dir
@@ -70,6 +70,14 @@ contains common helper or data files for the tests to 
 Execute up to
 .Ar n
 test jobs concurrently.
+.It Fl n
+Dry run.
+Do not execute the tests.
+Test suite executables
+.Em are
+called, with the
+.Fl n
+option passed on to them.
 .It Fl p Sy d= Ns Ar pattern
 When searching for tests,
 only descend into directories that match the given pattern.
@@ -131,9 +139,17 @@ Consequently, the
 utility can be used as a (nested) test suite runner if desired.
 .Pp
 A test suite must admit the
+.Fl n
+and 
 .Fl v
-option.
-It may honor it by printing test names to its standard output,
+options.
+It must honor
+.Fl n
+by performing a dry run, reporting status as usual
+without actually executing any tests.
+In addition, it may honor the
+.Fl v
+option by printing test names to its standard output,
 prefixed with
 .Dq ". "
 to distinguish them from regular status lines.
blob - 012ad1fc058bde22aa41aa231fb36d9baab8d986
blob + 63a4c86af485f4ff8efa935e36dadf3eeea2aae7
--- support/adapt-tst
+++ support/adapt-tst
@@ -3,7 +3,7 @@
 # This script adapts a test suite that exposes the simple report protocol of
 # test.h for use with exercise.
 #
-# Usage: adapt-tst cmd [-v] [arg ...]
+# Usage: adapt-tst cmd [-nv] [arg ...]
 #
 # Example: Given a test suite in 'foo.tst.c' that is built into an executable
 # 'foo.tst', create the script 'foo.ts' containing the following:
@@ -16,10 +16,12 @@ cmd="$1"
 shift
 
 # handle command line flags
+nflag=0
 vflag=0
-while getopts v ch
+while getopts nv ch
 do
 	case $ch in
+	n)	nflag=1 ;;
 	v)	vflag=$(($vflag + 1)) ;;
 	?)	echo "usage: adapt-tst cmd [-v] [arg ...]"
 	esac
@@ -35,12 +37,32 @@ trap "rm -f $tmp" EXIT
 
 # clear the flag variables for the test executable
 unset D V K X
-[ $vflag -ge 2 ] && export V=1
 
 # determine the total number of tests by performing a dry run
 D=1 "$cmd" "$@" >$tmp || exit 127
 run=$(echo $(wc -l <$tmp))
 
+# was a dry run requested in the first place?
+if [ $nflag -eq 1 ]
+then
+	if [ $vflag -ge 1 ]
+	then
+		# just dump the test names
+		IFS=
+		while read -r line
+		do
+			echo ". $line"
+		done <$tmp
+	fi
+
+	# succeed with a plain count
+	echo "run $run  ok 0  fail 0  error 0"
+	exit 0
+fi
+
+# let -vv set V, but not for dry runs
+[ $vflag -ge 2 ] && export V=1
+
 # run the tests in the background, redirecting output to a fifo
 rm -f $tmp
 mkfifo $tmp || exit 127
blob - /dev/null
blob + 3d4dffafc2e6a23ee1786320e3ac01e1f57301c8 (mode 755)
--- /dev/null
+++ tests/exercise/flag/n.t
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+set -e
+
+./assert-exercise $0 \
+        "run 1  ok 0  fail 0  error 0\n" \
+        '' \
+	-n <<EOF
+#!/bin/sh
+    exit 0
+EOF
+
+./assert-exercise $0 \
+        ". $0.tst\nrun 1  ok 0  fail 0  error 0\n" \
+        '' \
+	-nv <<EOF
+#!/bin/sh
+    exit 0
+EOF
+
+export tst=$0.ts
+./assert-exercise $0 \
+        "run 2  ok 0  fail 0  error 0\n" \
+        '' \
+	-n <<EOF
+#!/bin/sh
+    echo "run 2  ok 0  fail 0  error 0"
+    echo "run 2  ok 0  fail 0  error 0"
+    echo "run 2  ok 0  fail 0  error 0"
+    test "\$1" = "-n"
+EOF
+
+export tst=$0.ts
+./assert-exercise $0 \
+        ". $0.ts\n. . test1\n. . test2\nrun 2  ok 0  fail 0  error 0\n" \
+        '' \
+	-nv <<EOF
+#!/bin/sh
+    echo "run 2  ok 0  fail 0  error 0"
+    echo ". test1"
+    echo "run 2  ok 0  fail 0  error 0"
+    echo ". test2"
+    echo "run 2  ok 0  fail 0  error 0"
+    test "\$1" = "-n" -a "\$2" = "-v"
+EOF
+
+export tst=$0.ts
+./assert-exercise $0 \
+        ". $0.ts\n. . test1\n. . > hallo\nrun 1  ok 0  fail 0  error 0\n" \
+        '' \
+	-nvv <<EOF
+#!/bin/sh
+    echo "run 1  ok 0  fail 0  error 0"
+    echo ". test1"
+    echo ". > hallo"
+    echo "run 1  ok 0  fail 0  error 0"
+    test "\$1" = "-n" -a "\$2" = "-vv"
+EOF
blob - 366dc8f8ffb7e1bda6ee182c13795b2854bf6ba6
blob + ecdb3353b3508b43c2d7028dbf7a266ec4e00433
--- tests/support/adapt-tst.t
+++ tests/support/adapt-tst.t
@@ -6,6 +6,7 @@ cat >$tmp <<-"EOF"
 	#!/bin/sh
 	if [ -n "$D" ]
 	then
+	    [ -n "$V" ] && echo "foo()	-"
 	    echo "test_1()"
 	    echo "test_2()"
 	    echo "test_3()"
@@ -50,3 +51,32 @@ run 3  ok 2  fail 1  error 0\n" \
 		#!/bin/sh
 		exec ../../support/adapt-tst $tmp "\$@"
 	EOF
+
+./assert-exercise $0 \
+	"run 3  ok 0  fail 0  error 0\n" \
+	'' \
+	-n \
+	<<-EOF
+		#!/bin/sh
+		exec ../../support/adapt-tst $tmp "\$@"
+	EOF
+
+./assert-exercise $0 \
+	". $tst\n. . test_1()\n. . test_2()\n. . test_3()\n\
+run 3  ok 0  fail 0  error 0\n" \
+	'' \
+	-nv \
+	<<-EOF
+		#!/bin/sh
+		exec ../../support/adapt-tst $tmp "\$@"
+	EOF
+
+./assert-exercise $0 \
+	". $tst\n. . test_1()\n\
+. . test_2()\n. . test_3()\nrun 3  ok 0  fail 0  error 0\n" \
+	'' \
+	-nvv \
+	<<-EOF
+		#!/bin/sh
+		exec ../../support/adapt-tst $tmp "\$@"
+	EOF