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
Reviewed-on: #1
241 lines
5.9 KiB
Go
241 lines
5.9 KiB
Go
package runner
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/Mond1c/judge/dsl"
|
|
)
|
|
|
|
func writeFile(t *testing.T, dir, name, content 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)
|
|
}
|
|
}
|
|
|
|
func TestExpandGlobPairedStdioMode(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeFile(t, dir, "tests/01.in", "1 2 3\n")
|
|
writeFile(t, dir, "tests/01.ans", "6\n")
|
|
writeFile(t, dir, "tests/02.in", "10 20\n")
|
|
writeFile(t, dir, "tests/02.ans", "30\n")
|
|
|
|
cwd, _ := os.Getwd()
|
|
defer os.Chdir(cwd)
|
|
os.Chdir(dir)
|
|
|
|
tests, err := expandPattern(&dsl.Pattern{
|
|
InputGlob: "tests/*.in",
|
|
OutputGlob: "tests/*.ans",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(tests) != 2 {
|
|
t.Fatalf("expected 2 tests, got %d", len(tests))
|
|
}
|
|
for _, tc := range tests {
|
|
if tc.Stdin == nil {
|
|
t.Errorf("%s: stdin should be set in stdio mode", tc.Name)
|
|
}
|
|
if len(tc.Args) != 0 {
|
|
t.Errorf("%s: args should be empty without template", tc.Name)
|
|
}
|
|
if _, ok := tc.Stdout.(dsl.ExactMatcher); !ok {
|
|
t.Errorf("%s: stdout should be ExactMatcher, got %T", tc.Name, tc.Stdout)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestExpandGlobWithSharedOutput(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeFile(t, dir, "tests/01.in", "1\n")
|
|
writeFile(t, dir, "tests/02.in", "2\n")
|
|
writeFile(t, dir, "tests/03.in", "3\n")
|
|
writeFile(t, dir, "expected.ans", "ok\n")
|
|
|
|
cwd, _ := os.Getwd()
|
|
defer os.Chdir(cwd)
|
|
os.Chdir(dir)
|
|
|
|
tests, err := expandPattern(&dsl.Pattern{
|
|
InputGlob: "tests/*.in",
|
|
OutputGlob: "expected.ans",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("expand: %v", err)
|
|
}
|
|
if len(tests) != 3 {
|
|
t.Fatalf("expected 3 tests, got %d", len(tests))
|
|
}
|
|
for _, tc := range tests {
|
|
m, ok := tc.Stdout.(dsl.ExactMatcher)
|
|
if !ok {
|
|
t.Fatalf("%s: stdout should be ExactMatcher, got %T", tc.Name, tc.Stdout)
|
|
}
|
|
if m.Value != "ok\n" {
|
|
t.Errorf("%s: shared output = %q, want %q", tc.Name, m.Value, "ok\n")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestExpandGlobFileModeInputOnly(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeFile(t, dir, "tests/01.in", "hello\n")
|
|
writeFile(t, dir, "tests/01.ans", "HELLO\n")
|
|
|
|
cwd, _ := os.Getwd()
|
|
defer os.Chdir(cwd)
|
|
os.Chdir(dir)
|
|
|
|
tests, err := expandPattern(&dsl.Pattern{
|
|
InputGlob: "tests/*.in",
|
|
OutputGlob: "tests/*.ans",
|
|
Args: []string{"{input_path}"},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(tests) != 1 {
|
|
t.Fatalf("expected 1 test, got %d", len(tests))
|
|
}
|
|
tc := tests[0]
|
|
if tc.Stdin != nil {
|
|
t.Errorf("stdin should be nil in file mode for input")
|
|
}
|
|
if content, ok := tc.InFiles["01.in"]; !ok || content != "hello\n" {
|
|
t.Errorf("InFiles[01.in] = %q, want %q", content, "hello\n")
|
|
}
|
|
if _, ok := tc.Stdout.(dsl.ExactMatcher); !ok {
|
|
t.Errorf("stdout should still be ExactMatcher when output not in file mode, got %T", tc.Stdout)
|
|
}
|
|
if len(tc.Args) != 1 || tc.Args[0] != "01.in" {
|
|
t.Errorf("args = %v, want [01.in]", tc.Args)
|
|
}
|
|
}
|
|
|
|
func TestExpandGlobFileModeBoth(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeFile(t, dir, "tests/01.in", "1 2 3\n")
|
|
writeFile(t, dir, "tests/01.ans", "6\n")
|
|
|
|
cwd, _ := os.Getwd()
|
|
defer os.Chdir(cwd)
|
|
os.Chdir(dir)
|
|
|
|
tests, err := expandPattern(&dsl.Pattern{
|
|
InputGlob: "tests/*.in",
|
|
OutputGlob: "tests/*.ans",
|
|
Args: []string{"{input_path}", "{output_path}"},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tc := tests[0]
|
|
if tc.Stdin != nil {
|
|
t.Error("stdin should be nil")
|
|
}
|
|
if _, ok := tc.Stdout.(dsl.NoMatcher); !ok {
|
|
t.Errorf("stdout should be NoMatcher when output is file, got %T", tc.Stdout)
|
|
}
|
|
if content := tc.OutFiles["01.ans"]; content != "6\n" {
|
|
t.Errorf("OutFiles[01.ans] = %q, want %q", content, "6\n")
|
|
}
|
|
if len(tc.Args) != 2 || tc.Args[0] != "01.in" || tc.Args[1] != "01.ans" {
|
|
t.Errorf("args = %v, want [01.in 01.ans]", tc.Args)
|
|
}
|
|
}
|
|
|
|
func TestExpandGlobArgsWithStaticAndPlaceholders(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeFile(t, dir, "tests/01.in", "x\n")
|
|
writeFile(t, dir, "tests/01.ans", "x\n")
|
|
|
|
cwd, _ := os.Getwd()
|
|
defer os.Chdir(cwd)
|
|
os.Chdir(dir)
|
|
|
|
tests, err := expandPattern(&dsl.Pattern{
|
|
InputGlob: "tests/*.in",
|
|
OutputGlob: "tests/*.ans",
|
|
Args: []string{"--mode", "strict", "{input_path}"},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(tests[0].Args) != 3 || tests[0].Args[0] != "--mode" || tests[0].Args[2] != "01.in" {
|
|
t.Errorf("args = %v", tests[0].Args)
|
|
}
|
|
}
|
|
|
|
func TestExpandDirModeWithArgs(t *testing.T) {
|
|
dir := t.TempDir()
|
|
writeFile(t, dir, "cases/a/input.txt", "one\n")
|
|
writeFile(t, dir, "cases/a/expected.txt", "ONE\n")
|
|
writeFile(t, dir, "cases/b/input.txt", "two\n")
|
|
writeFile(t, dir, "cases/b/expected.txt", "TWO\n")
|
|
|
|
cwd, _ := os.Getwd()
|
|
defer os.Chdir(cwd)
|
|
os.Chdir(dir)
|
|
|
|
tests, err := expandPattern(&dsl.Pattern{
|
|
DirsGlob: "cases/*",
|
|
InputFile: "input.txt",
|
|
OutputFile: "expected.txt",
|
|
Args: []string{"{input_path}", "{output_path}"},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(tests) != 2 {
|
|
t.Fatalf("expected 2 tests, got %d", len(tests))
|
|
}
|
|
for _, tc := range tests {
|
|
if _, ok := tc.InFiles["input.txt"]; !ok {
|
|
t.Errorf("%s: missing InFiles[input.txt]", tc.Name)
|
|
}
|
|
if _, ok := tc.OutFiles["expected.txt"]; !ok {
|
|
t.Errorf("%s: missing OutFiles[expected.txt]", tc.Name)
|
|
}
|
|
if len(tc.Args) != 2 {
|
|
t.Errorf("%s: args = %v", tc.Name, tc.Args)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestExpandPatternRejectsAllLiterals(t *testing.T) {
|
|
_, err := expandPattern(&dsl.Pattern{
|
|
InputGlob: "tests/a.in",
|
|
OutputGlob: "tests/a.ans",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("expected error when no glob fields")
|
|
}
|
|
if !strings.Contains(err.Error(), "glob") {
|
|
t.Errorf("error %q does not mention glob", err.Error())
|
|
}
|
|
}
|
|
|
|
func TestExpandPatternNoMatches(t *testing.T) {
|
|
dir := t.TempDir()
|
|
cwd, _ := os.Getwd()
|
|
defer os.Chdir(cwd)
|
|
os.Chdir(dir)
|
|
|
|
_, err := expandPattern(&dsl.Pattern{
|
|
InputGlob: "missing/*.in",
|
|
OutputGlob: "missing/*.ans",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("expected error on zero matches")
|
|
}
|
|
}
|