package hostbox import ( "context" "errors" "testing" "time" ) func TestPlan9Fix1PrunedReceiptCannotReplayAfterClockReversal(t *testing.T) { s, path, in := journalFixture(t) origin := time.Now() now := origin s.Now = func() time.Time { return now } issue := func(q JournalRequest) JournalRequest { t.Helper() q, err := journalPrepare(q, now) if err != nil { t.Fatal(err) } return q } if _, err := s.Execute(t.Context(), "peer", issue(JournalRequest{Op: "create", Launch: in})); err != nil { t.Fatal(err) } old := issue(JournalRequest{Op: "producer", Target: in.Target, Producer: "old"}) if _, err := s.Execute(t.Context(), "peer", old); err != nil { t.Fatal(err) } now = origin.Add(JournalReceiptRetention + time.Minute) if _, err := s.Execute(t.Context(), "peer", issue(JournalRequest{Op: "producer", Target: in.Target, Producer: "new"})); err != nil { t.Fatal(err) } var n int if err := s.Launches.db.QueryRow("SELECT count(*) FROM journal_requests WHERE id=?", old.ID).Scan(&n); err != nil || n != 0 { t.Fatalf("old receipt was not pruned: count=%d err=%v", n, err) } if err := s.Launches.Close(); err != nil { t.Fatal(err) } journal, err := OpenLaunchJournal(path) if err != nil { t.Fatal(err) } defer journal.Close() s, err = NewJournalService(journal) if err != nil { t.Fatal(err) } now = origin s.Now = func() time.Time { return now } if _, err := s.Execute(t.Context(), "peer", old); !errors.Is(err, ErrJournalUncertain) { t.Fatalf("pruned request executed after clock reversal and root restart: %v", err) } if err := journal.db.QueryRow("SELECT count(*) FROM journal_requests WHERE id=?", old.ID).Scan(&n); err != nil || n != 0 { t.Fatalf("old request regained a receipt: count=%d err=%v", n, err) } } func TestPlan9Fix1DistinctInventoryCallsHaveDistinctNonces(t *testing.T) { s, _, _ := journalFixture(t) var requests []JournalRequest _, client := RemoteJournals(func(ctx context.Context, q JournalRequest) (JournalResponse, error) { if q.Op == "inventory-write" { requests = append(requests, q) } return s.Execute(ctx, "peer", q) }) in := StopInventory{Complete: true, Host: "app.example", Incarnation: "inc", InstallationStamp: 1, Box: "box", Enrollment: "enrollment", DirectoryRevision: "1"} if err := client.WriteStopInventory(t.Context(), in); err != nil { t.Fatal(err) } if err := client.WriteStopInventory(t.Context(), in); err != nil { t.Fatal(err) } if len(requests) != 2 || requests[0].ID == requests[1].ID || requests[0].Nonce == "" || requests[1].Nonce == "" { t.Fatalf("distinct inventory writes merged: %+v", requests) } } func TestPlan9Fix1PrunedInventoryReplayNeedsPermanentCommitProof(t *testing.T) { s, _, _ := journalFixture(t) now := time.Now() s.Now = func() time.Time { return now } prepare := func(in StopInventory, revision uint64) JournalRequest { t.Helper() q, err := journalPrepare(JournalRequest{Op: "inventory-write", Inventory: in, Revision: revision}, now) if err != nil { t.Fatal(err) } return q } in := StopInventory{Complete: true, Host: "app.example", Incarnation: "inc", InstallationStamp: 1, Box: "box", Enrollment: "enrollment", DirectoryRevision: "1"} old := prepare(in, 0) if _, err := s.Execute(t.Context(), "peer", old); err != nil { t.Fatal(err) } now = now.Add(JournalReceiptRetention + time.Minute) other := in other.Host = "other.example" if _, err := s.Execute(t.Context(), "peer", prepare(other, 0)); err != nil { t.Fatal(err) } var count int if err := s.Launches.db.QueryRow("SELECT count(*) FROM journal_requests WHERE id=?", old.ID).Scan(&count); err != nil || count != 0 { t.Fatalf("receipt not pruned: count=%d err=%v", count, err) } if _, err := s.Execute(t.Context(), "peer", old); err != nil { t.Fatalf("permanent commit proof did not replay: %v", err) } if _, err := s.Execute(t.Context(), "peer", prepare(in, 1)); err != nil { t.Fatal(err) } if _, err := s.Execute(t.Context(), "peer", old); !errors.Is(err, ErrJournalUncertain) { t.Fatalf("expired request without remaining positive proof: %v", err) } }