Files
judge/dsl/include_test.go
Mikhail Kornilovich 7ec3a43c7a
All checks were successful
build-dsl-smoke / Build judge (push) Successful in 12s
build-dsl-smoke / debug / clang / linux (push) Successful in 6s
build-dsl-smoke / debug / gcc / linux (push) Successful in 8s
build-dsl-smoke / release / clang / linux (push) Successful in 8s
build-dsl-smoke / release / gcc / linux (push) Successful in 6s
build-dsl-smoke / sanitized / clang / linux (push) Successful in 8s
build-dsl-smoke / sanitized / gcc / linux (push) Successful in 7s
build-dsl-smoke / debug / clang / windows (push) Successful in 13s
build-dsl-smoke / debug-valgrind / gcc / linux (push) Successful in 14s
build-dsl-smoke / release / clang / windows (push) Successful in 16s
build-dsl-smoke / debug / msvc / windows (push) Successful in 18s
build-dsl-smoke / release / msvc / windows (push) Successful in 17s
build-dsl-smoke / SUMMARY (push) Successful in 4s
Release / Build & publish (push) Successful in 48s
1. New build system
Reviewed-on: #1
2026-04-12 07:59:38 +00:00

211 lines
4.5 KiB
Go

package dsl
import (
"os"
"path/filepath"
"strings"
"testing"
)
func writeTempJdg(t *testing.T, dir, name, content string) string {
t.Helper()
path := filepath.Join(dir, name)
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
t.Fatal(err)
}
return path
}
func TestIncludeBasicMerge(t *testing.T) {
dir := t.TempDir()
writeTempJdg(t, dir, "common.jdg", `
toolchains {
gcc { platforms = "linux" }
}
build_defaults {
language = "c"
standard = "c11"
sources = "*.c"
output = "solution"
warnings = strict
}
`)
mainPath := writeTempJdg(t, dir, "main.jdg", `
include "common.jdg"
build "release" { profile = release }
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.Toolchains) != 1 || f.Toolchains[0].Name != "gcc" {
t.Errorf("toolchains not merged: %+v", f.Toolchains)
}
if f.BuildDefaults == nil || f.BuildDefaults.Language != "c" {
t.Errorf("build_defaults not merged: %+v", f.BuildDefaults)
}
if len(f.Builds) != 1 || f.Builds[0].Name != "release" {
t.Errorf("local build lost: %+v", f.Builds)
}
}
func TestIncludeLocalOverridesIncluded(t *testing.T) {
dir := t.TempDir()
writeTempJdg(t, dir, "common.jdg", `
build_defaults {
language = "c"
standard = "c11"
warnings = strict
}
`)
mainPath := writeTempJdg(t, dir, "main.jdg", `
include "common.jdg"
build_defaults {
standard = "c17"
}
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
`)
f, _, err := ParseFile(mainPath)
if err != nil {
t.Fatalf("parse: %v", err)
}
if f.BuildDefaults.Standard != "c17" {
t.Errorf("local should override included standard: got %q", f.BuildDefaults.Standard)
}
if f.BuildDefaults.Language != "c" {
t.Errorf("language should survive from include: got %q", f.BuildDefaults.Language)
}
if f.BuildDefaults.Warnings != WarningsStrict {
t.Errorf("warnings should survive from include: got %v", f.BuildDefaults.Warnings)
}
}
func TestIncludeRelativePathResolution(t *testing.T) {
dir := t.TempDir()
writeTempJdg(t, dir, "shared/tools.jdg", `
toolchains {
gcc { platforms = "linux" }
}
`)
mainPath := writeTempJdg(t, dir, "suite/main.jdg", `
include "../shared/tools.jdg"
build "release" {
language = "c"
sources = "solution.c"
output = "solution"
profile = release
}
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.Toolchains) != 1 {
t.Errorf("relative include failed to resolve: %+v", f.Toolchains)
}
}
func TestIncludeDuplicateToolchainErrors(t *testing.T) {
dir := t.TempDir()
writeTempJdg(t, dir, "common.jdg", `
toolchains {
gcc { platforms = "linux" }
}
`)
mainPath := writeTempJdg(t, dir, "main.jdg", `
include "common.jdg"
toolchains {
gcc { platforms = "linux" }
}
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
`)
_, _, err := ParseFile(mainPath)
if err == nil {
t.Fatal("expected duplicate toolchain error")
}
if !strings.Contains(err.Error(), "duplicate toolchain") {
t.Errorf("error %q does not mention duplicate toolchain", err.Error())
}
}
func TestIncludeCircularDetection(t *testing.T) {
dir := t.TempDir()
aPath := writeTempJdg(t, dir, "a.jdg", `
include "b.jdg"
group("ga") { weight = 1.0 test("t") { stdout = "ok\n" } }
`)
writeTempJdg(t, dir, "b.jdg", `
include "a.jdg"
`)
_, _, err := ParseFile(aPath)
if err == nil {
t.Fatal("expected circular include error")
}
if !strings.Contains(err.Error(), "circular include") {
t.Errorf("error %q does not mention circular include", err.Error())
}
}
func TestIncludeMissingFileErrors(t *testing.T) {
dir := t.TempDir()
mainPath := writeTempJdg(t, dir, "main.jdg", `
include "nonexistent.jdg"
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
`)
_, _, err := ParseFile(mainPath)
if err == nil {
t.Fatal("expected missing include error")
}
if !strings.Contains(err.Error(), "nonexistent.jdg") {
t.Errorf("error %q does not reference the missing path", err.Error())
}
}
func TestParseRejectsIncludeWithoutFileContext(t *testing.T) {
src := `
include "common.jdg"
group("g") { weight = 1.0 test("t") { stdout = "ok\n" } }
`
_, _, err := Parse(src)
if err == nil {
t.Fatal("expected error: include without file context")
}
if !strings.Contains(err.Error(), "file context") {
t.Errorf("error %q does not mention file context", err.Error())
}
}