Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
173 lines
5.2 KiB
Go
173 lines
5.2 KiB
Go
package agentstatus
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestCLIVersionCacheReusesVersionUntilExecutableChanges(t *testing.T) {
|
|
binaryPath := filepath.Join(t.TempDir(), "agent-cli")
|
|
if err := os.WriteFile(binaryPath, []byte("first"), 0o700); err != nil {
|
|
t.Fatalf("write first binary: %v", err)
|
|
}
|
|
cache := NewCLIVersionCache()
|
|
loads := 0
|
|
load := func() string {
|
|
loads++
|
|
return "1.0.0"
|
|
}
|
|
|
|
if got := cache.load(binaryPath, load); got != "1.0.0" {
|
|
t.Fatalf("first version = %q, want 1.0.0", got)
|
|
}
|
|
if got := cache.load(binaryPath, load); got != "1.0.0" {
|
|
t.Fatalf("cached version = %q, want 1.0.0", got)
|
|
}
|
|
if loads != 1 {
|
|
t.Fatalf("loads = %d, want 1 before binary change", loads)
|
|
}
|
|
|
|
replacementPath := filepath.Join(filepath.Dir(binaryPath), "replacement")
|
|
if err := os.WriteFile(replacementPath, []byte("second binary"), 0o700); err != nil {
|
|
t.Fatalf("write replacement binary: %v", err)
|
|
}
|
|
if err := os.Rename(replacementPath, binaryPath); err != nil {
|
|
t.Fatalf("replace binary: %v", err)
|
|
}
|
|
if got := cache.load(binaryPath, load); got != "1.0.0" {
|
|
t.Fatalf("version after replacement = %q, want 1.0.0", got)
|
|
}
|
|
if loads != 2 {
|
|
t.Fatalf("loads = %d, want 2 after binary replacement", loads)
|
|
}
|
|
}
|
|
|
|
func TestCLIVersionCacheDoesNotStoreFailedReads(t *testing.T) {
|
|
binaryPath := filepath.Join(t.TempDir(), "agent-cli")
|
|
if err := os.WriteFile(binaryPath, []byte("binary"), 0o700); err != nil {
|
|
t.Fatalf("write binary: %v", err)
|
|
}
|
|
cache := NewCLIVersionCache()
|
|
loads := 0
|
|
load := func() string {
|
|
loads++
|
|
if loads == 1 {
|
|
return ""
|
|
}
|
|
return "1.0.0"
|
|
}
|
|
|
|
if got := cache.load(binaryPath, load); got != "" {
|
|
t.Fatalf("failed read = %q, want empty", got)
|
|
}
|
|
if got := cache.load(binaryPath, load); got != "1.0.0" {
|
|
t.Fatalf("retry read = %q, want 1.0.0", got)
|
|
}
|
|
if loads != 2 {
|
|
t.Fatalf("loads = %d, want failed read retried", loads)
|
|
}
|
|
}
|
|
|
|
func TestGlobalBinDiscoveryCacheReusesResultUntilManagerChanges(t *testing.T) {
|
|
managerPath := filepath.Join(t.TempDir(), "pnpm")
|
|
if err := os.WriteFile(managerPath, []byte("first"), 0o700); err != nil {
|
|
t.Fatalf("write manager: %v", err)
|
|
}
|
|
cache := NewGlobalBinDiscoveryCache()
|
|
loads := 0
|
|
load := func() string {
|
|
loads++
|
|
return "/global/bin"
|
|
}
|
|
|
|
if got := cache.load(managerPath, "bin\x00-g", load); got != "/global/bin" {
|
|
t.Fatalf("first bin dir = %q, want /global/bin", got)
|
|
}
|
|
if got := cache.load(managerPath, "bin\x00-g", load); got != "/global/bin" {
|
|
t.Fatalf("cached bin dir = %q, want /global/bin", got)
|
|
}
|
|
if loads != 1 {
|
|
t.Fatalf("loads = %d, want 1 before manager changes", loads)
|
|
}
|
|
|
|
replacementPath := filepath.Join(filepath.Dir(managerPath), "replacement")
|
|
if err := os.WriteFile(replacementPath, []byte("second manager"), 0o700); err != nil {
|
|
t.Fatalf("write replacement manager: %v", err)
|
|
}
|
|
if err := os.Rename(replacementPath, managerPath); err != nil {
|
|
t.Fatalf("replace manager: %v", err)
|
|
}
|
|
if got := cache.load(managerPath, "bin\x00-g", load); got != "/global/bin" {
|
|
t.Fatalf("bin dir after manager replacement = %q, want /global/bin", got)
|
|
}
|
|
if loads != 2 {
|
|
t.Fatalf("loads = %d, want 2 after manager replacement", loads)
|
|
}
|
|
}
|
|
|
|
func TestAdapterProbeCacheStoresOnlyMatchingExecutable(t *testing.T) {
|
|
binaryPath := filepath.Join(t.TempDir(), "adapter")
|
|
if err := os.WriteFile(binaryPath, []byte("first"), 0o700); err != nil {
|
|
t.Fatalf("write first adapter: %v", err)
|
|
}
|
|
cache := NewAdapterProbeCache()
|
|
cache.markReady("codex", binaryPath)
|
|
if !cache.ready("codex", binaryPath) {
|
|
t.Fatal("ready = false after successful probe")
|
|
}
|
|
|
|
replacementPath := filepath.Join(filepath.Dir(binaryPath), "replacement")
|
|
if err := os.WriteFile(replacementPath, []byte("second adapter"), 0o700); err != nil {
|
|
t.Fatalf("write replacement adapter: %v", err)
|
|
}
|
|
if err := os.Rename(replacementPath, binaryPath); err != nil {
|
|
t.Fatalf("replace adapter: %v", err)
|
|
}
|
|
if cache.ready("codex", binaryPath) {
|
|
t.Fatal("ready = true after adapter replacement")
|
|
}
|
|
}
|
|
|
|
func TestAdapterProbeCacheExpiresPositiveHandshakeEvidence(t *testing.T) {
|
|
binaryPath := filepath.Join(t.TempDir(), "codex")
|
|
if err := os.WriteFile(binaryPath, []byte("codex"), 0o700); err != nil {
|
|
t.Fatalf("write binary: %v", err)
|
|
}
|
|
cache := NewAdapterProbeCache()
|
|
checkedAt := time.Unix(100, 0)
|
|
cache.markReadyAt("codex", binaryPath, checkedAt)
|
|
if !cache.readyWithin("codex", binaryPath, checkedAt.Add(time.Second), time.Minute) {
|
|
t.Fatal("fresh positive handshake cache = false, want true")
|
|
}
|
|
if cache.readyWithin("codex", binaryPath, checkedAt.Add(time.Minute+time.Nanosecond), time.Minute) {
|
|
t.Fatal("expired positive handshake cache = true, want false")
|
|
}
|
|
}
|
|
|
|
func TestDetectionCommandLimiterBoundsConcurrentCommands(t *testing.T) {
|
|
limiter := NewDetectionCommandLimiter(1)
|
|
release, acquired := limiter.acquire(context.Background())
|
|
if !acquired {
|
|
t.Fatal("first command did not acquire limiter")
|
|
}
|
|
|
|
blockedContext, cancel := context.WithTimeout(
|
|
context.Background(),
|
|
20*time.Millisecond,
|
|
)
|
|
defer cancel()
|
|
if _, acquired := limiter.acquire(blockedContext); acquired {
|
|
t.Fatal("second command acquired a full limiter")
|
|
}
|
|
|
|
release()
|
|
nextRelease, acquired := limiter.acquire(context.Background())
|
|
if !acquired {
|
|
t.Fatal("next command did not acquire released limiter")
|
|
}
|
|
nextRelease()
|
|
}
|