47 lines
2.8 KiB
Go
47 lines
2.8 KiB
Go
package companion
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// This exercises the bounded claim/ack/complete boundary as one flow. The
|
|
// fixture deliberately mixes replay, expired, malformed, unsupported, and
|
|
// redaction-sensitive commands so none can fall through to an adapter.
|
|
func TestDispatcherIntegrationContainsUnsafeAndUnavailableCommands(t *testing.T) {
|
|
stamp := time.Now().UTC()
|
|
adapter := &adapterFixture{}
|
|
registry := NewHandlerRegistry(HandlerAvailability{
|
|
BoundServerID: "server-1", Approved: true,
|
|
Capabilities: map[string]bool{"config.read": true},
|
|
}, adapter)
|
|
fixture := &dispatchFixture{commands: []ClaimedCommand{
|
|
{ID: "safe-read", ProfileKey: ProfileKey, CommandType: "config.read", Payload: map[string]any{}, FencingToken: 1, LeaseExpiresAt: stamp.Add(time.Minute), ExpiresAt: stamp.Add(time.Minute)},
|
|
{ID: "safe-read", ProfileKey: ProfileKey, CommandType: "config.read", Payload: map[string]any{}, FencingToken: 1, LeaseExpiresAt: stamp.Add(time.Minute), ExpiresAt: stamp.Add(time.Minute)},
|
|
{ID: "cancelled-before-claim", ProfileKey: ProfileKey, CommandType: "config.read", Payload: map[string]any{}, FencingToken: 2, LeaseExpiresAt: stamp.Add(-time.Second), ExpiresAt: stamp.Add(-time.Second)},
|
|
{ID: "malformed", ProfileKey: ProfileKey, CommandType: "raw.rcon", Payload: map[string]any{}, FencingToken: 3, LeaseExpiresAt: stamp.Add(time.Minute), ExpiresAt: stamp.Add(time.Minute)},
|
|
{ID: "unsupported-version", ProfileKey: ProfileKey, CommandType: "player.notify", Payload: map[string]any{"playerId": "76561198000000001", "message": "Moonlight"}, FencingToken: 4, LeaseExpiresAt: stamp.Add(time.Minute), ExpiresAt: stamp.Add(time.Minute)},
|
|
}}
|
|
|
|
dispatcher := Dispatcher{Client: fixture, Registry: registry, Now: func() time.Time { return stamp }}
|
|
if err := dispatcher.DispatchOnce(context.Background()); err != nil {
|
|
t.Fatalf("dispatch integration: %v", err)
|
|
}
|
|
if adapter.reads != 1 {
|
|
t.Fatalf("duplicate delivery invoked the adapter %d times", adapter.reads)
|
|
}
|
|
if len(fixture.acks) != 3 || fixture.acks[0] != "safe-read" || fixture.acks[1] != "safe-read" || fixture.acks[2] != "unsupported-version" {
|
|
t.Fatalf("only live, validated commands may be acknowledged: %v", fixture.acks)
|
|
}
|
|
if len(fixture.completed) != 5 {
|
|
t.Fatalf("every claimed command needs a terminal result: %+v", fixture.completed)
|
|
}
|
|
if fixture.completed[0].Payload["hostPath"] != nil || fixture.completed[1].Payload["hostPath"] != nil {
|
|
t.Fatalf("adapter output leaked protected details: %+v", fixture.completed[:2])
|
|
}
|
|
if fixture.completed[2].Payload["result"] != "validation-failed" || fixture.completed[3].Payload["result"] != "validation-failed" || fixture.completed[4].Payload["result"] != "unsupported" {
|
|
t.Fatalf("terminal failure classification is unsafe: %+v", fixture.completed)
|
|
}
|
|
}
|