owpengram-server/internal/store/postgres/message_effect_integration_test.go

135 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package postgres
import (
"context"
"testing"
"time"
"telesrv/internal/domain"
)
// TestSendPrivateEffectSurvivesReadPaths 回归迁移 0023消息特效 effect 经私聊全部读路径
// 保真——发送结果双盒、history、GetByIDs、以及更新事件重建路径离线 difference / 在线推送
// 共用)。漏一处读站点 = 特效静默丢失(发送方播了、接收方/重载看不到)。
func TestSendPrivateEffectSurvivesReadPaths(t *testing.T) {
pool := testPool(t)
ctx := context.Background()
suffix := randomSuffix(t)
users := NewUserStore(pool)
sender, err := users.Create(ctx, domain.User{AccessHash: 91, Phone: "+1996" + suffix + "01", FirstName: "EffectSender"})
if err != nil {
t.Fatalf("create sender: %v", err)
}
recipient, err := users.Create(ctx, domain.User{AccessHash: 92, Phone: "+1996" + suffix + "02", FirstName: "EffectRecipient"})
if err != nil {
t.Fatalf("create recipient: %v", err)
}
ids := []int64{sender.ID, recipient.ID}
t.Cleanup(func() {
_, _ = pool.Exec(ctx, "DELETE FROM dispatch_outbox WHERE target_user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM user_update_events WHERE user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM message_boxes WHERE owner_user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM private_messages WHERE sender_user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM dialogs WHERE user_id = ANY($1::bigint[])", ids)
_, _ = pool.Exec(ctx, "DELETE FROM users WHERE id = ANY($1::bigint[])", ids)
})
messages := NewMessageStore(pool, WithMessageAllocators(&perUserCounterAllocator{}))
const effect = int64(5104841169784993603)
res, err := messages.SendPrivateText(ctx, domain.SendPrivateTextRequest{
SenderUserID: sender.ID,
RecipientUserID: recipient.ID,
RandomID: time.Now().UnixNano(),
Message: "🎉 with effect",
Effect: effect,
Date: int(time.Now().Unix()),
})
if err != nil {
t.Fatalf("send effect message: %v", err)
}
// 发送结果双盒:发送方与接收方各自的副本都带特效。
if res.SenderMessage.Effect != effect || res.RecipientMessage.Effect != effect {
t.Fatalf("send result effect = sender %d recipient %d, want %d", res.SenderMessage.Effect, res.RecipientMessage.Effect, effect)
}
// history接收方拉取携带 effect。
hist, err := messages.ListByUser(ctx, recipient.ID, domain.MessageFilter{Limit: 10})
if err != nil {
t.Fatalf("recipient history: %v", err)
}
found := false
for _, m := range hist.Messages {
if m.ID == res.RecipientMessage.ID {
found = true
if m.Effect != effect {
t.Fatalf("history effect = %d, want %d", m.Effect, effect)
}
}
}
if !found {
t.Fatal("recipient history missing the effect message")
}
// GetByIDs 带 effect。
byID, err := messages.GetByIDs(ctx, sender.ID, []int{res.SenderMessage.ID})
if err != nil {
t.Fatalf("sender get by ids: %v", err)
}
if len(byID.Messages) != 1 {
t.Fatalf("get by ids = %d, want 1", len(byID.Messages))
}
if byID.Messages[0].Effect != effect {
t.Fatalf("get-by-id effect = %d, want %d", byID.Messages[0].Effect, effect)
}
// 更新事件重建路径关键getDifference/推送共用)带 effect。
events := NewUpdateEventStore(pool)
got, err := events.ListAfter(ctx, recipient.ID, 0, 20)
if err != nil {
t.Fatalf("list recipient events: %v", err)
}
rebuilt := false
for _, ev := range got {
if ev.Type == domain.UpdateEventNewMessage && ev.Message.ID == res.RecipientMessage.ID {
if ev.Message.Effect != effect {
t.Fatalf("update-event effect = %d, want %d重建路径丢失特效", ev.Message.Effect, effect)
}
rebuilt = true
}
}
if !rebuilt {
t.Fatal("recipient new_message event missing effect rebuild")
}
// getDialogs 的 top message 必须带 effectTDesktop 把 getDialogs 返回的消息入缓存
// 且不被后续 getHistory 覆盖dialog top message 漏 effect = 最新那条特效消息永久按
// 「无特效」渲染(真机实测的 buggetDialogs 返回的最新消息没有消息特效)。
dialogs := NewDialogStore(pool)
for _, owner := range []struct {
id int64
boxID int
label string
}{
{recipient.ID, res.RecipientMessage.ID, "recipient"},
{sender.ID, res.SenderMessage.ID, "sender"},
} {
list, err := dialogs.ListByUser(ctx, owner.id, domain.DialogFilter{Limit: 20})
if err != nil {
t.Fatalf("%s getDialogs: %v", owner.label, err)
}
top := false
for _, m := range list.Messages {
if m.ID == owner.boxID {
top = true
if m.Effect != effect {
t.Fatalf("%s dialog top message effect = %d, want %dgetDialogs 漏 effect", owner.label, m.Effect, effect)
}
}
}
if !top {
t.Fatalf("%s getDialogs missing top message box %d", owner.label, owner.boxID)
}
}
}