package host import ( "context" "encoding/json" "testing" "github.com/carlosframework/platform/internal/lease" "github.com/carlosframework/platform/internal/moves" "github.com/carlosframework/platform/internal/provision" ) // Final review finding 4: a version id of "null" (a versioning-suspended // bucket) pins nothing, so a ledger that recorded one is no evidence. The // next round restages the archive under real version ids and asks for // move.json again, and the source report never carries "null". func TestNullVersionsInTheLedgerAreRestaged(t *testing.T) { ctx := context.Background() h := newPhase1Harness(t) h.start(t, "manual") h.pass(t) l := h.ledger(t) if l.ArchiveVersions == nil || !l.ArchiveVersions.Pinned() { t.Fatalf("the first round staged no pinned archive: %+v", l.ArchiveVersions) } ref := *l.ArchiveVersions ref.ManifestVersion, ref.SealedVersion = "null", "null" l.ArchiveVersions, l.MoveJSONVersion = &ref, "null" if err := writeMoveLedger(ctx, h.f, "data-ie", moves.LedgerKey(p1Host, p1ID), l); err != nil { t.Fatal(err) } h.pass(t) body, err := h.f.Get(ctx, "data-ie", moves.LedgerKey(p1Host, p1ID)) if err != nil { t.Fatal(err) } var raw moveLedger if err := json.Unmarshal(body, &raw); err != nil { t.Fatal(err) } if raw.ArchiveVersions == nil || !raw.ArchiveVersions.Pinned() { t.Fatalf("the null-version archive was kept: %+v", raw.ArchiveVersions) } if raw.MoveJSONVersion != moveJSONPresent { t.Fatalf("move_json_version = %q, want %q (asked again, found present)", raw.MoveJSONVersion, moveJSONPresent) } if sr := h.sourceReport(t); sr.Archive == nil || !sr.Archive.Pinned() { t.Fatalf("the source report carries %+v", sr.Archive) } } // T5 refuses an archive reference that names "null" before it looks in its // cache of verdicts: a passing verdict cached for that reference would // otherwise vouch for whatever the key holds now. func TestT5RefusesANullArchiveVersionBeforeItsCache(t *testing.T) { ctx := context.Background() rec := provision.Record{Host: p1Host, Move: &provision.MoveState{ID: p1ID}} good := moves.ArchiveRef{ManifestKey: "m.json", ManifestVersion: "mv1", SealedObjectKey: "s.sealed", SealedVersion: "sv1", Plain: "sha256:p"} for name, mut := range map[string]func(*moves.ArchiveRef){ "manifest": func(r *moves.ArchiveRef) { r.ManifestVersion = "null" }, "sealed": func(r *moves.ArchiveRef) { r.SealedVersion = "null" }, "both": func(r *moves.ArchiveRef) { r.ManifestVersion, r.SealedVersion = "null", "null" }, "empty": func(r *moves.ArchiveRef) { r.SealedVersion = "" }, } { ref := good mut(&ref) w := &movesWorker{mirrors: map[string]lease.MirrorStore{}} w.archives = map[string]verifiedArchive{p1ID: {ref: ref, check: moves.Check{OK: true}, plain: ref.Plain}} got := w.checkArchive(ctx, rec, &moves.SourceReport{Archive: &ref}) if got.check.OK || got.check.Reason != t5NotPinned { t.Errorf("%s: T5 = %+v, want %q", name, got.check, t5NotPinned) } } }