Add lease-bound Remote key IPC and SDK validation

This commit is contained in:
ak47 committed 2026-11-05 21:28:29 -05:00
1 parent 9ac33560dc
commit 792cac5d0b
12 files changed
+807 -9

No files matched your search

+152
View File
@@ -0,0 +1,152 @@
// 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":"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)
}
}