Reuse reviewed CLI and socket fixture isolation for allowance gate
8 files changed,
+48
−18
apimode_test.go+12 −5auth_e2e_test.go+5 −2auth_test.go+1 −0config_test.go+1 −0e2e_test.go+2 −0internal/activator/activator_test.go+22 −9scopedkeys_e2e_test.go+2 −0update_test.go+3 −2
CI failed — run details
diff --git a/apimode_test.go b/apimode_test.go| index 0afdfb175..387ef1115 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 }) |
| @@ -3522,7 +3525,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 }) |
| @@ -3542,7 +3546,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 }) |
| @@ -3560,7 +3565,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. |
| @@ -3570,7 +3576,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) |
| @@ -3714,7 +3720,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 |