Borg/pkg/datanode/datanode_test.go
google-labs-jules[bot] 8ba0deab91 feat: Add _Good, _Bad, and _Ugly tests
Refactored the existing tests to use the `_Good`, `_Bad`, and `_Ugly`
testing convention. This provides a more structured approach to testing
and ensures that a wider range of scenarios are covered, including
valid inputs, invalid inputs, and edge cases.

In addition to refactoring the tests, this change also includes several
bug fixes that were uncovered by the new tests. These fixes improve the
robustness and reliability of the codebase.

The following packages and commands were affected:
- `pkg/datanode`
- `pkg/compress`
- `pkg/github`
- `pkg/matrix`
- `pkg/pwa`
- `pkg/vcs`
- `pkg/website`
- `cmd/all`
- `cmd/collect`
- `cmd/collect_github_repo`
- `cmd/collect_website`
- `cmd/compile`
- `cmd/root`
- `cmd/run`
- `cmd/serve`
2025-11-14 10:36:35 +00:00

407 lines
9.7 KiB
Go

package datanode
import (
"errors"
"io/fs"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
"testing"
)
func TestNew_Good(t *testing.T) {
dn := New()
if dn == nil {
t.Fatal("New() returned nil")
}
if dn.files == nil {
t.Error("New() did not initialize the files map")
}
}
func TestAddData_Good(t *testing.T) {
dn := New()
path := "foo.txt"
data := []byte("foo")
dn.AddData(path, data)
file, ok := dn.files[path]
if !ok {
t.Fatalf("file %q not found in datanode", path)
}
if string(file.content) != string(data) {
t.Errorf("expected data %q, got %q", data, file.content)
}
info, err := file.Stat()
if err != nil {
t.Fatalf("file.Stat() failed: %v", err)
}
if info.Name() != "foo.txt" {
t.Errorf("expected name foo.txt, got %s", info.Name())
}
}
func TestAddData_Ugly(t *testing.T) {
t.Run("Overwrite", func(t *testing.T) {
dn := New()
dn.AddData("foo.txt", []byte("foo"))
dn.AddData("foo.txt", []byte("bar"))
file, _ := dn.files["foo.txt"]
if string(file.content) != "bar" {
t.Errorf("expected data to be overwritten to 'bar', got %q", file.content)
}
})
t.Run("Weird Path", func(t *testing.T) {
dn := New()
// path.Clean treats "a/../b/./c.txt" as "b/c.txt" but our implementation is simpler
// and doesn't handle `..`. Let's test what it does handle.
path := "./b/./c.txt"
dn.AddData(path, []byte("c"))
if _, ok := dn.files["./b/./c.txt"]; !ok {
t.Errorf("expected path to be stored as is")
}
})
}
func TestOpen_Good(t *testing.T) {
dn := New()
dn.AddData("foo.txt", []byte("foo"))
file, err := dn.Open("foo.txt")
if err != nil {
t.Fatalf("Open failed: %v", err)
}
defer file.Close()
}
func TestOpen_Bad(t *testing.T) {
dn := New()
_, err := dn.Open("nonexistent.txt")
if err == nil {
t.Fatal("expected error opening nonexistent file, got nil")
}
if !errors.Is(err, fs.ErrNotExist) {
t.Errorf("expected fs.ErrNotExist, got %v", err)
}
}
func TestOpen_Ugly(t *testing.T) {
dn := New()
dn.AddData("bar/baz.txt", []byte("baz"))
file, err := dn.Open("bar") // Opening a directory
if err != nil {
t.Fatalf("expected no error when opening a directory, got %v", err)
}
defer file.Close()
// Reading from a directory should fail
_, err = file.Read(make([]byte, 1))
if err == nil {
t.Fatal("expected error reading from a directory, got nil")
}
var pathErr *fs.PathError
if !errors.As(err, &pathErr) || pathErr.Err != fs.ErrInvalid {
t.Errorf("expected fs.ErrInvalid when reading a directory, got %v", err)
}
}
func TestStat_Good(t *testing.T) {
dn := New()
dn.AddData("foo.txt", []byte("foo"))
dn.AddData("bar/baz.txt", []byte("baz"))
// Test file
info, err := dn.Stat("bar/baz.txt")
if err != nil {
t.Fatalf("Stat failed: %v", err)
}
if info.Name() != "baz.txt" {
t.Errorf("expected name baz.txt, got %s", info.Name())
}
if info.Size() != 3 {
t.Errorf("expected size 3, got %d", info.Size())
}
if info.IsDir() {
t.Error("expected baz.txt to not be a directory")
}
// Test directory
dirInfo, err := dn.Stat("bar")
if err != nil {
t.Fatalf("Stat directory failed: %v", err)
}
if !dirInfo.IsDir() {
t.Error("expected 'bar' to be a directory")
}
if dirInfo.Name() != "bar" {
t.Errorf("expected dir name 'bar', got %s", dirInfo.Name())
}
}
func TestStat_Bad(t *testing.T) {
dn := New()
_, err := dn.Stat("nonexistent")
if err == nil {
t.Fatal("expected error stating nonexistent file, got nil")
}
if !errors.Is(err, fs.ErrNotExist) {
t.Errorf("expected fs.ErrNotExist, got %v", err)
}
}
func TestStat_Ugly(t *testing.T) {
dn := New()
dn.AddData("foo.txt", []byte("foo"))
// Test root
info, err := dn.Stat(".")
if err != nil {
t.Fatalf("Stat('.') failed: %v", err)
}
if !info.IsDir() {
t.Error("expected '.' to be a directory")
}
if info.Name() != "." {
t.Errorf("expected name '.', got %s", info.Name())
}
}
func TestExists_Good(t *testing.T) {
dn := New()
dn.AddData("foo.txt", []byte("foo"))
dn.AddData("bar/baz.txt", []byte("baz"))
exists, err := dn.Exists("foo.txt")
if err != nil || !exists {
t.Errorf("expected foo.txt to exist, err: %v", err)
}
exists, err = dn.Exists("bar")
if err != nil || !exists {
t.Errorf("expected 'bar' directory to exist, err: %v", err)
}
}
func TestExists_Bad(t *testing.T) {
dn := New()
exists, err := dn.Exists("nonexistent")
if err != nil {
t.Errorf("unexpected error for nonexistent file: %v", err)
}
if exists {
t.Error("expected 'nonexistent' to not exist")
}
}
func TestExists_Ugly(t *testing.T) {
dn := New()
dn.AddData("dummy.txt", []byte("dummy"))
// Test root
exists, err := dn.Exists(".")
if err != nil || !exists {
t.Error("expected root '.' to exist")
}
// Test empty path
exists, err = dn.Exists("")
if err != nil {
// our stat treats "" as "."
if !strings.Contains(err.Error(), "exists") {
t.Errorf("unexpected error for empty path: %v", err)
}
}
if !exists {
t.Error("expected empty path '' to exist (as root)")
}
}
func TestReadDir_Good(t *testing.T) {
dn := New()
dn.AddData("foo.txt", []byte("foo"))
dn.AddData("bar/baz.txt", []byte("baz"))
dn.AddData("bar/qux.txt", []byte("qux"))
// Read root
entries, err := dn.ReadDir(".")
if err != nil {
t.Fatalf("ReadDir failed: %v", err)
}
expectedRootEntries := []string{"bar", "foo.txt"}
entryNames := toSortedNames(entries)
if !reflect.DeepEqual(entryNames, expectedRootEntries) {
t.Errorf("expected entries %v, got %v", expectedRootEntries, entryNames)
}
// Read subdirectory
barEntries, err := dn.ReadDir("bar")
if err != nil {
t.Fatalf("ReadDir('bar') failed: %v", err)
}
expectedBarEntries := []string{"baz.txt", "qux.txt"}
barEntryNames := toSortedNames(barEntries)
if !reflect.DeepEqual(barEntryNames, expectedBarEntries) {
t.Errorf("expected entries %v, got %v", expectedBarEntries, barEntryNames)
}
}
func TestReadDir_Bad(t *testing.T) {
dn := New()
dn.AddData("foo.txt", []byte("foo"))
// Read nonexistent dir
entries, err := dn.ReadDir("nonexistent")
if err != nil {
t.Fatalf("expected no error reading nonexistent dir, got %v", err)
}
if len(entries) != 0 {
t.Errorf("expected 0 entries for nonexistent dir, got %d", len(entries))
}
// Read file
_, err = dn.ReadDir("foo.txt")
if err == nil {
t.Fatal("expected error reading a file")
}
var pathErr *fs.PathError
if !errors.As(err, &pathErr) || pathErr.Err != fs.ErrInvalid {
t.Errorf("expected fs.ErrInvalid when reading a file, got %v", err)
}
}
func TestReadDir_Ugly(t *testing.T) {
dn := New()
dn.AddData("bar/baz.txt", []byte("baz"))
dn.AddData("empty_dir/", nil)
// Read dir with another dir but no files
entries, err := dn.ReadDir(".")
if err != nil {
t.Fatalf("ReadDir failed: %v", err)
}
expected := []string{"bar"} // empty_dir/ is ignored by AddData
names := toSortedNames(entries)
if !reflect.DeepEqual(names, expected) {
t.Errorf("expected %v, got %v", expected, names)
}
}
func TestWalk_Good(t *testing.T) {
dn := New()
dn.AddData("foo.txt", []byte("foo"))
dn.AddData("bar/baz.txt", []byte("baz"))
dn.AddData("bar/qux.txt", []byte("qux"))
var paths []string
dn.Walk(".", func(path string, d fs.DirEntry, err error) error {
paths = append(paths, path)
return nil
})
expectedPaths := []string{".", "bar", "bar/baz.txt", "bar/qux.txt", "foo.txt"}
sort.Strings(paths)
if !reflect.DeepEqual(paths, expectedPaths) {
t.Errorf("Walk expected paths %v, got %v", expectedPaths, paths)
}
}
func TestWalk_Bad(t *testing.T) {
dn := New()
// Walk non-existent path. fs.WalkDir will call the func with the error.
var called bool
err := dn.Walk("nonexistent", func(path string, d fs.DirEntry, err error) error {
called = true
if err == nil {
t.Error("expected error for nonexistent path")
}
if !errors.Is(err, fs.ErrNotExist) {
t.Errorf("unexpected error message: %v", err)
}
return err // propagate error
})
if !called {
t.Fatal("walk function was not called for nonexistent root")
}
if !errors.Is(err, fs.ErrNotExist) {
t.Errorf("expected Walk to return fs.ErrNotExist, got %v", err)
}
}
func TestWalk_Ugly(t *testing.T) {
dn := New()
dn.AddData("a/b.txt", []byte("b"))
dn.AddData("a/c.txt", []byte("c"))
// Test stopping walk
walkErr := errors.New("stop walking")
var paths []string
err := dn.Walk(".", func(path string, d fs.DirEntry, err error) error {
if path == "a/b.txt" {
return walkErr
}
paths = append(paths, path)
return nil
})
if err != walkErr {
t.Errorf("expected walk to return the callback error, got %v", err)
}
}
func TestCopyFile_Good(t *testing.T) {
dn := New()
dn.AddData("foo.txt", []byte("foo"))
tmpfile := filepath.Join(t.TempDir(), "test.txt")
err := dn.CopyFile("foo.txt", tmpfile, 0644)
if err != nil {
t.Fatalf("CopyFile failed: %v", err)
}
content, err := os.ReadFile(tmpfile)
if err != nil {
t.Fatalf("ReadFile failed: %v", err)
}
if string(content) != "foo" {
t.Errorf("expected foo, got %s", string(content))
}
}
func TestCopyFile_Bad(t *testing.T) {
dn := New()
tmpfile := filepath.Join(t.TempDir(), "test.txt")
// Source does not exist
err := dn.CopyFile("nonexistent.txt", tmpfile, 0644)
if err == nil {
t.Fatal("expected error for nonexistent source file")
}
// Destination is not writable
dn.AddData("foo.txt", []byte("foo"))
err = dn.CopyFile("foo.txt", "/nonexistent_dir/test.txt", 0644)
if err == nil {
t.Fatal("expected error for unwritable destination")
}
}
func TestCopyFile_Ugly(t *testing.T) {
dn := New()
dn.AddData("bar/baz.txt", []byte("baz"))
tmpfile := filepath.Join(t.TempDir(), "test.txt")
// Attempting to copy a directory
err := dn.CopyFile("bar", tmpfile, 0644)
if err == nil {
t.Fatal("expected error when trying to copy a directory")
}
}
func toSortedNames(entries []fs.DirEntry) []string {
var names []string
for _, e := range entries {
names = append(names, e.Name())
}
sort.Strings(names)
return names
}