Files
rdp-proxy/agents/rap-node-agent/internal/mesh/synthetic_test_service_test.go
T
2026-04-28 22:29:50 +03:00

236 lines
9.6 KiB
Go

package mesh
import (
"context"
"encoding/json"
"errors"
"strings"
"testing"
)
func TestSyntheticRuntimeTestServiceDirectRoute(t *testing.T) {
route := testServiceRoute("route-test-service-direct", []string{"node-a", "node-b"})
transport := syntheticTestTransport{nodes: map[string]*SyntheticRuntime{}}
nodeA := testRuntime("node-a", transport, route)
nodeB := testRuntime("node-b", transport, route)
transport.nodes["node-a"] = nodeA
transport.nodes["node-b"] = nodeB
result, err := nodeA.SendTestService(context.Background(), route.RouteID, SyntheticChannelRouteControl, testServiceRequest("request-direct", "hello"))
if err != nil {
t.Fatalf("send test service: %v", err)
}
if result.Ack.MessageType != SyntheticMessageTestServiceAck {
t.Fatalf("MessageType = %q, want %q", result.Ack.MessageType, SyntheticMessageTestServiceAck)
}
if result.Response.EchoPayload != "hello" {
t.Fatalf("EchoPayload = %q, want hello", result.Response.EchoPayload)
}
if len(result.Response.Path) != 2 || result.Response.Path[0] != "node-a" || result.Response.Path[1] != "node-b" {
t.Fatalf("Path = %#v, want node-a -> node-b", result.Response.Path)
}
metrics := nodeA.SnapshotMetrics()
if metrics.TestServiceRequestsSent != 1 || metrics.TestServiceDeliveriesSucceeded != 1 {
t.Fatalf("metrics = %+v, want one test service success", metrics)
}
}
func TestSyntheticRuntimeTestServiceSingleRelayRoute(t *testing.T) {
route := testServiceRoute("route-test-service-relay", []string{"node-a", "node-r", "node-b"})
transport := syntheticTestTransport{nodes: map[string]*SyntheticRuntime{}}
nodeA := testRuntime("node-a", transport, route)
nodeR := testRuntime("node-r", transport, route)
nodeB := testRuntime("node-b", transport, route)
transport.nodes["node-a"] = nodeA
transport.nodes["node-r"] = nodeR
transport.nodes["node-b"] = nodeB
result, err := nodeA.SendTestService(context.Background(), route.RouteID, SyntheticChannelRouteControl, testServiceRequest("request-relay", "relay"))
if err != nil {
t.Fatalf("send test service: %v", err)
}
if len(result.Response.Path) != 3 || result.Response.Path[0] != "node-a" || result.Response.Path[1] != "node-r" || result.Response.Path[2] != "node-b" {
t.Fatalf("Path = %#v, want node-a -> node-r -> node-b", result.Response.Path)
}
if nodeR.SnapshotMetrics().ProbesForwarded != 1 {
t.Fatalf("ProbesForwarded = %d, want 1", nodeR.SnapshotMetrics().ProbesForwarded)
}
}
func TestSyntheticRuntimeTestServiceUsesForcedFallback(t *testing.T) {
preferred := testServiceRoute("route-test-service-preferred", []string{"node-a", "node-r", "node-b"})
fallback := testServiceRoute("route-test-service-fallback", []string{"node-a", "node-b"})
transport := syntheticTestTransport{nodes: map[string]*SyntheticRuntime{}}
nodeA := testRuntime("node-a", transport, preferred, fallback)
nodeB := testRuntime("node-b", transport, preferred, fallback)
transport.nodes["node-a"] = nodeA
transport.nodes["node-b"] = nodeB
result, err := nodeA.SendTestServiceWithFallback(
context.Background(),
preferred.RouteID,
[]string{fallback.RouteID},
SyntheticChannelRouteControl,
testServiceRequest("request-fallback", "fallback"),
)
if err != nil {
t.Fatalf("send test service with fallback: %v", err)
}
if !result.FallbackUsed {
t.Fatal("FallbackUsed = false, want true")
}
if result.SelectedRouteID != fallback.RouteID {
t.Fatalf("SelectedRouteID = %q, want %q", result.SelectedRouteID, fallback.RouteID)
}
if result.Response.EchoPayload != "fallback" {
t.Fatalf("EchoPayload = %q, want fallback", result.Response.EchoPayload)
}
metrics := nodeA.SnapshotMetrics()
if metrics.TestServiceFallbacksUsed != 1 || metrics.TestServiceDeliveriesFailed != 1 || metrics.TestServiceDeliveriesSucceeded != 1 {
t.Fatalf("metrics = %+v, want fallback success with one preferred failure", metrics)
}
}
func TestSyntheticRuntimeTestServiceRejectsWrongOrganization(t *testing.T) {
route := testServiceRoute("route-test-service-wrong-org", []string{"node-a", "node-b"})
nodeA := testRuntime("node-a", syntheticTestTransport{}, route)
request := testServiceRequest("request-wrong-org", "hello")
request.OrganizationID = "org-other"
_, err := nodeA.SendTestService(context.Background(), route.RouteID, SyntheticChannelRouteControl, request)
if !errors.Is(err, ErrSyntheticOrganizationMismatch) {
t.Fatalf("err = %v, want ErrSyntheticOrganizationMismatch", err)
}
}
func TestSyntheticRuntimeTestServiceRejectsUnsupportedService(t *testing.T) {
route := testServiceRoute("route-test-service-unsupported", []string{"node-a", "node-b"})
nodeA := testRuntime("node-a", syntheticTestTransport{}, route)
request := testServiceRequest("request-unsupported", "hello")
request.ServiceType = "rdp"
_, err := nodeA.SendTestService(context.Background(), route.RouteID, SyntheticChannelRouteControl, request)
if !errors.Is(err, ErrUnsupportedSyntheticService) {
t.Fatalf("err = %v, want ErrUnsupportedSyntheticService", err)
}
}
func TestSyntheticRuntimeTestServiceRejectsOversizedPayload(t *testing.T) {
route := testServiceRoute("route-test-service-oversized", []string{"node-a", "node-b"})
nodeA := NewSyntheticRuntime(SyntheticRuntimeConfig{
Enabled: true,
Local: PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"},
Routes: []SyntheticRoute{route},
MaxTestPayloadBytes: 4,
})
_, err := nodeA.SendTestService(context.Background(), route.RouteID, SyntheticChannelRouteControl, testServiceRequest("request-oversized", "12345"))
if !errors.Is(err, ErrSyntheticPayloadTooLarge) {
t.Fatalf("err = %v, want ErrSyntheticPayloadTooLarge", err)
}
}
func TestSyntheticRuntimeTestServiceRejectsUnauthorizedChannel(t *testing.T) {
route := testServiceRoute("route-test-service-channel", []string{"node-a", "node-b"})
nodeA := testRuntime("node-a", syntheticTestTransport{}, route)
_, err := nodeA.SendTestService(context.Background(), route.RouteID, SyntheticChannelFabricControl, testServiceRequest("request-channel", "hello"))
if !errors.Is(err, ErrUnauthorizedChannel) {
t.Fatalf("err = %v, want ErrUnauthorizedChannel", err)
}
}
func TestSyntheticRuntimeTestServiceDisabledRejects(t *testing.T) {
route := testServiceRoute("route-test-service-disabled", []string{"node-a", "node-b"})
nodeA := NewSyntheticRuntime(SyntheticRuntimeConfig{
Enabled: false,
Local: PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"},
Routes: []SyntheticRoute{route},
})
_, err := nodeA.SendTestService(context.Background(), route.RouteID, SyntheticChannelRouteControl, testServiceRequest("request-disabled", "hello"))
if !errors.Is(err, ErrMeshRuntimeDisabled) {
t.Fatalf("err = %v, want ErrMeshRuntimeDisabled", err)
}
}
func TestSyntheticRelaySchedulerAcceptsTestServiceMessage(t *testing.T) {
scheduler := testRelayScheduler()
envelope := testRelayEnvelope(SyntheticChannelRouteControl, SyntheticMessageTestService, 42)
envelope.Payload = mustMarshalTestServiceRequest(testServiceRequest("request-relay-scheduler", "hello"))
if _, err := scheduler.Enqueue(envelope); err != nil {
t.Fatalf("enqueue test service: %v", err)
}
dequeued, err := scheduler.Dequeue()
if err != nil {
t.Fatalf("dequeue test service: %v", err)
}
if dequeued.MessageType != SyntheticMessageTestService {
t.Fatalf("MessageType = %q, want %q", dequeued.MessageType, SyntheticMessageTestService)
}
}
func testServiceRoute(routeID string, hops []string) SyntheticRoute {
route := testRoute(routeID, hops)
route.AllowedChannels = []string{SyntheticChannelRouteControl}
return route
}
func testServiceRequest(requestID string, payload string) SyntheticTestServiceRequest {
return SyntheticTestServiceRequest{
RequestID: requestID,
OrganizationID: SyntheticDefaultTestOrganizationID,
ServiceType: SyntheticTestServiceType,
Payload: payload,
}
}
func mustMarshalTestServiceRequest(request SyntheticTestServiceRequest) []byte {
payload, err := json.Marshal(request)
if err != nil {
panic(err)
}
return payload
}
func TestSyntheticRuntimeTestServiceRejectsMissingRequestID(t *testing.T) {
route := testServiceRoute("route-test-service-missing-request", []string{"node-a", "node-b"})
nodeA := testRuntime("node-a", syntheticTestTransport{}, route)
request := testServiceRequest("", "hello")
_, err := nodeA.SendTestService(context.Background(), route.RouteID, SyntheticChannelRouteControl, request)
if !errors.Is(err, ErrSyntheticRequestInvalid) {
t.Fatalf("err = %v, want ErrSyntheticRequestInvalid", err)
}
}
func TestSyntheticRuntimeTestServiceAllowsMaxPayloadBoundary(t *testing.T) {
route := testServiceRoute("route-test-service-max", []string{"node-a", "node-b"})
transport := syntheticTestTransport{nodes: map[string]*SyntheticRuntime{}}
nodeA := NewSyntheticRuntime(SyntheticRuntimeConfig{
Enabled: true,
Local: PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"},
Routes: []SyntheticRoute{route},
Transport: transport,
MaxTestPayloadBytes: 8,
})
nodeB := NewSyntheticRuntime(SyntheticRuntimeConfig{
Enabled: true,
Local: PeerIdentity{ClusterID: "cluster-1", NodeID: "node-b"},
Routes: []SyntheticRoute{route},
Transport: transport,
MaxTestPayloadBytes: 8,
})
transport.nodes["node-a"] = nodeA
transport.nodes["node-b"] = nodeB
result, err := nodeA.SendTestService(context.Background(), route.RouteID, SyntheticChannelRouteControl, testServiceRequest("request-max", strings.Repeat("a", 8)))
if err != nil {
t.Fatalf("send test service: %v", err)
}
if result.Response.EchoPayload != strings.Repeat("a", 8) {
t.Fatalf("EchoPayload = %q", result.Response.EchoPayload)
}
}