Skip to content

Commit 9e06d89

Browse files
committed
Fix Windows CI: .exe suffix, USERPROFILE, skip Unix-specific tests
- TestMain: append .exe to binary name on Windows - Add testEnvWithHome/setTestHome helpers for cross-platform HOME override (Windows uses USERPROFILE, not HOME) - Add exeSuffix() helper for fake binary creation - Skip Unix-specific tests on Windows: shell RC detection, PATH append, fallback path lookup - Normalize CRLF in skill frontmatter check (git may convert on Windows)
1 parent e773c6a commit 9e06d89

2 files changed

Lines changed: 72 additions & 24 deletions

File tree

cmd/codebase-memory-mcp/cli_test.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"os"
66
"os/exec"
77
"path/filepath"
8+
"runtime"
89
"strings"
910
"testing"
1011
"time"
@@ -20,7 +21,11 @@ func TestMain(m *testing.M) {
2021
panic("create temp dir: " + err.Error())
2122
}
2223

23-
binPath := filepath.Join(tmpDir, "codebase-memory-mcp")
24+
binName := "codebase-memory-mcp"
25+
if runtime.GOOS == "windows" {
26+
binName += ".exe"
27+
}
28+
binPath := filepath.Join(tmpDir, binName)
2429
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
2530
cmd := exec.CommandContext(ctx, "go", "build", "-o", binPath, "./")
2631
cmd.Dir = "."
@@ -45,6 +50,15 @@ func testCmd(t *testing.T, args ...string) *exec.Cmd {
4550
return exec.CommandContext(ctx, testBinPath, args...)
4651
}
4752

