Files
agent-radar 2ed3415fb7
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
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

161 lines
4.5 KiB
Go

package main
import (
"bytes"
"context"
"io"
"log/slog"
"os"
"path/filepath"
"strconv"
"strings"
"testing"
"time"
tuttitypes "github.com/tutti-os/tutti/services/tuttid/types"
)
func TestRunHelpExitsBeforeCreatingState(t *testing.T) {
stateDir := filepath.Join(t.TempDir(), "state")
t.Setenv("TUTTI_STATE_DIR", stateDir)
var stdout bytes.Buffer
var stderr bytes.Buffer
if exitCode := run([]string{"--help"}, &stdout, &stderr); exitCode != 0 {
t.Fatalf("run(--help) exit code = %d, want 0", exitCode)
}
if !strings.Contains(stdout.String(), "Usage: tuttid") {
t.Fatalf("run(--help) stdout = %q", stdout.String())
}
if stderr.Len() != 0 {
t.Fatalf("run(--help) stderr = %q, want empty", stderr.String())
}
if _, err := os.Stat(stateDir); !os.IsNotExist(err) {
t.Fatalf("state directory exists after --help: %v", err)
}
}
func TestRunRejectsUnexpectedArgumentsBeforeCreatingState(t *testing.T) {
stateDir := filepath.Join(t.TempDir(), "state")
t.Setenv("TUTTI_STATE_DIR", stateDir)
var stdout bytes.Buffer
var stderr bytes.Buffer
if exitCode := run([]string{"--version"}, &stdout, &stderr); exitCode != 2 {
t.Fatalf("run(--version) exit code = %d, want 2", exitCode)
}
if stdout.Len() != 0 {
t.Fatalf("run(--version) stdout = %q, want empty", stdout.String())
}
if !strings.Contains(stderr.String(), "unexpected arguments: --version") {
t.Fatalf("run(--version) stderr = %q", stderr.String())
}
if _, err := os.Stat(stateDir); !os.IsNotExist(err) {
t.Fatalf("state directory exists after invalid argument: %v", err)
}
}
func TestContextWithDesktopParentMonitorCancelsWhenParentPIDIsGone(t *testing.T) {
t.Setenv("TUTTI_DESKTOP_PARENT_PID", "999999999")
ctx, cancel := contextWithDesktopParentMonitor(context.Background(), testLogger())
defer cancel()
select {
case <-ctx.Done():
case <-time.After(2 * time.Second):
t.Fatal("parent monitor did not cancel after missing parent pid")
}
}
func TestContextWithDesktopParentMonitorKeepsStandaloneDaemonRunning(t *testing.T) {
t.Setenv("TUTTI_DESKTOP_PARENT_PID", "")
ctx, cancel := contextWithDesktopParentMonitor(context.Background(), testLogger())
defer cancel()
select {
case <-ctx.Done():
t.Fatal("standalone daemon context cancelled unexpectedly")
case <-time.After(100 * time.Millisecond):
}
}
func TestContextWithDesktopParentMonitorAcceptsLiveParentPID(t *testing.T) {
t.Setenv("TUTTI_DESKTOP_PARENT_PID", strconv.Itoa(os.Getpid()))
ctx, cancel := contextWithDesktopParentMonitor(context.Background(), testLogger())
defer cancel()
select {
case <-ctx.Done():
t.Fatal("live parent context cancelled unexpectedly")
case <-time.After(100 * time.Millisecond):
}
}
func TestProcessExists(t *testing.T) {
if !tuttitypes.ProcessExists(os.Getpid()) {
t.Fatal("ProcessExists(os.Getpid()) = false")
}
if tuttitypes.ProcessExists(-1) {
t.Fatal("ProcessExists(-1) = true")
}
}
func TestWiringUsesSupervisedAgentHostRun(t *testing.T) {
var source strings.Builder
for _, file := range []string{"wiring.go", "wiring_daemon_api.go"} {
raw, err := os.ReadFile(file)
if err != nil {
t.Fatalf("read %s: %v", file, err)
}
source.Write(raw)
source.WriteByte('\n')
}
combined := source.String()
if !strings.Contains(combined, "agentHost.Run(ctx)") {
t.Fatal("production wiring does not start the supervised Agent Host lifecycle")
}
for _, legacy := range []string{
"agentHost.RunRuntimeOperationWorker(ctx)",
"agentHost.RunGoalOperationWorker(ctx)",
"agentHost.RunGoalReconcileInboxWorker(ctx)",
"agentHost.RunWorktreeGarbageCollectionWorker(ctx)",
} {
if strings.Contains(combined, legacy) {
t.Fatalf("production wiring still starts an unsupervised Host worker: %s", legacy)
}
}
}
func TestWiringComposesTuttiModeGoalReviewLifecycle(t *testing.T) {
var source strings.Builder
for _, file := range []string{
"wiring_daemon_api.go",
"wiring_daemon_cli.go",
} {
raw, err := os.ReadFile(file)
if err != nil {
t.Fatalf("read %s: %v", file, err)
}
source.Write(raw)
source.WriteByte('\n')
}
for _, required := range []string{
"tuttiModeExecutions.ReviewerTargets = tuttiModeReviewerAgentAdapter{",
"tuttiModeReviewerTurnObserver{",
"tuttigoalreviewcli.NewProvider(",
"TuttiModeGoalReviewService: tuttiModeExecutions",
"registry.AgentSessionCapabilities = agentSessionCLIProjectionResolver{",
} {
if !strings.Contains(source.String(), required) {
t.Fatalf("production wiring is missing Goal Review composition: %s", required)
}
}
}
func testLogger() *slog.Logger {
return slog.New(slog.NewTextHandler(io.Discard, nil))
}