wraith/internal/ai/terminal_buffer_test.go
Vantz Stockwell 7ee5321d69
Some checks failed
Build & Sign Wraith / Build Windows + Sign (push) Has been cancelled
feat: AI copilot backend — OAuth PKCE, Claude API streaming, 16 tools, conversations
- OAuth PKCE flow for Max subscription auth (no API key needed)
- Claude API client with SSE streaming (Messages API v1)
- 16 tool definitions: terminal, SFTP, RDP, session management
- Tool dispatch router mapping to existing Wraith services
- Conversation manager with SQLite persistence
- Terminal output ring buffer for AI context
- RDP screenshot encoder (RGBA → JPEG with downscaling)
- Wired into Wails app as AIService

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 09:09:23 -04:00

176 lines
3.6 KiB
Go

package ai
import (
"fmt"
"sync"
"testing"
)
func TestWriteAndRead(t *testing.T) {
buf := NewTerminalBuffer(100)
buf.Write([]byte("line1\nline2\nline3\n"))
all := buf.ReadAll()
if len(all) != 3 {
t.Fatalf("expected 3 lines, got %d", len(all))
}
if all[0] != "line1" || all[1] != "line2" || all[2] != "line3" {
t.Errorf("unexpected lines: %v", all)
}
}
func TestRingBufferOverflow(t *testing.T) {
buf := NewTerminalBuffer(200)
// Write 300 lines
for i := 0; i < 300; i++ {
buf.Write([]byte(fmt.Sprintf("line %d\n", i)))
}
all := buf.ReadAll()
if len(all) != 200 {
t.Fatalf("expected 200 lines (ring buffer), got %d", len(all))
}
// First line should be "line 100" (oldest retained)
if all[0] != "line 100" {
t.Errorf("expected first line 'line 100', got %q", all[0])
}
// Last line should be "line 299"
if all[199] != "line 299" {
t.Errorf("expected last line 'line 299', got %q", all[199])
}
}
func TestReadLastSubset(t *testing.T) {
buf := NewTerminalBuffer(100)
buf.Write([]byte("a\nb\nc\nd\ne\n"))
last3 := buf.ReadLast(3)
if len(last3) != 3 {
t.Fatalf("expected 3 lines, got %d", len(last3))
}
if last3[0] != "c" || last3[1] != "d" || last3[2] != "e" {
t.Errorf("unexpected lines: %v", last3)
}
// Request more than available
last10 := buf.ReadLast(10)
if len(last10) != 5 {
t.Fatalf("expected 5 lines (all available), got %d", len(last10))
}
}
func TestConcurrentAccess(t *testing.T) {
buf := NewTerminalBuffer(1000)
var wg sync.WaitGroup
// Spawn 10 writers
for w := 0; w < 10; w++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
for i := 0; i < 100; i++ {
buf.Write([]byte(fmt.Sprintf("writer %d line %d\n", id, i)))
}
}(w)
}
// Spawn 5 readers
for r := 0; r < 5; r++ {
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 100; i++ {
_ = buf.ReadLast(10)
_ = buf.Len()
}
}()
}
wg.Wait()
total := buf.Len()
if total != 1000 {
t.Errorf("expected 1000 lines (10 writers * 100), got %d", total)
}
}
func TestWritePartialLines(t *testing.T) {
buf := NewTerminalBuffer(100)
// Write data without trailing newline
buf.Write([]byte("partial"))
// Should have no complete lines yet
if buf.Len() != 0 {
t.Errorf("expected 0 lines for partial write, got %d", buf.Len())
}
// Complete the line
buf.Write([]byte(" line\n"))
if buf.Len() != 1 {
t.Fatalf("expected 1 line after completing partial, got %d", buf.Len())
}
all := buf.ReadAll()
if all[0] != "partial line" {
t.Errorf("expected 'partial line', got %q", all[0])
}
}
func TestWriteMultiplePartials(t *testing.T) {
buf := NewTerminalBuffer(100)
buf.Write([]byte("hello "))
buf.Write([]byte("world"))
buf.Write([]byte("!\nfoo\n"))
all := buf.ReadAll()
if len(all) != 2 {
t.Fatalf("expected 2 lines, got %d: %v", len(all), all)
}
if all[0] != "hello world!" {
t.Errorf("expected 'hello world!', got %q", all[0])
}
if all[1] != "foo" {
t.Errorf("expected 'foo', got %q", all[1])
}
}
func TestClear(t *testing.T) {
buf := NewTerminalBuffer(100)
buf.Write([]byte("line1\nline2\n"))
buf.Clear()
if buf.Len() != 0 {
t.Errorf("expected 0 lines after clear, got %d", buf.Len())
}
}
func TestReadLastZero(t *testing.T) {
buf := NewTerminalBuffer(100)
buf.Write([]byte("line\n"))
result := buf.ReadLast(0)
if len(result) != 0 {
t.Errorf("expected empty result for ReadLast(0), got %d lines", len(result))
}
}
func TestReadLastNegative(t *testing.T) {
buf := NewTerminalBuffer(100)
buf.Write([]byte("line\n"))
result := buf.ReadLast(-1)
if len(result) != 0 {
t.Errorf("expected empty result for ReadLast(-1), got %d lines", len(result))
}
}