package storage import ( "context" "errors" "fmt" "os" "path/filepath" "strings" "testing" ) func TestDownloadObjectToTempSuccess(t *testing.T) { store := &FakeBackend{} store.SeedObject(FakeObject{Key: "sessions/a/current/run_id.txt", Data: []byte("run-123\n")}) path, err := DownloadObjectToTemp(context.Background(), store, "sessions/a/current/run_id.txt", "narratio-test-*.txt") if err != nil { t.Fatalf("DownloadObjectToTemp() error = %v", err) } t.Cleanup(func() { _ = os.Remove(path) }) data, err := os.ReadFile(path) if err != nil { t.Fatalf("ReadFile() error = %v", err) } if string(data) != "run-123\n" { t.Fatalf("downloaded data = %q, want %q", string(data), "run-123\n") } } func TestDownloadObjectToTempFailedDownloadRemovesTempFile(t *testing.T) { sentinel := errors.New("download failed") store := &FakeBackend{DownloadErr: sentinel} pattern := "narratio-test-fail-*.txt" before, err := filepath.Glob(filepath.Join(os.TempDir(), "narratio-test-fail-*.txt")) if err != nil { t.Fatalf("Glob(before) error = %v", err) } path, err := DownloadObjectToTemp(context.Background(), store, "sessions/a/current/run_id.txt", pattern) if !errors.Is(err, sentinel) { t.Fatalf("DownloadObjectToTemp() error = %v, want %v", err, sentinel) } if strings.TrimSpace(path) != "" { t.Fatalf("DownloadObjectToTemp() path = %q, want empty on failure", path) } after, err := filepath.Glob(filepath.Join(os.TempDir(), "narratio-test-fail-*.txt")) if err != nil { t.Fatalf("Glob(after) error = %v", err) } if len(after) != len(before) { t.Fatalf("temp file count changed after failed download: before=%d after=%d", len(before), len(after)) } } func TestDownloadObjectToTempCallerContextWrappingPreservesCause(t *testing.T) { sentinel := errors.New("object missing") store := &FakeBackend{DownloadErr: sentinel} _, err := DownloadObjectToTemp(context.Background(), store, "sessions/a/current/run_id.txt", "narratio-test-*.txt") if err == nil { t.Fatal("DownloadObjectToTemp() error = nil, want error") } err = fmt.Errorf("download run pointer failed: %w", err) if !errors.Is(err, sentinel) { t.Fatalf("wrapped error does not preserve sentinel cause: %v", err) } }