Files
galaxy-game/integration/anti_replay_test.go
2026-05-06 10:14:55 +03:00

60 lines
1.7 KiB
Go

package integration_test
import (
"context"
"testing"
"time"
"galaxy/integration/testenv"
usermodel "galaxy/model/user"
"galaxy/transcoder"
"github.com/google/uuid"
)
// TestAntiReplay_DuplicateRequestID submits the same authenticated
// request_id twice within the freshness window and asserts the
// second attempt is rejected by gateway as a replay (Redis
// reservation check).
func TestAntiReplay_DuplicateRequestID(t *testing.T) {
plat := testenv.Bootstrap(t, testenv.BootstrapOptions{})
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
sess := testenv.RegisterSession(t, plat, "pilot+replay@example.com")
gw, err := sess.DialAuthenticated(ctx, plat)
if err != nil {
t.Fatalf("dial: %v", err)
}
defer gw.Close()
payload, err := transcoder.GetMyAccountRequestToPayload(&usermodel.GetMyAccountRequest{})
if err != nil {
t.Fatalf("encode payload: %v", err)
}
requestID := uuid.NewString()
timestamp := time.Now().UnixMilli()
first, err := gw.Execute(ctx, usermodel.MessageTypeGetMyAccount, payload, testenv.ExecuteOptions{
RequestID: requestID,
TimestampMS: timestamp,
})
if err != nil {
t.Fatalf("first call failed: %v", err)
}
if first.ResultCode != "ok" {
t.Fatalf("first call result_code = %q, want ok", first.ResultCode)
}
_, err = gw.Execute(ctx, usermodel.MessageTypeGetMyAccount, payload, testenv.ExecuteOptions{
RequestID: requestID,
TimestampMS: timestamp,
})
if err == nil {
t.Fatalf("replay accepted: expected rejection on duplicate request_id")
}
if !testenv.IsFailedPrecondition(err) && !testenv.IsResourceExhausted(err) && !testenv.IsUnauthenticated(err) && !testenv.IsInvalidArgument(err) {
t.Fatalf("replay rejection has unexpected status: %v", err)
}
}