package grpcapi import ( "context" "crypto/sha256" "testing" "galaxy/gateway/internal/session" gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) func TestExecuteCommandRejectsPayloadHashWithInvalidLength(t *testing.T) { t.Parallel() delegate := &recordingEdgeGatewayService{} server, runGateway := newTestGateway(t, ServerDependencies{ Service: delegate, SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }}, }) defer runGateway.stop(t) addr := waitForListenAddr(t, server) conn := dialGatewayClient(t, addr) defer func() { require.NoError(t, conn.Close()) }() req := newValidExecuteCommandRequest() req.PayloadHash = []byte("short") client := gatewayv1.NewEdgeGatewayClient(conn) _, err := client.ExecuteCommand(context.Background(), req) require.Error(t, err) assert.Equal(t, codes.InvalidArgument, status.Code(err)) assert.Equal(t, "payload_hash must be a 32-byte SHA-256 digest", status.Convert(err).Message()) assert.Zero(t, delegate.executeCalls) } func TestExecuteCommandRejectsPayloadHashMismatch(t *testing.T) { t.Parallel() delegate := &recordingEdgeGatewayService{} server, runGateway := newTestGateway(t, ServerDependencies{ Service: delegate, SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }}, }) defer runGateway.stop(t) addr := waitForListenAddr(t, server) conn := dialGatewayClient(t, addr) defer func() { require.NoError(t, conn.Close()) }() req := newValidExecuteCommandRequest() sum := sha256.Sum256([]byte("other")) req.PayloadHash = sum[:] client := gatewayv1.NewEdgeGatewayClient(conn) _, err := client.ExecuteCommand(context.Background(), req) require.Error(t, err) assert.Equal(t, codes.InvalidArgument, status.Code(err)) assert.Equal(t, "payload_hash does not match payload_bytes", status.Convert(err).Message()) assert.Zero(t, delegate.executeCalls) } func TestSubscribeEventsRejectsPayloadHashWithInvalidLength(t *testing.T) { t.Parallel() delegate := &recordingEdgeGatewayService{} server, runGateway := newTestGateway(t, ServerDependencies{ Service: delegate, SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }}, }) defer runGateway.stop(t) addr := waitForListenAddr(t, server) conn := dialGatewayClient(t, addr) defer func() { require.NoError(t, conn.Close()) }() req := newValidSubscribeEventsRequest() req.PayloadHash = []byte("short") client := gatewayv1.NewEdgeGatewayClient(conn) err := subscribeEventsError(t, context.Background(), client, req) require.Error(t, err) assert.Equal(t, codes.InvalidArgument, status.Code(err)) assert.Equal(t, "payload_hash must be a 32-byte SHA-256 digest", status.Convert(err).Message()) assert.Zero(t, delegate.subscribeCalls) } func TestSubscribeEventsRejectsPayloadHashMismatch(t *testing.T) { t.Parallel() delegate := &recordingEdgeGatewayService{} server, runGateway := newTestGateway(t, ServerDependencies{ Service: delegate, SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }}, }) defer runGateway.stop(t) addr := waitForListenAddr(t, server) conn := dialGatewayClient(t, addr) defer func() { require.NoError(t, conn.Close()) }() req := newValidSubscribeEventsRequest() sum := sha256.Sum256([]byte("other")) req.PayloadHash = sum[:] client := gatewayv1.NewEdgeGatewayClient(conn) err := subscribeEventsError(t, context.Background(), client, req) require.Error(t, err) assert.Equal(t, codes.InvalidArgument, status.Code(err)) assert.Equal(t, "payload_hash does not match payload_bytes", status.Convert(err).Message()) assert.Zero(t, delegate.subscribeCalls) }