package storage import ( "context" "errors" "os" "path/filepath" "strings" "testing" ) func TestFakeBackendCapturesRequestAndReturnsItems(t *testing.T) { fake := &FakeBackend{} req := ArchiveRequest{SessionID: "s1", Items: []ArchiveItem{{Kind: "artifact", LocalPath: "artifacts/log.md"}}} res, err := fake.Archive(context.Background(), req) if err != nil { t.Fatalf("Archive() error = %v", err) } if len(fake.Requests) != 1 || fake.Requests[0].SessionID != "s1" { t.Fatalf("requests = %#v, want captured request", fake.Requests) } if len(res.Archived) != 1 { t.Fatalf("archived len = %d, want 1", len(res.Archived)) } } func TestFakeBackendError(t *testing.T) { fake := &FakeBackend{Err: errors.New("boom")} _, err := fake.Archive(context.Background(), ArchiveRequest{}) if err == nil { t.Fatal("expected error, got nil") } } func TestFakeBackendListPrefixFiltering(t *testing.T) { fake := &FakeBackend{} fake.SeedObject(FakeObject{Key: "dnd/campaigns/forsaken/audio/a.flac", Data: []byte("a")}) fake.SeedObject(FakeObject{Key: "dnd/campaigns/forsaken/audio/b.flac", Data: []byte("b")}) fake.SeedObject(FakeObject{Key: "dnd/campaigns/other/audio/c.flac", Data: []byte("c")}) items, err := fake.List(context.Background(), "dnd/campaigns/forsaken/audio/") if err != nil { t.Fatalf("List() error = %v", err) } if len(items) != 2 { t.Fatalf("List() len = %d, want 2", len(items)) } if items[0].Key != "dnd/campaigns/forsaken/audio/a.flac" || items[1].Key != "dnd/campaigns/forsaken/audio/b.flac" { t.Fatalf("List() keys = %#v", items) } } func TestFakeBackendDownload(t *testing.T) { fake := &FakeBackend{} fake.SeedObject(FakeObject{Key: "audio/a.flac", Data: []byte("audio-a")}) dst := filepath.Join(t.TempDir(), "nested", "a.flac") if err := fake.Download(context.Background(), "audio/a.flac", dst); err != nil { t.Fatalf("Download() error = %v", err) } data, err := os.ReadFile(dst) if err != nil { t.Fatalf("ReadFile() error = %v", err) } if string(data) != "audio-a" { t.Fatalf("downloaded content = %q, want %q", string(data), "audio-a") } } func TestFakeBackendUploadAndExists(t *testing.T) { fake := &FakeBackend{} local := filepath.Join(t.TempDir(), "upload.txt") if err := os.WriteFile(local, []byte("payload"), 0o644); err != nil { t.Fatalf("WriteFile() error = %v", err) } info, err := fake.Upload(context.Background(), local, `runs\id\artifact.txt`, UploadOptions{ Metadata: map[string]string{"kind": "artifact"}, }) if err != nil { t.Fatalf("Upload() error = %v", err) } if info.Key != "runs/id/artifact.txt" { t.Fatalf("Upload() key = %q, want normalized key", info.Key) } ok, err := fake.Exists(context.Background(), "runs/id/artifact.txt") if err != nil { t.Fatalf("Exists() error = %v", err) } if !ok { t.Fatal("Exists() = false, want true") } } func TestFakeBackendObjectErrors(t *testing.T) { fake := &FakeBackend{DownloadErr: errors.New("download fail"), UploadErr: errors.New("upload fail"), ListErr: errors.New("list fail"), ExistsErr: errors.New("exists fail")} if _, err := fake.List(context.Background(), "x"); err == nil || !strings.Contains(err.Error(), "list fail") { t.Fatalf("List() error = %v, want list fail", err) } if err := fake.Download(context.Background(), "x", filepath.Join(t.TempDir(), "x")); err == nil || !strings.Contains(err.Error(), "download fail") { t.Fatalf("Download() error = %v, want download fail", err) } local := filepath.Join(t.TempDir(), "x.txt") _ = os.WriteFile(local, []byte("x"), 0o644) if _, err := fake.Upload(context.Background(), local, "x", UploadOptions{}); err == nil || !strings.Contains(err.Error(), "upload fail") { t.Fatalf("Upload() error = %v, want upload fail", err) } if _, err := fake.Exists(context.Background(), "x"); err == nil || !strings.Contains(err.Error(), "exists fail") { t.Fatalf("Exists() error = %v, want exists fail", err) } }