// 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) } }