~kris/9p

llm9p

ref: f2d8604ad1f0dafbb375aa2f69d8633a28dcae0b llm9p/internal/llmfs/usage_test.go -rw-r--r-- 2.5 KiB
f2d8604a — pdfinn fix(llm): strip CLAUDECODE env var before spawning claude subprocess 6 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package llmfs

import (
	"io"
	"testing"
)

func TestUsageFile_Read(t *testing.T) {
	mock := NewMockBackend()
	mock.totalTokens = 45000
	mock.contextLimit = 200000

	usage := NewUsageFile(mock)

	// Read the full content
	buf := make([]byte, 100)
	n, err := usage.Read(buf, 0)
	if err != nil {
		t.Fatalf("Read() error: %v", err)
	}

	content := string(buf[:n])
	expected := "45000/200000\n"
	if content != expected {
		t.Errorf("Read() = %q, want %q", content, expected)
	}
}

func TestUsageFile_Read_Offset(t *testing.T) {
	mock := NewMockBackend()
	mock.totalTokens = 1000
	mock.contextLimit = 10000

	usage := NewUsageFile(mock)

	// Read with offset (skip first 5 bytes: "1000/")
	buf := make([]byte, 100)
	n, err := usage.Read(buf, 5)
	if err != nil {
		t.Fatalf("Read() error: %v", err)
	}

	content := string(buf[:n])
	expected := "10000\n"
	if content != expected {
		t.Errorf("Read(offset=5) = %q, want %q", content, expected)
	}
}

func TestUsageFile_Read_EOF(t *testing.T) {
	mock := NewMockBackend()
	mock.totalTokens = 100
	mock.contextLimit = 1000

	usage := NewUsageFile(mock)

	// Read past end
	buf := make([]byte, 100)
	n, err := usage.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 TestUsageFile_Write(t *testing.T) {
	mock := NewMockBackend()
	usage := NewUsageFile(mock)

	// Write should fail (read-only)
	n, err := usage.Write([]byte("test"), 0)
	if err == nil {
		t.Error("Write() should return error for read-only file")
	}
	if n != 0 {
		t.Errorf("Write() n = %d, want 0", n)
	}
}

func TestUsageFile_Stat(t *testing.T) {
	mock := NewMockBackend()
	mock.totalTokens = 12345
	mock.contextLimit = 200000

	usage := NewUsageFile(mock)
	stat := usage.Stat()

	// Content would be "12345/200000\n" = 14 chars
	expected := uint64(len("12345/200000\n"))
	if stat.Length != expected {
		t.Errorf("Stat().Length = %d, want %d", stat.Length, expected)
	}
}

func TestUsageFile_DynamicContent(t *testing.T) {
	mock := NewMockBackend()
	mock.totalTokens = 0
	mock.contextLimit = 100000

	usage := NewUsageFile(mock)

	// First read
	buf := make([]byte, 100)
	n, _ := usage.Read(buf, 0)
	if string(buf[:n]) != "0/100000\n" {
		t.Errorf("First read = %q, want '0/100000\\n'", string(buf[:n]))
	}

	// Update tokens
	mock.totalTokens = 50000

	// Second read should reflect the change
	n, _ = usage.Read(buf, 0)
	if string(buf[:n]) != "50000/100000\n" {
		t.Errorf("Second read = %q, want '50000/100000\\n'", string(buf[:n]))
	}
}