ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
detections / detections (push) Waiting to run
docs / links (push) Waiting to run
web / web (push) Waiting to run
80 lines
3.2 KiB
Go
80 lines
3.2 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// task_metadata.go 의 작업 메타데이터 수정 API 에러 응답을 한국어로 유지하는 회귀 방어
|
|
// 테스트다. 한국어 판정은 F3a 가 만든 assertChineseError(한글 포함·중국어 한자 0)를 재사용한다.
|
|
|
|
// TestTaskMetadataErrorConstantsLocalized 는 응답 상수 4종이 전부 한국어임을 단언한다.
|
|
// 어느 하나라도 중국어로 되돌리면 이 테스트가 실패한다.
|
|
func TestTaskMetadataErrorConstantsLocalized(t *testing.T) {
|
|
cases := map[string]string{
|
|
"errTaskMetaRequestTooLarge": errTaskMetaRequestTooLarge,
|
|
"errTaskMetaNoFields": errTaskMetaNoFields,
|
|
"errTaskMetaNameEmpty": errTaskMetaNameEmpty,
|
|
"errTaskMetaNameTooLongFmt": fmt.Sprintf(errTaskMetaNameTooLongFmt, maxTaskNameRunes),
|
|
}
|
|
for label, msg := range cases {
|
|
assertChineseError(t, label, msg)
|
|
}
|
|
}
|
|
|
|
// TestUpdateTaskMetadataResponsesLocalized 는 입력 검증 경로 4종을 실제 HTTP 응답 본문까지
|
|
// 검사한다. updateTaskMetadata 의 이 4경로(본문 초과·필드 누락·이름 공백·이름 길이 초과)는
|
|
// s.m.Task(맵 조회)와 요청 본문만 보고 s.m.UpdateTaskMetadata(DB)를 거치기 전에 반환하므로,
|
|
// tasks 맵에 작업 하나만 넣으면 DB 없이 끝까지 돈다. 상수가 응답에 실제로 실리는 연결까지 확인한다.
|
|
func TestUpdateTaskMetadataResponsesLocalized(t *testing.T) {
|
|
s := &Server{m: &Manager{tasks: map[string]*Task{"t1": {ID: "t1"}}}}
|
|
|
|
call := func(body string) *httptest.ResponseRecorder {
|
|
req := httptest.NewRequest(http.MethodPatch, "/api/tasks/t1/metadata", strings.NewReader(body))
|
|
req.SetPathValue("id", "t1")
|
|
rec := httptest.NewRecorder()
|
|
s.updateTaskMetadata(rec, req)
|
|
return rec
|
|
}
|
|
errBody := func(t *testing.T, rec *httptest.ResponseRecorder) string {
|
|
t.Helper()
|
|
var resp struct {
|
|
Error string `json:"error"`
|
|
}
|
|
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
|
t.Fatalf("응답 JSON 파싱 실패: %v (본문 %q)", err, rec.Body.String())
|
|
}
|
|
return resp.Error
|
|
}
|
|
|
|
cases := []struct {
|
|
name string
|
|
body string
|
|
code int
|
|
want string
|
|
}{
|
|
// 16KB 한도를 넘기는 유효 JSON 본문. MaxBytesReader 가 읽기 도중 한도 초과를 돌려준다.
|
|
{"request_too_large", `{"name":"` + strings.Repeat("a", maxTaskMetadataRequestSize+1024) + `"}`, http.StatusRequestEntityTooLarge, errTaskMetaRequestTooLarge},
|
|
// name·pinned 를 둘 다 빼면 수정할 필드가 없다.
|
|
{"no_fields", `{}`, http.StatusBadRequest, errTaskMetaNoFields},
|
|
{"name_empty", `{"name":" "}`, http.StatusBadRequest, errTaskMetaNameEmpty},
|
|
{"name_too_long", `{"name":"` + strings.Repeat("가", maxTaskNameRunes+1) + `"}`, http.StatusBadRequest, fmt.Sprintf(errTaskMetaNameTooLongFmt, maxTaskNameRunes)},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
rec := call(c.body)
|
|
if rec.Code != c.code {
|
|
t.Fatalf("상태 코드 = %d, 기대 = %d (본문 %q)", rec.Code, c.code, rec.Body.String())
|
|
}
|
|
if got := errBody(t, rec); got != c.want {
|
|
t.Fatalf("응답 문구 = %q, 기대 = %q", got, c.want)
|
|
}
|
|
assertChineseError(t, c.name, errBody(t, rec))
|
|
})
|
|
}
|
|
}
|