Brings 5 packages from low/zero coverage to solid test suites: - pkg/lab: 0% → 100% (Store pub/sub, Config env loading) - pkg/session: 0% → 89.9% (transcript parser, HTML renderer, search, video) - pkg/io/sigil: 43.8% → 98.5% (XOR/ShuffleMask obfuscators, ChaCha20-Poly1305) - pkg/repos: 18.9% → 81.9% (registry, topo sort, directory scan, org detection) - pkg/plugin: 54.8% → 67.1% (installer error paths, Remove, registry Load/Save) Co-Authored-By: Virgil <virgil@lethean.io>
189 lines
5 KiB
Go
189 lines
5 KiB
Go
package session
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// ── RenderMP4 ──────────────────────────────────────────────────────
|
|
|
|
func TestRenderMP4_Bad_VHSNotInstalled(t *testing.T) {
|
|
// Save PATH, set to empty so vhs won't be found.
|
|
origPath := t.TempDir() // use empty dir as PATH
|
|
t.Setenv("PATH", origPath)
|
|
|
|
sess := &Session{ID: "test", StartTime: time.Now(), Events: []Event{}}
|
|
err := RenderMP4(sess, "/tmp/test.mp4")
|
|
if err == nil {
|
|
t.Fatal("expected error when vhs not installed")
|
|
}
|
|
if !strings.Contains(err.Error(), "vhs not installed") {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
}
|
|
|
|
// ── extractCommand ─────────────────────────────────────────────────
|
|
|
|
func TestExtractCommand_Good_WithDesc(t *testing.T) {
|
|
got := extractCommand("go test ./... # run tests")
|
|
if got != "go test ./..." {
|
|
t.Fatalf("expected 'go test ./...', got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestExtractCommand_Good_NoDesc(t *testing.T) {
|
|
got := extractCommand("ls -la")
|
|
if got != "ls -la" {
|
|
t.Fatalf("expected ls -la, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestExtractCommand_Good_Empty(t *testing.T) {
|
|
got := extractCommand("")
|
|
if got != "" {
|
|
t.Fatalf("expected empty, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestExtractCommand_Good_HashInMiddle(t *testing.T) {
|
|
got := extractCommand(`echo "hello # world" # desc`)
|
|
if got != `echo "hello` {
|
|
// Note: the simple split finds first " # " occurrence.
|
|
t.Fatalf("unexpected: %s", got)
|
|
}
|
|
}
|
|
|
|
// ── generateTape ───────────────────────────────────────────────────
|
|
|
|
func TestGenerateTape_Good_BasicSession(t *testing.T) {
|
|
sess := &Session{
|
|
ID: "f3fb074c-8c72-4da6-a15a-85bae652ccaa",
|
|
StartTime: time.Date(2026, 2, 24, 10, 0, 0, 0, time.UTC),
|
|
Events: []Event{
|
|
{
|
|
Type: "tool_use", Tool: "Bash",
|
|
Input: "go test ./...", Output: "ok 1.2s",
|
|
Success: true,
|
|
},
|
|
{
|
|
Type: "tool_use", Tool: "Read",
|
|
Input: "/tmp/test.go",
|
|
},
|
|
{
|
|
Type: "tool_use", Tool: "Task",
|
|
Input: "[Explore] find tests",
|
|
},
|
|
},
|
|
}
|
|
|
|
tape := generateTape(sess, "/tmp/out.mp4")
|
|
if !strings.Contains(tape, "Output /tmp/out.mp4") {
|
|
t.Fatal("missing output directive")
|
|
}
|
|
if !strings.Contains(tape, "f3fb074c") {
|
|
t.Fatal("missing session ID")
|
|
}
|
|
if !strings.Contains(tape, "go test ./...") {
|
|
t.Fatal("missing bash command")
|
|
}
|
|
if !strings.Contains(tape, "Read: /tmp/test.go") {
|
|
t.Fatal("missing Read event")
|
|
}
|
|
if !strings.Contains(tape, "Agent:") {
|
|
t.Fatal("missing Task/Agent event")
|
|
}
|
|
if !strings.Contains(tape, "OK") {
|
|
t.Fatal("missing success indicator")
|
|
}
|
|
}
|
|
|
|
func TestGenerateTape_Good_FailedCommand(t *testing.T) {
|
|
sess := &Session{
|
|
ID: "fail-test",
|
|
StartTime: time.Now(),
|
|
Events: []Event{
|
|
{
|
|
Type: "tool_use", Tool: "Bash",
|
|
Input: "false", Output: "exit 1",
|
|
Success: false,
|
|
},
|
|
},
|
|
}
|
|
|
|
tape := generateTape(sess, "/tmp/fail.mp4")
|
|
if !strings.Contains(tape, "FAILED") {
|
|
t.Fatal("missing FAILED indicator")
|
|
}
|
|
}
|
|
|
|
func TestGenerateTape_Good_EmptySession(t *testing.T) {
|
|
sess := &Session{ID: "empty", StartTime: time.Now()}
|
|
tape := generateTape(sess, "/tmp/empty.mp4")
|
|
if !strings.Contains(tape, "Output /tmp/empty.mp4") {
|
|
t.Fatal("missing output directive")
|
|
}
|
|
if !strings.Contains(tape, "Sleep 3s") {
|
|
t.Fatal("missing final sleep")
|
|
}
|
|
}
|
|
|
|
func TestGenerateTape_Good_LongOutput(t *testing.T) {
|
|
longOutput := strings.Repeat("x", 300)
|
|
sess := &Session{
|
|
ID: "long",
|
|
StartTime: time.Now(),
|
|
Events: []Event{
|
|
{
|
|
Type: "tool_use", Tool: "Bash",
|
|
Input: "cat bigfile", Output: longOutput,
|
|
Success: true,
|
|
},
|
|
},
|
|
}
|
|
|
|
tape := generateTape(sess, "/tmp/long.mp4")
|
|
// Output should be truncated to 200 chars + "..."
|
|
if strings.Contains(tape, strings.Repeat("x", 300)) {
|
|
t.Fatal("output not truncated")
|
|
}
|
|
}
|
|
|
|
func TestGenerateTape_Good_SkipsNonToolEvents(t *testing.T) {
|
|
sess := &Session{
|
|
ID: "mixed",
|
|
StartTime: time.Now(),
|
|
Events: []Event{
|
|
{Type: "user", Input: "hello"},
|
|
{Type: "assistant", Input: "hi there"},
|
|
{Type: "tool_use", Tool: "Bash", Input: "echo hi", Output: "hi", Success: true},
|
|
},
|
|
}
|
|
|
|
tape := generateTape(sess, "/tmp/mixed.mp4")
|
|
if strings.Contains(tape, "hello") {
|
|
t.Fatal("user message should be skipped")
|
|
}
|
|
if strings.Contains(tape, "hi there") {
|
|
t.Fatal("assistant message should be skipped")
|
|
}
|
|
if !strings.Contains(tape, "echo hi") {
|
|
t.Fatal("bash command should be present")
|
|
}
|
|
}
|
|
|
|
func TestGenerateTape_Good_EmptyBashCommand(t *testing.T) {
|
|
sess := &Session{
|
|
ID: "empty-cmd",
|
|
StartTime: time.Now(),
|
|
Events: []Event{
|
|
{Type: "tool_use", Tool: "Bash", Input: "", Success: true},
|
|
},
|
|
}
|
|
|
|
tape := generateTape(sess, "/tmp/empty-cmd.mp4")
|
|
// Empty command should be skipped — no "$ " line.
|
|
if strings.Contains(tape, "$ ") {
|
|
t.Fatal("empty command should be skipped")
|
|
}
|
|
}
|