124 lines
5 KiB
Go
124 lines
5 KiB
Go
package postgres
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"testing"
|
||
|
||
"telesrv/internal/domain"
|
||
)
|
||
|
||
// TestStarGiftStorePostgres 回归迁移 0011:用户收到礼物实例对真实 PG 的 CRUD
|
||
// (创建 / keyset 分页 / excludeUnsaved / 隐藏切换 / 转换幂等)。
|
||
func TestStarGiftStorePostgres(t *testing.T) {
|
||
pool := testPool(t)
|
||
ctx := context.Background()
|
||
st := NewStarGiftStore(pool)
|
||
|
||
users := NewUserStore(pool)
|
||
suffix := randomSuffix(t)
|
||
owner, err := users.Create(ctx, domain.User{AccessHash: 81, Phone: "+1779" + suffix + "51", FirstName: "GiftOwner"})
|
||
if err != nil {
|
||
t.Fatalf("create owner: %v", err)
|
||
}
|
||
from, err := users.Create(ctx, domain.User{AccessHash: 82, Phone: "+1779" + suffix + "52", FirstName: "GiftSender"})
|
||
if err != nil {
|
||
t.Fatalf("create sender: %v", err)
|
||
}
|
||
ownerPeer := domain.Peer{Type: domain.PeerTypeUser, ID: owner.ID}
|
||
t.Cleanup(func() {
|
||
_, _ = pool.Exec(ctx, "DELETE FROM peer_star_gifts WHERE owner_peer_id IN ($1, $2)", owner.ID, int64(987654321))
|
||
_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", []int64{owner.ID, from.ID})
|
||
})
|
||
|
||
// 创建三份礼物(msg_id 递增)。
|
||
for i := 0; i < 3; i++ {
|
||
if _, err := st.Create(ctx, domain.SavedStarGift{
|
||
Owner: ownerPeer, FromUserID: from.ID, GiftID: 8001, MsgID: 100 + i,
|
||
Date: 1700000000 + i, ConvertStars: 50,
|
||
}); err != nil {
|
||
t.Fatalf("create gift #%d: %v", i, err)
|
||
}
|
||
}
|
||
|
||
// keyset 分页:每页 2,末页省略游标。
|
||
page1, err := st.ListByOwner(ctx, ownerPeer, false, "", 2)
|
||
if err != nil {
|
||
t.Fatalf("list page1: %v", err)
|
||
}
|
||
if len(page1.Gifts) != 2 || page1.Count != 3 || page1.NextOffset == "" {
|
||
t.Fatalf("page1 = %d count %d next %q, want 2/3/nonempty", len(page1.Gifts), page1.Count, page1.NextOffset)
|
||
}
|
||
if page1.Gifts[0].MsgID != 102 {
|
||
t.Fatalf("page1[0] msg_id = %d, want 102 (newest first)", page1.Gifts[0].MsgID)
|
||
}
|
||
page2, err := st.ListByOwner(ctx, ownerPeer, false, page1.NextOffset, 2)
|
||
if err != nil {
|
||
t.Fatalf("list page2: %v", err)
|
||
}
|
||
if len(page2.Gifts) != 1 || page2.NextOffset != "" {
|
||
t.Fatalf("page2 = %d next %q, want 1 + empty (terminal)", len(page2.Gifts), page2.NextOffset)
|
||
}
|
||
|
||
// 隐藏 msg_id=101 → excludeUnsaved 列表少一份。
|
||
if ok, err := st.SetUnsaved(ctx, domain.SavedStarGiftRef{Owner: ownerPeer, MsgID: 101}, true); err != nil || !ok {
|
||
t.Fatalf("set unsaved = %v err %v", ok, err)
|
||
}
|
||
shown, err := st.ListByOwner(ctx, ownerPeer, true, "", 100)
|
||
if err != nil || len(shown.Gifts) != 2 || shown.Count != 2 {
|
||
t.Fatalf("excludeUnsaved = %d count %d err %v, want 2/2", len(shown.Gifts), shown.Count, err)
|
||
}
|
||
|
||
// GetByRef(user msg_id)。
|
||
g, found, err := st.GetByRef(ctx, domain.SavedStarGiftRef{Owner: ownerPeer, MsgID: 100})
|
||
if err != nil || !found || g.GiftID != 8001 || g.ConvertStars != 50 {
|
||
t.Fatalf("get = %+v found %v err %v", g, found, err)
|
||
}
|
||
|
||
// 转换 msg_id=100 → converted,从列表消失;重复转换被拒。
|
||
conv, err := st.MarkConverted(ctx, domain.SavedStarGiftRef{Owner: ownerPeer, MsgID: 100})
|
||
if err != nil || conv.ConvertStars != 50 || !conv.Converted {
|
||
t.Fatalf("convert = %+v err %v, want ConvertStars 50 converted", conv, err)
|
||
}
|
||
if _, err := st.MarkConverted(ctx, domain.SavedStarGiftRef{Owner: ownerPeer, MsgID: 100}); !errors.Is(err, domain.ErrStarGiftAlreadyConverted) {
|
||
t.Fatalf("double convert err = %v, want ErrStarGiftAlreadyConverted", err)
|
||
}
|
||
full, _ := st.ListByOwner(ctx, ownerPeer, false, "", 100)
|
||
if full.Count != 2 {
|
||
t.Fatalf("count after convert = %d, want 2", full.Count)
|
||
}
|
||
// 转换不存在的礼物。
|
||
if _, err := st.MarkConverted(ctx, domain.SavedStarGiftRef{Owner: ownerPeer, MsgID: 999}); !errors.Is(err, domain.ErrStarGiftNotFound) {
|
||
t.Fatalf("convert missing err = %v, want ErrStarGiftNotFound", err)
|
||
}
|
||
|
||
// CountByOwner(展示在资料 = 非转换、非隐藏):100 已转换、101 已隐藏、102 仍展示 → 1。
|
||
n, err := st.CountByOwner(ctx, ownerPeer)
|
||
if err != nil || n != 1 {
|
||
t.Fatalf("CountByOwner = %d err %v, want 1 (100 converted, 101 hidden, 102 shown)", n, err)
|
||
}
|
||
|
||
// 频道礼物用 saved_id 定位,和用户 msg_id 身份键隔离。
|
||
channelPeer := domain.Peer{Type: domain.PeerTypeChannel, ID: 987654321}
|
||
if _, err := st.Create(ctx, domain.SavedStarGift{
|
||
Owner: ownerPeer, FromUserID: from.ID, GiftID: 8001, MsgID: 700,
|
||
Date: 1700000100, ConvertStars: 50,
|
||
}); err != nil {
|
||
t.Fatalf("create user gift with same msg_id namespace: %v", err)
|
||
}
|
||
channelSavedID, err := st.Create(ctx, domain.SavedStarGift{
|
||
Owner: channelPeer, FromUserID: from.ID, GiftID: 8001, MsgID: 0, SavedID: 0,
|
||
Date: 1700000101, ConvertStars: 50,
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("create channel gift: %v", err)
|
||
}
|
||
cg, found, err := st.GetByRef(ctx, domain.SavedStarGiftRef{Owner: channelPeer, SavedID: channelSavedID})
|
||
if err != nil || !found || cg.Owner != channelPeer || cg.MsgID != 0 || cg.SavedID != channelSavedID {
|
||
t.Fatalf("get channel gift = %+v found %v err %v", cg, found, err)
|
||
}
|
||
cn, err := st.CountByOwner(ctx, channelPeer)
|
||
if err != nil || cn != 1 {
|
||
t.Fatalf("channel CountByOwner = %d err %v, want 1", cn, err)
|
||
}
|
||
}
|