Skip to content

Commit dfc5f8e

Browse files
committed
test(acp): harden smoke setup and cover adapter scripts
1 parent abe66e6 commit dfc5f8e

File tree

2 files changed

+122
-1
lines changed

2 files changed

+122
-1
lines changed

internal/agent/acp_integration_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,14 @@ func TestACPReviewViaExternalAdapter(t *testing.T) {
6868
}
6969

7070
gitRun("init")
71+
disabledHooksDir := filepath.Join(repoPath, ".git", "hooks-disabled")
72+
if err := os.MkdirAll(disabledHooksDir, 0o755); err != nil {
73+
t.Fatalf("failed to create disabled hooks dir: %v", err)
74+
}
7175
gitRun("config", "user.email", "acp-integration@example.com")
7276
gitRun("config", "user.name", "ACP Integration")
7377
gitRun("add", "README.md")
74-
gitRun("commit", "-m", "seed")
78+
gitRun("-c", "commit.gpgsign=false", "-c", "core.hooksPath="+disabledHooksDir, "commit", "--no-verify", "-m", "seed")
7579
commitSHA := strings.TrimSpace(gitRun("rev-parse", "HEAD"))
7680
if commitSHA == "" {
7781
t.Fatal("failed to resolve HEAD commit SHA for integration test")

internal/agent/acp_script_test.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package agent
2+
3+
import (
4+
"bytes"
5+
"os"
6+
"os/exec"
7+
"path/filepath"
8+
"runtime"
9+
"strings"
10+
"testing"
11+
)
12+
13+
func acpScriptsDir(t *testing.T) string {
14+
t.Helper()
15+
_, file, _, ok := runtime.Caller(0)
16+
if !ok {
17+
t.Fatal("failed to resolve test file path")
18+
}
19+
return filepath.Join(filepath.Dir(file), "..", "..", "scripts")
20+
}
21+
22+
func writeACPTestCommand(t *testing.T, dir, name, script string) {
23+
t.Helper()
24+
path := filepath.Join(dir, name)
25+
if err := os.WriteFile(path, []byte(script), 0o755); err != nil {
26+
t.Fatalf("failed to write command %s: %v", name, err)
27+
}
28+
}
29+
30+
func runACPWrapperCommand(t *testing.T, commandPath string, env map[string]string, args ...string) (string, string, error) {
31+
t.Helper()
32+
33+
cmd := exec.Command(commandPath, args...)
34+
cmd.Env = os.Environ()
35+
for k, v := range env {
36+
cmd.Env = append(cmd.Env, k+"="+v)
37+
}
38+
39+
var stdout bytes.Buffer
40+
var stderr bytes.Buffer
41+
cmd.Stdout = &stdout
42+
cmd.Stderr = &stderr
43+
err := cmd.Run()
44+
return stdout.String(), stderr.String(), err
45+
}
46+
47+
func TestACPWrapperScripts(t *testing.T) {
48+
if runtime.GOOS == "windows" {
49+
t.Skip("ACP wrapper scripts are POSIX shell scripts")
50+
}
51+
52+
scriptsDir := acpScriptsDir(t)
53+
basePath := os.Getenv("PATH")
54+
55+
t.Run("ROBOREV_ACP_ADAPTER_COMMAND override takes precedence", func(t *testing.T) {
56+
fakeBinDir := t.TempDir()
57+
overrideCommand := filepath.Join(fakeBinDir, "override-acp")
58+
writeACPTestCommand(t, fakeBinDir, "override-acp", "#!/bin/sh\necho ACP_OVERRIDE_OK\n")
59+
60+
stdout, stderr, err := runACPWrapperCommand(t, filepath.Join(scriptsDir, "acp-agent"), map[string]string{
61+
"ROBOREV_ACP_ADAPTER_COMMAND": overrideCommand,
62+
"ROBOREV_ACP_ADAPTER": "gemini",
63+
"PATH": fakeBinDir + string(os.PathListSeparator) + basePath,
64+
})
65+
if err != nil {
66+
t.Fatalf("expected override command to succeed, got err=%v stderr=%q", err, stderr)
67+
}
68+
if !strings.Contains(stdout, "ACP_OVERRIDE_OK") {
69+
t.Fatalf("expected override marker in stdout, got: %q", stdout)
70+
}
71+
})
72+
73+
t.Run("Adapter dispatch invokes claude wrapper binary from PATH", func(t *testing.T) {
74+
fakeBinDir := t.TempDir()
75+
writeACPTestCommand(t, fakeBinDir, "claude-agent-acp", "#!/bin/sh\necho ACP_CLAUDE_OK\n")
76+
77+
stdout, stderr, err := runACPWrapperCommand(t, filepath.Join(scriptsDir, "acp-agent"), map[string]string{
78+
"ROBOREV_ACP_ADAPTER": "claude",
79+
"PATH": fakeBinDir + string(os.PathListSeparator) + basePath,
80+
})
81+
if err != nil {
82+
t.Fatalf("expected claude adapter dispatch to succeed, got err=%v stderr=%q", err, stderr)
83+
}
84+
if !strings.Contains(stdout, "ACP_CLAUDE_OK") {
85+
t.Fatalf("expected claude marker in stdout, got: %q", stdout)
86+
}
87+
})
88+
89+
t.Run("Gemini wrapper appends --experimental-acp flag", func(t *testing.T) {
90+
fakeBinDir := t.TempDir()
91+
writeACPTestCommand(t, fakeBinDir, "gemini", "#!/bin/sh\necho GEMINI_ARGS:$@\n")
92+
93+
stdout, stderr, err := runACPWrapperCommand(t, filepath.Join(scriptsDir, "acp-agent"), map[string]string{
94+
"ROBOREV_ACP_ADAPTER": "gemini",
95+
"PATH": fakeBinDir + string(os.PathListSeparator) + basePath,
96+
}, "--test-arg")
97+
if err != nil {
98+
t.Fatalf("expected gemini adapter dispatch to succeed, got err=%v stderr=%q", err, stderr)
99+
}
100+
if !strings.Contains(stdout, "GEMINI_ARGS:--experimental-acp --test-arg") {
101+
t.Fatalf("expected gemini experimental flag in args, got: %q", stdout)
102+
}
103+
})
104+
105+
t.Run("Unsupported adapter returns error", func(t *testing.T) {
106+
stdout, stderr, err := runACPWrapperCommand(t, filepath.Join(scriptsDir, "acp-agent"), map[string]string{
107+
"ROBOREV_ACP_ADAPTER": "unsupported",
108+
"PATH": basePath,
109+
})
110+
if err == nil {
111+
t.Fatalf("expected unsupported adapter to fail, stdout=%q stderr=%q", stdout, stderr)
112+
}
113+
if !strings.Contains(stderr, "unsupported ACP adapter") {
114+
t.Fatalf("expected unsupported adapter error message, got stderr=%q", stderr)
115+
}
116+
})
117+
}

0 commit comments

Comments
 (0)