Files
cthulhu/internal/review/document_word_spaces_test.go

79 lines
2.9 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package review
import (
"context"
"strings"
"testing"
"git.stormux.org/storm/cthulhu/internal/atspi"
)
type blockCaretReader struct {
caretTextReader
calls, blocks int
malformed bool
}
func (reader *blockCaretReader) ReadDocumentCaret(ctx context.Context, object atspi.ObjectReference, offset int, unit atspi.DocumentCaretUnit) (atspi.DocumentCaretText, error) {
reader.calls++
return reader.caretTextReader.ReadDocumentCaret(ctx, object, offset, unit)
}
func (reader *blockCaretReader) ReadDocumentCharacters(_ context.Context, object atspi.ObjectReference, offset int) (atspi.DocumentCaretText, error) {
reader.calls++
reader.blocks++
runes := []rune(reader.caretTextReader[object.ID()])
start := offset / 128 * 128
end := min(len(runes), start+128)
raw := string(runes[start:end])
if reader.malformed {
raw = ""
}
return atspi.DocumentCaretText{Start: start, End: end, RawText: raw, CharacterCount: len(runes)}, nil
}
func TestDocumentWordSpacesUseBoundedBlocks(t *testing.T) {
values := caretTextReader{webID("/text"): "A" + strings.Repeat(" \t\n\u2003", 250) + "猫"}
cursor := newCaretTextCursor(t, values)
reader := &blockCaretReader{caretTextReader: values}
for _, step := range []struct {
command DocumentCaretCommand
text string
}{{CaretNextWord, "猫"}, {CaretPreviousWord, "猫"}, {CaretPreviousWord, "A \t\n\u2003"}} {
move, err := cursor.MoveCaret(context.Background(), reader, step.command)
// Native word providers include varying trailing whitespace. Retain
// their text and verify the actual requested word and Unicode offset.
if err != nil || !strings.HasPrefix(move.Text, strings.TrimSpace(step.text)) {
t.Fatalf("%s: %+v error=%v", step.command, move, err)
}
}
t.Logf("three word commands across 1000 whitespace characters: %d reads, %d blocks", reader.calls, reader.blocks)
if reader.blocks == 0 || reader.calls > 50 {
t.Fatalf("word traversal used %d reads (%d blocks)", reader.calls, reader.blocks)
}
}
func TestDocumentCharacterMovementDoesNotReadBlocks(t *testing.T) {
values := caretTextReader{webID("/text"): "A B"}
cursor := newCaretTextCursor(t, values)
reader := &blockCaretReader{caretTextReader: values}
move, err := cursor.MoveCaret(context.Background(), reader, CaretNextCharacter)
if err != nil || move.Text != " " || reader.blocks != 0 || reader.calls != 1 {
t.Fatalf("move=%+v error=%v calls=%d blocks=%d", move, err, reader.calls, reader.blocks)
}
}
func TestDocumentWordMalformedBlockCannotSkipText(t *testing.T) {
values := caretTextReader{webID("/text"): "A B"}
cursor := newCaretTextCursor(t, values)
reader := &blockCaretReader{caretTextReader: values, malformed: true}
move, err := cursor.MoveCaret(context.Background(), reader, CaretNextWord)
if err != nil || move.Text != "B" || move.Position.Offset != 4 {
t.Fatalf("move=%+v error=%v", move, err)
}
}