76 lines
3.7 KiB
Go
76 lines
3.7 KiB
Go
package gateway
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
protocol "git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol/gen/go/protocol"
|
|
)
|
|
|
|
func TestValidateGatewayClipboardEnforcesServerOwnedPolicy(t *testing.T) {
|
|
policy := protocol.ClipboardPolicy{ClientToProviderEnabled: true, ProviderToClientEnabled: true, MaxTextBytes: 5, MaxUpdatesPerMinute: 2}
|
|
valid := protocol.GatewayClipboardText{Direction: "client_to_provider", Text: "hello", Encoding: "utf-8", LoopToken: "abcdefghijklmnop"}
|
|
if err := ValidateGatewayClipboard(policy, valid); err != nil {
|
|
t.Fatalf("ValidateGatewayClipboard() valid text = %v", err)
|
|
}
|
|
if err := ValidateGatewayClipboard(policy, protocol.GatewayClipboardText{Direction: "client_to_provider", Text: "hello", Encoding: "utf-8", LoopToken: "not base64url!"}); err == nil {
|
|
t.Fatal("ValidateGatewayClipboard() accepted malformed loop token")
|
|
}
|
|
if err := ValidateGatewayClipboard(policy, protocol.GatewayClipboardText{Direction: "client_to_provider", Text: strings.Repeat("x", 6), Encoding: "utf-8", LoopToken: "abcdefghijklmnop"}); err == nil {
|
|
t.Fatal("ValidateGatewayClipboard() accepted oversized text")
|
|
}
|
|
disabled := policy
|
|
disabled.ClientToProviderEnabled = false
|
|
if err := ValidateGatewayClipboard(disabled, valid); err == nil {
|
|
t.Fatal("ValidateGatewayClipboard() accepted disabled direction")
|
|
}
|
|
}
|
|
|
|
func TestClipboardGateSuppressesReflectionsAndBoundsRate(t *testing.T) {
|
|
now := time.Date(2026, time.January, 1, 0, 0, 0, 0, time.UTC)
|
|
policy := protocol.ClipboardPolicy{ClientToProviderEnabled: true, ProviderToClientEnabled: true, MaxTextBytes: 64, MaxUpdatesPerMinute: 2}
|
|
gate, err := newClipboardGate(policy, func() time.Time { return now })
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
client := protocol.GatewayClipboardText{Direction: "client_to_provider", Text: "client", Encoding: "utf-8", LoopToken: "abcdefghijklmnop"}
|
|
if suppress, err := gate.fromClient(client); err != nil || suppress {
|
|
t.Fatalf("fromClient() = suppress %t, err %v", suppress, err)
|
|
}
|
|
if _, suppress, err := gate.fromProvider("client"); err != nil || !suppress {
|
|
t.Fatalf("fromProvider() reflection = suppress %t, err %v", suppress, err)
|
|
}
|
|
host, suppress, err := gate.fromProvider("host")
|
|
if err != nil || suppress || host.Direction != "provider_to_client" {
|
|
t.Fatalf("fromProvider() host = %#v, suppress %t, err %v", host, suppress, err)
|
|
}
|
|
if suppress, err := gate.fromClient(host); err != nil || !suppress {
|
|
t.Fatalf("fromClient() host reflection = suppress %t, err %v", suppress, err)
|
|
}
|
|
if _, err := gate.fromClient(protocol.GatewayClipboardText{Direction: "client_to_provider", Text: "third", Encoding: "utf-8", LoopToken: "qrstuvwxyzABCDEF"}); !errors.Is(err, ErrClipboardRate) {
|
|
t.Fatalf("fromClient() rate error = %v, want ErrClipboardRate", err)
|
|
}
|
|
now = now.Add(time.Minute)
|
|
if suppress, err := gate.fromClient(protocol.GatewayClipboardText{Direction: "client_to_provider", Text: "after-window", Encoding: "utf-8", LoopToken: "0123456789abcdef"}); err != nil || suppress {
|
|
t.Fatalf("fromClient() after window = suppress %t, err %v", suppress, err)
|
|
}
|
|
}
|
|
|
|
func TestClipboardGatePermitsRetryAfterProviderWriteFailure(t *testing.T) {
|
|
policy := protocol.ClipboardPolicy{ClientToProviderEnabled: true, MaxTextBytes: 64, MaxUpdatesPerMinute: 2}
|
|
gate, err := newClipboardGate(policy, time.Now)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
value := protocol.GatewayClipboardText{Direction: "client_to_provider", Text: "retry", Encoding: "utf-8", LoopToken: "abcdefghijklmnop"}
|
|
if suppress, err := gate.fromClient(value); err != nil || suppress {
|
|
t.Fatalf("fromClient() = suppress %t, err %v", suppress, err)
|
|
}
|
|
gate.retractClient(value)
|
|
if suppress, err := gate.fromClient(value); err != nil || suppress {
|
|
t.Fatalf("fromClient() retry = suppress %t, err %v", suppress, err)
|
|
}
|
|
}
|