Hydrate accepted producer checkpoints
This commit is contained in:
@@ -322,6 +322,107 @@ func TestFilesystemCheckpointDecisionFamiliesAreStableAndSafe(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilesystemLoaderReadsAcceptedNormalizeWithoutStageDependencies(t *testing.T) {
|
||||
fixture := seedAcceptedNormalizeCheckpoint(t)
|
||||
identityRoot := filepath.Join(fixture.root, mustRelativePath(t, fixture.identity))
|
||||
for _, stage := range []string{"extract", "merge"} {
|
||||
if _, err := os.Stat(filepath.Join(identityRoot, laneManifestPath(stage, "step-1", "lane-a"))); !os.IsNotExist(err) {
|
||||
t.Fatalf("%s checkpoint stat error = %v, want absent prerequisite", stage, err)
|
||||
}
|
||||
}
|
||||
checkpoint, decision := fixture.loader.AcceptedNormalize("step-1", "lane-a", "normalize-module")
|
||||
if !decision.Reused || decision.Category != pipeline.CheckpointDecisionReused || decision.ReasonCode != pipeline.CheckpointReasonAcceptedArtifactReused {
|
||||
t.Fatalf("accepted normalize decision = %#v", decision)
|
||||
}
|
||||
if checkpoint.Output.Artifact.Content == nil || string(checkpoint.Output.Artifact.Content) != string(fixture.normalize.Artifact.Content) {
|
||||
t.Fatalf("accepted normalize output = %#v, want recorded artifact", checkpoint.Output)
|
||||
}
|
||||
if len(checkpoint.Warnings) != 1 || checkpoint.Warnings[0].ReasonCode != "normalized" {
|
||||
t.Fatalf("accepted normalize warnings = %#v", checkpoint.Warnings)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilesystemLoaderRejectsInvalidAcceptedNormalize(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*testing.T, *filesystemCheckpointFixture)
|
||||
code pipeline.CheckpointReasonCode
|
||||
}{
|
||||
{"missing", func(t *testing.T, fixture *filesystemCheckpointFixture) {
|
||||
if err := os.Remove(acceptedNormalizeManifest(t, *fixture)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}, pipeline.CheckpointReasonMissing},
|
||||
{"rejected status", func(t *testing.T, fixture *filesystemCheckpointFixture) {
|
||||
editManifest(t, acceptedNormalizeManifest(t, *fixture), func(m map[string]any) { m["status"] = string(StatusSucceededWithRejections) })
|
||||
}, pipeline.CheckpointReasonStatusNotReusable},
|
||||
{"corrupt payload", func(t *testing.T, fixture *filesystemCheckpointFixture) {
|
||||
if err := os.WriteFile(acceptedNormalizePayload(t, *fixture), []byte("{"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}, pipeline.CheckpointReasonDecodeFailed},
|
||||
{"wrong codec identity", func(t *testing.T, fixture *filesystemCheckpointFixture) {
|
||||
editJSON(t, acceptedNormalizePayload(t, *fixture), func(m map[string]any) { m["output"].(map[string]any)["artifact_kind"] = "" })
|
||||
}, pipeline.CheckpointReasonArtifactCodecIncompatible},
|
||||
{"wrong content digest", func(t *testing.T, fixture *filesystemCheckpointFixture) {
|
||||
editJSON(t, acceptedNormalizePayload(t, *fixture), func(m map[string]any) {
|
||||
m["output"].(map[string]any)["content"].(map[string]any)["content_digest"] = "sha256:wrong"
|
||||
})
|
||||
}, pipeline.CheckpointReasonArtifactDigestMismatch},
|
||||
{"unverifiable identity", func(t *testing.T, fixture *filesystemCheckpointFixture) {
|
||||
loader := fixture.loader.(*FilesystemLoader)
|
||||
fixture.loader = &FilesystemLoader{root: loader.root}
|
||||
}, pipeline.CheckpointReasonIdentityMismatch},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
fixture := seedAcceptedNormalizeCheckpoint(t)
|
||||
test.mutate(t, &fixture)
|
||||
_, decision := fixture.loader.AcceptedNormalize("step-1", "lane-a", "normalize-module")
|
||||
if decision.Reused || decision.ReasonCode != test.code {
|
||||
t.Fatalf("accepted normalize decision = %#v, want %q", decision, test.code)
|
||||
}
|
||||
if strings.Contains(decision.Detail, fixture.root) || strings.Contains(decision.Detail, string(fixture.normalize.Artifact.Content)) {
|
||||
t.Fatalf("accepted normalize decision leaked path or content: %#v", decision)
|
||||
}
|
||||
if _, err := os.Stat(acceptedNormalizePayload(t, fixture)); err != nil {
|
||||
t.Fatalf("accepted normalize payload was removed after rejection: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func seedAcceptedNormalizeCheckpoint(t *testing.T) filesystemCheckpointFixture {
|
||||
t.Helper()
|
||||
root := t.TempDir()
|
||||
identity := testIdentity(t)
|
||||
artifact := checkpointArtifact("normalize-module", `{"accepted":true}`)
|
||||
recorder, err := NewFilesystemRecorder(root, identity)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
stepRecorder := recorder.(pipeline.StepCheckpointRecorder)
|
||||
warnings := []contracts.Warning{{Scope: "normalize", ReasonCode: "normalized", Message: "normalized warning"}}
|
||||
if err := stepRecorder.NormalizeSucceededForStep("step-1", "lane-a", "normalize-module", []pipeline.CheckpointFingerprint{{Name: "merge", Value: "sha256:unavailable"}}, artifact, warnings); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
loader, err := NewFilesystemLoader(root, identity)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return filesystemCheckpointFixture{root: root, identity: identity, loader: loader, normalize: artifact}
|
||||
}
|
||||
|
||||
func acceptedNormalizeManifest(t *testing.T, fixture filesystemCheckpointFixture) string {
|
||||
t.Helper()
|
||||
return filepath.Join(fixture.root, mustRelativePath(t, fixture.identity), laneManifestPath("normalize", "step-1", "lane-a"))
|
||||
}
|
||||
|
||||
func acceptedNormalizePayload(t *testing.T, fixture filesystemCheckpointFixture) string {
|
||||
t.Helper()
|
||||
return filepath.Join(fixture.root, mustRelativePath(t, fixture.identity), lanePayloadPath("normalize", "step-1", "lane-a", "output.json"))
|
||||
}
|
||||
|
||||
type checkpointStage struct {
|
||||
name string
|
||||
manifest func(filesystemCheckpointFixture) string
|
||||
|
||||
Reference in New Issue
Block a user