Files
distributor/internal/app/prune_test.go

163 lines
5.3 KiB
Go

package app
import (
"strings"
"testing"
"time"
"gitea.maximumdirect.net/eric/distributor/internal/config"
"gitea.maximumdirect.net/eric/distributor/internal/state"
"gitea.maximumdirect.net/eric/distributor/internal/testutil"
)
func TestPlanPruneDisabledPolicy(t *testing.T) {
document := state.StateDocument{SingleOwner: &state.DistributorState{}}
report, err := PlanPrune(document, config.PrunePolicy{}, PrunePlanOptions{
PipelineID: "reports",
DestinationID: "archive",
})
if err != nil {
t.Fatalf("PlanPrune() error = %v", err)
}
if report.Enabled || report.CheckedCount != 0 || len(report.PrunedOutputs) != 0 {
t.Fatalf("report = %#v, want disabled empty plan", report)
}
}
func TestPlanPruneSingleOwnerOutputs(t *testing.T) {
now := time.Date(2026, 6, 8, 12, 0, 0, 0, time.UTC)
olderThan := config.Duration(48 * time.Hour)
destinationState := pruneSingleOwnerState(now)
report, err := PlanPrune(state.StateDocument{SingleOwner: &destinationState}, config.PrunePolicy{
Enabled: true,
OlderThan: &olderThan,
}, PrunePlanOptions{
PipelineID: "reports",
DestinationID: "archive",
Now: now,
})
if err != nil {
t.Fatalf("PlanPrune() error = %v", err)
}
if got, want := pruneRecordPaths(report.PrunedOutputs), "old.txt"; got != want {
t.Fatalf("pruned = %q, want %q", got, want)
}
if got, want := pruneRecordPaths(report.PreservedOutputs), "fresh.txt"; got != want {
t.Fatalf("preserved = %q, want %q", got, want)
}
}
func TestPlanPruneSharedRootCurrentOwnerOnly(t *testing.T) {
now := time.Date(2026, 6, 8, 12, 0, 0, 0, time.UTC)
keepLatest := 0
sharedRoot := pruneSharedRootState(now)
report, err := PlanPrune(state.StateDocument{SharedRoot: &sharedRoot}, config.PrunePolicy{
Enabled: true,
KeepLatest: &keepLatest,
}, PrunePlanOptions{
PipelineID: "reports",
DestinationID: "archive",
Now: now,
})
if err != nil {
t.Fatalf("PlanPrune() error = %v", err)
}
if got, want := report.CheckedCount, 1; got != want {
t.Fatalf("checked count = %d, want %d", got, want)
}
if got, want := pruneRecordPaths(report.PrunedOutputs), "archive.txt"; got != want {
t.Fatalf("pruned = %q, want %q", got, want)
}
}
func pruneSingleOwnerState(now time.Time) state.DistributorState {
manifest := testutil.ValidManifest(testutil.BundleOptions{})
publishedAt := now.Add(-96 * time.Hour)
return state.DistributorState{
SchemaVersion: state.SchemaVersion,
PipelineID: "reports",
DestinationID: "archive",
PublishedAt: publishedAt,
CreatedAt: publishedAt,
UpdatedAt: publishedAt,
State: state.StatePolicy{Mode: state.StateModeSingleOwner},
Reconciliation: state.ReconciliationPolicy{Mode: config.ReconciliationModeReplace},
Source: state.SourceState{Manifest: manifest},
DistributorVersion: "test",
Outputs: []state.OutputFile{{
Path: "old.txt",
Kind: state.OutputKindSource,
SourcePath: "report.md",
SHA256: manifest.Files[0].SHA256,
Size: manifest.Files[0].Size,
CreatedAt: now.Add(-96 * time.Hour),
UpdatedAt: now.Add(-72 * time.Hour),
}, {
Path: "fresh.txt",
Kind: state.OutputKindSource,
SourcePath: "summary.txt",
SHA256: manifest.Files[1].SHA256,
Size: manifest.Files[1].Size,
CreatedAt: now.Add(-24 * time.Hour),
UpdatedAt: now.Add(-24 * time.Hour),
}},
}
}
func pruneSharedRootState(now time.Time) state.SharedRootState {
manifest := testutil.ValidManifest(testutil.BundleOptions{})
archive := state.CurrentOwnerScope("reports", "archive")
html := state.CurrentOwnerScope("reports", "html")
return state.SharedRootState{
SchemaVersion: state.SharedRootSchemaVersion,
DistributorVersion: "test",
CreatedAt: now.Add(-96 * time.Hour),
UpdatedAt: now.Add(-24 * time.Hour),
State: state.StatePolicy{Mode: state.StateModeSharedRoot},
Owners: []state.OwnerRecord{{
Scope: archive,
Reconciliation: state.ReconciliationPolicy{Mode: config.ReconciliationModeReplace},
Source: state.SourceState{Manifest: manifest},
}, {
Scope: html,
Reconciliation: state.ReconciliationPolicy{Mode: config.ReconciliationModeReplace},
Source: state.SourceState{Manifest: manifest},
}},
Outputs: []state.SharedRootOutputFile{{
Path: "archive.txt",
Kind: state.OutputKindSource,
SourcePath: "report.md",
SHA256: manifest.Files[0].SHA256,
Size: manifest.Files[0].Size,
Owner: archive,
SourceID: manifest.ID,
SourceDigest: manifest.Digest,
SourceCreated: manifest.Created,
CreatedAt: now.Add(-96 * time.Hour),
UpdatedAt: now.Add(-72 * time.Hour),
}, {
Path: "html.txt",
Kind: state.OutputKindSource,
SourcePath: "summary.txt",
SHA256: manifest.Files[1].SHA256,
Size: manifest.Files[1].Size,
Owner: html,
SourceID: manifest.ID,
SourceDigest: manifest.Digest,
SourceCreated: manifest.Created,
CreatedAt: now.Add(-96 * time.Hour),
UpdatedAt: now.Add(-72 * time.Hour),
}},
}
}
func pruneRecordPaths(records []PruneOutputRecord) string {
paths := make([]string, 0, len(records))
for _, record := range records {
paths = append(paths, record.Path)
}
return strings.Join(paths, ",")
}