package runner import ( "os" "path/filepath" "testing" "github.com/Mond1c/judge/dsl" ) // Under a wrapper, only args that name a staged file become absolute; numeric // and flag args must be passed through verbatim (regression: a numeric arg "1" // was being turned into "/1", breaking programs that take non-path // arguments). func TestAbsoluteArgsOnlyRewritesStagedFiles(t *testing.T) { dir := t.TempDir() if err := os.WriteFile(filepath.Join(dir, "01.in"), []byte("x"), 0644); err != nil { t.Fatal(err) } got := absoluteArgs(dir, []string{"$.txt", "1", "1", "3", "01.in", "--flag"}) want := []string{"$.txt", "1", "1", "3", filepath.Join(dir, "01.in"), "--flag"} for i := range want { if got[i] != want[i] { t.Errorf("arg[%d] = %q, want %q", i, got[i], want[i]) } } } // A staged/expected value loaded from disk on Windows can carry CRLF. With // normalize_crlf the runner must normalize the EXPECTED side too, otherwise it // can never match the LF-normalized actual output. func TestNormalizeExpectationsCRLF(t *testing.T) { r := &Runner{file: &dsl.File{NormalizeCRLF: true}} test := &dsl.Test{ Stdout: dsl.ExactMatcher{Value: "1\r\n2\r\n"}, Stderr: dsl.NoMatcher{}, OutFiles: map[string]string{"out.txt": "a\r\nb\r\n"}, } r.normalizeExpectations(test) m, ok := test.Stdout.(dsl.ExactMatcher) if !ok { t.Fatalf("stdout matcher type changed: %T", test.Stdout) } if m.Value != "1\n2\n" { t.Errorf("expected stdout normalized to %q, got %q", "1\n2\n", m.Value) } if got := test.OutFiles["out.txt"]; got != "a\nb\n" { t.Errorf("expected outfile normalized to %q, got %q", "a\nb\n", got) } // And the normalized expected must match normalized actual end-to-end. if fails := test.Stdout.Match("stdout", normalizeOutput("1\r\n2\r\n", r.file)); len(fails) != 0 { t.Errorf("normalized expected should match normalized actual, got %v", fails) } } func TestNormalizeExpectationsTrimTrailingWS(t *testing.T) { r := &Runner{file: &dsl.File{TrimTrailingWS: true}} test := &dsl.Test{ Stdout: dsl.AnyOrderMatcher{Lines: []string{"foo ", "bar\t"}}, Stderr: dsl.NoMatcher{}, } r.normalizeExpectations(test) m := test.Stdout.(dsl.AnyOrderMatcher) if m.Lines[0] != "foo" || m.Lines[1] != "bar" { t.Errorf("anyOrder lines not trimmed: %q", m.Lines) } } // Regex matchers must never be rewritten: a literal \r in the pattern is // meaningful and normalization would corrupt it. func TestNormalizeExpectationsLeavesRegexAlone(t *testing.T) { r := &Runner{file: &dsl.File{NormalizeCRLF: true}} test := &dsl.Test{ Stdout: dsl.RegexMatcher{Pattern: "a\r\nb"}, Stderr: dsl.NoMatcher{}, } r.normalizeExpectations(test) if m := test.Stdout.(dsl.RegexMatcher); m.Pattern != "a\r\nb" { t.Errorf("regex pattern was modified: %q", m.Pattern) } } func TestNormalizeExpectationsNoopWhenDisabled(t *testing.T) { r := &Runner{file: &dsl.File{}} want := "1\r\n2\r\n" test := &dsl.Test{Stdout: dsl.ExactMatcher{Value: want}, Stderr: dsl.NoMatcher{}} r.normalizeExpectations(test) if m := test.Stdout.(dsl.ExactMatcher); m.Value != want { t.Errorf("value changed with normalization disabled: %q", m.Value) } }