test: 对齐 F06 群发与 M2 离线不保留完成态
This commit is contained in:
@@ -492,6 +492,13 @@
|
|||||||
- 备选方案:塞进 context。
|
- 备选方案:塞进 context。
|
||||||
- 影响:协议分发接线时从 `ConnInfo.RemoteIP` 传入。
|
- 影响:协议分发接线时从 `ConnInfo.RemoteIP` 传入。
|
||||||
|
|
||||||
|
10. **F06 群发断言与 M2 分发语义对齐(2026-09-30)**
|
||||||
|
- 原条款:F06 验收「发到当时成员」;早期单测在仅写 `pending` 的桩分发下断言 Submit 返回 `dispatched`。
|
||||||
|
- 实际做法:成员离线且默认不保留时,投递立即 `dropped`,消息为 `completed`(DEVELOPMENT 7.4/7.6);`TestF06GroupSendMembership` 改断言 `completed`;另加 `TestF06GroupSendKeepOfflinePending`:选离线保留时期望 `dispatched` 且接收者有 `pending`。不改消息分发实现。
|
||||||
|
- 原因:合入含 M2 完整分发的 main 后,旧断言与产品规则冲突;永远 `dispatched` 才是错的。
|
||||||
|
- 备选方案:测试里注入在线连接表使默认不保留也走 pending(与「离线不保留」场景重复覆盖)。
|
||||||
|
- 影响:仅测试期望;产品行为不变。
|
||||||
|
|
||||||
## 后台接口 A
|
## 后台接口 A
|
||||||
|
|
||||||
### A1 2026-09-30
|
### A1 2026-09-30
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func setup(t *testing.T) (*group.App, *identity.App, *message.App, *store.DB, *m
|
|||||||
DB: db, Talk: idApp, Downlink: down, MaxGroupMembers: 1000,
|
DB: db, Talk: idApp, Downlink: down, MaxGroupMembers: 1000,
|
||||||
Now: func() time.Time { return fixed }, DefaultRemoteIP: "1.1.1.1",
|
Now: func() time.Time { return fixed }, DefaultRemoteIP: "1.1.1.1",
|
||||||
})
|
})
|
||||||
lim := message.LimitsFromConfig(config.Default().Limits)
|
lim := message.LimitsFromFullConfig(config.Default())
|
||||||
lim.RequestsPerSecond = 0
|
lim.RequestsPerSecond = 0
|
||||||
msgApp := message.New(db, lim, auth.NewStubHashPool(),
|
msgApp := message.New(db, lim, auth.NewStubHashPool(),
|
||||||
message.WithNow(func() time.Time { return fixed }),
|
message.WithNow(func() time.Time { return fixed }),
|
||||||
@@ -325,6 +325,7 @@ func TestF06GroupSendMembership(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
// 默认不保留 + 成员离线(无连接、无 offline_since):投递立即 dropped,消息 completed(DEVELOPMENT 7.4/7.6)
|
||||||
res, err := msgApp.Submit(ctx, "alice", port.ConnInfo{}, &protocol.Send{
|
res, err := msgApp.Submit(ctx, "alice", port.ConnInfo{}, &protocol.Send{
|
||||||
V: protocol.Version, Type: protocol.TypeSend, RID: "s", ID: "m1",
|
V: protocol.Version, Type: protocol.TypeSend, RID: "s", ID: "m1",
|
||||||
To: protocol.Target{Kind: protocol.TargetGroup, ID: created.ID},
|
To: protocol.Target{Kind: protocol.TargetGroup, ID: created.ID},
|
||||||
@@ -333,14 +334,20 @@ func TestF06GroupSendMembership(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if res.State != message.StateDispatched {
|
if res.State != message.StateCompleted {
|
||||||
t.Fatalf("state=%s", res.State)
|
t.Fatalf("state=%s want completed (offline, keep=false)", res.State)
|
||||||
}
|
}
|
||||||
var cnt int
|
var cnt int
|
||||||
_ = db.Read.QueryRow(`SELECT COUNT(*) FROM deliveries d JOIN messages m ON m.seq=d.seq WHERE m.id='m1'`).Scan(&cnt)
|
_ = db.Read.QueryRow(`SELECT COUNT(*) FROM deliveries d JOIN messages m ON m.seq=d.seq WHERE m.id='m1'`).Scan(&cnt)
|
||||||
if cnt != 2 {
|
if cnt != 2 {
|
||||||
t.Fatalf("deliveries=%d want 2 (not sender)", cnt)
|
t.Fatalf("deliveries=%d want 2 (not sender)", cnt)
|
||||||
}
|
}
|
||||||
|
var pending, dropped int
|
||||||
|
_ = db.Read.QueryRow(`SELECT COUNT(*) FROM deliveries d JOIN messages m ON m.seq=d.seq WHERE m.id='m1' AND d.state='pending'`).Scan(&pending)
|
||||||
|
_ = db.Read.QueryRow(`SELECT COUNT(*) FROM deliveries d JOIN messages m ON m.seq=d.seq WHERE m.id='m1' AND d.state='dropped'`).Scan(&dropped)
|
||||||
|
if pending != 0 || dropped != 2 {
|
||||||
|
t.Fatalf("pending=%d dropped=%d want pending=0 dropped=2", pending, dropped)
|
||||||
|
}
|
||||||
var self int
|
var self int
|
||||||
_ = db.Read.QueryRow(`SELECT COUNT(*) FROM deliveries d JOIN messages m ON m.seq=d.seq WHERE m.id='m1' AND d.endpoint_id='alice'`).Scan(&self)
|
_ = db.Read.QueryRow(`SELECT COUNT(*) FROM deliveries d JOIN messages m ON m.seq=d.seq WHERE m.id='m1' AND d.endpoint_id='alice'`).Scan(&self)
|
||||||
if self != 0 {
|
if self != 0 {
|
||||||
@@ -363,6 +370,40 @@ func TestF06GroupSendMembership(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestF06GroupSendKeepOfflinePending(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
gApp, _, msgApp, db, _ := setup(t)
|
||||||
|
ctx := context.Background()
|
||||||
|
insertEP(t, db, "alice", 1)
|
||||||
|
insertEP(t, db, "bob", 1)
|
||||||
|
insertEP(t, db, "carol", 1)
|
||||||
|
created, err := gApp.Create(ctx, "alice", &protocol.GroupCreate{
|
||||||
|
V: protocol.Version, Type: protocol.TypeGroupCreate, RID: "1",
|
||||||
|
Name: "GKeep", Members: []protocol.GroupMemberIn{{ID: "bob"}, {ID: "carol"}},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ttl := int64(3600)
|
||||||
|
res, err := msgApp.Submit(ctx, "alice", port.ConnInfo{}, &protocol.Send{
|
||||||
|
V: protocol.Version, Type: protocol.TypeSend, RID: "s", ID: "mkeep",
|
||||||
|
To: protocol.Target{Kind: protocol.TargetGroup, ID: created.ID},
|
||||||
|
Body: protocol.Body{Enc: protocol.EncUTF8, Data: "kept"},
|
||||||
|
Offline: &protocol.OfflineOpts{Keep: true, TTLSeconds: &ttl},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if res.State != message.StateDispatched {
|
||||||
|
t.Fatalf("state=%s want dispatched (offline keep)", res.State)
|
||||||
|
}
|
||||||
|
var pending int
|
||||||
|
_ = db.Read.QueryRow(`SELECT COUNT(*) FROM deliveries d JOIN messages m ON m.seq=d.seq WHERE m.id='mkeep' AND d.state='pending'`).Scan(&pending)
|
||||||
|
if pending != 2 {
|
||||||
|
t.Fatalf("pending=%d want 2", pending)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGroupTransferRenameListGet(t *testing.T) {
|
func TestGroupTransferRenameListGet(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
gApp, _, _, db, _ := setup(t)
|
gApp, _, _, db, _ := setup(t)
|
||||||
|
|||||||
Reference in New Issue
Block a user