commit - 8e4033faa2a65945f3eef825447e1685d6b31def
commit + e6eae0468089573a77abb012145073dd8d1c4402
blob - aa59087be78be413b07f5af0ba3b78b914b8266a
blob + 7e552eddfecbe0b782dec4fa11b58fe32d9d2124
--- exercise
+++ exercise
# config options
-set opts(-p) {*.t} ;# pattern for test executable files
-set opts(-ps) {*.tests} ;# pattern for test suite executable files
-set opts(-pd) {*} ;# pattern for test search directories
+set opts(-d) {*} ;# pattern for test search directories
+set opts(-p) {*.t} ;# pattern for test executable files
+set opts(-s) {*.tests} ;# pattern for test suite executable files
# executing tests
upvar $countervar counters
# Should the test result be integrated as a nested test suite?
- set suite [string match $opts(-ps) [file tail $path]]
+ set suite [string match $opts(-s) [file tail $path]]
# Call files in current dir with "./".
set exe $path
if {[dict exists $dirs $normpath]} continue
dict set dirs $normpath {}
- set subs [glob -type d -nocomplain -directory $path $opts(-pd)]
- set suites [glob -type f -nocomplain -directory $path $opts(-ps)]
+ set subs [glob -type d -nocomplain -directory $path $opts(-d)]
set tests [glob -type f -nocomplain -directory $path $opts(-p)]
+ set suites [glob -type f -nocomplain -directory $path $opts(-s)]
find_files_iter result dirs [lsort $subs]
lappend result {*}[lsort $suites]
# main routine
+proc getopt {argvvar optstring optvar argvar} {
+ upvar $argvvar argv $optvar opt $argvar arg
+
+ set hd [lindex $argv 0]
+ set opt [string index $hd 1]
+ if {$opt eq "" || [string index $hd 0] ne "-"} { ;# no option argument
+ return 0
+ }
+ if {$hd eq "--"} {
+ set argv [lreplace $argv 0 0] ;# remove hd
+ return 0
+ }
+
+ # consume option character
+ set hd [string replace $hd 1 1]
+ if {$hd ne "-"} {
+ set argv [lreplace $argv 0 0 $hd] ;# replace hd
+ } else {
+ set argv [lreplace $argv 0 0] ;# consume exhausted hd
+ }
+
+ set idx [string first $opt $optstring]
+ if {$idx == -1 || $opt eq ":"} {
+ puts stderr "$::argv0: unknown option -- $opt"
+ set opt "?"
+ return 1
+ }
+
+ # handle option arguments
+ if {[string index $optstring [expr $idx + 1]] ne ":"} {
+ return 1 ;# no argument expected
+ }
+ if {$hd ne "-"} {
+ set arg [string replace $hd 0 0] ;# rest of hd -> optarg
+ set argv [lreplace $argv 0 0] ;# consume hd
+ } elseif {[llength $argv] > 0} {
+ set arg [lindex $argv 0] ;# next arg -> optarg
+ set argv [lreplace $argv 0 0] ;# consume arg
+ } else {
+ puts stderr "$::argv0: option requires an argument -- $opt"
+ if {[string index $optstring 0] eq ":"} {
+ set opt ":"
+ } else {
+ set opt "?"
+ }
+ }
+
+ return 1
+}
+
proc main {argc argv} {
+ global opts
set counters {run 0 ok 0 fail 0 error 0}
- # TODO: accept opts on command line
- # TODO: command-line --help
+ # handle command line options
+ set u {[-d pat] [-p pat] [-s pat] [path ...]}
+ while {[getopt argv {d:p:s:} opt arg]} {
+ if {$opt eq "?"} {
+ puts stderr "usage: [file tail $::argv0] $u"
+ exit 1
+ }
+ set opts(-$opt) $arg
+ }
+ set argc [llength $argv]
set paths [expr {$argc == 0 ? "." : $argv}]
set files [find_files $paths]
blob - 4d54c5639a0cffb8b75e634b9b9ad9880cf37c33
blob + 463ab25fde319dbe79fc192598eb3e0ace506e8a
--- exercise.1
+++ exercise.1
.Nm
searches for tests therein.
If given a file argument, it executes it as a single test (or test suite).
+To be recognized as tests, files must match the pattern
+.Pa *.t .
+To be run as test suites (see below), files must match the pattern
+.Pa *.tests .
.Pp
-Tests are represented as executable files that are expected to exit 0 on
+The options are as follows:
+.Pp
+.Bl -tag
+.It Fl d Ar pattern
+When searching for tests,
+only descend into directories that match the given pattern.
+Defaults to
+.Dq *
+(all directories).
+.It Fl p Ar pattern
+Process (only) files matching the given pattern as tests.
+Defaults to
+.Dq *.t .
+.It Fl s Ar pattern
+Process (only) files matching the given pattern as test suites.
+Defaults to
+.Dq *.tests .
+.El
+.
+.Ss Test Files
+Tests are represented simply as executable files that are expected to exit 0 on
success.
Any output to standard error and non-zero exits are interpreted as negative
results (test failures).
Standard output is ignored.
As a special case, exit status 127 is interpreted as an error during the test,
implying an inconclusive result.
-.Pp
-To be recognized as tests, files must match the pattern
-.Pa *.t .
-To be run as test suites (see below), files must match the pattern
-.Pa *.tests .
.
.Ss Test Suites
Multiple tests can be combined into one executable.