Files
mesh-catalog/modules/pacman/cmd/pacman-tools/keeper_hooks_test.go
T
jschoubben d70135bf08 issue 1841/S5: join the upgrade parts to the keeper's loop, so a node's log, records, unfinished runs and asks are taken up by its own keeper
At its start the keeper reads the log into runs once, prunes old records and carries unfinished runs on;
after every released lock it carries them on again; it takes each ask at <node>.* and prunes records daily.
The root helper's client is a constructor (newRootActs) the helper replaces; until then every act is
refused, named.
2026-10-22 14:39:59 +02:00

82 lines
2.8 KiB
Go

package main
// The upgrade parts joined to the keeper's loop (keeperHooks): the log read into runs and old records pruned at
// the start, an ask for this node taken from `asks`, and the records pruned again a day later.
import (
"context"
"strings"
"testing"
"time"
)
func TestTheKeeperRunsTheUpgradePartsAtItsStartOnItsAsksAndDaily(t *testing.T) {
db := &pacmanDB{sl: syncDBs, checkup: Ran{Status: 2}}
db.set("glibc 2.42-1\n", "")
k, states, _, clock, _ := newTestKeeper(db)
log := capturedLog(t)
k.Machine.ReadFile = func(path string) ([]byte, error) {
if path == PacmanLog {
return []byte(log), nil
}
return nil, errNoFile
}
k.MakeHooks = keeperHooks
k.Logf = t.Logf
k.Config = KeeperConfig{RecordDays: 180}
records := states.store(StateRecords)
records.Put(NodeKey("node-a", "20250101T040000Z"), Record{Node: "node-a", Run: "20250101T040000Z"})
records.Put(NodeKey("node-b", "20250101T040000Z"), Record{Node: "node-b", Run: "20250101T040000Z"})
done := Run{Node: "node-a", Run: "20261003T040000Z", Kind: RunUpgrade, From: FromAsk, Ask: "ask-1",
Steps: []Step{{Step: StepRefused, At: t0, Why: "a test"}}}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ended := make(chan error, 1)
go func() { ended <- k.Run(ctx) }()
until := func(what string, ok func() bool) {
t.Helper()
for deadline := time.Now().Add(5 * time.Second); time.Now().Before(deadline); time.Sleep(time.Millisecond) {
if ok() {
return
}
}
t.Fatalf("never: %s", what)
}
until("the log read into runs", func() bool {
keys, _ := states.store(StateRuns).Keys()
return len(keys) > 1
})
until("the old record pruned at the start", func() bool {
e, _ := records.Get(NodeKey("node-a", "20250101T040000Z"))
return e == nil
})
if e, _ := records.Get(NodeKey("node-b", "20250101T040000Z")); e == nil {
t.Error("another node's record was pruned")
}
// a run an ask started, ended; its ask left behind by a keeper that went away.
states.store(StateRuns).Put(NodeKey("node-a", done.Run), done)
asks := states.store(StateAsks)
asks.Put(NodeKey("node-a", "ask-1"), Ask{ID: "ask-1", Node: "node-a", Act: ActUpgrade, At: t0})
until("the ask a run names deleted", func() bool {
e, _ := asks.Get(NodeKey("node-a", "ask-1"))
return e == nil
})
records.Put(NodeKey("node-a", "20250102T040000Z"), Record{Node: "node-a", Run: "20250102T040000Z"})
time.Sleep(20 * time.Millisecond)
if e, _ := records.Get(NodeKey("node-a", "20250102T040000Z")); e == nil {
t.Fatal("pruned before a day passed")
}
clock.Advance(UpdatesEvery)
until("the old record pruned a day later", func() bool {
e, _ := records.Get(NodeKey("node-a", "20250102T040000Z"))
return e == nil
})
cancel()
if err := <-ended; err == nil || !strings.Contains(err.Error(), "canceled") {
t.Errorf("Run: %v", err)
}
}