All checks were successful
go-test / go test (push) Successful in 56s
- Add dsl/matcher_test.go covering ExactMatcher, ContainsMatcher,
RegexMatcher, NumericEpsMatcher, AnyOrderMatcher and NoMatcher —
previously 0% — including epsilon, count mismatch, unparsable
numbers, invalid regex, and splitLines edge cases.
- Add dsl/ast_test.go for the new Test.SetInputFile / SetStdin /
SetOutputFile / SetStdout helpers and Pattern.IsDirMode.
- Add dsl/build_string_test.go covering BuildProfile.String,
WarningLevel.String and BuildConfig.MergeFrom (wrapper, defines
into nil map, defines override existing, nil src).
- Add dsl/merge_test.go driving mergeFiles to 100%: legacy build
fields, duplicate toolchain/build/group from include, binary /
sources / normalize_crlf / trim_trailing_ws propagation, local
overrides of timeout and memory_limit.
- Add dsl/parser_features_test.go for parseTest / parseGroup happy
paths that were missing: file/outFile, env, wrapper, per-test
timeout/memory overrides, non-zero exitCode, scoring partial /
all_or_none and unknown scoring.
- Add dsl/parser_errors_test.go, a 54-case table-driven test that
hits every `expect(...)` error branch in parseGroup and parseTest
(missing LPAREN/RPAREN/LBRACE/RBRACE/ASSIGN, wrong token types on
weight/timeout/memory_limit/scoring/env/wrapper/file/outFile, and
unclosed blocks).
- Add dsl/parser_misc_test.go covering parsePattern dir-mode with
args, unknown pattern field, non-ident in pattern, top-level
binary / sources / normalize_crlf / trim_trailing_ws / bare-int
memory_limit, parseBool invalid ident and non-ident, matcher
without an operator, validateBuilds legacy+structured conflict.
- Add dsl/build_parser_test.go covering every BuildConfig field
(sources, includes, sanitize, link, extra, platforms, compilers,
defines), OS overrides on named builds, nested / duplicate OS
override errors, unknown build / profile / warnings / platform,
missing = on assign-string and assign-string-list, define(...)
error cases, and parseToolchainsBlock (duplicate name, missing
platforms, bad name token, unknown field, unknown compiler class,
binary and class propagation).
- Add dsl/lexer_test.go for Token.String, TokenType.String UNKNOWN
branch, line comments, unterminated string and heredoc, unknown
escape sequence, escape decoding, unexpected character, every
K/M/G/KiB/MiB/GiB size suffix, ms/s/m duration suffixes, negative
integer lexing and float literals.
- Extend runner/result_test.go with Status.String and
TestResult.addFailure (both previously 0%).
- Add .gitea/workflows/go-test.yml running `go vet` and
`go test -race -coverprofile=coverage.out ./...` on push,
pull_request and manual dispatch, uploading coverage.out as an
artifact.
Coverage: dsl 60.5% -> 85%+, runner 29.0% -> 30.5%.
238 lines
4.5 KiB
Go
238 lines
4.5 KiB
Go
package dsl
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func parseOrFatal(t *testing.T, src string) *File {
|
|
t.Helper()
|
|
f, _, err := Parse(src)
|
|
if err != nil {
|
|
t.Fatalf("parse error: %v", err)
|
|
}
|
|
return f
|
|
}
|
|
|
|
func parseExpectError(t *testing.T, src, wantSubstr string) {
|
|
t.Helper()
|
|
_, _, err := Parse(src)
|
|
if err == nil {
|
|
t.Fatalf("expected error containing %q, got nil", wantSubstr)
|
|
}
|
|
if !strings.Contains(err.Error(), wantSubstr) {
|
|
t.Errorf("error = %q, want substring %q", err.Error(), wantSubstr)
|
|
}
|
|
}
|
|
|
|
func TestParseTestFileAndOutFile(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
|
|
group("g") {
|
|
weight = 1.0
|
|
test("files") {
|
|
file("input.txt") = "1 2 3\n"
|
|
outFile("result.txt") = "6\n"
|
|
stdout = ""
|
|
}
|
|
}
|
|
`
|
|
f := parseOrFatal(t, src)
|
|
tst := f.Groups[0].Tests[0]
|
|
if tst.InFiles["input.txt"] != "1 2 3\n" {
|
|
t.Errorf("InFiles[input.txt] = %q", tst.InFiles["input.txt"])
|
|
}
|
|
if tst.OutFiles["result.txt"] != "6\n" {
|
|
t.Errorf("OutFiles[result.txt] = %q", tst.OutFiles["result.txt"])
|
|
}
|
|
}
|
|
|
|
func TestParseTestEnvAndWrapper(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
|
|
group("g") {
|
|
weight = 1.0
|
|
test("env") {
|
|
env("FOO") = "bar"
|
|
env("BAZ") = "qux"
|
|
wrapper = "valgrind"
|
|
stdout = ""
|
|
}
|
|
}
|
|
`
|
|
f := parseOrFatal(t, src)
|
|
tst := f.Groups[0].Tests[0]
|
|
if tst.Env["FOO"] != "bar" || tst.Env["BAZ"] != "qux" {
|
|
t.Errorf("Env = %v", tst.Env)
|
|
}
|
|
if tst.Wrapper != "valgrind" {
|
|
t.Errorf("Wrapper = %q", tst.Wrapper)
|
|
}
|
|
}
|
|
|
|
func TestParseTestTimeoutAndMemoryOverride(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
timeout 10s
|
|
|
|
group("g") {
|
|
weight = 1.0
|
|
memory_limit = 256MB
|
|
test("override") {
|
|
timeout = 2s
|
|
memory_limit = 64MB
|
|
stdout = ""
|
|
}
|
|
}
|
|
`
|
|
f := parseOrFatal(t, src)
|
|
tst := f.Groups[0].Tests[0]
|
|
if tst.Timeout != 2*time.Second {
|
|
t.Errorf("Timeout = %v, want 2s", tst.Timeout)
|
|
}
|
|
if tst.MemoryLimit != 64*1024*1024 {
|
|
t.Errorf("MemoryLimit = %d, want %d", tst.MemoryLimit, 64*1024*1024)
|
|
}
|
|
}
|
|
|
|
func TestParseTestExitCodeNonZero(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
|
|
group("g") {
|
|
weight = 1.0
|
|
test("fail") {
|
|
exitCode = 42
|
|
stdout = ""
|
|
}
|
|
}
|
|
`
|
|
f := parseOrFatal(t, src)
|
|
tst := f.Groups[0].Tests[0]
|
|
if tst.ExitCode == nil || *tst.ExitCode != 42 {
|
|
t.Errorf("ExitCode = %v, want 42", tst.ExitCode)
|
|
}
|
|
}
|
|
|
|
func TestParseTestUnknownKeyword(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
group("g") {
|
|
weight = 1.0
|
|
test("bad") {
|
|
bogus = "x"
|
|
}
|
|
}
|
|
`
|
|
parseExpectError(t, src, `"bogus"`)
|
|
}
|
|
|
|
func TestParseGroupScoringPartial(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
group("g") {
|
|
weight = 1.0
|
|
scoring = partial
|
|
test("t") { stdout = "" }
|
|
}
|
|
`
|
|
f := parseOrFatal(t, src)
|
|
if f.Groups[0].Scoring != ScoringPartial {
|
|
t.Errorf("Scoring = %v, want partial", f.Groups[0].Scoring)
|
|
}
|
|
}
|
|
|
|
func TestParseGroupScoringAllOrNone(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
group("g") {
|
|
weight = 1.0
|
|
scoring = all_or_none
|
|
test("t") { stdout = "" }
|
|
}
|
|
`
|
|
f := parseOrFatal(t, src)
|
|
if f.Groups[0].Scoring != ScoringAllOrNone {
|
|
t.Errorf("Scoring = %v, want all_or_none", f.Groups[0].Scoring)
|
|
}
|
|
}
|
|
|
|
func TestParseGroupScoringUnknown(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
group("g") {
|
|
weight = 1.0
|
|
scoring = magic
|
|
test("t") { stdout = "" }
|
|
}
|
|
`
|
|
parseExpectError(t, src, "unknown scoring mode")
|
|
}
|
|
|
|
func TestParseGroupEnvAndWrapper(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
group("g") {
|
|
weight = 1.0
|
|
env("LANG") = "C"
|
|
env("DEBUG") = "1"
|
|
wrapper = "strace"
|
|
test("t") { stdout = "" }
|
|
}
|
|
`
|
|
f := parseOrFatal(t, src)
|
|
g := f.Groups[0]
|
|
if g.Env["LANG"] != "C" || g.Env["DEBUG"] != "1" {
|
|
t.Errorf("group Env = %v", g.Env)
|
|
}
|
|
if g.Wrapper != "strace" {
|
|
t.Errorf("group Wrapper = %q", g.Wrapper)
|
|
}
|
|
}
|
|
|
|
func TestParseGroupMemoryLimit(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
group("g") {
|
|
weight = 1.0
|
|
memory_limit = 128MB
|
|
test("t") { stdout = "" }
|
|
}
|
|
`
|
|
f := parseOrFatal(t, src)
|
|
if f.Groups[0].MemoryLimit != 128*1024*1024 {
|
|
t.Errorf("group MemoryLimit = %d", f.Groups[0].MemoryLimit)
|
|
}
|
|
}
|
|
|
|
func TestParseGroupUnknownKeyword(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
group("g") {
|
|
weight = 1.0
|
|
foobar = 1
|
|
test("t") { stdout = "" }
|
|
}
|
|
`
|
|
parseExpectError(t, src, `"foobar"`)
|
|
}
|
|
|
|
func TestParseGroupMissingWeight(t *testing.T) {
|
|
src := `
|
|
build "go build ."
|
|
group("g") {
|
|
test("t") { stdout = "" }
|
|
}
|
|
`
|
|
_, warns, err := Parse(src)
|
|
if err != nil && !strings.Contains(err.Error(), "weight") {
|
|
return
|
|
}
|
|
if err == nil && len(warns) == 0 {
|
|
t.Error("expected error or warning about missing weight")
|
|
}
|
|
}
|