Files
mesh-catalog/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/collect_test.go
T
jschoubben 35ff67bda0
mesh/delivery-group group feat/774-l3-reland rejected: composed together: the checker's verdict at the members' heads (b48c90fea31f): integration: mesh-self-ch…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: integration: mesh-self-check/cmd/mesh-self-check.TestTheSelfCheckWholeRunsOnTheBus: the run answered {Run:doctor-1793351737-1 At:20…
Design 47's last milestones: the keeper, self-check, healers, hand-acts, provisioner, vault, artifact sweep, disk readings, credential forms (issues 774, 1952, 1953, 1954, 1955)
One commit with exactly the tree of the reviewed head 35b4509c0a, on main 12c2574c9d, so two compiled programs added and removed on the branch leave no trace in history (issue 1577).
2026-10-30 02:21:51 +01:00

174 lines
8.0 KiB
Go

package main
import (
"context"
"encoding/json"
"strings"
"testing"
)
// A collection's test of novox/hq ADR 0349 ("How it is checked", design 57 L1, issue 684): zsh's file holds every
// placed contributor's item and loses one whose contributor leaves. Against a real bus, on the client's own account.
const zshrc = "/home/nox/.zshrc"
// zshCollector is zsh as a handed collector: its rc names its normal slot the old way, read as the collection
// shell:zsh:normal, and a collection of the new form.
func zshCollector(t *testing.T) Plan {
tpl, _ := templates(t, map[string]string{"zshrc": "# zsh\n${shell:zsh:normal}# then\n${collected:zsh-widgets}# end\n"})
return Plan{Templates: tpl, Files: []PlannedFile{{ID: "rc", Path: zshrc, Template: "zshrc",
OwnerAtRuntime: "owned"}},
Collections: []PlannedCollection{{Name: "shell:zsh:normal", Comment: "#"}, {Name: "zsh-widgets"}}}
}
// contributor is a module whose only part on the node is its item of collection, from its own template.
func contributor(t *testing.T, collection, text string) Plan {
tpl, _ := templates(t, map[string]string{"item": text})
return Plan{Templates: tpl, Items: []PlannedItem{{Collection: collection, Template: "item"}},
Placement: map[string]string{"machine:account-home": "/home/nox"}}
}
func TestNatsZshsFileHoldsEveryPlacedContributorsItemAndLosesOneWhoseContributorLeaves(t *testing.T) {
b := startBus(t)
heard := b.listen(t)
e := startEngine(t, map[string]string{zshrc: "owned", "/etc/fzf.conf": "owned"})
b.assign(t, "zsh", zshCollector(t))
b.assign(t, "powerlevel10k", contributor(t, "shell:zsh:normal",
"source ${machine:account-home}/.p10k.zsh\n"))
b.assign(t, "mesh-cli", contributor(t, "shell:zsh:normal", "alias nox=mesh-cli"))
b.config(t, "fzf", "binding", `"^T"`)
fzf := contributor(t, "zsh-widgets", "bindkey ${config:binding} fzf-file-widget\n")
b.assign(t, "fzf", fzf)
aClient(t, b, e, t.TempDir())
every := "# zsh\n# mesh-cli\nalias nox=mesh-cli\n# powerlevel10k\nsource /home/nox/.p10k.zsh\n# then\n" +
"bindkey ^T fzf-file-widget\n# end\n"
eventually(t, "zshrc holds every contributor's item", func() bool { return e.read(t, zshrc) == every })
// Each item recorded under the node, the collection and its contributor; filled, the contributor's report says so.
eventually(t, "the items are recorded", func() bool {
got := b.keys(t, CollectBucket, node+".")
return len(got) == 3 && got[0] == "g14.shell=3Azsh=3Anormal.mesh-cli" &&
got[1] == "g14.shell=3Azsh=3Anormal.powerlevel10k" && got[2] == "g14.zsh-widgets.fzf"
})
kept, err := b.kv[CollectBucket].Get(context.Background(), "g14.shell=3Azsh=3Anormal.powerlevel10k")
if err != nil {
t.Fatal(err)
}
var it ItemRecord
if err := json.Unmarshal(kept.Value(), &it); err != nil || it.Text != "source /home/nox/.p10k.zsh\n" ||
it.Collection != "shell:zsh:normal" || it.Contributor != "powerlevel10k" {
t.Errorf("the item kept is %s (%v)", kept.Value(), err)
}
eventually(t, "powerlevel10k's report says its item", func() bool {
r, _ := heard.last("powerlevel10k")
return r.Status == StatusApplied && len(r.Items) == 1 && r.Items[0] == "shell:zsh:normal"
})
// A contributor's own value changes: its item, and so zshrc, follow.
b.config(t, "fzf", "binding", `"^F"`)
eventually(t, "zshrc follows the item", func() bool { return strings.Contains(e.read(t, zshrc), "bindkey ^F") })
// powerlevel10k leaves the node: its item goes, and zshrc without it.
b.del(t, PlansBucket, node+".powerlevel10k")
without := "# zsh\n# mesh-cli\nalias nox=mesh-cli\n# then\nbindkey ^F fzf-file-widget\n# end\n"
eventually(t, "zshrc loses the item of the contributor that left", func() bool { return e.read(t, zshrc) == without })
if got := b.keys(t, CollectBucket, node+".shell=3Azsh=3Anormal.powerlevel10k"); len(got) != 0 {
t.Errorf("the item of a contributor that left is kept: %v", got)
}
// And a contributor that stops contributing, though it stays: the same.
b.assign(t, "fzf", Plan{Templates: fzf.Templates, Files: []PlannedFile{{ID: "conf", Path: "/etc/fzf.conf",
Template: "item", OwnerAtRuntime: "owned"}}, Placement: fzf.Placement})
eventually(t, "zshrc loses an item no longer contributed", func() bool {
return e.read(t, zshrc) == "# zsh\n# mesh-cli\nalias nox=mesh-cli\n# then\n# end\n"
})
}
func TestNatsACollectorStartingWithItsNodeHoldsTheItemsAlreadyThereAndOnesRecordedWhileAway(t *testing.T) {
b := startBus(t)
e := startEngine(t, map[string]string{zshrc: "owned"})
b.assign(t, "zsh", zshCollector(t))
b.assign(t, "mesh-cli", contributor(t, "shell:zsh:normal", "alias nox=mesh-cli\n"))
state := t.TempDir()
_, stop := aClient(t, b, e, state)
eventually(t, "zshrc holds mesh-cli's item", func() bool { return strings.Contains(e.read(t, zshrc), "alias nox") })
stop()
b.del(t, PlansBucket, node+".mesh-cli")
b.assign(t, "zsh-autosuggestions", contributor(t, "shell:zsh:normal", "source suggestions.zsh\n"))
aClient(t, b, e, state)
want := "# zsh\n# zsh-autosuggestions\nsource suggestions.zsh\n# then\n# end\n"
eventually(t, "zshrc is filled from the items now", func() bool { return e.read(t, zshrc) == want })
eventually(t, "the item of the module that left while away is removed", func() bool {
return len(b.keys(t, CollectBucket, node+".shell=3Azsh=3Anormal.mesh-cli")) == 0
})
}
// A collection the plan does not name, and an item naming a secret, fail with the reason; an item is never
// recorded with a secret in it.
func TestNatsACollectionNotPlannedAndAnItemNamingASecretFail(t *testing.T) {
b := startBus(t)
heard := b.listen(t)
e := startEngine(t, map[string]string{zshrc: "owned"})
p := zshCollector(t)
p.Collections = p.Collections[:1]
b.assign(t, "zsh", p)
b.assign(t, "leaky", contributor(t, "shell:zsh:normal", "export TOKEN=${secret:token}\n"))
aClient(t, b, e, t.TempDir())
for module, why := range map[string]string{"zsh": "the plan names no collection zsh-widgets",
"leaky": "where no secret is"} {
eventually(t, module+" fails", func() bool {
r, _ := heard.last(module)
return r.Status == StatusFailed && strings.Contains(r.Reason, why)
})
}
if got := b.keys(t, CollectBucket, node+"."); len(got) != 0 {
t.Errorf("recorded %v", got)
}
if _, asked := e.counts(zshrc); asked != 0 {
t.Errorf("a collector naming a collection its plan does not was written")
}
}
func TestAnItemsKeyHoldsAnyCollectionAndReadsBack(t *testing.T) {
for collection, want := range map[string]string{
"zsh-widgets": "g14.zsh-widgets.fzf",
"shell:zsh:normal": "g14.shell=3Azsh=3Anormal.fzf",
"contribution:node-hotkeys:trigger": "g14.contribution=3Anode-hotkeys=3Atrigger.fzf",
} {
key := CollectKey(node, collection, "fzf")
if key != want {
t.Errorf("%s: %s, want %s", collection, key, want)
}
c, who, ok := itemOfKey(node, key)
if !ok || c != collection || who != "fzf" {
t.Errorf("%s reads back as %q %q %v", key, c, who, ok)
}
}
for _, bad := range []string{"g14.x", "ace.zsh-widgets.fzf", "g14.=ZZ.fzf", "g14.a.b.c", "g14.Upper.fzf"} {
if _, _, ok := itemOfKey(node, bad); ok {
t.Errorf("%s read as an item's key", bad)
}
}
}
func TestAPlansItemsAndCollectionsAreJudged(t *testing.T) {
p := Plan{Templates: Templates{Source: "x", Digest: "sha256:" + strings.Repeat("0", 64)},
Items: []PlannedItem{{Collection: "a", Template: "item"}, {Collection: "a", Template: "../x"},
{Collection: "Bad", Template: "y"}},
Collections: []PlannedCollection{{Name: "c", Comment: "#\n"}, {Name: "c"}}}
got := strings.Join(p.problems(), "\n")
for _, want := range []string{"item a is named twice", `template "../x"`, `item "Bad" is not`,
"collection c: its comment holds a line break", "collection c is named twice"} {
if !strings.Contains(got, want) {
t.Errorf("the problems %q do not say %q", got, want)
}
}
// A plan contributing an item and filling no file is one the client acts on.
if wrong := (Plan{Templates: p.Templates, Items: p.Items[:1]}).problems(); len(wrong) != 0 {
t.Errorf("a contributor's plan: %v", wrong)
}
if wrong := (Plan{Templates: p.Templates}).problems(); len(wrong) != 1 {
t.Errorf("a plan doing nothing: %v", wrong)
}
}