package llmfs import ( "fmt" "io" "strings" "testing" ) func TestCompactFile_Read_Initial(t *testing.T) { mock := NewMockBackend() compact := NewCompactFile(mock) // Initial read should return "ready" buf := make([]byte, 100) n, err := compact.Read(buf, 0) if err != nil { t.Fatalf("Read() error: %v", err) } content := string(buf[:n]) expected := "ready\n" if content != expected { t.Errorf("Read() = %q, want %q", content, expected) } } func TestCompactFile_Write_TriggerCompaction(t *testing.T) { mock := NewMockBackend() mock.totalTokens = 160000 mock.contextLimit = 200000 compact := NewCompactFile(mock) // Write to trigger compaction n, err := compact.Write([]byte("1"), 0) if err != nil { t.Fatalf("Write() error: %v", err) } if n != 1 { t.Errorf("Write() n = %d, want 1", n) } // Verify compaction was called if !mock.compactCalled { t.Error("Compact() was not called on backend") } // Read should show "ok: tokens/limit" buf := make([]byte, 100) readN, _ := compact.Read(buf, 0) content := string(buf[:readN]) if !strings.HasPrefix(content, "ok:") { t.Errorf("Read() after compaction = %q, want prefix 'ok:'", content) } } func TestCompactFile_Write_EmptyNoOp(t *testing.T) { mock := NewMockBackend() compact := NewCompactFile(mock) // Empty write should be no-op n, err := compact.Write([]byte(""), 0) if err != nil { t.Fatalf("Write() error: %v", err) } if n != 0 { t.Errorf("Write('') n = %d, want 0", n) } // Compaction should not be triggered if mock.compactCalled { t.Error("Compact() should not be called for empty write") } } func TestCompactFile_Write_WhitespaceNoOp(t *testing.T) { mock := NewMockBackend() compact := NewCompactFile(mock) // Whitespace-only write should be no-op _, err := compact.Write([]byte(" \n\t "), 0) if err != nil { t.Fatalf("Write() error: %v", err) } // Compaction should not be triggered if mock.compactCalled { t.Error("Compact() should not be called for whitespace-only write") } } func TestCompactFile_Write_Error(t *testing.T) { mock := NewMockBackend() mock.compactError = fmt.Errorf("compaction failed") compact := NewCompactFile(mock) // Write should still succeed (error is stored for read) n, err := compact.Write([]byte("1"), 0) if err != nil { t.Fatalf("Write() error: %v", err) } if n != 1 { t.Errorf("Write() n = %d, want 1", n) } // Read should show error buf := make([]byte, 100) readN, _ := compact.Read(buf, 0) content := string(buf[:readN]) if !strings.HasPrefix(content, "error:") { t.Errorf("Read() after error = %q, want prefix 'error:'", content) } if !strings.Contains(content, "compaction failed") { t.Errorf("Read() should contain error message, got %q", content) } } func TestCompactFile_Read_EOF(t *testing.T) { mock := NewMockBackend() compact := NewCompactFile(mock) // Read past end buf := make([]byte, 100) n, err := compact.Read(buf, 1000) if err != io.EOF { t.Errorf("Read(offset=1000) error = %v, want io.EOF", err) } if n != 0 { t.Errorf("Read(offset=1000) n = %d, want 0", n) } } func TestCompactFile_Stat(t *testing.T) { mock := NewMockBackend() compact := NewCompactFile(mock) stat := compact.Stat() // Initial content is "ready\n" = 6 chars expected := uint64(6) if stat.Length != expected { t.Errorf("Stat().Length = %d, want %d", stat.Length, expected) } } func TestCompactFile_MultipleCompactions(t *testing.T) { mock := NewMockBackend() mock.totalTokens = 180000 mock.contextLimit = 200000 compact := NewCompactFile(mock) // First compaction compact.Write([]byte("1"), 0) if !mock.compactCalled { t.Error("First compaction not called") } // Reset flag mock.compactCalled = false mock.totalTokens = 100000 // Second compaction compact.Write([]byte("1"), 0) if !mock.compactCalled { t.Error("Second compaction not called") } // Check result reflects new token count buf := make([]byte, 100) readN, _ := compact.Read(buf, 0) content := string(buf[:readN]) if !strings.Contains(content, "25000") { // 100000 / 4 from mock t.Errorf("Read() = %q, should contain reduced token count", content) } }