chore: refresh gramsrv public release
This commit is contained in:
parent
75cebe8dbf
commit
70b6820474
1274 changed files with 378751 additions and 59919 deletions
186
internal/store/postgres/channel_multi_pin_integration_test.go
Normal file
186
internal/store/postgres/channel_multi_pin_integration_test.go
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
// TestChannelMultiPin 验证超级群多置顶模型:多条共存、filterPinned 搜索、
|
||||
// 上限、unpinAll 批量清除、删除被置顶消息后的缓存重算。
|
||||
func TestChannelMultiPin(t *testing.T) {
|
||||
pool := testPool(t)
|
||||
ctx := context.Background()
|
||||
suffix := randomSuffix(t)
|
||||
|
||||
users := NewUserStore(pool)
|
||||
owner, err := users.Create(ctx, domain.User{AccessHash: 91, Phone: "+1676" + suffix + "01", FirstName: "MultiPinOwner"})
|
||||
if err != nil {
|
||||
t.Fatalf("create owner: %v", err)
|
||||
}
|
||||
member, err := users.Create(ctx, domain.User{AccessHash: 92, Phone: "+1676" + suffix + "02", FirstName: "MultiPinMember"})
|
||||
if err != nil {
|
||||
t.Fatalf("create member: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", []int64{owner.ID, member.ID})
|
||||
})
|
||||
|
||||
channels := NewChannelStore(pool)
|
||||
created, err := channels.CreateChannel(ctx, domain.CreateChannelRequest{
|
||||
CreatorUserID: owner.ID,
|
||||
Title: "MultiPin " + suffix,
|
||||
Megagroup: true,
|
||||
MemberUserIDs: []int64{member.ID},
|
||||
Date: 1700000920,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("create channel: %v", err)
|
||||
}
|
||||
channelID := created.Channel.ID
|
||||
|
||||
const pinCount = 11
|
||||
ids := make([]int, 0, pinCount)
|
||||
for i := 0; i < pinCount; i++ {
|
||||
sent, err := channels.SendChannelMessage(ctx, domain.SendChannelMessageRequest{
|
||||
UserID: owner.ID,
|
||||
ChannelID: channelID,
|
||||
RandomID: int64(852000 + i),
|
||||
Message: "pin-target",
|
||||
Date: 1700000921 + i,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("send %d: %v", i, err)
|
||||
}
|
||||
ids = append(ids, sent.Message.ID)
|
||||
}
|
||||
|
||||
pin := func(id int, pinned bool) (domain.UpdateChannelPinnedMessageResult, error) {
|
||||
return channels.UpdatePinnedMessage(ctx, domain.UpdateChannelPinnedMessageRequest{
|
||||
UserID: owner.ID,
|
||||
ChannelID: channelID,
|
||||
MessageID: id,
|
||||
Pinned: pinned,
|
||||
Date: 1700000950,
|
||||
})
|
||||
}
|
||||
|
||||
// 多条共存:pin 前三条,互不替代。
|
||||
for _, id := range ids[:3] {
|
||||
res, err := pin(id, true)
|
||||
if err != nil {
|
||||
t.Fatalf("pin %d: %v", id, err)
|
||||
}
|
||||
if !res.Event.Pinned || len(res.Event.MessageIDs) != 1 || res.Event.MessageIDs[0] != id {
|
||||
t.Fatalf("pin event = %+v, want pinned [%d]", res.Event, id)
|
||||
}
|
||||
}
|
||||
view, err := channels.GetChannel(ctx, owner.ID, channelID)
|
||||
if err != nil {
|
||||
t.Fatalf("get channel: %v", err)
|
||||
}
|
||||
if view.Channel.PinnedMessageID != ids[2] {
|
||||
t.Fatalf("pinned_message_id = %d, want latest pinned %d", view.Channel.PinnedMessageID, ids[2])
|
||||
}
|
||||
history, err := channels.ListChannelHistory(ctx, owner.ID, domain.ChannelHistoryFilter{
|
||||
ChannelID: channelID, PinnedOnly: true, Limit: 50,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("filterPinned search: %v", err)
|
||||
}
|
||||
if len(history.Messages) != 3 {
|
||||
t.Fatalf("filterPinned messages = %d, want 3 coexisting pins: %+v", len(history.Messages), history.Messages)
|
||||
}
|
||||
for _, msg := range history.Messages {
|
||||
if !msg.Pinned {
|
||||
t.Fatalf("filterPinned message %d lacks pinned flag", msg.ID)
|
||||
}
|
||||
}
|
||||
// 普通历史页的消息行直接携带 pinned 标志(多置顶都标,不只最新)。
|
||||
page, err := channels.ListChannelHistory(ctx, member.ID, domain.ChannelHistoryFilter{ChannelID: channelID, Limit: 50})
|
||||
if err != nil {
|
||||
t.Fatalf("list history: %v", err)
|
||||
}
|
||||
flagged := 0
|
||||
for _, msg := range page.Messages {
|
||||
if msg.Pinned {
|
||||
flagged++
|
||||
}
|
||||
}
|
||||
if flagged != 3 {
|
||||
t.Fatalf("history pinned flags = %d, want 3", flagged)
|
||||
}
|
||||
|
||||
// unpin 最新一条:其它置顶保留,缓存回落到次新。
|
||||
if _, err := pin(ids[2], false); err != nil {
|
||||
t.Fatalf("unpin latest: %v", err)
|
||||
}
|
||||
view, err = channels.GetChannel(ctx, owner.ID, channelID)
|
||||
if err != nil {
|
||||
t.Fatalf("get channel after unpin: %v", err)
|
||||
}
|
||||
if view.Channel.PinnedMessageID != ids[1] {
|
||||
t.Fatalf("pinned_message_id after unpin = %d, want %d", view.Channel.PinnedMessageID, ids[1])
|
||||
}
|
||||
|
||||
// 无数量上限(对齐官方):剩余全部 pin 上,共 pinCount 条同时置顶。
|
||||
for _, id := range ids[2:] {
|
||||
if _, err := pin(id, true); err != nil {
|
||||
t.Fatalf("pin %d: %v", id, err)
|
||||
}
|
||||
}
|
||||
history, err = channels.ListChannelHistory(ctx, owner.ID, domain.ChannelHistoryFilter{
|
||||
ChannelID: channelID, PinnedOnly: true, Limit: 50,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("filterPinned all pinned: %v", err)
|
||||
}
|
||||
if len(history.Messages) != pinCount {
|
||||
t.Fatalf("filterPinned messages = %d, want %d coexisting pins", len(history.Messages), pinCount)
|
||||
}
|
||||
|
||||
// 删除被置顶的最新消息:置顶集合自动排除,缓存重算。
|
||||
latest := ids[pinCount-1]
|
||||
if _, err := channels.DeleteChannelMessages(ctx, domain.DeleteChannelMessagesRequest{
|
||||
UserID: owner.ID, ChannelID: channelID, IDs: []int{latest}, Date: 1700000961,
|
||||
}); err != nil {
|
||||
t.Fatalf("delete pinned message: %v", err)
|
||||
}
|
||||
view, err = channels.GetChannel(ctx, owner.ID, channelID)
|
||||
if err != nil {
|
||||
t.Fatalf("get channel after delete: %v", err)
|
||||
}
|
||||
if view.Channel.PinnedMessageID != ids[pinCount-2] {
|
||||
t.Fatalf("pinned_message_id after delete = %d, want %d", view.Channel.PinnedMessageID, ids[pinCount-2])
|
||||
}
|
||||
|
||||
// unpinAll:一条事件批量携带剩余全部置顶 id,缓存清零,再次调用 no-op。
|
||||
res, err := channels.UnpinAllChannelMessages(ctx, domain.UnpinAllChannelMessagesRequest{
|
||||
UserID: owner.ID, ChannelID: channelID, Date: 1700000962,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unpin all: %v", err)
|
||||
}
|
||||
if res.Event.Pinned || len(res.Event.MessageIDs) != pinCount-1 {
|
||||
t.Fatalf("unpin all event = %+v, want pinned=false with %d ids", res.Event, pinCount-1)
|
||||
}
|
||||
if res.Channel.PinnedMessageID != 0 {
|
||||
t.Fatalf("pinned_message_id after unpin all = %d, want 0", res.Channel.PinnedMessageID)
|
||||
}
|
||||
if _, err := channels.UnpinAllChannelMessages(ctx, domain.UnpinAllChannelMessagesRequest{
|
||||
UserID: owner.ID, ChannelID: channelID, Date: 1700000963,
|
||||
}); !errors.Is(err, domain.ErrChannelNotModified) {
|
||||
t.Fatalf("unpin all again err = %v, want ErrChannelNotModified", err)
|
||||
}
|
||||
history, err = channels.ListChannelHistory(ctx, owner.ID, domain.ChannelHistoryFilter{
|
||||
ChannelID: channelID, PinnedOnly: true, Limit: 50,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("filterPinned after unpin all: %v", err)
|
||||
}
|
||||
if len(history.Messages) != 0 {
|
||||
t.Fatalf("filterPinned after unpin all = %+v, want empty", history.Messages)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue