carlos / platform Public

Reuse reviewed CLI and socket test isolation for storage gate

claude agent, operated by paul@keymail.dev 988a052e36726cb7e06e4004a31c0763baf49adb parent eaf6e63
8 files changed, +48 −18
  • apimode_test.go +12 −5
  • auth_e2e_test.go +5 −2
  • auth_test.go +1 −0
  • config_test.go +1 −0
  • e2e_test.go +2 −0
  • internal/activator/activator_test.go +22 −9
  • scopedkeys_e2e_test.go +2 −0
  • update_test.go +3 −2
diff --git a/apimode_test.go b/apimode_test.go
index 681094f26..b4c3b1060 100644
--- a/apimode_test.go
+++ b/apimode_test.go
@@ -51,6 +51,7 @@ func clearDeploymentEnv(t *testing.T) {
t.Setenv("CARLOS_DEPLOYMENT_BUCKET", "")
t.Setenv("CARLOS_DEPLOYMENT_DIR", "")
t.Setenv("CARLOS_CONSOLE", "")
+ t.Setenv("CARLOS_CONFIG", filepath.Join(t.TempDir(), "config"))
}
func TestResolveModeDirectWins(t *testing.T) {
@@ -3299,6 +3300,7 @@ func TestDefaultAccountConfigDefault(t *testing.T) {
// A config account paired with THIS console is honored without asking
// the console anything.
cfgPath := writeConfig(t, ".", `{"console": "`+s.console+`", "account": "acme"}`)
+ t.Setenv("CARLOS_CONFIG", cfgPath)
a, err := s.defaultAccount(context.Background())
if err != nil || a.Seg != "acme" || a.Exact {
t.Fatalf("config account = %+v, %v; want the name, resolved server-side", a, err)
@@ -3426,6 +3428,7 @@ func TestConsoleMovedOfferLogsInAndRepointsConfig(t *testing.T) {
}))
t.Cleanup(old.Close)
cfgPath := writeConfig(t, ".", `{"console": "`+old.URL+`", "account": "acme"}`)
+ t.Setenv("CARLOS_CONFIG", cfgPath)
oldIn := chooserIn
chooserIn = strings.NewReader("y\ny\n") // log in? yes. repoint config? yes.
t.Cleanup(func() { chooserIn = oldIn })
@@ -3513,7 +3516,8 @@ func TestResolveModeOffersLoginAndContinues(t *testing.T) {
captureStdout(t)
forceTerminal(t, true)
fc := newFakeConsole(t)
- writeConfig(t, ".", `{"console": "`+fc.ts.URL+`"}`)
+ cfgPath := writeConfig(t, ".", `{"console": "`+fc.ts.URL+`"}`)
+ t.Setenv("CARLOS_CONFIG", cfgPath)
oldIn := chooserIn
chooserIn = strings.NewReader("y\n")
t.Cleanup(func() { chooserIn = oldIn })
@@ -3533,7 +3537,8 @@ func TestResolveModeOfferDeclinedKeepsTheError(t *testing.T) {
captureStdout(t)
forceTerminal(t, true)
fc := newFakeConsole(t)
- writeConfig(t, ".", `{"console": "`+fc.ts.URL+`"}`)
+ cfgPath := writeConfig(t, ".", `{"console": "`+fc.ts.URL+`"}`)
+ t.Setenv("CARLOS_CONFIG", cfgPath)
oldIn := chooserIn
chooserIn = strings.NewReader("n\n")
t.Cleanup(func() { chooserIn = oldIn })
@@ -3551,7 +3556,8 @@ func TestResolveModeNonTTYErrorsUnchanged(t *testing.T) {
captureStdout(t)
forceTerminal(t, false)
fc := newFakeConsole(t)
- writeConfig(t, ".", `{"console": "`+fc.ts.URL+`"}`)
+ cfgPath := writeConfig(t, ".", `{"console": "`+fc.ts.URL+`"}`)
+ t.Setenv("CARLOS_CONFIG", cfgPath)
// No prompt machinery runs at all: scripts get the string they have
// always matched.
@@ -3561,7 +3567,7 @@ func TestResolveModeNonTTYErrorsUnchanged(t *testing.T) {
}
// And the nothing-configured case keeps ITS exact wording too.
- os.RemoveAll(".carlos")
+ os.Remove(cfgPath)
if _, err := resolveMode(""); err == nil ||
!strings.Contains(err.Error(), "no deployment target configured") {
t.Fatalf("non-TTY unconfigured = %v", err)
@@ -3705,7 +3711,8 @@ func TestDefaultAppConfigPairing(t *testing.T) {
`{"accounts":[{"sqid":"bdk","name":"tom@keymail.dev","apps":["shop","blog"]}]}`)
// Paired with THIS console: honored without any fetch.
- writeConfig(t, ".", `{"console": "`+s.console+`", "app": "shop"}`)
+ cfgPath := writeConfig(t, ".", `{"console": "`+s.console+`", "app": "shop"}`)
+ t.Setenv("CARLOS_CONFIG", cfgPath)
app, err := s.defaultApp(context.Background(), apiAcct{Seg: "bdk", Exact: true}, false)
if err != nil || app != "shop" || *hits != 0 {
t.Fatalf("config app = %q, %v, hits=%d", app, err, *hits)
diff --git a/auth_e2e_test.go b/auth_e2e_test.go
index 6d2189118..f7aaa45a2 100644
--- a/auth_e2e_test.go
+++ b/auth_e2e_test.go
@@ -48,14 +48,17 @@ func TestAuthCLI(t *testing.T) {
fc := newFakeConsole(t)
home := t.TempDir()
creds := filepath.Join(home, ".carlos", "credentials")
- env := append(os.Environ(),
+ env := carlosTestEnv(t,
"CARLOS_CREDENTIALS="+creds,
"HOME="+home,
"CARLOS_CONSOLE=",
+ "CARLOS_CONFIG=",
)
run := func(args ...string) (string, error) {
- cmd := exec.Command(bin, args...)
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer cancel()
+ cmd := exec.CommandContext(ctx, bin, args...)
cmd.Env = env
// pick() walks cwd ancestors for .carlos/config, so the subprocess must not run from the real checkout.
cmd.Dir = home
diff --git a/auth_test.go b/auth_test.go
index 5a51b4955..38dd7e89b 100644
--- a/auth_test.go
+++ b/auth_test.go
@@ -23,6 +23,7 @@ func useTempCredentials(t *testing.T) string {
home := t.TempDir()
t.Setenv("HOME", home)
t.Setenv("CARLOS_CONSOLE", "")
+ t.Setenv("CARLOS_CONFIG", "")
t.Chdir(t.TempDir())
path := filepath.Join(t.TempDir(), "carlos", "credentials")
t.Setenv("CARLOS_CREDENTIALS", path)
diff --git a/config_test.go b/config_test.go
index 1089631c0..23cff19b9 100644
--- a/config_test.go
+++ b/config_test.go
@@ -98,6 +98,7 @@ func TestConfigDefaultWalk(t *testing.T) {
home := t.TempDir()
t.Setenv("HOME", home)
t.Setenv("CARLOS_CONSOLE", "")
+ t.Setenv("CARLOS_CONFIG", "")
t.Setenv("CARLOS_CREDENTIALS", filepath.Join(home, "credentials"))
root := filepath.Join(home, "project")
if err := os.MkdirAll(root, 0o755); err != nil {
diff --git a/e2e_test.go b/e2e_test.go
index 1a30a9d32..5c1dc280d 100644
--- a/e2e_test.go
+++ b/e2e_test.go
@@ -86,6 +86,8 @@ func carlosTestEnv(t *testing.T, extra ...string) []string {
"CARLOS_CREDENTIALS="+filepath.Join(scratch, "credentials"),
"HOME="+scratch,
"CARLOS_CONSOLE=",
+ "CARLOS_CONFIG=",
+ "CARLOS_DESTINATION=",
)
return append(env, extra...)
}
diff --git a/internal/activator/activator_test.go b/internal/activator/activator_test.go
index c27ccd6ca..a16d90892 100644
--- a/internal/activator/activator_test.go
+++ b/internal/activator/activator_test.go
@@ -863,6 +863,19 @@ func tmpSock(t *testing.T) string {
return s
}
+// shortTempDir is a direct child of the configured temp root. t.TempDir
+// includes the test's full name, which can push a derived .control socket
+// past sockaddr_un.sun_path's limit when TMPDIR is a disk-backed gate path.
+func shortTempDir(t *testing.T) string {
+ t.Helper()
+ dir, err := os.MkdirTemp(os.TempDir(), "ca-")
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Cleanup(func() { os.RemoveAll(dir) })
+ return dir
+}
+
// --- tests ---------------------------------------------------------------------
// Many concurrent requests during a wake coalesce into exactly one wake: one
@@ -4832,7 +4845,7 @@ func TestExecBackendStartPassesControlSocketInEnvAndStartsPurgeListener(t *testi
rt := registry.Route{
Host: "control-socket.example.com",
Kind: "instance",
- Socket: filepath.Join(t.TempDir(), "instance.sock"),
+ Socket: filepath.Join(shortTempDir(t), "instance.sock"),
}
wantControlSocket := rt.Socket + ".control"
@@ -4898,7 +4911,7 @@ func TestExecBackendStartWithNilCacheStillBindsControlSocket(t *testing.T) {
rt := registry.Route{
Host: host,
Kind: "instance",
- Socket: filepath.Join(t.TempDir(), "instance.sock"),
+ Socket: filepath.Join(shortTempDir(t), "instance.sock"),
}
wantControlSocket := rt.Socket + ".control"
@@ -4981,7 +4994,7 @@ func (f *fakeTimerStore) CountTimers(host, kind string) (int, error) { retu
func startAndReachControlSocket(t *testing.T, b *ExecBackend, host string) (controlSocket, token string, stop func()) {
t.Helper()
stageRecordingLiveFullEnv(t, b, host, "v1")
- rt := registry.Route{Host: host, Kind: "instance", Socket: filepath.Join(t.TempDir(), "instance.sock")}
+ rt := registry.Route{Host: host, Kind: "instance", Socket: filepath.Join(shortTempDir(t), "instance.sock")}
controlSocket = rt.Socket + ".control"
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
@@ -5116,7 +5129,7 @@ func TestExecBackendStartMergesConfigEnvUnderOwnEnv(t *testing.T) {
rt := registry.Route{
Host: host,
Kind: "instance",
- Socket: filepath.Join(t.TempDir(), "instance.sock"),
+ Socket: filepath.Join(shortTempDir(t), "instance.sock"),
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
@@ -5163,7 +5176,7 @@ func TestExecBackendStartAdvertisesHeaderPurgeChannel(t *testing.T) {
rt := registry.Route{
Host: host,
Kind: "instance",
- Socket: filepath.Join(t.TempDir(), "instance.sock"),
+ Socket: filepath.Join(shortTempDir(t), "instance.sock"),
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
@@ -5202,7 +5215,7 @@ func TestExecBackendStartWithNilCacheSetsNoPurgeVar(t *testing.T) {
rt := registry.Route{
Host: host,
Kind: "instance",
- Socket: filepath.Join(t.TempDir(), "instance.sock"),
+ Socket: filepath.Join(shortTempDir(t), "instance.sock"),
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
@@ -5247,7 +5260,7 @@ func TestExecBackendStartTenantCannotClaimAbsentPurgeChannel(t *testing.T) {
rt := registry.Route{
Host: host,
Kind: "instance",
- Socket: filepath.Join(t.TempDir(), "instance.sock"),
+ Socket: filepath.Join(shortTempDir(t), "instance.sock"),
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
@@ -5295,7 +5308,7 @@ func TestExecBackendStartOverridesTenantSuppliedPurgeVars(t *testing.T) {
rt := registry.Route{
Host: host,
Kind: "instance",
- Socket: filepath.Join(t.TempDir(), "instance.sock"),
+ Socket: filepath.Join(shortTempDir(t), "instance.sock"),
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
@@ -5344,7 +5357,7 @@ func TestExecBackendStartPurgesHostCacheOnSpawn(t *testing.T) {
rt := registry.Route{
Host: "deploy.example.com",
Kind: "instance",
- Socket: filepath.Join(t.TempDir(), "instance.sock"),
+ Socket: filepath.Join(shortTempDir(t), "instance.sock"),
}
proc, _, _ := b.Start(ctx, rt) // health-wait failure is expected; the spawn still happened
if proc != nil {
diff --git a/scopedkeys_e2e_test.go b/scopedkeys_e2e_test.go
index 56f27be90..e3bbadecf 100644
--- a/scopedkeys_e2e_test.go
+++ b/scopedkeys_e2e_test.go
@@ -33,6 +33,8 @@ func carlosTestEnv(t *testing.T, extra ...string) []string {
"CARLOS_CREDENTIALS="+filepath.Join(scratch, "credentials"),
"HOME="+scratch,
"CARLOS_CONSOLE=",
+ "CARLOS_CONFIG=",
+ "CARLOS_DESTINATION=",
)
return append(env, extra...)
}
diff --git a/update_test.go b/update_test.go
index 3c0815aaf..e16d12cc6 100644
--- a/update_test.go
+++ b/update_test.go
@@ -119,9 +119,10 @@ func TestUpdateHintGates(t *testing.T) {
maybeUpdateHint("ship")
t.Setenv("CARLOS_NO_UPDATE_CHECK", "")
- writeConfig(t, ".", `{"update_check": "off"}`)
+ cfgPath := writeConfig(t, ".", `{"update_check": "off"}`)
+ t.Setenv("CARLOS_CONFIG", cfgPath)
maybeUpdateHint("ship")
- os.RemoveAll(".carlos")
+ os.Remove(cfgPath)
maybeUpdateHint("edge") // box verb
maybeUpdateHint("version") // parsed output