88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
package cc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func withRunner(fn func(ctx context.Context, cwd string, args []string) ([]byte, []byte, error)) func() {
|
|
orig := RunClaude
|
|
RunClaude = fn
|
|
return func() { RunClaude = orig }
|
|
}
|
|
|
|
func TestSpawnClaude_CleanJSON(t *testing.T) {
|
|
restore := withRunner(func(_ context.Context, _ string, _ []string) ([]byte, []byte, error) {
|
|
return []byte(`{"result":"ok","session_id":"abc123"}`), nil, nil
|
|
})
|
|
defer restore()
|
|
|
|
res, err := SpawnClaude(context.Background(), Opts{Prompt: "hello"})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if res.SessionID != "abc123" {
|
|
t.Errorf("SessionID = %q, want abc123", res.SessionID)
|
|
}
|
|
if res.ResultText != "ok" {
|
|
t.Errorf("ResultText = %q, want ok", res.ResultText)
|
|
}
|
|
}
|
|
|
|
func TestSpawnClaude_NDJSONTail(t *testing.T) {
|
|
ndjson := `{"type":"progress","data":"thinking"}
|
|
{"type":"progress","data":"still thinking"}
|
|
{"result":"done","session_id":"sess99"}`
|
|
|
|
restore := withRunner(func(_ context.Context, _ string, _ []string) ([]byte, []byte, error) {
|
|
return []byte(ndjson), nil, nil
|
|
})
|
|
defer restore()
|
|
|
|
res, err := SpawnClaude(context.Background(), Opts{Prompt: "go"})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if res.SessionID != "sess99" {
|
|
t.Errorf("SessionID = %q, want sess99", res.SessionID)
|
|
}
|
|
if res.ResultText != "done" {
|
|
t.Errorf("ResultText = %q, want done", res.ResultText)
|
|
}
|
|
}
|
|
|
|
func TestSpawnClaude_NonZeroExit(t *testing.T) {
|
|
restore := withRunner(func(_ context.Context, _ string, _ []string) ([]byte, []byte, error) {
|
|
return nil, []byte("something went wrong"), errors.New("exit status 1")
|
|
})
|
|
defer restore()
|
|
|
|
_, err := SpawnClaude(context.Background(), Opts{Prompt: "hi"})
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
var ce *ClaudeError
|
|
if !errors.As(err, &ce) {
|
|
t.Errorf("expected ClaudeError, got %T: %v", err, err)
|
|
}
|
|
}
|
|
|
|
func TestSpawnClaude_Timeout(t *testing.T) {
|
|
restore := withRunner(func(ctx context.Context, _ string, _ []string) ([]byte, []byte, error) {
|
|
// Respect context cancellation — as the real runner would.
|
|
<-ctx.Done()
|
|
return nil, nil, ctx.Err()
|
|
})
|
|
defer restore()
|
|
|
|
_, err := SpawnClaude(context.Background(), Opts{Prompt: "slow", TimeoutMs: 1})
|
|
if err == nil {
|
|
t.Fatal("expected timeout error, got nil")
|
|
}
|
|
var te *ClaudeTimeoutError
|
|
if !errors.As(err, &te) {
|
|
t.Errorf("expected ClaudeTimeoutError, got %T: %v", err, err)
|
|
}
|
|
}
|