Artifact 7a1dfb458a69a1b2851a4246b3aa4637f1c3094054ea6a68cb718290dccb2e25:
- File
simio/storage_test.go
— part of check-in
[f5744359d3]
at
2026-04-19 16:30:54
on branch trunk
— Initial open source release
libfossil is a pure-Go implementation of the Fossil SCM, reading and writing the same .fossil SQLite repository format as upstream Fossil.
This is the first public release of code that previously lived in a private repository. The module path is github.com/danmestas/libfossil and the binary is named libfossil to avoid $PATH collisions with upstream fossil.
Included: - Repo lifecycle (create, clone), checkout/checkin, timeline, merge, diff, annotate, shun, tag, branch, bisect, stash, undo/redo - Sync-over-HTTP protocol (client and handler) - Two SQLite drivers: modernc (pure Go, default) and ncruces (wasm-capable) - Observer interfaces (SyncObserver, CheckoutObserver) with an optional OpenTelemetry implementation in observer/otel (separate submodule) - Deterministic simulation testing harness with BUGGIFY fault injection - Kong-based embeddable CLI under cli/ and a standalone binary under cmd/libfossil/ (user: [email protected], size: 12042) [annotate] [blame] [check-ins using]
package simio import ( "errors" "os" "path/filepath" "testing" "time" ) func TestOSStorageStat(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "test.txt") // Create a file content := []byte("test content") if err := os.WriteFile(path, content, 0644); err != nil { t.Fatalf("failed to create test file: %v", err) } storage := OSStorage{} info, err := storage.Stat(path) if err != nil { t.Fatalf("Stat failed: %v", err) } if info.Name() != "test.txt" { t.Errorf("expected name test.txt, got %s", info.Name()) } if info.Size() != int64(len(content)) { t.Errorf("expected size %d, got %d", len(content), info.Size()) } if info.IsDir() { t.Error("expected file, got directory") } } func TestOSStorageStatNotFound(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "nonexistent.txt") storage := OSStorage{} _, err := storage.Stat(path) if err == nil { t.Fatal("expected error for nonexistent file, got nil") } if !os.IsNotExist(err) { t.Errorf("expected IsNotExist error, got: %v", err) } } func TestOSStorageRemove(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "test.txt") // Create a file if err := os.WriteFile(path, []byte("test"), 0644); err != nil { t.Fatalf("failed to create test file: %v", err) } storage := OSStorage{} if err := storage.Remove(path); err != nil { t.Fatalf("Remove failed: %v", err) } // Verify file no longer exists if _, err := os.Stat(path); !os.IsNotExist(err) { t.Error("file still exists after Remove") } } func TestOSStorageReadWriteFile(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "test.txt") storage := OSStorage{} content := []byte("test content\nline 2\n") // Write file if err := storage.WriteFile(path, content, 0644); err != nil { t.Fatalf("WriteFile failed: %v", err) } // Read file back got, err := storage.ReadFile(path) if err != nil { t.Fatalf("ReadFile failed: %v", err) } if string(got) != string(content) { t.Errorf("content mismatch:\nwant: %q\ngot: %q", content, got) } // Verify file permissions info, err := os.Stat(path) if err != nil { t.Fatalf("stat failed: %v", err) } mode := info.Mode() if mode.Perm() != 0644 { t.Errorf("expected permissions 0644, got %o", mode.Perm()) } } func TestOSStorageMkdirAll(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "a", "b", "c") storage := OSStorage{} if err := storage.MkdirAll(path, 0755); err != nil { t.Fatalf("MkdirAll failed: %v", err) } // Verify directory exists info, err := os.Stat(path) if err != nil { t.Fatalf("stat failed: %v", err) } if !info.IsDir() { t.Error("expected directory, got file") } // Verify intermediate directories were created for _, subpath := range []string{ filepath.Join(dir, "a"), filepath.Join(dir, "a", "b"), } { info, err := os.Stat(subpath) if err != nil { t.Errorf("intermediate directory %s not created: %v", subpath, err) } if !info.IsDir() { t.Errorf("expected %s to be directory", subpath) } } // Verify calling MkdirAll on existing directory is idempotent if err := storage.MkdirAll(path, 0755); err != nil { t.Errorf("MkdirAll on existing directory failed: %v", err) } } func TestOSStorageReadFileNotFound(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "nonexistent.txt") storage := OSStorage{} _, err := storage.ReadFile(path) if err == nil { t.Fatal("expected error for nonexistent file, got nil") } if !os.IsNotExist(err) { t.Errorf("expected IsNotExist error, got: %v", err) } } func TestOSStorageWriteFileOverwrite(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "test.txt") storage := OSStorage{} // Write initial content if err := storage.WriteFile(path, []byte("initial"), 0644); err != nil { t.Fatalf("initial WriteFile failed: %v", err) } // Overwrite with new content newContent := []byte("overwritten") if err := storage.WriteFile(path, newContent, 0600); err != nil { t.Fatalf("overwrite WriteFile failed: %v", err) } // Verify new content got, err := storage.ReadFile(path) if err != nil { t.Fatalf("ReadFile failed: %v", err) } if string(got) != string(newContent) { t.Errorf("content mismatch:\nwant: %q\ngot: %q", newContent, got) } // Verify file is readable after overwrite (skip permission check — WASI // sandboxes may not preserve exact permission bits). info, err := os.Stat(path) if err != nil { t.Fatalf("stat failed: %v", err) } if info.Size() != int64(len(newContent)) { t.Errorf("size = %d, want %d", info.Size(), len(newContent)) } } func TestOSStorageRemoveNotFound(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "nonexistent.txt") storage := OSStorage{} err := storage.Remove(path) if err == nil { t.Fatal("expected error when removing nonexistent file, got nil") } if !os.IsNotExist(err) { t.Errorf("expected IsNotExist error, got: %v", err) } } func TestMemStorageRoundTrip(t *testing.T) { storage := NewMemStorage() path := "/test/file.txt" content := []byte("test content\nline 2\n") // Write file if err := storage.WriteFile(path, content, 0644); err != nil { t.Fatalf("WriteFile failed: %v", err) } // Read file back got, err := storage.ReadFile(path) if err != nil { t.Fatalf("ReadFile failed: %v", err) } if string(got) != string(content) { t.Errorf("content mismatch:\nwant: %q\ngot: %q", content, got) } // Verify we got a copy, not a reference got[0] = 'X' original, _ := storage.ReadFile(path) if original[0] == 'X' { t.Error("ReadFile returned reference to internal data, expected copy") } } func TestMemStorageStatNotFound(t *testing.T) { storage := NewMemStorage() path := "/nonexistent.txt" _, err := storage.Stat(path) if err == nil { t.Fatal("expected error for nonexistent file, got nil") } // Use errors.Is to check wrapped error if !os.IsNotExist(err) && !errors.Is(err, os.ErrNotExist) { t.Errorf("expected IsNotExist error, got: %v", err) } } func TestMemStorageRemove(t *testing.T) { storage := NewMemStorage() path := "/test.txt" // Create a file if err := storage.WriteFile(path, []byte("test"), 0644); err != nil { t.Fatalf("WriteFile failed: %v", err) } // Verify it exists if _, err := storage.Stat(path); err != nil { t.Fatalf("Stat failed after WriteFile: %v", err) } // Remove it if err := storage.Remove(path); err != nil { t.Fatalf("Remove failed: %v", err) } // Verify it no longer exists _, err := storage.Stat(path) if !os.IsNotExist(err) && !errors.Is(err, os.ErrNotExist) { t.Errorf("file still exists after Remove, Stat error: %v", err) } } func TestMemStorageMkdirAll(t *testing.T) { storage := NewMemStorage() path := "/a/b/c" // Create nested directories if err := storage.MkdirAll(path, 0755); err != nil { t.Fatalf("MkdirAll failed: %v", err) } // Verify directory exists info, err := storage.Stat(path) if err != nil { t.Fatalf("Stat failed: %v", err) } if !info.IsDir() { t.Error("expected directory, got file") } // Verify intermediate directories were created for _, subpath := range []string{"/a", "/a/b"} { info, err := storage.Stat(subpath) if err != nil { t.Errorf("intermediate directory %s not created: %v", subpath, err) } if !info.IsDir() { t.Errorf("expected %s to be directory", subpath) } } // Verify calling MkdirAll on existing directory is idempotent if err := storage.MkdirAll(path, 0755); err != nil { t.Errorf("MkdirAll on existing directory failed: %v", err) } } func TestOSStorageReadDir(t *testing.T) { dir := t.TempDir() // Create a file filePath := filepath.Join(dir, "test.txt") if err := os.WriteFile(filePath, []byte("test"), 0644); err != nil { t.Fatalf("failed to create test file: %v", err) } // Create a subdirectory subdir := filepath.Join(dir, "subdir") if err := os.Mkdir(subdir, 0755); err != nil { t.Fatalf("failed to create subdirectory: %v", err) } storage := OSStorage{} entries, err := storage.ReadDir(dir) if err != nil { t.Fatalf("ReadDir failed: %v", err) } if len(entries) != 2 { t.Fatalf("expected 2 entries, got %d", len(entries)) } // Verify entries (sorted by name) names := make([]string, len(entries)) for i, e := range entries { names[i] = e.Name() } expectedNames := []string{"subdir", "test.txt"} for i, expected := range expectedNames { if names[i] != expected { t.Errorf("entry %d: expected name %s, got %s", i, expected, names[i]) } } // Verify IsDir if entries[0].IsDir() != true { t.Errorf("expected subdir to be directory") } if entries[1].IsDir() != false { t.Errorf("expected test.txt to be file") } } func TestMemStorageReadDir(t *testing.T) { storage := NewMemStorage() // Create files in root and subdirectory if err := storage.WriteFile("/file1.txt", []byte("content1"), 0644); err != nil { t.Fatalf("WriteFile failed: %v", err) } if err := storage.WriteFile("/subdir/file2.txt", []byte("content2"), 0644); err != nil { t.Fatalf("WriteFile failed: %v", err) } if err := storage.WriteFile("/subdir/file3.txt", []byte("content3"), 0644); err != nil { t.Fatalf("WriteFile failed: %v", err) } // Test ReadDir at root - should show file1.txt and subdir entries, err := storage.ReadDir("/") if err != nil { t.Fatalf("ReadDir(/) failed: %v", err) } if len(entries) != 2 { t.Fatalf("expected 2 entries at root, got %d", len(entries)) } // Verify entries are sorted by name if entries[0].Name() != "file1.txt" { t.Errorf("expected first entry to be file1.txt, got %s", entries[0].Name()) } if entries[0].IsDir() { t.Errorf("expected file1.txt to be file, not directory") } if entries[1].Name() != "subdir" { t.Errorf("expected second entry to be subdir, got %s", entries[1].Name()) } if !entries[1].IsDir() { t.Errorf("expected subdir to be directory, not file") } // Test ReadDir in subdir subdirEntries, err := storage.ReadDir("/subdir") if err != nil { t.Fatalf("ReadDir(/subdir) failed: %v", err) } if len(subdirEntries) != 2 { t.Fatalf("expected 2 entries in subdir, got %d", len(subdirEntries)) } // Verify files in subdir if subdirEntries[0].Name() != "file2.txt" { t.Errorf("expected file2.txt, got %s", subdirEntries[0].Name()) } if subdirEntries[1].Name() != "file3.txt" { t.Errorf("expected file3.txt, got %s", subdirEntries[1].Name()) } } func TestMemStorageChtimes(t *testing.T) { storage := NewMemStorage() path := "/test/file.txt" storage.WriteFile(path, []byte("content"), 0644) mtime := time.Date(2026, 3, 15, 12, 0, 0, 0, time.UTC) if err := storage.Chtimes(path, mtime, mtime); err != nil { t.Fatalf("Chtimes: %v", err) } info, err := storage.Stat(path) if err != nil { t.Fatalf("Stat: %v", err) } if !info.ModTime().Equal(mtime) { t.Fatalf("ModTime = %v, want %v", info.ModTime(), mtime) } } func TestMemStorageChtimesNotExist(t *testing.T) { storage := NewMemStorage() err := storage.Chtimes("/nonexistent.txt", time.Now(), time.Now()) if err == nil { t.Fatal("expected error for nonexistent file") } if !errors.Is(err, os.ErrNotExist) { t.Fatalf("expected ErrNotExist, got: %v", err) } } func TestOSStorageChtimes(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "test.txt") os.WriteFile(path, []byte("content"), 0644) storage := OSStorage{} mtime := time.Date(2026, 3, 15, 12, 0, 0, 0, time.UTC) if err := storage.Chtimes(path, mtime, mtime); err != nil { t.Fatalf("Chtimes: %v", err) } info, err := os.Stat(path) if err != nil { t.Fatalf("Stat: %v", err) } if !info.ModTime().Equal(mtime) { t.Fatalf("ModTime = %v, want %v", info.ModTime(), mtime) } } func TestMemStorageReadDirNotExist(t *testing.T) { storage := NewMemStorage() _, err := storage.ReadDir("/nonexistent") if err == nil { t.Fatal("expected error for nonexistent directory, got nil") } if !os.IsNotExist(err) && !errors.Is(err, os.ErrNotExist) { t.Errorf("expected IsNotExist error, got: %v", err) } }