// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package tentacle import ( "encoding/json" "errors" "strings" "testing" "git.stormux.org/storm/cthulhu/internal/tentaclewire" ) func focusRequest(lease tentaclewire.RemoteLease, sequence uint64, remote bool) tentaclewire.RemoteFocusRequest { return tentaclewire.RemoteFocusRequest{RemoteOperation: tentaclewire.RemoteOperation{Lease: lease.Lease, Epoch: lease.Epoch, Sequence: sequence}, Remote: remote} } func nextSDKEvent(t *testing.T, session *Session) tentaclewire.SessionEvent { t.Helper() var event tentaclewire.SessionEvent if err := json.Unmarshal(invokeSessionSDK(t, session, "event", nil), &event); err != nil { t.Fatal(err) } return event } func TestRemoteCaptureSDKFocusAndInputEvents(t *testing.T) { for _, language := range []string{"go", "python"} { t.Run(language, func(t *testing.T) { manager := test_manager(t, DefaultLimits(), nil) session := startSessionSDK(t, manager, language, "capture", "keyboard-capture") lease := speech_fixture_lease(t, session, "controller", []string{"remote-present", "keyboard-capture"}) if _, code := remoteCall(t, session, "remote.focus", focusRequest(lease, 1, true)); code != -32601 { t.Fatal("focus admitted without capture owner", code) } deliveries := session.EnableRemoteCapture() if session.EnableRemoteCapture() != deliveries { t.Fatal("attachment created another capture mailbox") } if _, code := remoteCall(t, session, "remote.focus", focusRequest(lease, 1, true)); code != 0 { t.Fatal("valid focus request refused", code) } delivery := <-deliveries if !delivery.Remote || delivery.Lease != lease || delivery.Sequence != 1 || delivery.Context.Err() != nil { t.Fatal("focus delivery changed identity or lifetime", delivery) } if _, code := remoteCall(t, session, "remote.focus", focusRequest(lease, 1, false)); code != -32001 { t.Fatal("replayed focus sequence accepted", code) } if err := session.PublishRemoteFocus(lease, tentaclewire.RemoteFocusRemote, "requested"); err != nil { t.Fatal(err) } if event := nextSDKEvent(t, session); event.Kind != "remote.focus" || event.Focus != "remote" || event.Reason != "requested" || event.Lease != lease.Lease { t.Fatal("bad focus event", event) } keys := []tentaclewire.RemoteCapturedKey{ {Code: 50, Name: "Shift_L", Pressed: true}, {Code: 38, Name: "a", Pressed: true}, {Code: 38, Pressed: true, Repeat: true}, {Code: 38}, {Code: 50}, } for _, key := range keys { if err := session.PublishRemoteInput(lease, key); err != nil { t.Fatal(err) } } for _, key := range keys { event := nextSDKEvent(t, session) if event.Kind != "remote.input" || event.Input == nil || *event.Input != key || event.Epoch != lease.Epoch { t.Fatal("captured key changed in transit", event) } } for _, invalid := range []tentaclewire.RemoteCapturedKey{ {Code: 7, Name: "a", Pressed: true}, {Code: 38, Name: "A", Pressed: true}, {Code: 38, Name: "a"}, // Release carries no name. {Code: 38, Repeat: true}, } { if !errors.Is(session.PublishRemoteInput(lease, invalid), ErrPermission) { t.Fatal("invalid captured key published", invalid) } } if !errors.Is(session.PublishRemoteFocus(lease, "remote", "network"), ErrPermission) { t.Fatal("unknown focus reason published") } session.RevokeRemote() if event := nextSDKEvent(t, session); event.Kind != "remote.revoked" { t.Fatal("missing revocation", event) } if !errors.Is(session.PublishRemoteInput(lease, keys[0]), ErrPermission) || !errors.Is(session.PublishRemoteFocus(lease, "local", "local"), ErrPermission) { t.Fatal("retired lease published capture events") } }) } } func TestRemoteCaptureSDKPermissionAndParameters(t *testing.T) { for _, language := range []string{"go", "python"} { t.Run(language, func(t *testing.T) { manager := test_manager(t, DefaultLimits(), nil) session := startSessionSDK(t, manager, language, "capture", "keyboard-capture", "keyboard-inject") deliveries := session.EnableRemoteCapture() lease := speech_fixture_lease(t, session, "controller", []string{"remote-present"}) if _, code := remoteCall(t, session, "remote.focus", focusRequest(lease, 1, true)); code != -32001 { t.Fatal("speech-only controller requested capture", code) } if !errors.Is(session.PublishRemoteInput(lease, tentaclewire.RemoteCapturedKey{Code: 38, Name: "a", Pressed: true}), ErrPermission) { t.Fatal("input published without keyboard-capture") } lease = speech_fixture_lease(t, session, "controlled", []string{"keyboard-inject"}) if _, code := remoteCall(t, session, "remote.focus", focusRequest(lease, 1, true)); code != -32001 { t.Fatal("controlled role requested capture", code) } lease = speech_fixture_lease(t, session, "controller", []string{"keyboard-capture"}) data, _ := json.Marshal(focusRequest(lease, 1, true)) for _, raw := range []string{ strings.Replace(string(data), `"remote":true`, `"remote":null`, 1), strings.Replace(string(data), `,"remote":true`, ``, 1), strings.Replace(string(data), `"sequence":1`, `"sequence":1,"origin":"local"`, 1), } { if _, code := remoteCall(t, session, "remote.focus", json.RawMessage(raw)); code != -32602 { t.Fatal("invalid focus parameters admitted", code, raw) } } if len(deliveries) != 0 { t.Fatal("denied focus reached the owner") } for sequence := uint64(1); sequence <= tentaclewire.RemoteFocusQueueSize; sequence++ { if _, code := remoteCall(t, session, "remote.focus", focusRequest(lease, sequence, sequence%2 == 1)); code != 0 { t.Fatal("focus request refused before saturation", code) } } if _, code := remoteCall(t, session, "remote.focus", focusRequest(lease, 99, false)); code != -32002 { t.Fatal("full focus queue did not fail", code) } if _, err := session.RemoteContext(lease, "keyboard-capture"); err == nil { t.Fatal("full focus queue left capture consent active") } if len(deliveries) != 0 { t.Fatal("revocation did not drain pending focus work") } }) } }