// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package tentacle import ( "encoding/json" "errors" "reflect" "strings" "testing" "git.stormux.org/storm/cthulhu/internal/tentaclewire" ) func brailleRequest(lease tentaclewire.RemoteLease, sequence uint64, value tentaclewire.RemoteBraille) tentaclewire.RemoteBrailleRequest { return tentaclewire.RemoteBrailleRequest{RemoteOperation: tentaclewire.RemoteOperation{Lease: lease.Lease, Epoch: lease.Epoch, Sequence: sequence}, Braille: value} } func TestRemoteBrailleSDKDirectionsAndEvents(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, "braille", "braille-stream") lease := speech_fixture_lease(t, session, "controlled", []string{"output-observe", "braille-stream"}) size := tentaclewire.RemoteBraille{Op: "size", Width: 40} if _, code := remoteCall(t, session, "remote.braille", brailleRequest(lease, 1, size)); code != -32601 { t.Fatal("Braille admitted without owner", code) } deliveries := session.EnableRemoteBraille() if _, code := remoteCall(t, session, "remote.braille", brailleRequest(lease, 1, size)); code != 0 { t.Fatal("size refused", code) } if delivery := <-deliveries; delivery.Role != "controlled" || !reflect.DeepEqual(delivery.Braille, size) || delivery.Lease != lease { t.Fatal("size delivery changed", delivery) } route := tentaclewire.RemoteBraille{Op: "gesture", Gesture: "route", Index: 7} if _, code := remoteCall(t, session, "remote.braille", brailleRequest(lease, 2, route)); code != 0 { t.Fatal("gesture refused", code) } <-deliveries cells := tentaclewire.RemoteBraille{Op: "cells", Cells: []int{1, 255, 0}} if _, code := remoteCall(t, session, "remote.braille", brailleRequest(lease, 3, cells)); code != -32001 { t.Fatal("controlled child sent display cells to its reader", code) } if err := session.PublishRemoteBraille(lease, cells); err != nil { t.Fatal(err) } if event := nextSDKEvent(t, session); event.Kind != "remote.braille" || event.Braille == nil || !reflect.DeepEqual(*event.Braille, cells) { t.Fatal("cells event changed", event) } if !errors.Is(session.PublishRemoteBraille(lease, route), ErrPermission) { t.Fatal("controlled reader published a gesture") } session.RevokeRemote() nextSDKEvent(t, session) lease = speech_fixture_lease(t, session, "controller", []string{"remote-present", "braille-stream"}) if _, code := remoteCall(t, session, "remote.braille", brailleRequest(lease, 1, cells)); code != 0 { t.Fatal("controller cells refused", code) } if delivery := <-deliveries; delivery.Role != "controller" || !reflect.DeepEqual(delivery.Braille.Cells, cells.Cells) { t.Fatal("controller cells changed", delivery) } if _, code := remoteCall(t, session, "remote.braille", brailleRequest(lease, 2, size)); code != -32001 { t.Fatal("controller sent a size request", code) } for _, value := range []tentaclewire.RemoteBraille{{Op: "geometry", Width: 32}, {Op: "gesture", Gesture: "pan-right"}} { if err := session.PublishRemoteBraille(lease, value); err != nil { t.Fatal(err) } if event := nextSDKEvent(t, session); event.Braille == nil || !reflect.DeepEqual(*event.Braille, value) { t.Fatal("controller event changed", event) } } data, _ := json.Marshal(brailleRequest(lease, 3, cells)) for _, raw := range []string{ strings.Replace(string(data), `[1,255,0]`, `[1,256,0]`, 1), strings.Replace(string(data), `"op":"cells"`, `"op":"text"`, 1), strings.Replace(string(data), `"op":"cells"`, `"op":"cells","width":3`, 1), strings.Replace(string(data), `"sequence":3`, `"sequence":3,"origin":"local"`, 1), } { if _, code := remoteCall(t, session, "remote.braille", json.RawMessage(raw)); code != -32602 { t.Fatal("invalid Braille admitted", code, raw) } } session.RevokeRemote() nextSDKEvent(t, session) if !errors.Is(session.PublishRemoteBraille(lease, cells), ErrPermission) { t.Fatal("retired lease published Braille") } }) } } func TestRemoteBrailleSDKGrantAndSaturation(t *testing.T) { manager := test_manager(t, DefaultLimits(), nil) session := startSessionSDK(t, manager, "go", "braille", "braille-stream") deliveries := session.EnableRemoteBraille() lease := speech_fixture_lease(t, session, "controlled", []string{"output-observe"}) size := tentaclewire.RemoteBraille{Op: "size", Width: 40} if _, code := remoteCall(t, session, "remote.braille", brailleRequest(lease, 1, size)); code != -32001 { t.Fatal("Braille admitted without grant", code) } session.RevokeRemote() invokeSessionSDK(t, session, "event", nil) lease = speech_fixture_lease(t, session, "controlled", []string{"braille-stream"}) for sequence := uint64(1); sequence <= tentaclewire.RemoteBrailleQueueSize; sequence++ { if _, code := remoteCall(t, session, "remote.braille", brailleRequest(lease, sequence, size)); code != 0 { t.Fatal("refused before saturation", code) } } if _, code := remoteCall(t, session, "remote.braille", brailleRequest(lease, 99, size)); code != -32002 { t.Fatal("saturation did not fail", code) } if _, err := session.RemoteContext(lease, "braille-stream"); err == nil || len(deliveries) != 0 { t.Fatal("saturation left the lease or queue") } }