Add opt-in Tentacle protocol 1.1, explicit remote grants, lifecycle IPC and expiring core leases in both SDKs. Revoke access before update preparation, including failed updates. Add transient secret entries, shared Braille cell export and isolated Xorg recovery experiments with focused tests and documented limitations. Production consent, desktop services and live interoperability remain pending.
128 lines
3.5 KiB
Go
128 lines
3.5 KiB
Go
package braille
|
|
|
|
import (
|
|
"bytes"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestDisplayMasksPreserveEveryRawCell(t *testing.T) {
|
|
text := make([]rune, 256)
|
|
dots := make([]byte, 256)
|
|
for index := range text {
|
|
text[index] = rune(0x2800 + index)
|
|
dots[index] = 0x40
|
|
}
|
|
andMask, orMask, err := displayMasks(string(text), nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for index := range text {
|
|
if andMask[index] != 0 || orMask[index] != byte(index) {
|
|
t.Fatalf("cell %d: and=%x or=%x", index, andMask[index], orMask[index])
|
|
}
|
|
}
|
|
andMask, orMask, err = displayMasks(string(text), dots)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for index := range text {
|
|
if andMask[index] != 0 || orMask[index] != byte(index)|0x40 {
|
|
t.Fatalf("cell %d lost raw dots or attributes", index)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDisplayMasksRetainTextTranslation(t *testing.T) {
|
|
andMask, orMask, err := displayMasks("a界 ⠁", []byte{0x40, 0, 0, 0x80})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(andMask, []byte{0xff, 0xff, 0xff, 0}) ||
|
|
!bytes.Equal(orMask, []byte{0x40, 0, 0, 0x81}) {
|
|
t.Fatalf("and=%x or=%x", andMask, orMask)
|
|
}
|
|
for _, tc := range []struct {
|
|
text string
|
|
dots []byte
|
|
}{{"\xff", nil}, {"界", []byte{1, 2}}, {"", []byte{1}}} {
|
|
if _, _, err := displayMasks(tc.text, tc.dots); err == nil {
|
|
t.Fatal("accepted invalid frame")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRawCellsCursorPaddingAndSnapshotOwnership(t *testing.T) {
|
|
v := viewport{width: 4}
|
|
if err := v.setFrame(Frame{ID: 8, Text: "⠁⠃", Cursor: 2, Dots: []byte{0x40, 0}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cells, err := v.rawCells(0xc0)
|
|
if err != nil || !bytes.Equal(cells, []byte{0x41, 3, 0xc0, 0}) {
|
|
t.Fatalf("cells=%x error=%v", cells, err)
|
|
}
|
|
if route, ok := v.route(RouteBase + 2); !ok || route != (RoutingEvent{ID: 8, Offset: 2}) {
|
|
t.Fatalf("end-of-line route=%+v ok=%v", route, ok)
|
|
}
|
|
if _, ok := v.route(RouteBase + 3); ok {
|
|
t.Fatal("padding has a routing target")
|
|
}
|
|
cells[0] = 0xff
|
|
withoutCursor, err := v.rawCells(0)
|
|
if err != nil || !bytes.Equal(withoutCursor, []byte{0x41, 3, 0, 0}) {
|
|
t.Fatalf("snapshot or cursor mutated viewport: %x, %v", withoutCursor, err)
|
|
}
|
|
if err := v.setFrame(Frame{ID: 9, Cursor: -1}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cleared, err := v.rawCells(0xc0)
|
|
if err != nil || !bytes.Equal(cleared, make([]byte, 4)) {
|
|
t.Fatalf("empty replacement=%x, %v", cleared, err)
|
|
}
|
|
if _, ok := v.route(RouteBase); ok {
|
|
t.Fatal("empty replacement retained routing")
|
|
}
|
|
if cells[1] != 3 {
|
|
t.Fatal("replacement changed an earlier snapshot")
|
|
}
|
|
}
|
|
|
|
func TestRawCellsRequireTranslationAndValidWidth(t *testing.T) {
|
|
v := viewport{width: 4}
|
|
if err := v.setFrame(Frame{Text: "cat", Cursor: -1}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := v.rawCells(0xc0); err == nil {
|
|
t.Fatal("ordinary text was exported as guessed dots")
|
|
}
|
|
for _, width := range []int{-1, 0, 4097} {
|
|
invalid := viewport{width: width}
|
|
if _, err := invalid.rawCells(0); err == nil {
|
|
t.Fatalf("accepted width %d", width)
|
|
}
|
|
}
|
|
v = viewport{width: 4096}
|
|
if err := v.setFrame(Frame{Cursor: -1}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cells, err := v.rawCells(0)
|
|
if err != nil || len(cells) != 4096 {
|
|
t.Fatalf("maximum width: %d, %v", len(cells), err)
|
|
}
|
|
}
|
|
|
|
func TestRawCellsFailureDoesNotAlterViewport(t *testing.T) {
|
|
v := viewport{width: 2}
|
|
if err := v.setFrame(Frame{Text: "abcd", Cursor: -1}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
v.pan(PanRight)
|
|
before := v
|
|
if _, err := v.rawCells(0xc0); err == nil {
|
|
t.Fatal("accepted untranslated text")
|
|
}
|
|
if !reflect.DeepEqual(v, before) {
|
|
t.Fatal("failed export changed local presentation")
|
|
}
|
|
}
|