60 lines
1.7 KiB
Go
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)
|
|
}
|
|
}
|