Define adapter interfaces and fake implementations

This commit is contained in:
2026-05-02 11:16:27 -05:00
parent 78e7e4f41b
commit 2854da48c2
24 changed files with 876 additions and 73 deletions

View File

@@ -0,0 +1,29 @@
// Package storage declares archive/storage backend adapter boundaries.
package storage
import "context"
// Backend is the adapter boundary for archive/storage operations.
type Backend interface {
Archive(ctx context.Context, req ArchiveRequest) (ArchiveResult, error)
}
// ArchiveItem describes one item to archive.
type ArchiveItem struct {
Kind string
LocalPath string
RemoteKey string
}
// ArchiveRequest describes one archive operation.
type ArchiveRequest struct {
SessionID string
ManifestPath string
Items []ArchiveItem
}
// ArchiveResult describes archive operation output.
type ArchiveResult struct {
Archived []ArchiveItem
Metadata map[string]any
}

View File

@@ -0,0 +1,40 @@
package storage
import "context"
// NoopBackend is a deterministic no-op archive/storage adapter.
type NoopBackend struct{}
// Archive returns the requested items as archived with placeholder metadata.
func (n *NoopBackend) Archive(ctx context.Context, req ArchiveRequest) (ArchiveResult, error) {
if err := ctx.Err(); err != nil {
return ArchiveResult{}, err
}
return ArchiveResult{Archived: append([]ArchiveItem(nil), req.Items...), Metadata: map[string]any{"placeholder": true}}, nil
}
// FakeBackend captures archive requests and returns deterministic responses.
type FakeBackend struct {
Requests []ArchiveRequest
Err error
Result ArchiveResult
}
// Archive records request and returns configured response.
func (f *FakeBackend) Archive(ctx context.Context, req ArchiveRequest) (ArchiveResult, error) {
if err := ctx.Err(); err != nil {
return ArchiveResult{}, err
}
f.Requests = append(f.Requests, req)
if f.Err != nil {
return ArchiveResult{}, f.Err
}
res := f.Result
if res.Archived == nil {
res.Archived = append([]ArchiveItem(nil), req.Items...)
}
if res.Metadata == nil {
res.Metadata = map[string]any{"fake": true}
}
return res, nil
}

View File

@@ -0,0 +1,31 @@
package storage
import (
"context"
"errors"
"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")
}
}