//go:build linux package host import ( "os" "reflect" "testing" ) func TestPlan14ServingSameBootNamespace(t *testing.T) { f, r := servingRebootRecordFixture(t, "complete") f.fs.boot = func() (string, error) { return r.Source.BootID, nil } oldMount := r.Source.Parent.Mount + 123 for _, d := range []*servingArtifactDirectory{&r.Source.Parent, &r.Source.Directory, &r.Authorization.Directory, &r.Namespace, &r.Event} { if d.Inode != 0 { d.Mount = oldMount } } for i := range r.Source.Files { if r.Source.Files[i].Present { r.Source.Files[i].Mount = oldMount } } if err := f.ledger.save(r); err != nil { t.Fatal(err) } p, err := f.fs.historicalNamespaceParent() if err != nil { t.Fatal(err) } p.Parent.Mount = oldMount if err := f.ledger.write("namespace-parent.json", p); err != nil { t.Fatal(err) } var n servingParkNamespace body, err := f.disk.Read("namespace.json") if err != nil || servingParkDecode(body, &n) != nil { t.Fatal(err) } n.Parent.Mount, n.Root.Mount = oldMount, oldMount if err := f.ledger.write("namespace.json", n); err != nil { t.Fatal(err) } if r.Authorization.Legacy { c, err := f.ledger.legacyConsumption(r.Authorization.Successor) if err != nil { t.Fatal(err) } if c != nil { c.Source, c.Authorization = r.Source, r.Authorization if err := f.ledger.write(servingLegacyKey("legacy", r.Authorization.Successor), c); err != nil { t.Fatal(err) } } } historicalLedger := *f.ledger historicalLedger.historical = true for i := 0; i < 2; i++ { if err := historicalLedger.prepareRebootLocked(t.Context(), r, nil); err != nil { t.Fatal("prepare same-boot namespace", err) } if err := historicalLedger.commitRebootLocked(t.Context(), r, nil); err != nil { t.Fatal("commit same-boot namespace", err) } } if err := f.fs.recoverRecordedNamespace(t.Context()); err != nil { t.Fatal(err) } current, err := f.ledger.read(r.Authorization.ID) if err != nil || current.Source.Parent.Mount == oldMount { t.Fatal("binding", err) } if err := f.ledger.save(current); err != nil { t.Fatal(err) } historical, err := f.ledger.readHistorical(r.Authorization.ID) if err != nil || !reflect.DeepEqual(historical, r) { t.Fatal("history changed", err) } if _, err := os.Stat(f.fs.data); err != nil { t.Fatal(err) } } func TestPlan14ServingNamespaceMountReuse(t *testing.T) { f, r := servingRebootRecordFixture(t, "complete") f.fs.boot = func() (string, error) { return r.Source.BootID, nil } p, e := f.fs.historicalNamespaceParent() if e != nil { t.Fatal(e) } stale := p.Parent stale.Mount += 123 if e = f.ledger.write("current-namespace.json", servingParkBootBinding{Version: 1, ID: "namespace", BeforeBoot: p.BootID, BootID: p.BootID, BeforeParent: p.Parent, Parent: stale}); e != nil { t.Fatal(e) } if e = f.ledger.write("current-retirement-"+r.Authorization.ID+".json", servingParkBootBinding{Version: 1, ID: "retirement-" + r.Authorization.ID, BeforeBoot: r.Source.BootID, BootID: r.Source.BootID, BeforeParent: r.Source.Parent, Parent: stale}); e != nil { t.Fatal(e) } h := *f.ledger h.historical = true if e = h.prepareRebootLocked(t.Context(), r, nil); e != nil { t.Fatal("prepare reused mount", e) } if e = h.commitRebootLocked(t.Context(), r, nil); e != nil { t.Fatal("commit reused mount", e) } if e = f.fs.recoverRecordedNamespace(t.Context()); e != nil { t.Fatal(e) } current, e := f.ledger.read(r.Authorization.ID) if e != nil || current.Source.Parent != r.Source.Parent { t.Fatal("return to original mount", e) } original, e := f.ledger.readHistorical(r.Authorization.ID) if e != nil || !reflect.DeepEqual(original, r) { t.Fatal("history changed", e) } }