package mtprotoedge import ( "bytes" "encoding/binary" "testing" "time" "github.com/iamxvbaba/td/proto" "go.uber.org/zap" ) // storeLogicalRPCResultForTest publishes the same production invariant as the // outbound actor: the exact rpc_result frame enters the logical-session outbox // before its metadata receipt becomes visible. Tests that call the receipt // ledger directly must not invent the old impossible state where a replay row // exists without an unacknowledged server frame. func storeLogicalRPCResultForTest( t *testing.T, s *Server, c *Conn, reqMsgID int64, encoded *encodedOutboundMessage, ) { t.Helper() if s == nil || c == nil || encoded == nil || len(encoded.body) == 0 { t.Fatal("invalid logical rpc_result fixture") } if c.outboundState == nil { s.conns.attachLogicalSession(c, s.outboundTrackedBudget) } else { s.conns.adoptLogicalSession(c) } physicalReqMsgID := encoded.writtenRequestID() if physicalReqMsgID == 0 { physicalReqMsgID = reqMsgID } frameBody := encoded.body if physicalReqMsgID != reqMsgID && encoded.typeID == proto.ResultTypeID { physical, err := cloneRPCResultForRequest(encoded, physicalReqMsgID, true) if err != nil { t.Fatalf("retarget logical rpc_result fixture: %v", err) } frameBody = physical.body } state := c.outboundState state.mu.Lock() if state.budget == nil || !state.budget.reserve(len(frameBody)) { state.mu.Unlock() t.Fatal("reserve logical rpc_result fixture") } candidate := reqMsgID*4 + 1 if candidate <= 0 { candidate = 1 } frame := &outboundFrame{ msgID: state.reserveMsgID(candidate), seqNo: state.peekSeqNo(true), typeID: proto.ResultTypeID, body: frameBody, reqMsgID: physicalReqMsgID, priority: encoded.priority, delivery: encoded.delivery, compressed: encoded.compressed, uncompressedBytes: encoded.uncompressedBytes, layer: encoded.layer, layerInvariant: encoded.layerInvariant, reservedBytes: len(frameBody), reservationBudget: state.budget, } if err := state.admitReserved(frame); err != nil { frame.releaseReservation(state.budget) state.mu.Unlock() t.Fatalf("admit logical rpc_result fixture: %v", err) } encoded.replayMsgID = frame.msgID encoded.replaySeqNo = frame.seqNo state.mu.Unlock() s.rpcResults.Complete(c.authKeyID, c.sessionID, reqMsgID, encoded, true) } func acknowledgeLogicalRPCResultForTest(t *testing.T, s *Server, c *Conn, reqMsgID int64) { t.Helper() if s == nil || c == nil || c.outboundState == nil { t.Fatal("missing logical rpc_result fixture") } state := c.outboundState state.mu.Lock() msgID := state.byRequest[reqMsgID] requestIDs := state.ack([]int64{msgID}) state.mu.Unlock() if len(requestIDs) != 1 || requestIDs[0] != reqMsgID { t.Fatalf("logical ACK resolved request ids %v", requestIDs) } if !s.rpcResults.Acknowledge(c.authKeyID, c.sessionID, reqMsgID) { t.Fatal("logical ACK did not release result receipt") } } func TestLogicalSessionOwnsExactResultAcrossPhysicalReconnect(t *testing.T) { manager := NewSessionManager(zap.NewNop()) budget := newOutboundTrackedBudget(1024) authKeyID := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} first := &Conn{authKeyID: authKeyID, sessionID: 42} manager.attachLogicalSession(first, budget) body := append([]byte{0xf3, 0x5c, 0x6d, 0xf3}, make([]byte, 28)...) binary.LittleEndian.PutUint64(body[4:12], uint64(77)) if !budget.reserve(len(body)) { t.Fatal("reserve result body") } frame := &outboundFrame{ msgID: 101, seqNo: 1, typeID: proto.ResultTypeID, body: body, reqMsgID: 77, reservedBytes: len(body), reservationBudget: budget, } first.outboundState.mu.Lock() if err := first.outboundState.admitReserved(frame); err != nil { first.outboundState.mu.Unlock() t.Fatalf("admit result: %v", err) } first.outboundState.mu.Unlock() second := &Conn{authKeyID: authKeyID, sessionID: 42} manager.attachLogicalSession(second, budget) if first.outboundState != second.outboundState { t.Fatal("physical reconnect did not reuse logical outbound state") } replay, ok := manager.rpcResult(authKeyID, 42, 77) if !ok { t.Fatal("logical result not found after reconnect") } if replay.replayMsgID != frame.msgID || replay.replaySeqNo != frame.seqNo || !bytes.Equal(replay.body, body) { t.Fatalf("replay identity/body = msg:%d seq:%d bytes:%d", replay.replayMsgID, replay.replaySeqNo, len(replay.body)) } if &replay.body[0] != &frame.body[0] { t.Fatal("replay created a second payload owner") } attempt, err := cloneRPCResultForRequest(replay, replay.reqMsgID, false) if err != nil { t.Fatalf("clone same-request replay descriptor: %v", err) } if attempt.replayMsgID != frame.msgID || attempt.replaySeqNo != frame.seqNo || !sameBacking(attempt.body, frame.body) { t.Fatal("queued duplicate lost stable logical frame identity") } } func TestLateCompletionAdoptionDoesNotClearOfflineRetention(t *testing.T) { manager := NewSessionManager(zap.NewNop()) budget := newOutboundTrackedBudget(1024) key := sessionKey{authKeyID: [8]byte{1, 3, 5, 7}, sessionID: 421} c := &Conn{authKeyID: key.authKeyID, sessionID: key.sessionID} manager.attachLogicalSession(c, budget) offlineAt := time.Unix(1_800_000_000, 0) manager.mu.Lock() manager.markLogicalSessionOfflineLocked(key, offlineAt) manager.mu.Unlock() manager.adoptLogicalSession(c) snapshot := manager.runtimeSnapshot() if snapshot.logical != 1 || snapshot.offlineLogical != 1 { t.Fatalf("late completion snapshot = logical:%d offline:%d, want 1/1", snapshot.logical, snapshot.offlineLogical) } manager.sweepLogicalSessions(offlineAt.Add(logicalSessionOfflineTTL + time.Second)) snapshot = manager.runtimeSnapshot() if snapshot.logical != 0 || snapshot.offlineLogical != 0 { t.Fatalf("post-TTL snapshot = logical:%d offline:%d, want 0/0", snapshot.logical, snapshot.offlineLogical) } } func TestRetiredLateCompletionCannotRecreateDestroyedLogicalSession(t *testing.T) { manager := NewSessionManager(zap.NewNop()) budget := newOutboundTrackedBudget(1024) key := sessionKey{authKeyID: [8]byte{2, 4, 6, 8}, sessionID: 422} c := &Conn{authKeyID: key.authKeyID, sessionID: key.sessionID} manager.attachLogicalSession(c, budget) c.retire() manager.mu.Lock() state := manager.destroyLogicalSessionLocked(key) manager.mu.Unlock() manager.releaseLogicalSession(key, state) manager.adoptLogicalSession(c) if snapshot := manager.runtimeSnapshot(); snapshot.logical != 0 { t.Fatalf("retired late completion recreated %d logical sessions", snapshot.logical) } } func TestLogicalSessionACKReleasesPayloadAndReceipt(t *testing.T) { manager := NewSessionManager(zap.NewNop()) budget := newOutboundTrackedBudget(1024) authKeyID := [8]byte{8, 7, 6, 5, 4, 3, 2, 1} c := &Conn{authKeyID: authKeyID, sessionID: 43} manager.attachLogicalSession(c, budget) body := make([]byte, 64) if !budget.reserve(len(body)) { t.Fatal("reserve result body") } frame := &outboundFrame{ msgID: 201, seqNo: 1, typeID: proto.ResultTypeID, body: body, reqMsgID: 88, reservedBytes: len(body), reservationBudget: budget, } c.outboundState.mu.Lock() if err := c.outboundState.admitReserved(frame); err != nil { c.outboundState.mu.Unlock() t.Fatalf("admit result: %v", err) } c.outboundState.mu.Unlock() ledger := newRPCExecutionLedger(time.Now, rpcExecutionLedgerCapacity{ maxPending: 16, maxPendingPerAuth: 16, globalMaxEntries: 16, authMaxEntries: 16, sessionMaxEntries: 16, replayStore: manager, }) claim, err := ledger.Acquire(authKeyID, 43, 88) if err != nil || claim.state != rpcResultAcquireOwner { t.Fatalf("acquire owner = %#v, %v", claim, err) } claim.owner.CompleteExecution(true) claim.owner.HandOff() ledger.Complete(authKeyID, 43, 88, &encodedOutboundMessage{body: body, typeID: proto.ResultTypeID, reqMsgID: 88}, true) key := rpcExecutionKey{authKeyID: authKeyID, sessionID: 43, reqMsgID: 88} shard := ledger.shard(key) shard.mu.Lock() entry := shard.byKey[key].Value.(*rpcExecutionReceipt) if entry.unavailable { shard.mu.Unlock() t.Fatal("logical outbox receipt was marked unavailable") } shard.mu.Unlock() if got := ledger.receiptBudgetBytes(); got != rpcExecutionReceiptBudgetBytes { t.Fatalf("receipt budget bytes = %d, want %d", got, rpcExecutionReceiptBudgetBytes) } c.outboundState.mu.Lock() acked := c.outboundState.ack([]int64{201}) c.outboundState.mu.Unlock() if len(acked) != 1 || acked[0] != 88 { t.Fatalf("acked request ids = %v", acked) } if !ledger.Acknowledge(authKeyID, 43, 88) { t.Fatal("ledger did not observe ACK") } if got := budget.snapshot(); got != 0 { t.Fatalf("tracked payload bytes after ACK = %d", got) } shard.mu.Lock() _, retained := shard.byKey[key] shard.mu.Unlock() if retained { t.Fatal("ACK retained a completed receipt") } } func TestLogicalSessionCapacityNeverEvictsUnackedFrame(t *testing.T) { budget := newOutboundTrackedBudget(1024) state := newOutboundStateWithLimits(budget, 1, 16) firstBody := make([]byte, 8) if !budget.reserve(len(firstBody)) { t.Fatal("reserve first body") } first := &outboundFrame{ msgID: 1, seqNo: 1, typeID: proto.ResultTypeID, body: firstBody, reqMsgID: 11, reservedBytes: len(firstBody), reservationBudget: budget, } if err := state.admitReserved(first); err != nil { t.Fatalf("admit first: %v", err) } second := &outboundFrame{msgID: 2, seqNo: 3, typeID: proto.ResultTypeID, body: make([]byte, 8), reqMsgID: 12} if err := state.admitReserved(second); err == nil { t.Fatal("capacity admitted a second unacknowledged frame") } if state.pending[first.msgID] != first || state.byRequest[first.reqMsgID] != first.msgID { t.Fatal("capacity failure evicted or rewired the existing frame") } state.releaseAll() } func TestLogicalSessionDestroyReleasesPayloadAndCompletedReceipt(t *testing.T) { s := New(Options{}) authKeyID := [8]byte{9, 1} c := &Conn{authKeyID: authKeyID, sessionID: 91} claim, err := s.rpcResults.Acquire(authKeyID, 91, 901) if err != nil || claim.owner == nil { t.Fatalf("acquire owner: %#v err=%v", claim, err) } claim.owner.CompleteExecution(true) storeLogicalRPCResultForTest(t, s, c, 901, &encodedOutboundMessage{ body: make([]byte, 32), typeID: proto.ResultTypeID, reqMsgID: 901, }) if _, ok := s.rpcResults.Replay(authKeyID, 91, 901); !ok { t.Fatal("logical result fixture was not published") } if removed := s.conns.DestroySessionForAuthKey(authKeyID, 91); removed { t.Fatal("construction-only logical session unexpectedly reported active") } if _, ok := s.rpcResults.Replay(authKeyID, 91, 901); ok { t.Fatal("destroy retained completed receipt") } if got := s.outboundTrackedBudget.snapshot(); got != 0 { t.Fatalf("destroy retained %d payload bytes", got) } } func TestBusinessAuthRevocationReleasesOfflineTempLogicalSession(t *testing.T) { s := New(Options{}) rawAuthKeyID := [8]byte{9, 2} businessAuthKeyID := [8]byte{9, 3} c := &Conn{authKeyID: rawAuthKeyID, sessionID: 92} c.SetBusinessAuthKeyID(businessAuthKeyID) claim, err := s.rpcResults.Acquire(rawAuthKeyID, 92, 902) if err != nil || claim.owner == nil { t.Fatalf("acquire owner: %#v err=%v", claim, err) } claim.owner.CompleteExecution(true) storeLogicalRPCResultForTest(t, s, c, 902, &encodedOutboundMessage{ body: make([]byte, 48), typeID: proto.ResultTypeID, reqMsgID: 902, }) if closed := s.conns.CloseSessionsForBusinessAuthKey(businessAuthKeyID); closed != 0 { t.Fatalf("offline logical revocation closed %d physical conns", closed) } if _, ok := s.rpcResults.Replay(rawAuthKeyID, 92, 902); ok { t.Fatal("business auth revocation retained temp-key receipt") } if got := s.outboundTrackedBudget.snapshot(); got != 0 { t.Fatalf("business auth revocation retained %d payload bytes", got) } }