test(desktop): make session spawner env capture atomic
- commit
- fbb23ebf9822a1bebfe808b190b35c023f1c3076
- author
- brice · · 2026-04-19 12:38 UTC
- parent
- ef69324
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +30 -1
M internal/infrastructure/desktop/adapter_test.go +30 -1
| @@ -28,7 +28,7 @@ func (e testSessionSpawnEnvironment) SessionRootCachePath(sessionID entity.Sessi | |||
| 28 | 28 | ||
| 29 | 29 | func TestMain(m *testing.M) { | |
| 30 | 30 | if envFile := os.Getenv(testCaptureEnvFile); envFile != "" && len(os.Args) >= 2 && os.Args[1] == "browse" { | |
| 31 | - | if err := os.WriteFile(envFile, []byte(strings.Join(os.Environ(), "\n")), 0o644); err != nil { | |
| 31 | + | if err := writeFileAtomically(envFile, []byte(strings.Join(os.Environ(), "\n")), 0o644); err != nil { | |
| 32 | 32 | os.Exit(2) | |
| 33 | 33 | } | |
| 34 | 34 | os.Exit(0) | |
| @@ -37,6 +37,35 @@ func TestMain(m *testing.M) { | |||
| 37 | 37 | os.Exit(m.Run()) | |
| 38 | 38 | } | |
| 39 | 39 | ||
| 40 | + | func writeFileAtomically(path string, data []byte, perm os.FileMode) error { | |
| 41 | + | tmpFile, err := os.CreateTemp(filepath.Dir(path), filepath.Base(path)+".tmp-*") | |
| 42 | + | if err != nil { | |
| 43 | + | return err | |
| 44 | + | } | |
| 45 | + | ||
| 46 | + | tmpPath := tmpFile.Name() | |
| 47 | + | defer func() { | |
| 48 | + | _ = os.Remove(tmpPath) | |
| 49 | + | }() | |
| 50 | + | ||
| 51 | + | if _, err := tmpFile.Write(data); err != nil { | |
| 52 | + | _ = tmpFile.Close() | |
| 53 | + | return err | |
| 54 | + | } | |
| 55 | + | if err := tmpFile.Chmod(perm); err != nil { | |
| 56 | + | _ = tmpFile.Close() | |
| 57 | + | return err | |
| 58 | + | } | |
| 59 | + | if err := tmpFile.Close(); err != nil { | |
| 60 | + | return err | |
| 61 | + | } | |
| 62 | + | if err := os.Rename(tmpPath, path); err != nil { | |
| 63 | + | return err | |
| 64 | + | } | |
| 65 | + | ||
| 66 | + | return nil | |
| 67 | + | } | |
| 68 | + | ||
| 40 | 69 | func TestSanitizedChildEnv_RemovesLayerShellPreloadOnly(t *testing.T) { | |
| 41 | 70 | env := sanitizedChildEnv([]string{ | |
| 42 | 71 | "PATH=/usr/bin", | |
| @@ -28,7 +28,7 @@ func (e testSessionSpawnEnvironment) SessionRootCachePath(sessionID entity.Sessi | |||||
| 28 | 28 | ||||
| 29 | func TestMain(m *testing.M) { | 29 | func TestMain(m *testing.M) { | ||
| 30 | if envFile := os.Getenv(testCaptureEnvFile); envFile != "" && len(os.Args) >= 2 && os.Args[1] == "browse" { | 30 | if envFile := os.Getenv(testCaptureEnvFile); envFile != "" && len(os.Args) >= 2 && os.Args[1] == "browse" { | ||
| 31 | - | if err := os.WriteFile(envFile, []byte(strings.Join(os.Environ(), "\n")), 0o644); err != nil { | 31 | + | if err := writeFileAtomically(envFile, []byte(strings.Join(os.Environ(), "\n")), 0o644); err != nil { |
| 32 | os.Exit(2) | 32 | os.Exit(2) | ||
| 33 | } | 33 | } | ||
| 34 | os.Exit(0) | 34 | os.Exit(0) | ||
| @@ -37,6 +37,35 @@ func TestMain(m *testing.M) { | |||||
| 37 | os.Exit(m.Run()) | 37 | os.Exit(m.Run()) | ||
| 38 | } | 38 | } | ||
| 39 | 39 | ||||
| 40 | + | func writeFileAtomically(path string, data []byte, perm os.FileMode) error { | |||
| 41 | + | tmpFile, err := os.CreateTemp(filepath.Dir(path), filepath.Base(path)+".tmp-*") | |||
| 42 | + | if err != nil { | |||
| 43 | + | return err | |||
| 44 | + | } | |||
| 45 | + | ||||
| 46 | + | tmpPath := tmpFile.Name() | |||
| 47 | + | defer func() { | |||
| 48 | + | _ = os.Remove(tmpPath) | |||
| 49 | + | }() | |||
| 50 | + | ||||
| 51 | + | if _, err := tmpFile.Write(data); err != nil { | |||
| 52 | + | _ = tmpFile.Close() | |||
| 53 | + | return err | |||
| 54 | + | } | |||
| 55 | + | if err := tmpFile.Chmod(perm); err != nil { | |||
| 56 | + | _ = tmpFile.Close() | |||
| 57 | + | return err | |||
| 58 | + | } | |||
| 59 | + | if err := tmpFile.Close(); err != nil { | |||
| 60 | + | return err | |||
| 61 | + | } | |||
| 62 | + | if err := os.Rename(tmpPath, path); err != nil { | |||
| 63 | + | return err | |||
| 64 | + | } | |||
| 65 | + | ||||
| 66 | + | return nil | |||
| 67 | + | } | |||
| 68 | + | ||||
| 40 | func TestSanitizedChildEnv_RemovesLayerShellPreloadOnly(t *testing.T) { | 69 | func TestSanitizedChildEnv_RemovesLayerShellPreloadOnly(t *testing.T) { | ||
| 41 | env := sanitizedChildEnv([]string{ | 70 | env := sanitizedChildEnv([]string{ | ||
| 42 | "PATH=/usr/bin", | 71 | "PATH=/usr/bin", | ||