package core import ( "os" "path/filepath" "runtime" "testing" ) func TestAtomicWriteFile_Basic(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "test.txt") data := []byte("hello world") if err := AtomicWriteFile(path, data, 0644); err != nil { t.Fatalf("AtomicWriteFile: %v", err) } got, err := os.ReadFile(path) if err != nil { t.Fatalf("ReadFile: %v", err) } if string(got) != string(data) { t.Errorf("got %q, want %q", got, data) } } func TestAtomicWriteFile_Overwrite(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "test.txt") if err := AtomicWriteFile(path, []byte("first"), 0644); err != nil { t.Fatalf("first write: %v", err) } if err := AtomicWriteFile(path, []byte("second"), 0644); err != nil { t.Fatalf("second write: %v", err) } got, _ := os.ReadFile(path) if string(got) != "second" { t.Errorf("got %q, want %q", got, "second") } } func TestAtomicWriteFile_Permissions(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("Unix file permissions not supported on Windows") } dir := t.TempDir() path := filepath.Join(dir, "test.txt") if err := AtomicWriteFile(path, []byte("x"), 0600); err != nil { t.Fatalf("AtomicWriteFile: %v", err) } info, err := os.Stat(path) if err != nil { t.Fatalf("Stat: %v", err) } if perm := info.Mode().Perm(); perm != 0600 { t.Errorf("perm = %o, want 0600", perm) } } func TestAtomicWriteFile_NoTempLeftOnSuccess(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "test.txt") _ = AtomicWriteFile(path, []byte("data"), 0644) entries, _ := os.ReadDir(dir) for _, e := range entries { if e.Name() != "test.txt" { t.Errorf("unexpected file left: %s", e.Name()) } } } // TestAtomicWriteFile_NoTempLeftWhenRenameFails is a regression test for a // `.tmp-*` leak in the rename-failure path. Before the fix, AtomicWriteFile // returned the rename error directly without removing the tmp file it had // just created — so repeated failures would litter the parent directory // with stale `.tmp-*` files and confuse callers that scan that directory // (cron store, session store, etc.). // // We force a rename failure by writing to a path that already exists as a // directory; os.Rename refuses to replace a non-empty directory with a // regular file on every supported platform. func TestAtomicWriteFile_NoTempLeftWhenRenameFails(t *testing.T) { dir := t.TempDir() target := filepath.Join(dir, "blocked") if err := os.MkdirAll(target, 0o755); err != nil { t.Fatalf("mkdir target dir: %v", err) } if err := AtomicWriteFile(target, []byte("payload"), 0o644); err == nil { t.Fatal("AtomicWriteFile should fail when target is an existing directory") } entries, err := os.ReadDir(dir) if err != nil { t.Fatalf("ReadDir: %v", err) } for _, e := range entries { if e.Name() != "blocked" { t.Errorf("rename failure left orphan file %q in %s; cleanup is missing", e.Name(), dir) } } }