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%.
194 lines
4.1 KiB
Go
194 lines
4.1 KiB
Go
package dsl
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestParsePatternDirsMode(t *testing.T) {
|
|
src := `
|
|
build "make"
|
|
group("g") {
|
|
weight = 1.0
|
|
pattern {
|
|
dirs = "tests/*"
|
|
input = "in.txt"
|
|
output = "out.txt"
|
|
args = "--case" "{name}"
|
|
}
|
|
}
|
|
`
|
|
f, _, err := Parse(src)
|
|
if err != nil {
|
|
t.Fatalf("parse: %v", err)
|
|
}
|
|
pat := f.Groups[0].Pattern
|
|
if pat == nil {
|
|
t.Fatal("no pattern")
|
|
}
|
|
if pat.DirsGlob != "tests/*" {
|
|
t.Errorf("DirsGlob = %q", pat.DirsGlob)
|
|
}
|
|
if pat.InputFile != "in.txt" || pat.OutputFile != "out.txt" {
|
|
t.Errorf("InputFile/OutputFile = %q/%q", pat.InputFile, pat.OutputFile)
|
|
}
|
|
if len(pat.Args) != 2 || pat.Args[0] != "--case" || pat.Args[1] != "{name}" {
|
|
t.Errorf("Args = %v", pat.Args)
|
|
}
|
|
}
|
|
|
|
func TestParsePatternUnknownField(t *testing.T) {
|
|
src := `
|
|
build "make"
|
|
group("g") {
|
|
weight = 1.0
|
|
pattern { bogus = "x" }
|
|
}
|
|
`
|
|
_, _, err := Parse(src)
|
|
if err == nil || !strings.Contains(err.Error(), "unknown pattern field") {
|
|
t.Errorf("want unknown pattern field error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestParsePatternNonIdent(t *testing.T) {
|
|
src := `
|
|
build "make"
|
|
group("g") {
|
|
weight = 1.0
|
|
pattern { "x" = "y" }
|
|
}
|
|
`
|
|
_, _, err := Parse(src)
|
|
if err == nil {
|
|
t.Error("expected error on non-ident in pattern")
|
|
}
|
|
}
|
|
|
|
func TestParseNormalizeCRLFAndTrimWS(t *testing.T) {
|
|
src := `
|
|
build "make"
|
|
normalize_crlf = true
|
|
trim_trailing_ws = false
|
|
group("g") { weight = 1.0 test("t") { stdout = "" } }
|
|
`
|
|
f, _, err := Parse(src)
|
|
if err != nil {
|
|
t.Fatalf("parse: %v", err)
|
|
}
|
|
if !f.NormalizeCRLF {
|
|
t.Error("NormalizeCRLF should be true")
|
|
}
|
|
if f.TrimTrailingWS {
|
|
t.Error("TrimTrailingWS should be false")
|
|
}
|
|
}
|
|
|
|
func TestParseBinaryAndSources(t *testing.T) {
|
|
src := `
|
|
build "make"
|
|
binary = "sol"
|
|
sources = "main.c"
|
|
group("g") { weight = 1.0 test("t") { stdout = "" } }
|
|
`
|
|
f, _, err := Parse(src)
|
|
if err != nil {
|
|
t.Fatalf("parse: %v", err)
|
|
}
|
|
if f.Binary != "sol" {
|
|
t.Errorf("Binary = %q", f.Binary)
|
|
}
|
|
if f.Sources != "main.c" {
|
|
t.Errorf("Sources = %q", f.Sources)
|
|
}
|
|
}
|
|
|
|
func TestParseMemoryLimitBareInt(t *testing.T) {
|
|
src := `
|
|
build "make"
|
|
memory_limit = 1024
|
|
group("g") { weight = 1.0 test("t") { stdout = "" } }
|
|
`
|
|
f, _, err := Parse(src)
|
|
if err != nil {
|
|
t.Fatalf("parse: %v", err)
|
|
}
|
|
if f.MemoryLimit != 1024 {
|
|
t.Errorf("MemoryLimit = %d, want 1024", f.MemoryLimit)
|
|
}
|
|
}
|
|
|
|
func TestParseBoolInvalidIdent(t *testing.T) {
|
|
_, _, err := Parse("build \"make\"\nnormalize_crlf = maybe\n")
|
|
if err == nil || !strings.Contains(err.Error(), "true/false") {
|
|
t.Errorf("want true/false error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestParseBoolNonIdent(t *testing.T) {
|
|
_, _, err := Parse("build \"make\"\nnormalize_crlf = \"true\"\n")
|
|
if err == nil || !strings.Contains(err.Error(), "true/false") {
|
|
t.Errorf("want true/false error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestParseTopLevelNonIdent(t *testing.T) {
|
|
_, _, err := Parse(`"stray"`)
|
|
if err == nil || !strings.Contains(err.Error(), "unexpected token") {
|
|
t.Errorf("want unexpected token error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestParseMatcherOrAssignNoMatcher(t *testing.T) {
|
|
src := `
|
|
build "make"
|
|
group("g") {
|
|
weight = 1.0
|
|
test("t") { stdout 42 }
|
|
}
|
|
`
|
|
_, _, err := Parse(src)
|
|
if err == nil || !strings.Contains(err.Error(), "expected matcher") {
|
|
t.Errorf("want matcher error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestParseStringListEmpty(t *testing.T) {
|
|
src := `
|
|
build "make"
|
|
group("g") {
|
|
weight = 1.0
|
|
test("t") { args = stdout = "" }
|
|
}
|
|
`
|
|
_, _, err := Parse(src)
|
|
if err == nil {
|
|
t.Error("expected error on empty string list")
|
|
}
|
|
}
|
|
|
|
func TestParseFileMissing(t *testing.T) {
|
|
_, _, err := ParseFile("/nonexistent/judge-test-does-not-exist.jdg")
|
|
if err == nil {
|
|
t.Error("expected error on missing file")
|
|
}
|
|
}
|
|
|
|
func TestValidateBuildsMixedLegacyAndStructured(t *testing.T) {
|
|
src := `
|
|
build "legacy shell"
|
|
build_defaults {
|
|
language = "c"
|
|
standard = "c11"
|
|
sources = "*.c"
|
|
output = "sol"
|
|
warnings = strict
|
|
}
|
|
group("g") { weight = 1.0 test("t") { stdout = "" } }
|
|
`
|
|
_, _, err := Parse(src)
|
|
if err == nil || !strings.Contains(err.Error(), "cannot mix legacy") {
|
|
t.Errorf("want mix-legacy error, got %v", err)
|
|
}
|
|
}
|