chore: refresh gramsrv public release
This commit is contained in:
parent
75cebe8dbf
commit
70b6820474
1274 changed files with 378751 additions and 59919 deletions
72
internal/mtprotoedge/conn_mgmt_fixes_test.go
Normal file
72
internal/mtprotoedge/conn_mgmt_fixes_test.go
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package mtprotoedge
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"github.com/gotd/td/proto"
|
||||
"github.com/gotd/td/tg"
|
||||
)
|
||||
|
||||
// TestPushSkipsConnReboundToOtherUser 锁定跨账号投递窗口的修复:pushToUserWithSender 在锁外
|
||||
// 发送前复查 c.userID。模拟「收集 conns 后、send 前」连接被并发换绑(atomic userID 改了但
|
||||
// byUser 索引尚未更新)的窗口,验证本属于 userA 的 update 不会投递到已易主为 userB 的连接。
|
||||
func TestPushSkipsConnReboundToOtherUser(t *testing.T) {
|
||||
sm := NewSessionManager(zaptest.NewLogger(t))
|
||||
const userA, userB = int64(100), int64(200)
|
||||
mk := func(sid int64, authKey byte) *Conn {
|
||||
c := &Conn{
|
||||
sessionID: sid,
|
||||
authKeyID: [8]byte{authKey},
|
||||
outbound: make(chan outboundOp, 4),
|
||||
outboundControl: make(chan outboundOp, 4),
|
||||
outboundStop: make(chan struct{}),
|
||||
}
|
||||
c.userID.Store(userA)
|
||||
c.userIDResolved.Store(true)
|
||||
c.receivesUpdates.Store(true)
|
||||
sm.Register(c)
|
||||
return c
|
||||
}
|
||||
stale := mk(1, 1) // 注册为 userA 后被换绑到 userB
|
||||
live := mk(2, 2) // 始终 userA
|
||||
|
||||
// 直接改 atomic userID、不动 byUser 索引:复现锁释放后到 send 前的换绑窗口。
|
||||
stale.userID.Store(userB)
|
||||
|
||||
// 走 best-effort 推送:与普通推送共用 pushToUserWithSender(含 userID 复查),但只入队
|
||||
// 不等 op.done,故无需起 outbound actor 即可观察「投递 vs 跳过」(op 进 buffered c.outbound)。
|
||||
if _, err := sm.PushToUserExceptSessionBestEffort(context.Background(), userA, 0, proto.MessageFromServer, &tg.UpdatesTooLong{}, time.Second); err != nil {
|
||||
t.Fatalf("push: %v", err)
|
||||
}
|
||||
if n := len(stale.outbound); n != 0 {
|
||||
t.Fatalf("rebound conn received %d ops, want 0 (must skip cross-account delivery)", n)
|
||||
}
|
||||
if n := len(live.outbound); n != 1 {
|
||||
t.Fatalf("live conn received %d ops, want 1", n)
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegisterEvictsAtSessionCap 锁定单 auth_key 的 session 数上限:超出 maxSessionsPerAuthKey
|
||||
// 的新 session 注册会驱逐一个现有 session,防对抗客户端用海量 session_id 撑爆索引。
|
||||
func TestRegisterEvictsAtSessionCap(t *testing.T) {
|
||||
sm := NewSessionManager(zaptest.NewLogger(t))
|
||||
authKey := [8]byte{7}
|
||||
for i := 1; i <= maxSessionsPerAuthKey+5; i++ {
|
||||
// 裸 Conn(无 outbound/rpc 通道):被驱逐时 Close() 为安全 no-op。
|
||||
sm.Register(&Conn{sessionID: int64(i), authKeyID: authKey})
|
||||
}
|
||||
sm.mu.RLock()
|
||||
perKey := len(sm.byAuthKey[authKey])
|
||||
total := len(sm.bySession)
|
||||
sm.mu.RUnlock()
|
||||
if perKey != maxSessionsPerAuthKey {
|
||||
t.Fatalf("sessions for auth key = %d, want cap %d", perKey, maxSessionsPerAuthKey)
|
||||
}
|
||||
if total != maxSessionsPerAuthKey {
|
||||
t.Fatalf("total online = %d, want %d", total, maxSessionsPerAuthKey)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue