Files
cthulhu/internal/braille/virtual_native_test.go
Chase CichorzandClaude Opus 5.5 551ef86d5f Export and display Remote Braille through the reader
A controlled reader renders accepted application frames in a new
virtual-only cthulhu-braille mode at the controller's width and applies
its pan and route gestures; reader UI, flashes and secure frames are
never exported, and hidden frames are unroutable. A controller reader
reports its display width, shows peer cells as an untranslated raw
frame and forwards local pan and routing keys. The physical helper now
reports its width and edge pans.

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

97 lines
2.7 KiB
Go

//go:build brlapi && cgo
// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package braille
import (
"bytes"
"context"
"encoding/json"
"strings"
"testing"
)
func runVirtualLines(t *testing.T, lines ...string) []VirtualResponse {
t.Helper()
var output bytes.Buffer
if err := RunVirtual(context.Background(), strings.NewReader(strings.Join(lines, "\n")+"\n"), &output); err != nil {
t.Fatal(err)
}
var responses []VirtualResponse
decoder := json.NewDecoder(&output)
for decoder.More() {
var response VirtualResponse
if err := decoder.Decode(&response); err != nil {
t.Fatal(err)
}
responses = append(responses, response)
}
return responses
}
func TestVirtualHelperRendersPansAndRoutes(t *testing.T) {
responses := runVirtualLines(t,
`{"frame":{"text":"abcdef","cursor":1,"id":9}}`, // No width yet: nothing rendered.
`{"width":4}`,
`{"pan":"right"}`,
`{"route":1}`,
`{"pan":"left"}`,
`{"width":0}`,
`{"frame":{"text":"x","cursor":-1,"id":10}}`,
)
if len(responses) != 4 {
t.Fatalf("responses = %+v", responses)
}
first := responses[0].Cells
// Computer Braille a=dot1, b=dots12; the cursor on b adds dots 7 and 8.
if len(first) != 4 || first[0] != 0x01 || first[1] != 0x03|VirtualCursorDots {
t.Fatalf("first page = %#v", first)
}
if second := responses[1].Cells; len(second) != 4 || second[0] == first[0] {
t.Fatalf("pan right did not change the page: %#v", second)
}
if route := responses[2].Route; route == nil || route.ID != 9 || route.Offset != 5 {
t.Fatalf("route = %+v", route)
}
if !equalCells(responses[3].Cells, first) {
t.Fatalf("pan left did not restore the first page: %#v", responses[3].Cells)
}
}
func equalCells(a, b []int) bool {
if len(a) != len(b) {
return false
}
for index := range a {
if a[index] != b[index] {
return false
}
}
return true
}
func TestVirtualHelperUsesContractedFrameTable(t *testing.T) {
responses := runVirtualLines(t, `{"width":8}`,
`{"frame":{"text":"the cat","cursor":-1,"id":1,"contract":true,"table":"en-ueb-g2.ctb"}}`)
if len(responses) != 1 || len(responses[0].Cells) != 8 {
t.Fatalf("responses = %+v", responses)
}
// Contraction makes "the" a single cell, so the line fits in fewer cells
// than its seven characters: the last cell is blank padding.
if responses[0].Cells[7] != 0 {
t.Fatalf("contracted output was not shorter: %#v", responses[0].Cells)
}
}
func TestVirtualHelperRejectsInvalidRequests(t *testing.T) {
for _, line := range []string{`{"width":5000}`, `{}`, `not json`, `{"pan":"up"}`} {
var output bytes.Buffer
if RunVirtual(context.Background(), strings.NewReader(line+"\n"), &output) == nil {
t.Fatal("invalid request accepted", line)
}
}
}