Files
Chase CichorzandClaude Opus 5.5 6867d901b2 Support Remote browser and media keys and connection history UI
Accept the eighteen browser, volume, media and launch identities in the input vocabulary and both SDKs. Exercise media-key capture on the private Xorg harness, and permit only the new remember-host checkbox in the connection form integration test.

Validated: affected-package race tests, Tentacles make check, private native_remote_input.py and native_remote_keys.py. Physical input, live peer interoperability, speech and Braille acceptance remain pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 21:17:01 -05:00

157 lines
5.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package tentaclewire
import (
"encoding/json"
"fmt"
"os/exec"
"path/filepath"
"strings"
"testing"
)
func TestRemoteKeySDKValidation(t *testing.T) {
cases := []struct {
data string
valid bool
}{
{`{"name":"a","pressed":true}`, true},
{`{"name":"Control_R","pressed":false}`, true},
{`{"name":"KP_Enter","pressed":true}`, true},
{`{"name":"semicolon","pressed":false}`, true},
{`{"name":"XF86AudioRaiseVolume","pressed":true}`, true},
{`{"name":"XF86Calculator","pressed":false}`, true},
{`{"name":"XF86Eject","pressed":true}`, false},
{`{"name":"XF86PowerOff","pressed":true}`, false},
{`{"name":"Prior","pressed":true}`, false},
{`{"name":"A","pressed":true}`, false},
{`{"name":"F01","pressed":true}`, false},
{`{"name":"F+1","pressed":true}`, false},
{`{"name":"F25","pressed":true}`, false},
{`{"name":"F1","pressed":true}`, false},
{`{"name":"KP_01","pressed":true}`, false},
{`{"name":"ISO_Level3_Shift","pressed":true}`, false},
{`{"name":"dead_acute","pressed":true}`, false},
{`{"name":"U20AC","pressed":true}`, false},
{`{"name":"../anything","pressed":true}`, false},
{`{"name":"a"}`, false},
{`{"name":"a","pressed":null}`, false},
{`{"name":"a","pressed":0}`, false},
{`{"name":"a","pressed":"false"}`, false},
{`{"Name":"a","pressed":true}`, false},
{`{"name":"a","Pressed":true}`, false},
{`{"name":"a","pressed":false,"origin":"local"}`, false},
{`{"name":"a","pressed":true,"scan_code":38}`, false},
{`{"pressed":false}`, false},
{`{"name":null,"pressed":false}`, false},
{`{"name":"","pressed":false}`, false},
{`{"name":1,"pressed":false}`, false},
{`{"name":"a","name":"b","pressed":false}`, false},
{`null`, false}, {`[]`, false}, {`{}`, false},
}
for _, group := range []struct {
first, last int
name func(int) string
}{
{'a', 'z', func(code int) string { return string(rune(code)) }},
{'0', '9', func(code int) string { return string(rune(code)) }},
{1, 24, func(code int) string { return fmt.Sprintf("F%d", code) }},
{0, 9, func(code int) string { return fmt.Sprintf("KP_%d", code) }},
} {
for code := group.first; code <= group.last; code++ {
for _, pressed := range []bool{false, true} {
data, _ := json.Marshal(RemoteKey{Name: group.name(code), Pressed: pressed})
cases = append(cases, struct {
data string
valid bool
}{string(data), true})
}
}
}
var probes []any
for _, test := range cases {
var key RemoteKey
if valid := DecodeStrict([]byte(test.data), &key) == nil && ValidRemoteKey(key); valid != test.valid {
t.Fatalf("Go key validation %s: %v", test.data, valid)
}
probes = append(probes, map[string]any{"raw": test.data, "valid": test.valid})
}
checkRemoteKeyPython(t, "valid_remote_key", probes)
}
func TestRemoteKeyRequestSDKValidation(t *testing.T) {
base := `{"lease":"` + strings.Repeat("a", 32) + `","epoch":1,"sequence":1,"key":{"name":"a","pressed":false}}`
cases := []struct {
data string
valid bool
}{
{base, true},
{strings.Replace(base, `"sequence":1`, `"sequence":18446744073709551615`, 1), true},
{strings.Replace(base, `"epoch":1`, `"epoch":18446744073709551615`, 1), true},
}
for _, field := range []string{"epoch", "sequence"} {
for _, invalid := range []string{"0", "-1", "1.0", "true", "null", "18446744073709551616"} {
cases = append(cases, struct {
data string
valid bool
}{strings.Replace(base, `"`+field+`":1`, `"`+field+`":`+invalid, 1), false})
}
}
for _, data := range []string{
strings.Replace(base, `"lease":"`+strings.Repeat("a", 32)+`"`, `"lease":null`, 1),
strings.Replace(base, strings.Repeat("a", 32), "short", 1),
strings.Replace(base, `"key":{"name":"a","pressed":false}`, `"key":null`, 1),
strings.Replace(base, `"key":{"name":"a","pressed":false}`, `"key":{}`, 1),
strings.Replace(base, `"epoch":1,`, "", 1),
strings.Replace(base, `,"key":{"name":"a","pressed":false}`, "", 1),
strings.Replace(base, `"epoch":1`, `"epoch":1,"epoch":2`, 1),
strings.Replace(base, `"epoch":1`, `"epoch":1,"origin":"local"`, 1),
strings.Replace(base, `"epoch":1`, `"epoch":1,"keys":[]`, 1),
strings.Replace(base, `"epoch":1`, `"Epoch":1`, 1),
`null`, `[]`, `{}`,
} {
cases = append(cases, struct {
data string
valid bool
}{data, false})
}
var probes []any
for _, test := range cases {
var request RemoteKeyRequest
if valid := DecodeStrict([]byte(test.data), &request) == nil && ValidRemoteKeyRequest(request); valid != test.valid {
t.Fatalf("Go key request validation %s: %v", test.data, valid)
}
probes = append(probes, map[string]any{"raw": test.data, "valid": test.valid})
}
checkRemoteKeyPython(t, "valid_remote_key_request", probes)
}
func checkRemoteKeyPython(t *testing.T, validator string, probes []any) {
t.Helper()
path, err := filepath.Abs("../../sdk/python")
if err != nil {
t.Fatal(err)
}
script := `import json, sys
sys.path.insert(0, sys.argv[1])
from cthulhu_tentacle import _object, ProtocolError
from cthulhu_tentacle import session
validate = getattr(session, sys.argv[2])
for case in json.load(sys.stdin):
try:
actual = validate(json.loads(case['raw'], object_pairs_hook=_object))
except (ProtocolError, ValueError):
actual = False
assert actual == case['valid'], str(case)[:180]
`
data, _ := json.Marshal(probes)
command := exec.Command("python3", "-B", "-c", script, path, validator)
command.Stdin = strings.NewReader(string(data))
if output, err := command.CombinedOutput(); err != nil {
t.Fatalf("Python key validation: %v: %s", err, output)
}
}