This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/storage/pvc_test.go
Jeffrey Smith 5b72ed254f
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 4s
CI/CD / test-frontend (pull_request) Has been skipped
CI/CD / test-runners (pull_request) Has been skipped
CI/CD / e2e-smoke (pull_request) Has been skipped
CI/CD / test-go-pg (pull_request) Successful in 2m44s
CI/CD / test-sqlite (pull_request) Successful in 2m57s
CI/CD / build-and-deploy (pull_request) Successful in 1m25s
Feat v0.8.0 files sandbox module
Bridge ObjectStore (PVC/S3) into the Starlark sandbox with extension-scoped
key namespacing. New files module with put/get/meta/list/delete/exists
builtins gated by files.read and files.write permissions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:14:28 +00:00

354 lines
8.0 KiB
Go

package storage
import (
"bytes"
"context"
"io"
"os"
"path/filepath"
"testing"
)
func tempStore(t *testing.T) *PVCStore {
t.Helper()
dir := t.TempDir()
s, err := NewPVC(dir)
if err != nil {
t.Fatalf("NewPVC(%q): %v", dir, err)
}
return s
}
func TestPVC_PutGetRoundTrip(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
data := []byte("hello, storage world")
key := "files/test-1/att-1_test.txt"
// Put
err := s.Put(ctx, key, bytes.NewReader(data), int64(len(data)), "text/plain")
if err != nil {
t.Fatalf("Put: %v", err)
}
// Get
rc, size, ct, err := s.Get(ctx, key)
if err != nil {
t.Fatalf("Get: %v", err)
}
defer rc.Close()
if size != int64(len(data)) {
t.Errorf("size = %d, want %d", size, len(data))
}
if ct != "text/plain" {
t.Errorf("content_type = %q, want %q", ct, "text/plain")
}
got, _ := io.ReadAll(rc)
if !bytes.Equal(got, data) {
t.Errorf("data = %q, want %q", got, data)
}
}
func TestPVC_PutAtomicWrite(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
key := "files/ch/file.bin"
data := []byte("atomic test data")
err := s.Put(ctx, key, bytes.NewReader(data), int64(len(data)), "application/octet-stream")
if err != nil {
t.Fatalf("Put: %v", err)
}
// File should exist at final path, no temp files left
absPath := filepath.Join(s.basePath, "files", "ch")
entries, _ := os.ReadDir(absPath)
for _, e := range entries {
if e.Name() != "file.bin" {
t.Errorf("unexpected file in dir: %s", e.Name())
}
}
}
func TestPVC_PutSizeMismatch(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
data := []byte("short")
err := s.Put(ctx, "files/ch/f.txt", bytes.NewReader(data), 999, "text/plain")
if err == nil {
t.Fatal("expected size mismatch error")
}
}
func TestPVC_GetNotFound(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
_, _, _, err := s.Get(ctx, "files/nonexistent/file.txt")
if err != ErrNotFound {
t.Errorf("err = %v, want ErrNotFound", err)
}
}
func TestPVC_Delete(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
key := "files/ch/delete-me.txt"
_ = s.Put(ctx, key, bytes.NewReader([]byte("bye")), 3, "text/plain")
err := s.Delete(ctx, key)
if err != nil {
t.Fatalf("Delete: %v", err)
}
exists, _ := s.Exists(ctx, key)
if exists {
t.Error("file still exists after Delete")
}
}
func TestPVC_DeleteIdempotent(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
// Delete a file that doesn't exist — should not error
err := s.Delete(ctx, "files/no-such/file.txt")
if err != nil {
t.Errorf("Delete nonexistent: %v", err)
}
}
func TestPVC_DeletePrefix(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
// Create several files under a channel prefix
prefix := "files/test-abc/"
for _, name := range []string{"a.txt", "b.png", "c.pdf"} {
key := prefix + name
_ = s.Put(ctx, key, bytes.NewReader([]byte("x")), 1, "text/plain")
}
// Also create a file in a different channel
other := "files/test-other/keep.txt"
_ = s.Put(ctx, other, bytes.NewReader([]byte("y")), 1, "text/plain")
// Delete the channel prefix
err := s.DeletePrefix(ctx, "files/test-abc")
if err != nil {
t.Fatalf("DeletePrefix: %v", err)
}
// Verify channel files are gone
for _, name := range []string{"a.txt", "b.png", "c.pdf"} {
exists, _ := s.Exists(ctx, prefix+name)
if exists {
t.Errorf("%s still exists after DeletePrefix", name)
}
}
// Verify other channel is untouched
exists, _ := s.Exists(ctx, other)
if !exists {
t.Error("other channel file was incorrectly deleted")
}
}
func TestPVC_DeletePrefixNonexistent(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
// Should not error
err := s.DeletePrefix(ctx, "files/does-not-exist/")
if err != nil {
t.Errorf("DeletePrefix nonexistent: %v", err)
}
}
func TestPVC_Exists(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
key := "files/ch/exists.txt"
_ = s.Put(ctx, key, bytes.NewReader([]byte("hi")), 2, "text/plain")
exists, err := s.Exists(ctx, key)
if err != nil {
t.Fatalf("Exists: %v", err)
}
if !exists {
t.Error("Exists returned false for existing file")
}
exists, err = s.Exists(ctx, "files/ch/nope.txt")
if err != nil {
t.Fatalf("Exists (missing): %v", err)
}
if exists {
t.Error("Exists returned true for missing file")
}
}
func TestPVC_Healthy(t *testing.T) {
s := tempStore(t)
if err := s.Healthy(context.Background()); err != nil {
t.Errorf("Healthy: %v", err)
}
}
func TestPVC_Stats(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
// Empty store
stats, err := s.Stats(ctx)
if err != nil {
t.Fatalf("Stats: %v", err)
}
if stats.TotalFiles != 0 || stats.TotalBytes != 0 {
t.Errorf("empty store: files=%d bytes=%d", stats.TotalFiles, stats.TotalBytes)
}
if !stats.Healthy || !stats.Configured {
t.Error("expected healthy + configured")
}
// Add some files
for i := 0; i < 3; i++ {
key := filepath.Join("files", "ch", string(rune('a'+i))+".txt")
data := bytes.Repeat([]byte("x"), 100*(i+1))
_ = s.Put(ctx, key, bytes.NewReader(data), int64(len(data)), "text/plain")
}
stats, err = s.Stats(ctx)
if err != nil {
t.Fatalf("Stats: %v", err)
}
if stats.TotalFiles != 3 {
t.Errorf("files = %d, want 3", stats.TotalFiles)
}
if stats.TotalBytes != 600 { // 100 + 200 + 300
t.Errorf("bytes = %d, want 600", stats.TotalBytes)
}
}
func TestPVC_PathTraversal(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
bad := []string{
"../etc/passwd",
"files/../../etc/shadow",
"/absolute/path",
"",
}
for _, key := range bad {
err := s.Put(ctx, key, bytes.NewReader([]byte("x")), 1, "text/plain")
if err == nil {
t.Errorf("Put(%q) should have failed", key)
}
_, _, _, err = s.Get(ctx, key)
if err == nil {
t.Errorf("Get(%q) should have failed", key)
}
err = s.Delete(ctx, key)
if err == nil {
t.Errorf("Delete(%q) should have failed", key)
}
}
}
func TestPVC_SubdirCreation(t *testing.T) {
s := tempStore(t)
// Verify well-known subdirs were created
for _, sub := range []string{"files", "processing"} {
info, err := os.Stat(filepath.Join(s.basePath, sub))
if err != nil {
t.Errorf("subdir %q not created: %v", sub, err)
continue
}
if !info.IsDir() {
t.Errorf("%q is not a directory", sub)
}
}
}
func TestPVC_List(t *testing.T) {
s := tempStore(t)
ctx := context.Background()
// Empty prefix — no files.
entries, err := s.List(ctx, "ext/pkg1/", 100)
if err != nil {
t.Fatalf("List empty: %v", err)
}
if len(entries) != 0 {
t.Errorf("expected 0 entries, got %d", len(entries))
}
// Add some files under a prefix.
for _, name := range []string{"a.txt", "b.png", "sub/c.pdf"} {
key := "ext/pkg1/" + name
_ = s.Put(ctx, key, bytes.NewReader([]byte("x")), 1, "text/plain")
}
// Add a file under a different prefix.
_ = s.Put(ctx, "ext/pkg2/other.txt", bytes.NewReader([]byte("y")), 1, "text/plain")
// List all under pkg1.
entries, err = s.List(ctx, "ext/pkg1/", 100)
if err != nil {
t.Fatalf("List: %v", err)
}
if len(entries) != 3 {
t.Errorf("expected 3 entries, got %d", len(entries))
}
// List with limit.
entries, err = s.List(ctx, "ext/pkg1/", 2)
if err != nil {
t.Fatalf("List limited: %v", err)
}
if len(entries) != 2 {
t.Errorf("expected 2 entries (limit), got %d", len(entries))
}
// List with sub-prefix.
entries, err = s.List(ctx, "ext/pkg1/sub/", 100)
if err != nil {
t.Fatalf("List sub: %v", err)
}
if len(entries) != 1 {
t.Errorf("expected 1 entry in sub/, got %d", len(entries))
}
// pkg2 prefix should only find 1.
entries, err = s.List(ctx, "ext/pkg2/", 100)
if err != nil {
t.Fatalf("List pkg2: %v", err)
}
if len(entries) != 1 {
t.Errorf("expected 1 entry in pkg2, got %d", len(entries))
}
}
func TestNewPVC_InvalidPath(t *testing.T) {
// Path that can't be created (nested under a file)
tmp := t.TempDir()
filePath := filepath.Join(tmp, "blocker")
os.WriteFile(filePath, []byte("x"), 0o644)
_, err := NewPVC(filepath.Join(filePath, "subdir"))
if err == nil {
t.Error("expected error for invalid path")
}
}