spark-server/internal/transport/http/file_test.go
2026-09-18 18:27:49 +08:00

141 lines
4.8 KiB
Go

package httpx
import (
"context"
"encoding/json"
"net/http"
"strconv"
"strings"
"testing"
"time"
"go.uber.org/zap"
"spark-server/internal/infrastructure/id"
authlogic "spark-server/internal/module/auth/logic"
convlogic "spark-server/internal/module/conversation/logic"
convmodel "spark-server/internal/module/conversation/model"
favlogic "spark-server/internal/module/favorite/logic"
favmodel "spark-server/internal/module/favorite/model"
msgentity "spark-server/internal/module/message/entity"
msgmodel "spark-server/internal/module/message/model"
uploadlogic "spark-server/internal/module/upload/logic"
userlogic "spark-server/internal/module/user/logic"
usermodel "spark-server/internal/module/user/model"
"spark-server/internal/pkg/errs"
)
type stubPresign struct{}
func (s *stubPresign) PresignPut(_ context.Context, key, _ string, _ int64, _ time.Duration) (string, error) {
return "http://rustfs.test/" + key + "?sig=1", nil
}
func (s *stubPresign) PresignGet(_ context.Context, key string, _ time.Duration) (string, error) {
return "http://rustfs.test/" + key + "?get=1", nil
}
func testFileEngine(t *testing.T) (*ginEngineBundle, *id.Generator, *msgmodel.MemoryRepo, *convmodel.MemoryP2P) {
t.Helper()
j, err := authlogic.NewJWT(&authlogic.Options{Secret: "test-secret-test-secret", Issuer: "spark-im"})
if err != nil {
t.Fatal(err)
}
ids, err := id.New(1)
if err != nil {
t.Fatal(err)
}
users := userlogic.NewService(usermodel.NewMemoryRepo(), usermodel.NewMemoryCodes(), ids, nil)
msgs := msgmodel.NewMemoryRepo()
convs := convmodel.NewMemoryP2P()
files := uploadlogic.NewService(&stubPresign{}, uploadlogic.Options{
Now: func() time.Time { return time.Date(2026, 9, 17, 0, 0, 0, 0, time.UTC) },
})
favs := favlogic.NewService(favmodel.NewMemoryRepo(), msgs, convs, nil, ids)
r := NewEngine(zap.NewNop(), &EngineDeps{
Auth: j, Login: authlogic.NewLoginService(j, users), Users: users,
Files: files, Favorites: favs,
})
return &ginEngineBundle{engine: r}, ids, msgs, convs
}
func TestUploadCredentialHTTP(t *testing.T) {
bundle, _, _, _ := testFileEngine(t)
h := bundle.engine
tok := loginUser(t, h, "test01@spark.com", 1)
env := authJSON(t, h, &tok, http.MethodPost, "/v1/files", `{"purpose":"chat_image","mime":"image/jpeg","size":1024}`)
if env.Code != "0" {
t.Fatalf("%+v", env)
}
var cred struct {
ObjectKey string `json:"object_key"`
Method string `json:"method"`
}
if err := json.Unmarshal(env.Data, &cred); err != nil || cred.Method != "PUT" || !strings.Contains(cred.ObjectKey, "chat/image/20260917/") {
t.Fatalf("%s %v", env.Data, err)
}
bad := authJSON(t, h, &tok, http.MethodPost, "/v1/files", `{"purpose":"avatar","mime":"application/pdf","size":10}`)
if bad.Code != errs.ErrInvalidArgument.Code {
t.Fatalf("mime %+v", bad)
}
batch := authJSON(t, h, &tok, http.MethodPost, "/v1/files/batch", `{"items":[{"purpose":"chat_image","mime":"image/jpeg","size":1024},{"purpose":"chat_image","mime":"image/jpeg","size":2048}]}`)
if batch.Code != "0" {
t.Fatalf("batch %+v", batch)
}
var set struct {
Items []struct {
ObjectKey string `json:"object_key"`
} `json:"items"`
}
if err := json.Unmarshal(batch.Data, &set); err != nil || len(set.Items) != 2 || set.Items[0].ObjectKey == set.Items[1].ObjectKey {
t.Fatalf("%s %v", batch.Data, err)
}
dl := authJSON(t, h, &tok, http.MethodPost, "/v1/files/downloads/batch", `{"object_keys":["chat/image/20260917/a.jpg","perm/moment/image/20260917/b.jpg"]}`)
if dl.Code != "0" {
t.Fatalf("downloads %+v", dl)
}
var dls struct {
Items []struct {
ObjectKey string `json:"object_key"`
DownloadURL string `json:"download_url"`
} `json:"items"`
}
if err := json.Unmarshal(dl.Data, &dls); err != nil || len(dls.Items) != 2 || dls.Items[0].DownloadURL == "" {
t.Fatalf("%s %v", dl.Data, err)
}
}
func TestFavoriteTextHTTP(t *testing.T) {
bundle, ids, msgs, convs := testFileEngine(t)
h := bundle.engine
tok := loginUser(t, h, "test01@spark.com", 1)
p2p := convlogic.NewP2PService(convs, ids)
convID, err := p2p.EnsureP2P(t.Context(), tok.UserID, tok.UserID+1)
if err != nil {
t.Fatal(err)
}
raw, err := msgentity.NewText("keep").Marshal()
if err != nil {
t.Fatal(err)
}
msgID, err := ids.NextID()
if err != nil {
t.Fatal(err)
}
if err := msgs.Create(t.Context(), &msgentity.Message{
ID: msgID, ConversationID: convID, SenderID: tok.UserID, ClientMsgID: "http-1",
Type: msgentity.TypeText, Content: raw, Status: msgentity.StatusNormal,
}); err != nil {
t.Fatal(err)
}
body := `{"msg_id":` + strconv.FormatInt(msgID, 10) + `}`
env := authJSON(t, h, &tok, http.MethodPost, "/v1/favorites", body)
if env.Code != "0" {
t.Fatalf("fav %+v", env)
}
list := authJSON(t, h, &tok, http.MethodGet, "/v1/favorites", "")
if list.Code != "0" || !strings.Contains(string(list.Data), `"keep"`) {
t.Fatalf("list %+v", list)
}
}