[tools] test-runner: Add --generate-skip flag

Generates expected cases that fail, using a SKIP header

Change-Id: I2738fa2cf47c715fe6e978edf51aa928c5e3b216
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53049
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2021-06-03 10:47:24 +00:00 committed by Tint LUCI CQ
parent 194c58f89c
commit 2270b434bc
1 changed files with 51 additions and 26 deletions

View File

@ -70,12 +70,13 @@ optional flags:`)
func run() error { func run() error {
var formatList, filter, dxcPath, xcrunPath string var formatList, filter, dxcPath, xcrunPath string
numCPU := runtime.NumCPU() numCPU := runtime.NumCPU()
generateExpected := false generateExpected, generateSkip := false, false
flag.StringVar(&formatList, "format", "all", "comma separated list of formats to emit. Possible values are: all, wgsl, spvasm, msl, hlsl") flag.StringVar(&formatList, "format", "all", "comma separated list of formats to emit. Possible values are: all, wgsl, spvasm, msl, hlsl")
flag.StringVar(&filter, "filter", "**.wgsl, **.spvasm, **.spv", "comma separated list of glob patterns for test files") flag.StringVar(&filter, "filter", "**.wgsl, **.spvasm, **.spv", "comma separated list of glob patterns for test files")
flag.StringVar(&dxcPath, "dxc", "", "path to DXC executable for validating HLSL output") flag.StringVar(&dxcPath, "dxc", "", "path to DXC executable for validating HLSL output")
flag.StringVar(&xcrunPath, "xcrun", "", "path to xcrun executable for validating MSL output") flag.StringVar(&xcrunPath, "xcrun", "", "path to xcrun executable for validating MSL output")
flag.BoolVar(&generateExpected, "generate-expected", false, "create or update all expected outputs") flag.BoolVar(&generateExpected, "generate-expected", false, "create or update all expected outputs")
flag.BoolVar(&generateSkip, "generate-skip", false, "create or update all expected outputs that fail with SKIP")
flag.IntVar(&numCPU, "j", numCPU, "maximum number of concurrent threads to run tests") flag.IntVar(&numCPU, "j", numCPU, "maximum number of concurrent threads to run tests")
flag.Usage = showUsage flag.Usage = showUsage
flag.Parse() flag.Parse()
@ -199,7 +200,7 @@ func run() error {
go func() { go func() {
defer wg.Done() defer wg.Done()
for job := range jobs { for job := range jobs {
job.run(exe, dxcPath, xcrunPath, generateExpected) job.run(exe, dxcPath, xcrunPath, generateExpected, generateSkip)
} }
}() }()
} }
@ -355,12 +356,12 @@ type job struct {
result *status result *status
} }
func (j job) run(exe, dxcPath, xcrunPath string, generateExpected bool) { func (j job) run(exe, dxcPath, xcrunPath string, generateExpected, generateSkip bool) {
// Is there an expected output? // Is there an expected output?
expected := loadExpectedFile(j.file, j.format) expected := loadExpectedFile(j.file, j.format)
skipped := false
if strings.HasPrefix(expected, "SKIP") { // Special SKIP token if strings.HasPrefix(expected, "SKIP") { // Special SKIP token
*j.result = status{code: skip} skipped = true
return
} }
expected = strings.ReplaceAll(expected, "\r\n", "\n") expected = strings.ReplaceAll(expected, "\r\n", "\n")
@ -382,17 +383,49 @@ func (j job) run(exe, dxcPath, xcrunPath string, generateExpected bool) {
} }
// Invoke the compiler... // Invoke the compiler...
var err error ok, out := invoke(exe, args...)
if ok, out := invoke(exe, args...); ok { out = strings.ReplaceAll(out, "\r\n", "\n")
out = strings.ReplaceAll(out, "\r\n", "\n") matched := expected == "" || expected == out
if generateExpected {
// If --generate-expected was passed, write out the output if ok && generateExpected {
err = saveExpectedFile(j.file, j.format, out) saveExpectedFile(j.file, j.format, out)
} else if expected != "" && expected != out { matched = true
// Expected output did not match }
dmp := diffmatchpatch.New()
diff := dmp.DiffPrettyText(dmp.DiffMain(expected, out, true)) switch {
err = fmt.Errorf(`Output was not as expected case ok && matched:
// Test passed
*j.result = status{code: pass}
return
// --- Below this point the test has failed ---
case skipped:
if generateSkip {
saveExpectedFile(j.file, j.format, "SKIP: FAILED\n\n"+out)
}
*j.result = status{code: skip}
return
case !ok:
// Compiler returned non-zero exit code
if generateSkip {
saveExpectedFile(j.file, j.format, "SKIP: FAILED\n\n"+out)
}
err := fmt.Errorf("%s", out)
*j.result = status{code: fail, err: err}
return
default:
// Compiler returned zero exit code, or output was not as expected
if generateSkip {
saveExpectedFile(j.file, j.format, "SKIP: FAILED\n\n"+out)
}
// Expected output did not match
dmp := diffmatchpatch.New()
diff := dmp.DiffPrettyText(dmp.DiffMain(expected, out, true))
err := fmt.Errorf(`Output was not as expected
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Expected: -- -- Expected: --
@ -408,17 +441,9 @@ func (j job) run(exe, dxcPath, xcrunPath string, generateExpected bool) {
-- Diff: -- -- Diff: --
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
%s`, %s`,
expected, out, diff) expected, out, diff)
}
} else {
// Compiler returned a non-zero exit code
err = fmt.Errorf("%s", out)
}
if err != nil {
*j.result = status{code: fail, err: err} *j.result = status{code: fail, err: err}
} else { return
*j.result = status{code: pass}
} }
} }