diff options
| -rw-r--r-- | backend/game/hub.go | 11 | ||||
| -rw-r--r-- | backend/game/hub_test.go | 53 |
2 files changed, 60 insertions, 4 deletions
diff --git a/backend/game/hub.go b/backend/game/hub.go index 8c0a574..3caa6d4 100644 --- a/backend/game/hub.go +++ b/backend/game/hub.go @@ -71,8 +71,8 @@ func (hub *Hub) EnqueueTestTasks(ctx context.Context, submissionID, gameID, user submissionID, int(row.TestcaseID), language, - code, - row.Stdin, + normalizeCRLF(code), + normalizeCRLF(row.Stdin), row.Stdout, ) if err != nil { @@ -175,9 +175,12 @@ func (hub *Hub) processTaskResultRunTestcase( return nil } +func normalizeCRLF(s string) string { + return strings.ReplaceAll(strings.ReplaceAll(s, "\r\n", "\n"), "\r", "\n") +} + func normalizeTestcaseResultOutput(s string) string { - re := regexp.MustCompile(`\r\n|\r`) - return re.ReplaceAllString(strings.TrimSpace(s), "\n") + return normalizeCRLF(strings.TrimSpace(s)) } func isTestcaseResultCorrect(expectedStdout, actualStdout string) bool { diff --git a/backend/game/hub_test.go b/backend/game/hub_test.go index 5aa440b..1d493b9 100644 --- a/backend/game/hub_test.go +++ b/backend/game/hub_test.go @@ -249,6 +249,59 @@ func TestNormalizeTestcaseResultOutput(t *testing.T) { } } +func TestNormalizeCRLF(t *testing.T) { + tests := []struct { + name string + input string + want string + }{ + {"CRLF to LF", "hello\r\nworld", "hello\nworld"}, + {"CR to LF", "hello\rworld", "hello\nworld"}, + {"LF unchanged", "hello\nworld", "hello\nworld"}, + {"lone CRLF", "\r\n", "\n"}, + {"empty string", "", ""}, + {"multiple CRLF", "a\r\nb\r\nc", "a\nb\nc"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := normalizeCRLF(tt.input) + if got != tt.want { + t.Errorf("normalizeCRLF(%q) = %q, want %q", tt.input, got, tt.want) + } + }) + } +} + +func TestEnqueueTestTasks_NormalizesCRLF(t *testing.T) { + testcases := []db.Testcase{ + {TestcaseID: 1, ProblemID: 10, Stdin: "input\r\n", Stdout: "output"}, + } + + tq := &mockTaskQueue{} + mq := &mockQuerier{ + listTestcasesByGameIDFunc: func(_ context.Context, _ int32) ([]db.Testcase, error) { + return testcases, nil + }, + } + + hub := &Hub{q: mq, taskQueue: tq, ctx: context.Background()} + + err := hub.EnqueueTestTasks(context.Background(), 100, 1, 42, "php", "<?php\r\necho 1;") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if len(tq.enqueued) != 1 { + t.Fatalf("expected 1 enqueued task, got %d", len(tq.enqueued)) + } + if tq.enqueued[0].Stdin != "input\n" { + t.Errorf("expected stdin CRLF normalized, got %q", tq.enqueued[0].Stdin) + } + if tq.enqueued[0].Code != "<?php\necho 1;" { + t.Errorf("expected code CRLF normalized, got %q", tq.enqueued[0].Code) + } +} + func TestCalcCodeSize_PHP(t *testing.T) { hub := &Hub{} tests := []struct { |
