diff --git a/cmd/internal-tools/corpus-sweep/main.go b/cmd/internal-tools/corpus-sweep/main.go index c4dbc5d..21e14ad 100644 --- a/cmd/internal-tools/corpus-sweep/main.go +++ b/cmd/internal-tools/corpus-sweep/main.go @@ -154,16 +154,28 @@ func parseArguments(arguments []string, stderr io.Writer) (config, error) { } configuration.extraArguments = flagSet.Args() - for name, value := range map[string]string{ - "--corpus": configuration.corpusRoot, - "--spec": configuration.specPath, - "--seeds": seedSpecification, - "--output": configuration.outputDirectory, + // Every missing flag is named together, in flag order: stopping at the + // first turns one rerun into one rerun per missing flag. + var missing []error + for _, required := range []struct { + name string + value string + }{ + {"--corpus", configuration.corpusRoot}, + {"--spec", configuration.specPath}, + {"--seeds", seedSpecification}, + {"--output", configuration.outputDirectory}, } { - if value == "" { - return config{}, fmt.Errorf("%s is required", name) + if required.value == "" { + missing = append( + missing, + fmt.Errorf("%s is required", required.name), + ) } } + if err := errors.Join(missing...); err != nil { + return config{}, err + } if configuration.maxSteps <= 0 { return config{}, fmt.Errorf( "--max-steps must be positive: every implementation needs the same step budget", diff --git a/cmd/internal-tools/corpus-sweep/main_test.go b/cmd/internal-tools/corpus-sweep/main_test.go new file mode 100644 index 0000000..84981de --- /dev/null +++ b/cmd/internal-tools/corpus-sweep/main_test.go @@ -0,0 +1,34 @@ +package main + +import ( + "io" + "strings" + "testing" +) + +// Three flags missing is one rerun, not three: the operator is told about all +// of them at once, in flag order, whatever order the check happened to walk. +func TestParseArguments_NamesEveryMissingRequiredFlagInFlagOrder(t *testing.T) { + _, err := parseArguments( + []string{"--spec", "s", "--max-steps", "10"}, + io.Discard, + ) + if err == nil { + t.Fatal("got no error, want every missing flag named") + } + message := err.Error() + previous := -1 + for _, name := range []string{"--corpus", "--seeds", "--output"} { + at := strings.Index(message, name) + if at < 0 { + t.Fatalf("got %q, want %s named", message, name) + } + if at < previous { + t.Errorf("got %q, want the flags named in flag order", message) + } + previous = at + } + if strings.Contains(message, "--spec") { + t.Errorf("got %q, want the supplied --spec left out", message) + } +}