package fs import ( "testing" ) // --- helpers --- // storeRead is a test helper: Open + Read. func storeRead(t *testing.T, s FileTree, name string) []byte { t.Helper() e, err := s.Open(name) if err != nil { t.Fatalf("Open(%q): %v", name, err) } data, err := e.Read() if err != nil { t.Fatalf("Read(%q): %v", name, err) } return data } // storeWrite is a test helper: Open + Write. func storeWrite(t *testing.T, s FileTree, name string, data []byte) { t.Helper() e, err := s.Open(name) if err != nil { t.Fatalf("Open(%q): %v", name, err) } if err := e.Write(data); err != nil { t.Fatalf("Write(%q): %v", name, err) } } // --- contract checks --- func checkReadableContract(t *testing.T, s FileTree, name string) { t.Helper() fi, err := s.Stat(name) if err != nil { t.Fatalf("Stat(%q): %v", name, err) } if fi.Name() != name { t.Errorf("Stat(%q).Name() = %q", name, fi.Name()) } if _, err := s.Stat("__nonexistent__"); err == nil { t.Error("Stat(nonexistent) should error") } entries, err := s.List() if err != nil { t.Fatalf("List: %v", err) } found := false for _, e := range entries { if e.Name() == name { found = true } } if !found { t.Errorf("List() missing %q", name) } e, err := s.Open(name) if err != nil { t.Fatalf("Open(%q): %v", name, err) } if _, err := e.Read(); err != nil { t.Fatalf("Read(%q): %v", name, err) } } func checkReadWriteContract(t *testing.T, s FileTree, name string) { t.Helper() want := []byte("hello") e, err := s.Open(name) if err != nil { t.Fatalf("Open: %v", err) } if err := e.Write(want); err != nil { t.Fatalf("Write: %v", err) } got, err := e.Read() if err != nil { t.Fatalf("Read after Write: %v", err) } if string(got) != string(want) { t.Errorf("Read = %q; want %q", got, want) } want2 := []byte("world") if err := e.Write(want2); err != nil { t.Fatalf("Write overwrite: %v", err) } got2, err := e.Read() if err != nil { t.Fatalf("Read after overwrite: %v", err) } if string(got2) != string(want2) { t.Errorf("Read after overwrite = %q; want %q", got2, want2) } checkReadableContract(t, s, name) } func checkStoreContract(t *testing.T, s FileTree, name string) { t.Helper() if err := s.Create(name); err != nil { t.Fatalf("Create: %v", err) } if _, err := s.Stat(name); err != nil { t.Fatalf("Stat after Create: %v", err) } renamed := name + "-renamed" if err := s.Rename(name, renamed); err != nil { t.Fatalf("Rename: %v", err) } if _, err := s.Stat(name); err == nil { t.Error("Stat(old) should error after Rename") } if _, err := s.Stat(renamed); err != nil { t.Errorf("Stat(new) after Rename: %v", err) } s.Delete(renamed) //nolint:errcheck if err := s.Create(name); err != nil { t.Fatalf("Create after rename cleanup: %v", err) } if err := s.Delete(name); err != nil { t.Fatalf("Delete: %v", err) } if _, err := s.Stat(name); err == nil { t.Error("Stat after Delete should error") } if err := s.Delete("__nonexistent__"); err == nil { t.Error("Delete(nonexistent) should error") } checkReadWriteContract(t, s, name) } // ===== FlatDir ===== func TestFlatDirContract(t *testing.T) { checkStoreContract(t, NewTree([]string{t.TempDir()}, 0644), "test-file") } func TestFlatDirCreateMkdirError(t *testing.T) { fd := NewTree([]string{"/nonexistent/path"}, 0644) if err := fd.Create("f"); err == nil { t.Error("Create should fail when dir doesn't exist") } } func TestFlatDirPutMkdirError(t *testing.T) { fd := NewTree([]string{"/nonexistent/path"}, 0644) e, err := fd.Open("f") if err != nil { t.Fatalf("Open: %v", err) } if err := e.Write([]byte("x")); err == nil { t.Error("Write should fail when dir doesn't exist") } }