owpengram-server/internal/app/stargifts/animation_test.go
2026-07-16 12:38:53 +08:00

93 lines
3.7 KiB
Go

package stargifts
import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"testing"
"telesrv/internal/domain"
"telesrv/internal/store/memory"
)
const validGiftLottie = `{"v":"5.7.4","fr":30,"ip":0,"op":60,"w":512,"h":512,"layers":[{"ty":4,"nm":"gift"}],"assets":[]}`
func TestPrepareAnimationNormalizesLottieAndTGS(t *testing.T) {
fromJSON, err := prepareAnimation("gift.lottie", []byte(" \n"+validGiftLottie+"\n"))
if err != nil {
t.Fatalf("prepare lottie: %v", err)
}
if fromJSON.SourceFormat != domain.StarGiftAnimationLottie || len(fromJSON.TGS) == 0 || fromJSON.Width != 512 || fromJSON.Height != 512 {
t.Fatalf("prepared lottie = %+v", fromJSON)
}
fromTGS, err := prepareAnimation("gift.tgs", fromJSON.TGS)
if err != nil {
t.Fatalf("prepare tgs: %v", err)
}
if fromTGS.SourceFormat != domain.StarGiftAnimationTGS || string(fromTGS.JSON) != string(fromJSON.JSON) || hex.EncodeToString(fromTGS.SHA256) != hex.EncodeToString(fromJSON.SHA256) {
t.Fatalf("tgs round trip differs: json=%v hash=%x/%x", string(fromTGS.JSON) == string(fromJSON.JSON), fromTGS.SHA256, fromJSON.SHA256)
}
}
func TestPrepareAnimationRejectsExternalAssetAndExpression(t *testing.T) {
for name, raw := range map[string]string{
"external": `{"v":"5.7","fr":30,"ip":0,"op":30,"w":512,"h":512,"layers":[{}],"assets":[{"p":"https://example.test/x.png"}]}`,
"expression": `{"v":"5.7","fr":30,"ip":0,"op":30,"w":512,"h":512,"layers":[{"ks":{"o":{"x":"time*10"}}}]}`,
"wrong-size": `{"v":"5.7","fr":30,"ip":0,"op":30,"w":256,"h":256,"layers":[{}]}`,
"frame-rate": `{"v":"5.7","fr":121,"ip":0,"op":30,"w":512,"h":512,"layers":[{}]}`,
"duration": `{"v":"5.7","fr":30,"ip":0,"op":901,"w":512,"h":512,"layers":[{}]}`,
} {
t.Run(name, func(t *testing.T) {
if _, err := prepareAnimation("gift.json", []byte(raw)); !errors.Is(err, domain.ErrStarGiftFileInvalid) {
t.Fatalf("err=%v, want ErrStarGiftFileInvalid", err)
}
})
}
}
type testGiftBlob struct{ data map[string][]byte }
func (b *testGiftBlob) Name() string { return "localfs" }
func (b *testGiftBlob) Put(_ context.Context, data []byte) (string, error) {
sum := sha256.Sum256(data)
key := hex.EncodeToString(sum[:])
b.data[key] = append([]byte(nil), data...)
return key, nil
}
func (b *testGiftBlob) Get(_ context.Context, key string) ([]byte, error) {
return append([]byte(nil), b.data[key]...), nil
}
func TestCreateCatalogRevisionPreservesHistoricalRevision(t *testing.T) {
ctx := context.Background()
store := memory.NewStarGiftStore()
svc := NewService(store, &testGiftBlob{data: map[string][]byte{}}, 2)
animation, err := svc.PrepareAnimation("gift.json", []byte(validGiftLottie))
if err != nil {
t.Fatal(err)
}
first, err := svc.CreateCatalogRevision(ctx, domain.StarGiftCatalogWrite{
Stars: 50, ConvertStars: 25, Enabled: true, SortOrder: 1, Title: "First", Animation: animation,
})
if err != nil {
t.Fatalf("create first: %v", err)
}
second, err := svc.CreateCatalogRevision(ctx, domain.StarGiftCatalogWrite{
GiftID: first.Gift.ID, Stars: 80, ConvertStars: 40, Enabled: true, SortOrder: 1, Title: "Second", Animation: animation,
})
if err != nil {
t.Fatalf("create second: %v", err)
}
current, found, _ := svc.GiftByID(ctx, first.Gift.ID)
if !found || current.RevisionID != second.Gift.RevisionID || current.Stars != 80 {
t.Fatalf("current=%+v found=%v", current, found)
}
historical, found, _ := svc.GiftRevisionByID(ctx, first.Gift.RevisionID)
if !found || historical.Stars != 50 || historical.Title != "First" {
t.Fatalf("historical=%+v found=%v", historical, found)
}
if _, err := svc.SetCatalogEnabled(ctx, first.Gift.ID+999, false); !errors.Is(err, domain.ErrStarGiftNotFound) {
t.Fatalf("disable missing err=%v, want ErrStarGiftNotFound", err)
}
}