diff options
Diffstat (limited to 'internal/lsp/debounce_throttle_test.go')
| -rw-r--r-- | internal/lsp/debounce_throttle_test.go | 123 |
1 files changed, 62 insertions, 61 deletions
diff --git a/internal/lsp/debounce_throttle_test.go b/internal/lsp/debounce_throttle_test.go index 012ec68..0b49b1b 100644 --- a/internal/lsp/debounce_throttle_test.go +++ b/internal/lsp/debounce_throttle_test.go @@ -1,84 +1,85 @@ package lsp import ( - "context" - "encoding/json" - "testing" - "time" - "codeberg.org/snonux/hexai/internal/llm" + "context" + "encoding/json" + "testing" + "time" + + "codeberg.org/snonux/hexai/internal/llm" ) // timeLLM records the time when Chat is invoked. type timeLLM struct{ t time.Time } func (t *timeLLM) Chat(ctx context.Context, _ []llm.Message, _ ...llm.RequestOption) (string, error) { - t.t = time.Now() - return "ok", nil + t.t = time.Now() + return "ok", nil } func (t *timeLLM) Name() string { return "fake" } func (t *timeLLM) DefaultModel() string { return "m" } func TestCompletionDebounce_WaitsUntilQuiet(t *testing.T) { - s := newTestServer() - s.compCache = make(map[string]string) - s.triggerChars = []string{".", ":", "/", "_"} - s.maxTokens = 32 - s.completionDebounce = 30 * time.Millisecond - s.markActivity() // simulate recent input + s := newTestServer() + s.compCache = make(map[string]string) + s.triggerChars = []string{".", ":", "/", "_"} + s.maxTokens = 32 + s.completionDebounce = 30 * time.Millisecond + s.markActivity() // simulate recent input - f := &timeLLM{} - s.llmClient = f + f := &timeLLM{} + s.llmClient = f - line := "func f(i int) " - p := CompletionParams{Position: Position{Line: 0, Character: len(line)}, TextDocument: TextDocumentIdentifier{URI: "file://debounce.go"}} - p.Context = json.RawMessage([]byte(`{"triggerKind":1}`)) + line := "func f(i int) " + p := CompletionParams{Position: Position{Line: 0, Character: len(line)}, TextDocument: TextDocumentIdentifier{URI: "file://debounce.go"}} + p.Context = json.RawMessage([]byte(`{"triggerKind":1}`)) - start := time.Now() - _, ok := s.tryLLMCompletion(p, "", line, "", "", "", false, "") - if !ok { - t.Fatalf("expected ok=true") - } - if f.t.IsZero() { - t.Fatalf("expected LLM to be called") - } - if f.t.Sub(start) < 25*time.Millisecond { // allow minor timing noise - t.Fatalf("expected debounce delay, got %s", f.t.Sub(start)) - } + start := time.Now() + _, ok := s.tryLLMCompletion(p, "", line, "", "", "", false, "") + if !ok { + t.Fatalf("expected ok=true") + } + if f.t.IsZero() { + t.Fatalf("expected LLM to be called") + } + if f.t.Sub(start) < 25*time.Millisecond { // allow minor timing noise + t.Fatalf("expected debounce delay, got %s", f.t.Sub(start)) + } } func TestCompletionThrottle_SerializesCalls(t *testing.T) { - s := newTestServer() - s.compCache = make(map[string]string) - s.triggerChars = []string{".", ":", "/", "_"} - s.maxTokens = 32 - s.throttleInterval = 25 * time.Millisecond + s := newTestServer() + s.compCache = make(map[string]string) + s.triggerChars = []string{".", ":", "/", "_"} + s.maxTokens = 32 + s.throttleInterval = 25 * time.Millisecond - // first call uses timeLLM to record time - f1 := &timeLLM{} - s.llmClient = f1 - line := "func f(i int) " - p := CompletionParams{Position: Position{Line: 0, Character: len(line)}, TextDocument: TextDocumentIdentifier{URI: "file://throttle.go"}} - p.Context = json.RawMessage([]byte(`{"triggerKind":1}`)) - start := time.Now() - if _, ok := s.tryLLMCompletion(p, "", line, "", "", "", false, ""); !ok { - t.Fatalf("first call expected ok=true") - } - if f1.t.IsZero() { - t.Fatalf("expected first call time recorded") - } + // first call uses timeLLM to record time + f1 := &timeLLM{} + s.llmClient = f1 + line := "func f(i int) " + p := CompletionParams{Position: Position{Line: 0, Character: len(line)}, TextDocument: TextDocumentIdentifier{URI: "file://throttle.go"}} + p.Context = json.RawMessage([]byte(`{"triggerKind":1}`)) + start := time.Now() + if _, ok := s.tryLLMCompletion(p, "", line, "", "", "", false, ""); !ok { + t.Fatalf("first call expected ok=true") + } + if f1.t.IsZero() { + t.Fatalf("expected first call time recorded") + } - // second call immediately after; should be delayed by ~interval. - // Clear cache to ensure we actually call the LLM again. - s.compCache = make(map[string]string) - f2 := &timeLLM{} - s.llmClient = f2 - if _, ok := s.tryLLMCompletion(p, "", line, "", "", "", false, ""); !ok { - t.Fatalf("second call expected ok=true") - } - if f2.t.IsZero() { - t.Fatalf("expected second call time recorded") - } - if f2.t.Sub(start) < s.throttleInterval { - t.Fatalf("expected throttle spacing >= %s, got %s", s.throttleInterval, f2.t.Sub(start)) - } + // second call immediately after; should be delayed by ~interval. + // Clear cache to ensure we actually call the LLM again. + s.compCache = make(map[string]string) + f2 := &timeLLM{} + s.llmClient = f2 + if _, ok := s.tryLLMCompletion(p, "", line, "", "", "", false, ""); !ok { + t.Fatalf("second call expected ok=true") + } + if f2.t.IsZero() { + t.Fatalf("expected second call time recorded") + } + if f2.t.Sub(start) < s.throttleInterval { + t.Fatalf("expected throttle spacing >= %s, got %s", s.throttleInterval, f2.t.Sub(start)) + } } |
