owpengram-server/internal/mtprotoedge/layer_rpc_execution_test.go

154 lines
5 KiB
Go

package mtprotoedge
import (
"context"
"errors"
"sync/atomic"
"testing"
"time"
"github.com/iamxvbaba/td/bin"
"github.com/iamxvbaba/td/mt"
"github.com/iamxvbaba/td/proto"
"github.com/iamxvbaba/td/tg"
"github.com/iamxvbaba/td/tlprofile"
)
// preparedOnlyLayerRPCResult is intentionally incapable of encoding. The
// binding guard must reject it solely from immutable admission identity before
// any result method other than Prepared can be observed.
type preparedOnlyLayerRPCResult struct {
tlprofile.Result
prepared tlprofile.PreparedCall
}
func (r *preparedOnlyLayerRPCResult) Prepared() tlprofile.PreparedCall { return r.prepared }
func TestBindAdmittedLayerRPCResultRequiresExactRequestIdentity(t *testing.T) {
dispatcher := tlprofile.NewDispatcher()
admit := func(request bin.Encoder) tlprofile.Admission {
t.Helper()
body := &bin.Buffer{Buf: exactLayerRPCBody(t, request)}
admitted, err := dispatcher.Admit(tlprofile.Profile227, body, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
return admitted
}
request := admit(&tg.HelpGetConfigRequest{})
other := admit(&tg.HelpGetNearestDCRequest{})
if _, err := bindAdmittedLayerRPCResult(request, &preparedOnlyLayerRPCResult{prepared: other.Prepared()}); !errors.Is(err, errLayerRPCResultIdentityMismatch) {
t.Fatalf("mismatched result error = %v, want %v", err, errLayerRPCResultIdentityMismatch)
}
bound, err := bindAdmittedLayerRPCResult(request, &preparedOnlyLayerRPCResult{prepared: request.Prepared()})
if err != nil {
t.Fatal(err)
}
if bound == nil || bound.call.Identity() != request.Call().Identity() {
t.Fatal("matching result did not retain the admitted call identity")
}
}
type mismatchedProjectionLayerRPC struct {
*admissionOnlyLayerRPC
result tlprofile.Result
calls atomic.Int32
}
func (h *mismatchedProjectionLayerRPC) DispatchAdmitted(
context.Context,
[8]byte,
int64,
int64,
uint64,
tlprofile.Admission,
) (tlprofile.Result, string, error) {
h.calls.Add(1)
return h.result, "help.getConfig", nil
}
func TestProjectionFailureCachesInternalWithoutRepeatingBusiness(t *testing.T) {
dispatcher := tlprofile.NewDispatcher()
admit := func(request bin.Encoder) tlprofile.Admission {
t.Helper()
body := &bin.Buffer{Buf: exactLayerRPCBody(t, request)}
admitted, err := dispatcher.Admit(tlprofile.Profile227, body, tlprofile.Limits{})
if err != nil {
t.Fatal(err)
}
return admitted
}
request := admit(&tg.HelpGetConfigRequest{})
other := admit(&tg.HelpGetNearestDCRequest{})
handler := &mismatchedProjectionLayerRPC{
admissionOnlyLayerRPC: newAdmissionOnlyLayerRPC(),
result: &preparedOnlyLayerRPCResult{prepared: other.Prepared()},
}
s := New(Options{DC: 2, LayerRPC: handler})
c := newOutboundTestConn(t, &collectingSessionTransport{}, newOutboundTrackedBudget(1<<20))
c.authKeyID = [8]byte{0x41, 0x01}
c.sessionID = 4101
const reqMsgID = int64(410100)
claim, err := s.rpcResults.AcquireLayerIdentified(
c.authKeyID, c.sessionID, reqMsgID,
tlprofile.Profile227, request.Prepared().Identity(),
)
if err != nil || claim.owner == nil {
t.Fatalf("owner acquisition err=%v", err)
}
if err := s.handleAdmittedLayerRPC(
context.Background(), c, reqMsgID, claim.admissionSeq,
"help.getConfig", request, claim.owner,
); err != nil {
t.Fatalf("publish projection failure: %v", err)
}
deadline := time.Now().Add(2 * time.Second)
var completed rpcResultAcquire
for {
completed, err = s.rpcResults.AcquireLayerIdentified(
c.authKeyID, c.sessionID, reqMsgID,
tlprofile.Profile227, request.Prepared().Identity(),
)
if err == nil && completed.state == rpcResultAcquireCompleted {
break
}
if time.Now().After(deadline) {
t.Fatalf("projection failure did not become completed: state=%d err=%v", completed.state, err)
}
time.Sleep(time.Millisecond)
}
if !completed.executionKnown || !completed.executionOK {
t.Fatalf("projection failure lost successful business outcome: known=%v ok=%v", completed.executionKnown, completed.executionOK)
}
if got := handler.calls.Load(); got != 1 {
t.Fatalf("business calls=%d, want 1", got)
}
var envelope proto.Result
if err := envelope.Decode(&bin.Buffer{Buf: completed.encoded.body}); err != nil {
t.Fatal(err)
}
var rpcErr mt.RPCError
if err := rpcErr.Decode(&bin.Buffer{Buf: envelope.Result}); err != nil {
t.Fatal(err)
}
if rpcErr.ErrorCode != 500 || rpcErr.ErrorMessage != "INTERNAL" {
t.Fatalf("projection terminal = %+v", rpcErr)
}
// A same-msg replay is served from the completed exact identity; there is no
// second DispatchAdmitted call even though projection failed after business
// success.
replay, err := s.rpcResults.AcquireLayerIdentified(
c.authKeyID, c.sessionID, reqMsgID,
tlprofile.Profile227, request.Prepared().Identity(),
)
if err != nil || replay.state != rpcResultAcquireCompleted || replay.encoded != completed.encoded {
t.Fatalf("projection replay = state:%d err:%v", replay.state, err)
}
if got := handler.calls.Load(); got != 1 {
t.Fatalf("replay repeated business calls=%d", got)
}
}