mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-17 16:38:54 +00:00
Phase 4 of plans/exit.md: the aux/terminal sub-entrypoints. pkg/auxents and
pkg/terminals are now os.Exit-free; even the dispatchers return exit codes
instead of exiting.
- auxents.Dispatch returns (handled bool, exitCode int); entrypoint.Main --
the one sanctioned exit point -- exits with the code.
- terminals.Dispatch returns an exit code; the climain caller wraps it in a
lib.ExitRequest, which also retires the 'terminal did not exit the process'
panic.
- Usage functions (hex, unhex, lecat, termcvt, repl, script, regtest) no
longer take an exitCode parameter and exit; call sites print usage and
return the code explicitly.
- Inner I/O helpers (hexDumpFile, unhexFile, lecatFile, termcvtFile) return
errors; each sub-main prints 'mlr {verb}: ...' as before and returns 1.
lecatFile formerly looped forever on a non-EOF read error; it now returns
the error.
- The regtest directory walk (Execute / executeSinglePath /
executeSingleDirectory / hasCaseSubdirectories) plumbs errors up to
RegTestMain; regression_test.go updated for the new Execute signature.
Stderr messages and exit codes are unchanged across mlr aux-list, hex, unhex,
lecat, termcvt, help, version, repl, script, and regtest surfaces (checked by
hand); all 4779 regression cases pass; make lint is clean; docs rebuild with
zero churn.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
122 lines
3.1 KiB
Go
122 lines
3.1 KiB
Go
// TODO
|
|
|
|
package regtest
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const defaultPath = "./test/cases"
|
|
|
|
func regTestUsage(verbName string, o *os.File) {
|
|
fmt.Fprintf(o, "Usage: mlr %s [options] [one or more directories/files]\n", verbName)
|
|
fmt.Fprintf(o, "If no directories/files are specified, the directory %s is used by default.\n", defaultPath)
|
|
fmt.Fprintf(o, "Recursively walks the directory/ies looking for foo.cmd files having Miller command-lines,\n")
|
|
fmt.Fprintf(o, "with foo.expout and foo.experr files having expected stdout and stderr, respectively.\n")
|
|
fmt.Fprintf(o, "If foo.should-fail exists and is a file, the command is expected to exit non-zero back to\n")
|
|
fmt.Fprintf(o, "the shell.\n")
|
|
fmt.Fprintf(o, "\n")
|
|
fmt.Fprintf(o, "Options:\n")
|
|
fmt.Fprintf(o, "[none] Print directory-level pass/fails, and overall pass/fail.\n")
|
|
fmt.Fprintf(o, "-m {...} Specify name of Miller executable to use.\n")
|
|
fmt.Fprintf(o, "-c Shorthand for -m ../c/mlr.\n")
|
|
fmt.Fprintf(o, "-p Create the .expout and .experr files, rather than checking them.\n")
|
|
fmt.Fprintf(o, "-v Also include pass/fail at command-file level.\n")
|
|
fmt.Fprintf(o, "-vv Also include pass/fail reasons for each command-file.\n")
|
|
fmt.Fprintf(o, "-vvv Also include full stdout/stderr/exit-code for each command-file.\n")
|
|
fmt.Fprintf(o, "-j Just show the Miller command-line, put/filter script if any, and output.\n")
|
|
fmt.Fprintf(o, "-s {n} After running tests, re-run first n failed .cmd files with verbosity level 3.\n")
|
|
fmt.Fprintf(o, "-S After running tests, re-run all failed .cmd files with verbosity level 3.\n")
|
|
}
|
|
|
|
// Here the args are the full Miller command line: "mlr regtest --foo bar".
|
|
func RegTestMain(args []string) int {
|
|
|
|
exeName := os.Args[0]
|
|
verbName := args[0]
|
|
argc := len(args)
|
|
argi := 1
|
|
verbosityLevel := 0
|
|
doPopulate := false
|
|
plainMode := false
|
|
firstNFailsToShow := 0
|
|
|
|
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
|
|
arg := args[argi]
|
|
|
|
if !strings.HasPrefix(arg, "-") {
|
|
break // No more flag options to process
|
|
}
|
|
argi++
|
|
|
|
switch arg {
|
|
case "-h", "--help":
|
|
regTestUsage(verbName, os.Stdout)
|
|
return 0
|
|
|
|
case "-m":
|
|
if argi >= argc {
|
|
regTestUsage(verbName, os.Stderr)
|
|
return 1
|
|
}
|
|
exeName = args[argi]
|
|
argi++
|
|
|
|
case "-s":
|
|
if argi >= argc {
|
|
regTestUsage(verbName, os.Stderr)
|
|
return 1
|
|
}
|
|
temp, err := strconv.Atoi(args[argi])
|
|
if err != nil {
|
|
regTestUsage(verbName, os.Stderr)
|
|
return 1
|
|
}
|
|
firstNFailsToShow = temp
|
|
argi++
|
|
|
|
case "-S":
|
|
firstNFailsToShow = 1000000000
|
|
|
|
case "-p":
|
|
doPopulate = true
|
|
|
|
case "-v":
|
|
verbosityLevel++
|
|
|
|
case "-j":
|
|
plainMode = true
|
|
|
|
default:
|
|
regTestUsage(verbName, os.Stderr)
|
|
return 1
|
|
}
|
|
}
|
|
casePaths := args[argi:]
|
|
if len(casePaths) == 0 {
|
|
casePaths = []string{defaultPath}
|
|
}
|
|
|
|
regtester := NewRegTester(
|
|
exeName,
|
|
doPopulate,
|
|
verbosityLevel,
|
|
plainMode,
|
|
firstNFailsToShow,
|
|
)
|
|
|
|
ok, err := regtester.Execute(casePaths)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "mlr %s: %v\n", verbName, err)
|
|
return 1
|
|
}
|
|
|
|
if !ok {
|
|
return 1
|
|
}
|
|
|
|
return 0
|
|
}
|