package storage import ( "os" "path/filepath" "strings" "testing" ) func setupStorage(t *testing.T) *Storage { t.Helper() dir := t.TempDir() s, err := NewStorage(dir) if err != nil { t.Fatalf("NewStorage: %v", err) } return s } func TestSaveUpload(t *testing.T) { s := setupStorage(t) path, err := s.SaveUpload(1, "test.blend", strings.NewReader("data")) if err != nil { t.Fatalf("SaveUpload: %v", err) } data, err := os.ReadFile(path) if err != nil { t.Fatalf("read saved file: %v", err) } if string(data) != "data" { t.Errorf("got %q, want %q", data, "data") } } func TestSaveUpload_PathTraversal(t *testing.T) { s := setupStorage(t) path, err := s.SaveUpload(1, "../../etc/passwd", strings.NewReader("evil")) if err != nil { t.Fatalf("SaveUpload: %v", err) } // filepath.Base strips traversal, so the file should be inside the job dir if !strings.HasPrefix(path, s.JobPath(1)) { t.Errorf("saved file %q escaped job directory %q", path, s.JobPath(1)) } if filepath.Base(path) != "passwd" { t.Errorf("expected basename 'passwd', got %q", filepath.Base(path)) } } func TestSaveOutput(t *testing.T) { s := setupStorage(t) path, err := s.SaveOutput(42, "output.png", strings.NewReader("img")) if err != nil { t.Fatalf("SaveOutput: %v", err) } data, err := os.ReadFile(path) if err != nil { t.Fatalf("read saved output: %v", err) } if string(data) != "img" { t.Errorf("got %q, want %q", data, "img") } } func TestGetFile(t *testing.T) { s := setupStorage(t) savedPath, err := s.SaveUpload(1, "readme.txt", strings.NewReader("hello")) if err != nil { t.Fatalf("SaveUpload: %v", err) } f, err := s.GetFile(savedPath) if err != nil { t.Fatalf("GetFile: %v", err) } defer f.Close() buf := make([]byte, 64) n, _ := f.Read(buf) if string(buf[:n]) != "hello" { t.Errorf("got %q, want %q", string(buf[:n]), "hello") } } func TestJobPath(t *testing.T) { s := setupStorage(t) path := s.JobPath(99) if !strings.Contains(path, "99") { t.Errorf("JobPath(99) = %q, expected to contain '99'", path) } }