test: expand dsl/runner coverage and add go-test CI workflow
All checks were successful
go-test / go test (push) Successful in 56s
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%.
This commit is contained in:
220
dsl/merge_test.go
Normal file
220
dsl/merge_test.go
Normal file
@@ -0,0 +1,220 @@
|
||||
package dsl
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestMergeLegacyBuildFields(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeTempJdg(t, dir, "common.jdg", `
|
||||
build "make"
|
||||
build_linux "make linux"
|
||||
build_windows "make windows"
|
||||
build_darwin "make darwin"
|
||||
timeout 7s
|
||||
memory_limit = 256MB
|
||||
`)
|
||||
mainPath := writeTempJdg(t, dir, "main.jdg", `
|
||||
include "common.jdg"
|
||||
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
|
||||
`)
|
||||
f, _, err := ParseFile(mainPath)
|
||||
if err != nil {
|
||||
t.Fatalf("parse: %v", err)
|
||||
}
|
||||
if f.Build != "make" || f.BuildLinux != "make linux" ||
|
||||
f.BuildWindows != "make windows" || f.BuildDarwin != "make darwin" {
|
||||
t.Errorf("legacy build fields not merged: %+v", f)
|
||||
}
|
||||
if f.Timeout != 7*time.Second {
|
||||
t.Errorf("Timeout = %v, want 7s", f.Timeout)
|
||||
}
|
||||
if f.MemoryLimit != 256*1024*1024 {
|
||||
t.Errorf("MemoryLimit = %d", f.MemoryLimit)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeDuplicateToolchainFromInclude(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeTempJdg(t, dir, "common.jdg", `
|
||||
toolchains {
|
||||
gcc { platforms = "linux" }
|
||||
}
|
||||
`)
|
||||
mainPath := writeTempJdg(t, dir, "main.jdg", `
|
||||
toolchains {
|
||||
gcc { platforms = "linux" }
|
||||
}
|
||||
include "common.jdg"
|
||||
build "make"
|
||||
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
|
||||
`)
|
||||
_, _, err := ParseFile(mainPath)
|
||||
if err == nil {
|
||||
t.Fatal("expected duplicate toolchain error from merge")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "duplicate toolchain") {
|
||||
t.Errorf("error %q does not mention duplicate toolchain", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeDuplicateBuildErrors(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeTempJdg(t, dir, "common.jdg", `
|
||||
build "release" { profile = release }
|
||||
`)
|
||||
mainPath := writeTempJdg(t, dir, "main.jdg", `
|
||||
build_defaults {
|
||||
language = "c"
|
||||
standard = "c11"
|
||||
sources = "*.c"
|
||||
output = "solution"
|
||||
warnings = strict
|
||||
}
|
||||
build "release" { profile = debug }
|
||||
include "common.jdg"
|
||||
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
|
||||
`)
|
||||
_, _, err := ParseFile(mainPath)
|
||||
if err == nil {
|
||||
t.Fatal("expected duplicate build error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "duplicate build") {
|
||||
t.Errorf("error %q does not mention duplicate build", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeDuplicateGroupErrors(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeTempJdg(t, dir, "common.jdg", `
|
||||
group("shared") { weight = 0.5 test("t") { stdout = "ok\n" } }
|
||||
`)
|
||||
mainPath := writeTempJdg(t, dir, "main.jdg", `
|
||||
build "make"
|
||||
group("shared") { weight = 0.5 test("t2") { stdout = "ok\n" } }
|
||||
include "common.jdg"
|
||||
`)
|
||||
_, _, err := ParseFile(mainPath)
|
||||
if err == nil {
|
||||
t.Fatal("expected duplicate group error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "duplicate group") {
|
||||
t.Errorf("error %q does not mention duplicate group", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeGroupsAppended(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeTempJdg(t, dir, "common.jdg", `
|
||||
build "make"
|
||||
group("included") { weight = 0.5 test("t") { stdout = "ok\n" } }
|
||||
`)
|
||||
mainPath := writeTempJdg(t, dir, "main.jdg", `
|
||||
include "common.jdg"
|
||||
group("local") { weight = 0.5 test("t") { stdout = "ok\n" } }
|
||||
`)
|
||||
f, _, err := ParseFile(mainPath)
|
||||
if err != nil {
|
||||
t.Fatalf("parse: %v", err)
|
||||
}
|
||||
if len(f.Groups) != 2 {
|
||||
t.Fatalf("want 2 groups, got %d", len(f.Groups))
|
||||
}
|
||||
names := []string{f.Groups[0].Name, f.Groups[1].Name}
|
||||
if !(contains(names, "included") && contains(names, "local")) {
|
||||
t.Errorf("groups = %v", names)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeBuildsAppended(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeTempJdg(t, dir, "common.jdg", `
|
||||
build_defaults {
|
||||
language = "c"
|
||||
standard = "c11"
|
||||
sources = "*.c"
|
||||
output = "solution"
|
||||
warnings = strict
|
||||
}
|
||||
build "release" { profile = release }
|
||||
`)
|
||||
mainPath := writeTempJdg(t, dir, "main.jdg", `
|
||||
include "common.jdg"
|
||||
build "debug" { profile = debug }
|
||||
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
|
||||
`)
|
||||
f, _, err := ParseFile(mainPath)
|
||||
if err != nil {
|
||||
t.Fatalf("parse: %v", err)
|
||||
}
|
||||
if len(f.Builds) != 2 {
|
||||
t.Fatalf("want 2 builds, got %d", len(f.Builds))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeBinarySourcesAndFlags(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeTempJdg(t, dir, "common.jdg", `
|
||||
build "make"
|
||||
binary = "solution"
|
||||
sources = "*.c"
|
||||
normalize_crlf = true
|
||||
trim_trailing_ws = true
|
||||
`)
|
||||
mainPath := writeTempJdg(t, dir, "main.jdg", `
|
||||
include "common.jdg"
|
||||
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
|
||||
`)
|
||||
f, _, err := ParseFile(mainPath)
|
||||
if err != nil {
|
||||
t.Fatalf("parse: %v", err)
|
||||
}
|
||||
if f.Binary != "solution" {
|
||||
t.Errorf("Binary = %q, want solution", f.Binary)
|
||||
}
|
||||
if f.Sources != "*.c" {
|
||||
t.Errorf("Sources = %q, want *.c", f.Sources)
|
||||
}
|
||||
if !f.NormalizeCRLF {
|
||||
t.Error("NormalizeCRLF not merged")
|
||||
}
|
||||
if !f.TrimTrailingWS {
|
||||
t.Error("TrimTrailingWS not merged")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeLocalOverridesTimeout(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeTempJdg(t, dir, "common.jdg", `
|
||||
build "make"
|
||||
timeout 10s
|
||||
memory_limit = 128MB
|
||||
`)
|
||||
mainPath := writeTempJdg(t, dir, "main.jdg", `
|
||||
include "common.jdg"
|
||||
timeout 3s
|
||||
memory_limit = 64MB
|
||||
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
|
||||
`)
|
||||
f, _, err := ParseFile(mainPath)
|
||||
if err != nil {
|
||||
t.Fatalf("parse: %v", err)
|
||||
}
|
||||
if f.Timeout != 3*time.Second {
|
||||
t.Errorf("Timeout = %v, want local 3s", f.Timeout)
|
||||
}
|
||||
if f.MemoryLimit != 64*1024*1024 {
|
||||
t.Errorf("MemoryLimit = %d, want local 64MB", f.MemoryLimit)
|
||||
}
|
||||
}
|
||||
|
||||
func contains(xs []string, s string) bool {
|
||||
for _, x := range xs {
|
||||
if x == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user