package release import ( "bytes" "context" "os" "testing" ) func TestPlan14GenerationSiblingWrites(t *testing.T) { for _, mode := range []string{"repair", "sync", "backfill", "bound-backfill"} { type outcome struct { sibling, live, version, previous, output string restarts int } outcomes := map[string]outcome{} for _, authority := range []string{"pinned", "unknown", "unreserved", "legacy"} { t.Run(mode+"/"+authority, func(t *testing.T) { f := newReuseFixture(t) version := "v2" if mode == "backfill" || mode == "bound-backfill" { version = "v1" if err := Promote(t.Context(), f.s, f.priv, "bab", "myapp", "canary/x", version); err != nil { t.Fatal(err) } } else if err := StageArtifact(f.opt, "bab", version, "myapp", []byte("new v2")); err != nil { t.Fatal(err) } _, raw, err := GetManifestRaw(t.Context(), f.s, "bab", "myapp", version) if err != nil { t.Fatal(err) } ptr, err := Channel(t.Context(), f.s, f.pub, "bab", "myapp", "canary/x") if err != nil { t.Fatal(err) } ptr.Digest, ptr.HistoryDigests = "", nil if mode == "sync" || mode == "bound-backfill" { ptr.Digest = ManifestDigest(raw) } signed, err := signPointer(RootSigner(f.priv), ptr) if err != nil { t.Fatal(err) } _, etag, err := GetQualified(t.Context(), f.s, ChannelKey("bab", "myapp", "canary/x")) if err != nil { t.Fatal(err) } if _, err := f.s.Put(t.Context(), ChannelKey("bab", "myapp", "canary/x"), signed, etag); err != nil { t.Fatal(err) } path := StagedManifestPath(f.opt, "bab", version, "myapp") original := []byte("{\"stale\":true}") if mode == "sync" { if err := StageManifest(f.opt, "bab", version, "myapp", original); err != nil { t.Fatal(err) } } else if err := os.Remove(path); err != nil && !os.IsNotExist(err) { t.Fatal(err) } var before os.FileInfo if mode == "sync" { before, err = os.Stat(path) if err != nil { t.Fatal(err) } } g, _ := generationPinFixture(t, f.opt, "bab", "myapp", version) var source PinSource = RootGenerationPins{Ledger: g, Verify: func(context.Context, []GenerationReservation) error { return nil }} if authority == "unknown" { source = RootGenerationPins{Ledger: g} } if authority == "unreserved" { source = PinSourceFunc(func(context.Context, string) (StagedPaths, error) { return StagedPaths{}, nil }) } var opts []PassOption if authority != "legacy" { opts = append(opts, WithRootGenerationPins(source)) } restarts := 0 var output bytes.Buffer withCapturedStdout(t, &output, func() { if err := Pass(t.Context(), f.reg, f.s, f.pub, f.opt, func(string) error { restarts++; return nil }, opts...); err != nil { t.Fatal(err) } }) got, readErr := os.ReadFile(path) live, err := LiveVersion(f.opt, "h1.example.com") if err != nil { t.Fatal(err) } row, err := f.reg.Get("h1.example.com") if err != nil || row == nil { t.Fatal(err) } outcomes[authority] = outcome{string(got), live, row.Version, row.PrevVersion, output.String(), restarts} if authority == "pinned" || authority == "unknown" { if mode == "sync" { after, err := os.Stat(path) if readErr != nil || err != nil || !bytes.Equal(got, original) || !os.SameFile(before, after) { t.Fatalf("reserved sibling replaced: %q %v %v", got, readErr, err) } } else if !os.IsNotExist(readErr) { t.Fatalf("reserved tree gained sibling: %q %v", got, readErr) } } else if readErr != nil || !bytes.Equal(got, raw) { t.Fatalf("permitted sibling not written: %q %v", got, readErr) } }) } if outcomes["unreserved"] != outcomes["legacy"] { t.Fatalf("%s changed legacy effects: branch=%+v main=%+v", mode, outcomes["unreserved"], outcomes["legacy"]) } } } func TestPlan14GenerationVerifiedSiblingWrites(t *testing.T) { f := newReuseFixture(t) if err := StageArtifact(f.opt, "bab", "v2", "myapp", []byte("new v2")); err != nil { t.Fatal(err) } m, raw, err := GetManifestRaw(t.Context(), f.s, "bab", "myapp", "v2") if err != nil { t.Fatal(err) } path := VersionPath(f.opt, "bab", "v2", "myapp") calls := 0 chk := stageCheck{verified: map[string]string{path: m.Artifacts[adoptPlatform].SHA256}, beforeWrite: func(string) error { calls++; return os.ErrPermission }} if _, err := stageFrom(t.Context(), f.s, f.opt, "bab", "myapp", "v2", "h1.example.com", chk, true, m, raw, true); err != nil { t.Fatal(err) } if _, err := os.Stat(StagedManifestPath(f.opt, "bab", "v2", "myapp")); !os.IsNotExist(err) || calls != 1 { t.Fatalf("verified cache bypassed sibling check: %v calls=%d", err, calls) } }