53+
// testEnvWithHome returns env vars with HOME (and USERPROFILE on Windows) set.
54+
func testEnvWithHome(home string, extra ...string) []string {
55+
env := append(os.Environ(), "HOME="+home)
56+
if runtime.GOOS == "windows" {
57+
env = append(env, "USERPROFILE="+home)
58+
}
59+
return append(env, extra...)
60+
}
61+
4862
func TestCLI_Version(t *testing.T) {
4963
out, err := testCmd(t, "--version").CombinedOutput()
5064
if err != nil {
@@ -59,7 +73,7 @@ func TestCLI_Version(t *testing.T) {
5973
func TestCLI_InstallDryRun(t *testing.T) {
6074
home := t.TempDir()
6175
cmd := testCmd(t, "install", "--dry-run")
62-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+t.TempDir())
76+
cmd.Env = testEnvWithHome(home, "PATH="+t.TempDir())
6377
out, err := cmd.CombinedOutput()
6478
if err != nil {
6579
t.Fatalf("install --dry-run failed: %v\n%s", err, out)
@@ -78,7 +92,7 @@ func TestCLI_InstallDryRun(t *testing.T) {
7892
func TestCLI_UninstallDryRun(t *testing.T) {
7993
home := t.TempDir()
8094
cmd := testCmd(t, "uninstall", "--dry-run")
81-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+t.TempDir())
95+
cmd.Env = testEnvWithHome(home, "PATH="+t.TempDir())
8296
out, err := cmd.CombinedOutput()
8397
if err != nil {
8498
t.Fatalf("uninstall --dry-run failed: %v\n%s", err, out)
@@ -116,7 +130,7 @@ func TestCLI_InstallAndUninstall(t *testing.T) {
116130

117131
// Install
118132
cmd := testCmd(t, "install")
119-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+emptyPath, "SHELL=/bin/zsh")
133+
cmd.Env = testEnvWithHome(home, "PATH="+emptyPath, "SHELL=/bin/zsh")
120134
out, err := cmd.CombinedOutput()
121135
if err != nil {
122136
t.Fatalf("install failed: %v\n%s", err, out)
@@ -138,7 +152,7 @@ func TestCLI_InstallAndUninstall(t *testing.T) {
138152

139153
// Uninstall
140154
cmd = testCmd(t, "uninstall")
141-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+emptyPath)
155+
cmd.Env = testEnvWithHome(home, "PATH="+emptyPath)
142156
out, err = cmd.CombinedOutput()
143157
if err != nil {
144158
t.Fatalf("uninstall failed: %v\n%s", err, out)
@@ -166,7 +180,7 @@ func TestCLI_InstallRemovesOldSkill(t *testing.T) {
166180
}
167181

168182
cmd := testCmd(t, "install")
169-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+emptyPath, "SHELL=/bin/zsh")
183+
cmd.Env = testEnvWithHome(home, "PATH="+emptyPath, "SHELL=/bin/zsh")
170184
out, err := cmd.CombinedOutput()
171185
if err != nil {
172186
t.Fatalf("install failed: %v\n%s", err, out)
@@ -186,7 +200,7 @@ func TestCLI_InstallIdempotent(t *testing.T) {
186200

187201
for i := 0; i < 2; i++ {
188202
cmd := testCmd(t, "install")
189-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+emptyPath, "SHELL=/bin/zsh")
203+
cmd.Env = testEnvWithHome(home, "PATH="+emptyPath, "SHELL=/bin/zsh")
190204
out, err := cmd.CombinedOutput()
191205
if err != nil {
192206
t.Fatalf("install round %d failed: %v\n%s", i, err, out)
@@ -204,7 +218,7 @@ func TestCLI_InstallForceOverwrites(t *testing.T) {
204218
emptyPath := t.TempDir()
205219

206220
cmd := testCmd(t, "install")
207-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+emptyPath, "SHELL=/bin/zsh")
221+
cmd.Env = testEnvWithHome(home, "PATH="+emptyPath, "SHELL=/bin/zsh")
208222
if out, err := cmd.CombinedOutput(); err != nil {
209223
t.Fatalf("first install failed: %v\n%s", err, out)
210224
}
@@ -215,7 +229,7 @@ func TestCLI_InstallForceOverwrites(t *testing.T) {
215229
}
216230

217231
cmd = testCmd(t, "install")
218-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+emptyPath, "SHELL=/bin/zsh")
232+
cmd.Env = testEnvWithHome(home, "PATH="+emptyPath, "SHELL=/bin/zsh")
219233
out, err := cmd.CombinedOutput()
220234
if err != nil {
221235
t.Fatalf("second install failed: %v\n%s", err, out)
@@ -226,7 +240,7 @@ func TestCLI_InstallForceOverwrites(t *testing.T) {
226240
}
227241

228242
cmd = testCmd(t, "install", "--force")
229-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+emptyPath, "SHELL=/bin/zsh")
243+
cmd.Env = testEnvWithHome(home, "PATH="+emptyPath, "SHELL=/bin/zsh")
230244
out, err = cmd.CombinedOutput()
231245
if err != nil {
232246
t.Fatalf("force install failed: %v\n%s", err, out)
@@ -238,12 +252,15 @@ func TestCLI_InstallForceOverwrites(t *testing.T) {
238252
}
239253

240254
func TestCLI_InstallPATHAppend(t *testing.T) {
255+
if runtime.GOOS == "windows" {
256+
t.Skip("shell RC PATH append is Unix-specific")
257+
}
258+
241259
home := t.TempDir()
242-
t.Setenv("SHELL", "/bin/zsh")
243260
emptyPath := t.TempDir()
244261

245262
cmd := testCmd(t, "install")
246-
cmd.Env = append(os.Environ(), "HOME="+home, "PATH="+emptyPath, "SHELL=/bin/zsh")
263+
cmd.Env = testEnvWithHome(home, "PATH="+emptyPath, "SHELL=/bin/zsh")
247264
out, err := cmd.CombinedOutput()
248265
if err != nil {
249266
t.Fatalf("install failed: %v\n%s", err, out)

cmd/codebase-memory-mcp/install_test.go

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,31 @@ package main
33
import (
44
"os"
55
"path/filepath"
6+
"runtime"
67
"strings"
78
"testing"
89
)
910

11+
// setTestHome overrides the home directory for both Unix (HOME) and Windows (USERPROFILE).
12+
func setTestHome(t *testing.T, home string) {
13+
t.Helper()
14+
t.Setenv("HOME", home)
15+
if runtime.GOOS == "windows" {
16+
t.Setenv("USERPROFILE", home)
17+
}
18+
}
19+
20+
// exeSuffix returns ".exe" on Windows, empty string otherwise.
21+
func exeSuffix() string {
22+
if runtime.GOOS == "windows" {
23+
return ".exe"
24+
}
25+
return ""
26+
}
27+
1028
func TestInstallSkillCreation(t *testing.T) {
1129
home := t.TempDir()
12-
t.Setenv("HOME", home)
30+
setTestHome(t, home)
1331

1432
claudeSkillsDir := filepath.Join(home, ".claude", "skills")
1533

@@ -41,7 +59,8 @@ func TestInstallSkillCreation(t *testing.T) {
4159
if len(data) == 0 {
4260
t.Fatalf("skill file %s is empty", skillFile)
4361
}
44-
if !strings.HasPrefix(string(data), "---\n") {
62+
normalized := strings.ReplaceAll(string(data), "\r\n", "\n")
63+
if !strings.HasPrefix(normalized, "---\n") {
4564
t.Fatalf("skill %s missing YAML frontmatter", name)
4665
}
4766
if !strings.Contains(string(data), "name: "+name) {
@@ -52,7 +71,7 @@ func TestInstallSkillCreation(t *testing.T) {
5271

5372
func TestInstallIdempotent(t *testing.T) {
5473
home := t.TempDir()
55-
t.Setenv("HOME", home)
74+
setTestHome(t, home)
5675

5776
claudeSkillsDir := filepath.Join(home, ".claude", "skills")
5877

@@ -79,7 +98,7 @@ func TestInstallIdempotent(t *testing.T) {
7998

8099
func TestUninstallRemovesSkills(t *testing.T) {
81100
home := t.TempDir()
82-
t.Setenv("HOME", home)
101+
setTestHome(t, home)
83102

84103
claudeSkillsDir := filepath.Join(home, ".claude", "skills")
85104

@@ -110,7 +129,7 @@ func TestUninstallRemovesSkills(t *testing.T) {
110129

111130
func TestFindCLI_NotFound(t *testing.T) {
112131
t.Setenv("PATH", t.TempDir())
113-
t.Setenv("HOME", t.TempDir())
132+
setTestHome(t, t.TempDir())
114133

115134
result := findCLI("nonexistent-binary-xyz")
116135
if result != "" {
@@ -121,7 +140,7 @@ func TestFindCLI_NotFound(t *testing.T) {
121140
func TestFindCLI_FoundOnPATH(t *testing.T) {
122141
tmpDir := t.TempDir()
123142

124-
fakeBin := filepath.Join(tmpDir, "fakecli")
143+
fakeBin := filepath.Join(tmpDir, "fakecli"+exeSuffix())
125144
if err := os.WriteFile(fakeBin, []byte("#!/bin/sh\n"), 0o600); err != nil {
126145
t.Fatalf("write fake binary: %v", err)
127146
}
@@ -130,15 +149,19 @@ func TestFindCLI_FoundOnPATH(t *testing.T) {
130149
}
131150

132151
t.Setenv("PATH", tmpDir)
133-
result := findCLI("fakecli")
152+
result := findCLI("fakecli" + exeSuffix())
134153
if result == "" {
135154
t.Fatal("expected to find fakecli on PATH")
136155
}
137156
}
138157

139158
func TestFindCLI_FallbackPaths(t *testing.T) {
159+
if runtime.GOOS == "windows" {
160+
t.Skip("fallback paths use Unix-specific locations")
161+
}
162+
140163
home := t.TempDir()
141-
t.Setenv("HOME", home)
164+
setTestHome(t, home)
142165
t.Setenv("PATH", t.TempDir())
143166

144167
localBin := filepath.Join(home, ".local", "bin")
@@ -173,8 +196,12 @@ func TestDetectBinaryPath(t *testing.T) {
173196
}
174197

175198
func TestDetectShellRC(t *testing.T) {
199+
if runtime.GOOS == "windows" {
200+
t.Skip("shell RC detection is Unix-specific")
201+
}
202+
176203
home := t.TempDir()
177-
t.Setenv("HOME", home)
204+
setTestHome(t, home)
178205

179206
tests := []struct {
180207
shell string
@@ -201,8 +228,12 @@ func TestDetectShellRC(t *testing.T) {
201228
}
202229

203230
func TestDetectShellRC_BashWithBashrc(t *testing.T) {
231+
if runtime.GOOS == "windows" {
232+
t.Skip("shell RC detection is Unix-specific")
233+
}
234+
204235
home := t.TempDir()
205-
t.Setenv("HOME", home)
236+
setTestHome(t, home)
206237
t.Setenv("SHELL", "/bin/bash")
207238

208239
bashrc := filepath.Join(home, ".bashrc")
@@ -233,7 +264,7 @@ func TestDryRun(t *testing.T) {
233264

234265
func TestCodexInstructionsCreation(t *testing.T) {
235266
home := t.TempDir()
236-
t.Setenv("HOME", home)
267+
setTestHome(t, home)
237268

238269
instrDir := filepath.Join(home, ".codex", "instructions")
239270
instrFile := filepath.Join(instrDir, "codebase-memory-mcp.md")
@@ -284,7 +315,7 @@ func TestSkillFilesContent(t *testing.T) {
284315

285316
func TestRemoveOldMonolithicSkill(t *testing.T) {
286317
home := t.TempDir()
287-
t.Setenv("HOME", home)
318+
setTestHome(t, home)
288319

289320
oldDir := filepath.Join(home, ".claude", "skills", "codebase-memory-mcp")
290321
if err := os.MkdirAll(oldDir, 0o750); err != nil {

0 commit comments

Comments
 (0)