99 lines
3.3 KiB
Go
99 lines
3.3 KiB
Go
package server
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"chat-agent-system/internal/ctxmgr"
|
|
)
|
|
|
|
func TestPrepareChatTurn_AttachmentOnlyAndEmptyRejected(t *testing.T) {
|
|
stored, only, reject := prepareChatTurn("", []TurnAttachment{{
|
|
Filename: "F-030-PIR.pdf",
|
|
AssetID: 9,
|
|
ParseState: "pending",
|
|
}})
|
|
if reject != "" || !only {
|
|
t.Fatalf("attachment-only should pass, only=%v reject=%q", only, reject)
|
|
}
|
|
if !strings.Contains(stored, "F-030-PIR.pdf") {
|
|
t.Fatalf("stored message = %q", stored)
|
|
}
|
|
|
|
if _, _, reject = prepareChatTurn(" ", nil); reject != "message cannot be empty" {
|
|
t.Fatalf("empty turn reject = %q", reject)
|
|
}
|
|
stored, only, reject = prepareChatTurn("总结一下", []TurnAttachment{{Filename: "a.pdf"}})
|
|
if reject != "" || only || stored != "总结一下" {
|
|
t.Fatalf("text+attachment stored=%q only=%v reject=%q", stored, only, reject)
|
|
}
|
|
}
|
|
|
|
func TestTurnAttachmentHashKey_ChangesBodyHash(t *testing.T) {
|
|
a := turnAttachmentHashKey([]TurnAttachment{{Filename: "a.pdf", AssetID: 1}})
|
|
b := turnAttachmentHashKey([]TurnAttachment{{Filename: "a.pdf", AssetID: 2}})
|
|
if a == b {
|
|
t.Fatal("different assets must not share a hash key")
|
|
}
|
|
if ctxmgr.HashTurnBodyWithKey("sess", "hello", "") != ctxmgr.HashTurnBody("sess", "hello") {
|
|
t.Fatal("empty extra must match the plain body hash")
|
|
}
|
|
if ctxmgr.HashTurnBodyWithKey("sess", "hello", a) == ctxmgr.HashTurnBodyWithKey("sess", "hello", b) {
|
|
t.Fatal("attachment key must change the turn hash")
|
|
}
|
|
}
|
|
|
|
func TestChatStream_EmptyMessageWithoutAttachmentRejected(t *testing.T) {
|
|
srv := newTestServer(t)
|
|
body, _ := json.Marshal(StreamChatRequest{SessionID: "s-empty"})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/chat/stream", bytes.NewReader(body))
|
|
rec := httptest.NewRecorder()
|
|
srv.Routes().ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusBadRequest || !strings.Contains(rec.Body.String(), "message cannot be empty") {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestChatStream_AttachmentOnlyPassesEmptyCheck(t *testing.T) {
|
|
srv := newTestServer(t)
|
|
body, _ := json.Marshal(StreamChatRequest{
|
|
SessionID: "s-upload",
|
|
Attachments: []TurnAttachment{{
|
|
Filename: "F-030-PIR.pdf",
|
|
ParseState: "pending",
|
|
}},
|
|
})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/chat/stream", bytes.NewReader(body))
|
|
rec := httptest.NewRecorder()
|
|
srv.Routes().ServeHTTP(rec, req)
|
|
if rec.Code == http.StatusBadRequest && strings.Contains(rec.Body.String(), "message cannot be empty") {
|
|
t.Fatalf("attachment-only must not be rejected as empty: %s", rec.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestChat_AttachmentOnlyPendingRepliesInsteadOf400(t *testing.T) {
|
|
srv := newTestServer(t)
|
|
body, _ := json.Marshal(ChatRequest{
|
|
SessionID: "s-upload-sync",
|
|
ProjectName: "内窥镜研发项目",
|
|
Attachments: []TurnAttachment{{
|
|
Filename: "F-030-PIR.pdf",
|
|
ParseState: "pending",
|
|
}},
|
|
})
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/chat", bytes.NewReader(body))
|
|
withBearerAuth(req, loginTestAdmin(t, srv))
|
|
rec := httptest.NewRecorder()
|
|
srv.Routes().ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
|
|
}
|
|
if !strings.Contains(rec.Body.String(), "解析") {
|
|
t.Fatalf("expected parse guidance, got %s", rec.Body.String())
|
|
}
|
|
}
|