Files
VerseVDI-Protocol/tests/go/protocol_test.go
sechmachine c554cac00d
Verify Protocol / verify (push) Canceled after 0s
Verify Protocol / module (push) Successful in 53s
feat(protocol): carry complete encoded media frames
2026-07-30 22:23:22 +07:00

251 lines
14 KiB
Go

package protocol_test
import (
"reflect"
"strings"
"testing"
protocol "git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol/gen/go/protocol"
)
func TestManifestRejectsForbiddenAndUnknownFields(t *testing.T) {
valid := `{"version":"1","purpose":"launch","session_id":"session-1","reconnect_sequence":0,"gateway":{"id":"gateway-1","addresses":["gateway.control.test:443"],"public_identity":"gateway-1"},"tunnel":{"versions":["verse-gateway-v1/1"],"features":["control.v1"]},"profile":{"id":"standard","bounds":{"minimum_kbps":1,"target_kbps":2,"maximum_kbps":3}},"grant":{"opaque_value":"opaque-one-time-grant-value-with-at-least-43-bytes","expires_at":"2099-01-01T00:00:00Z","audience":"versevdi-gateway"},"correlation_id":"correlation-1"}`
manifest, err := protocol.DecodeConnectionManifest([]byte(valid))
if err != nil || manifest.Gateway.ID != "gateway-1" {
t.Fatalf("valid manifest = %+v, err = %v", manifest, err)
}
for _, field := range []string{"provider_url", "vm_address", "password"} {
payload := strings.Replace(valid, `"correlation_id":"correlation-1"`, `"correlation_id":"correlation-1","`+field+`":"forbidden"`, 1)
if _, err := protocol.DecodeConnectionManifest([]byte(payload)); err == nil {
t.Fatalf("DecodeConnectionManifest accepted forbidden field %q", field)
}
}
}
func TestPageInfoRejectsOutOfBoundsLimit(t *testing.T) {
if _, err := protocol.DecodePageInfo([]byte(`{"limit":101,"next_cursor":""}`)); err == nil {
t.Fatal("DecodePageInfo accepted limit above the contract maximum")
}
}
func TestGeneratedDecodersRejectMissingRequiredFieldsAndTrailingValues(t *testing.T) {
if _, err := protocol.DecodeErrorEnvelope([]byte(`{"status":false,"error":"safe","code":"invalid_request","message":"safe","resolution":"retry","violations":[]} {}`)); err == nil {
t.Fatal("DecodeErrorEnvelope accepted a trailing JSON value")
}
if _, err := protocol.DecodeErrorEnvelope([]byte(`{"error":"safe","code":"invalid_request","message":"safe","resolution":"retry","request_id":"req-1","violations":[]}`)); err == nil {
t.Fatal("DecodeErrorEnvelope accepted a missing required boolean")
}
}
func TestGatewayContractsRejectUnknownVersionsAndFields(t *testing.T) {
registration := `{"version":"1","gateway_id":"gateway-1","instance_identity":"instance-1","certificate_identity":"cert-1","public_identity":"public-1","address":"gateway.test:443","provider_identity":"apollo-provider-1","protocol_min_version":1,"protocol_max_version":1,"connection_capacity":8,"bandwidth_capacity_kbps":100000,"features":["datagram.media"],"capabilities":{"transport":"quic","framing":"datagram-v1","media":"encoded","audio":"encoded","source_rate_control":"server","client_decode":["h264-opus"]}}`
if _, err := protocol.DecodeGatewayRegistration([]byte(registration)); err != nil {
t.Fatalf("valid gateway registration rejected: %v", err)
}
for _, invalid := range []string{
strings.Replace(registration, `"version":"1"`, `"version":"2"`, 1),
strings.Replace(registration, `"version":"1"`, `"version":"0"`, 1),
strings.Replace(registration, `"features":["datagram.media"]`, `"features":["datagram.media"],"provider_url":"https://provider.invalid"`, 1),
} {
if _, err := protocol.DecodeGatewayRegistration([]byte(invalid)); err == nil {
t.Fatalf("invalid gateway registration accepted: %s", invalid)
}
}
if _, err := protocol.DecodeGatewayRegistration([]byte("{")); err == nil {
t.Fatal("DecodeGatewayRegistration accepted malformed JSON")
}
}
func TestGatewayRegistrationRejectsInvertedProtocolBounds(t *testing.T) {
registration := `{"version":"1","gateway_id":"gateway-1","instance_identity":"instance-1","certificate_identity":"cert-1","public_identity":"public-1","address":"gateway.test:443","provider_identity":"apollo-provider-1","protocol_min_version":2,"protocol_max_version":1,"connection_capacity":8,"bandwidth_capacity_kbps":100000,"features":["datagram.media"],"capabilities":{"transport":"quic","framing":"datagram-v1","media":"encoded","audio":"encoded","source_rate_control":"server","client_decode":["h264-opus"]}}`
if _, err := protocol.DecodeGatewayRegistration([]byte(registration)); err == nil {
t.Fatal("DecodeGatewayRegistration accepted inverted protocol bounds")
}
}
func TestGatewayHeartbeatCarriesBoundedObservedTelemetry(t *testing.T) {
valid := `{"version":"1","gateway_id":"gateway-1","sequence":1,"observed_at":"2099-01-01T00:00:00Z","active_connections":1,"egress_kbps":64,"state":"ready","telemetry":{"admitted_sessions":2,"admission_rejects":3,"reconnects":4,"drain_transitions":5,"media_drops":6,"media_packets":7,"media_bytes":8000,"queue_delay_micros":9,"processing_delay_micros":10,"processing_samples":11,"pacing_delay_micros":12,"provider_errors":13,"input_rejected":14,"control_rtt_micros":15,"control_jitter_micros":16,"control_loss_ppm":17,"pending_reliable":18,"provider_state":"ready"}}`
if _, err := protocol.DecodeGatewayHeartbeat([]byte(valid)); err != nil {
t.Fatalf("valid gateway heartbeat rejected: %v", err)
}
for _, invalid := range []string{
strings.Replace(valid, `,"telemetry":{`, `,"session_id":"forbidden","telemetry":{`, 1),
strings.Replace(valid, `"control_loss_ppm":17`, `"control_loss_ppm":1000001`, 1),
strings.Replace(valid, `"provider_state":"ready"`, `"provider_state":"provider.example:47984"`, 1),
} {
if _, err := protocol.DecodeGatewayHeartbeat([]byte(invalid)); err == nil {
t.Fatalf("invalid gateway heartbeat accepted: %s", invalid)
}
}
}
func TestCapabilityIntersectionRejectsNoOverlap(t *testing.T) {
first := protocol.CapabilityProfile{Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded", SourceRateControl: "server", ClientDecode: []string{"h264-opus"}}
if got, err := protocol.IntersectCapabilityProfiles(first, first); err != nil || !reflect.DeepEqual(got, first) {
t.Fatalf("IntersectCapabilityProfiles matching profiles = %+v, %v", got, err)
}
second := first
second.ClientDecode = []string{"hevc-opus"}
if _, err := protocol.IntersectCapabilityProfiles(first, second); err == nil {
t.Fatal("IntersectCapabilityProfiles accepted profiles without a common codec profile")
}
}
func TestCapabilityIntersectionSelectsRegisteredOrderedProfiles(t *testing.T) {
gateway := protocol.CapabilityProfile{
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded",
SourceRateControl: "server", ClientDecode: []string{"hevc-opus", "h264-opus"},
}
h264Client := gateway
h264Client.ClientDecode = []string{"h264-opus"}
selected, err := protocol.IntersectCapabilityProfiles(gateway, h264Client)
if err != nil || !reflect.DeepEqual(selected.ClientDecode, []string{"h264-opus"}) {
t.Fatalf("H.264 profile intersection = %+v, %v", selected, err)
}
hevcClient := gateway
hevcClient.ClientDecode = []string{"hevc-opus"}
selected, err = protocol.IntersectCapabilityProfiles(gateway, hevcClient)
if err != nil || !reflect.DeepEqual(selected.ClientDecode, []string{"hevc-opus"}) {
t.Fatalf("HEVC profile intersection = %+v, %v", selected, err)
}
noOverlap := gateway
noOverlap.ClientDecode = []string{"h264-opus"}
if _, err := protocol.IntersectCapabilityProfiles(noOverlap, hevcClient); err == nil {
t.Fatal("intersection accepted registered profiles without overlap")
}
for _, invalid := range [][]string{{"h264-hevc-opus"}, {"h264-opus", "h264-opus"}} {
profile := gateway
profile.ClientDecode = invalid
if err := profile.Validate(); err == nil {
t.Fatalf("CapabilityProfile accepted invalid registered profile set %q", invalid)
}
}
}
func TestCapabilityProfileRequiresRegisteredFraming(t *testing.T) {
valid := protocol.CapabilityProfile{
Transport: "quic-tls13", Framing: "datagram-v2", Media: "encoded",
Audio: "encoded", SourceRateControl: "server", ClientDecode: []string{"h264-opus"},
}
if err := valid.Validate(); err != nil {
t.Fatalf("registered datagram-v2 rejected: %v", err)
}
invalid := valid
invalid.Framing = "datagram-v3"
if err := invalid.Validate(); err == nil {
t.Fatal("unregistered framing accepted")
}
}
func TestTunnelAdmissionRequiresDeviceSignature(t *testing.T) {
request := protocol.TunnelAdmissionRequest{
Version: "1", SessionID: "session-1", GatewayID: "gateway-1", Audience: "versevdi-gateway",
Grant: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_", ReconnectSequence: 0,
ClientNonce: "0123456789abcdef", Capabilities: protocol.CapabilityProfile{
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded",
SourceRateControl: "server", ClientDecode: []string{"h264-opus"},
},
}
if _, err := protocol.EncodeTunnelAdmissionRequest(request); err == nil {
t.Fatal("EncodeTunnelAdmissionRequest accepted an unsigned device admission")
}
}
func TestTunnelAdmissionTranscriptIsDomainSeparatedAndLengthDelimited(t *testing.T) {
request := protocol.TunnelAdmissionRequest{
Version: "1", SessionID: "session", GatewayID: "gateway", Audience: "audience",
Grant: strings.Repeat("g", 43), ReconnectSequence: 0, ClientNonce: strings.Repeat("n", 16),
DeviceSignature: strings.Repeat("s", 86), Capabilities: protocol.CapabilityProfile{
Transport: "quic-tls13", Framing: "datagram-v1", Media: "encoded", Audio: "encoded",
SourceRateControl: "server", ClientDecode: []string{"h264-opus"},
},
}
want := "versevdi/tunnel-admission/v17:session7:gateway8:audience43:" + strings.Repeat("g", 43) + "1:016:" + strings.Repeat("n", 16) + "10:quic-tls1311:datagram-v17:encoded7:encoded6:server1:19:h264-opus"
if got := string(request.DeviceAdmissionTranscript()); got != want {
t.Fatalf("DeviceAdmissionTranscript() = %q, want %q", got, want)
}
}
func TestSessionAuthorityRejectsProviderRoute(t *testing.T) {
valid := `{"version":"1","session_id":"session-1","gateway_id":"gateway-1","audience":"versevdi-gateway","reconnect_sequence":0,"expires_at":"2099-01-01T00:00:00Z","capabilities":{"transport":"quic","framing":"datagram-v1","media":"encoded","audio":"encoded","source_rate_control":"server","client_decode":["h264-opus"]},"provider_profile":"apollo","provider_identity":"provider-1"}`
if _, err := protocol.DecodeSessionAuthority([]byte(valid)); err != nil {
t.Fatalf("valid session authority rejected: %v", err)
}
if _, err := protocol.DecodeSessionAuthority([]byte(strings.Replace(valid, `"provider_identity":"provider-1"`, `"provider_identity":"provider-1","rtsp_url":"rtsp://provider.invalid"`, 1))); err == nil {
t.Fatal("session authority accepted a provider route")
}
}
func TestProviderSessionWorkIsStrictAndSessionBound(t *testing.T) {
valid := `{"version":"1","session_id":"session-1","gateway_id":"gateway-1","reconnect_sequence":0,"expires_at":"2099-01-01T00:00:00Z","provider_profile":"apollo","provider_identity":"provider-1","policy_version_id":"policy-1","stream_policy":{"resolution_width":2560,"resolution_height":1440,"fps":120,"codec":"HEVC","bitrate_kbps":40000,"audio_enabled":true},"application_id":"42","client_id":"paired-client-1","management_host":"apollo.test","management_port":47990,"stream_host":"apollo.test","stream_port":47984,"client_certificate_pem":"certificate","client_private_key_pem":"private-key","server_certificate_pem":"server-certificate","clipboard_policy":{"client_to_provider_enabled":false,"provider_to_client_enabled":false,"max_text_bytes":65536,"max_updates_per_minute":30},"provider_application_termination_allowed":false}`
if _, err := protocol.DecodeProviderSessionWork([]byte(valid)); err != nil {
t.Fatalf("valid provider work rejected: %v", err)
}
if _, err := protocol.DecodeProviderSessionWork([]byte(strings.Replace(valid, `"application_id":"42"`, `"application_id":"42","management_password":"forbidden"`, 1))); err == nil {
t.Fatal("provider work accepted a management credential")
}
if _, err := protocol.DecodeProviderSessionWork([]byte(strings.Replace(valid, `,"clipboard_policy":{"client_to_provider_enabled":false,"provider_to_client_enabled":false,"max_text_bytes":65536,"max_updates_per_minute":30}`, "", 1))); err == nil {
t.Fatal("provider work accepted missing clipboard policy")
}
for _, invalid := range []string{
strings.Replace(valid, `,"stream_policy":{"resolution_width":2560,"resolution_height":1440,"fps":120,"codec":"HEVC","bitrate_kbps":40000,"audio_enabled":true}`, "", 1),
strings.Replace(valid, `"fps":120`, `"fps":241`, 1),
strings.Replace(valid, `"codec":"HEVC"`, `"codec":"VP9"`, 1),
strings.Replace(valid, `"audio_enabled":true`, `"audio_enabled":true,"unknown":false`, 1),
} {
if _, err := protocol.DecodeProviderSessionWork([]byte(invalid)); err == nil {
t.Fatalf("provider work accepted invalid stream policy: %s", invalid)
}
}
}
func TestGatewayClipboardAuditIsMetadataOnlyAndStrict(t *testing.T) {
valid := `{"version":"1","session_id":"session-1","direction":"client_to_provider","outcome":"rejected","text_bytes":64,"reason":"rate"}`
if _, err := protocol.DecodeGatewayClipboardAudit([]byte(valid)); err != nil {
t.Fatalf("valid clipboard audit rejected: %v", err)
}
for _, invalid := range []string{
strings.Replace(valid, `"reason":"rate"`, `"reason":"text"`, 1),
strings.Replace(valid, `"text_bytes":64`, `"text_bytes":65537`, 1),
strings.Replace(valid, `"reason":"rate"`, `"reason":"rate","text":"forbidden"`, 1),
} {
if _, err := protocol.DecodeGatewayClipboardAudit([]byte(invalid)); err == nil {
t.Fatalf("invalid clipboard audit accepted: %s", invalid)
}
}
}
func TestGatewayClipboardTextMeasuresDecodedUTF8Bytes(t *testing.T) {
for name, text := range map[string]string{
"ascii-boundary": strings.Repeat("a", 65536),
"utf8-boundary": strings.Repeat("é", 32768),
"escape-heavy": strings.Repeat(`"`, 32768),
} {
t.Run(name, func(t *testing.T) {
value := protocol.GatewayClipboardText{
Direction: "client_to_provider",
Text: text,
Encoding: "utf-8",
LoopToken: "abcdefghijklmnop",
}
encoded, err := protocol.EncodeGatewayClipboardText(value)
if err != nil {
t.Fatalf("EncodeGatewayClipboardText() error = %v", err)
}
decoded, err := protocol.DecodeGatewayClipboardText(encoded)
if err != nil || decoded.Text != text {
t.Fatalf("DecodeGatewayClipboardText() = %d bytes, %v", len(decoded.Text), err)
}
})
}
tooLarge := protocol.GatewayClipboardText{
Direction: "client_to_provider",
Text: strings.Repeat("a", 65537),
Encoding: "utf-8",
LoopToken: "abcdefghijklmnop",
}
if _, err := protocol.EncodeGatewayClipboardText(tooLarge); err == nil {
t.Fatal("EncodeGatewayClipboardText() accepted 65,537 decoded UTF-8 bytes")
}
}