The controller plans config, templates and moved providers' provisions, hands bus accounts to the vault and judges the new manifest words, on the feature's SDK and node-engine validator (feature 57, config and provisioning).
180 lines
9.9 KiB
Go
180 lines
9.9 KiB
Go
package catalogue
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// A collection is declared and filled by the client (novox/hq ADR 0349 §13, design 57 L1, issue 684): a collector
|
|
// names a collection it collects, a contributor an item from a template of its own, and a handed composition plans
|
|
// both for the node's provisioner client and renders neither. The three old namespaces read as collections of their
|
|
// own name. Each file is filled one way: a piece of the other form on the machine is said as not placed.
|
|
|
|
const (
|
|
collectorZsh = `{"module":"zsh","version":"1","moved":true,
|
|
"claims":[{"name":"node-login-shell","scope":"node"}],
|
|
"collections":[{"name":"widgets","comment":"#"}],
|
|
"build":{"artifacts":[{"name":"files","kind":"archive","from":"files"}]},
|
|
"resources":[{"id":"rc","type":"file","path":"${machine:account-home}/.zshrc","owner":"${machine:account}",
|
|
"mode":"0644","template":"files/zshrc"}]}`
|
|
zshrcText = "# zsh\n${shell:zsh:normal}${collected:widgets}"
|
|
contributorText = "source ${machine:account-home}/.p10k.zsh\n"
|
|
contributorP10k = `{"module":"prompt","version":"1","moved":true,
|
|
"items":[{"collection":"shell:zsh:normal","template":"files/zsh"}],
|
|
"build":{"artifacts":[{"name":"files","kind":"archive","from":"files"}]}}`
|
|
oldFormAliases = `{"module":"aliases","version":"1",
|
|
"shell":[{"for":"zsh","slot":"normal","code":"alias ll='ls -l'\n"}]}`
|
|
)
|
|
|
|
func builtWith(module string, texts map[string]string) []Built {
|
|
return []Built{{Name: "files", Kind: ArtifactArchive,
|
|
Reference: ArtifactStoreScheme + module + "/files/blobs/sha256:" + strings.Repeat("e", 64),
|
|
Digest: "sha256:" + strings.Repeat("e", 64), Texts: texts}}
|
|
}
|
|
|
|
func collectionsOn(t *testing.T) Resolution {
|
|
t.Helper()
|
|
zsh := held(t, collectorZsh, builtWith("zsh", map[string]string{"zshrc": zshrcText}))
|
|
prompt := held(t, contributorP10k, builtWith("prompt", map[string]string{"zsh": contributorText}))
|
|
aliases, err := ParseManifest([]byte(oldFormAliases))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r, err := Resolve(shelf(zsh, prompt, aliases), []string{"zsh", "prompt", "aliases"}, workstation(), World{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r.Account = "op"
|
|
return r
|
|
}
|
|
|
|
func TestAContributorsBuildKeepsItsItemsTemplateAndText(t *testing.T) {
|
|
m := held(t, contributorP10k, builtWith("prompt", map[string]string{"zsh": contributorText}))
|
|
if m.Handed == nil || !reflect.DeepEqual(m.Handed.Items, map[string]string{"shell:zsh:normal": "zsh"}) {
|
|
t.Fatalf("the build kept %+v", m.Handed)
|
|
}
|
|
if !reflect.DeepEqual(m.Items, []Item{{Collection: "shell:zsh:normal", Content: contributorText}}) {
|
|
t.Fatalf("the held items are %+v: the template's text, read back", m.Items)
|
|
}
|
|
}
|
|
|
|
func TestAHandedCollectorAndContributorArePlannedAndNeitherIsRendered(t *testing.T) {
|
|
c, got := composeWith(t, collectionsOn(t), handingTo("store:5000"))
|
|
if strings.Contains(got, ".p10k.zsh") || strings.Contains(got, "alias ll") {
|
|
t.Fatalf("the controller rendered a contribution into a handed collector: %s", got)
|
|
}
|
|
zsh, prompt := c.Plans["zsh"], c.Plans["prompt"]
|
|
wantCollections := []PlanCollection{{Name: "shell:zsh:normal", Comment: "#"}, {Name: "widgets", Comment: "#"}}
|
|
if !reflect.DeepEqual(zsh.Collections, wantCollections) || len(zsh.Items) != 0 {
|
|
t.Fatalf("zsh's plan collects %+v and contributes %+v", zsh.Collections, zsh.Items)
|
|
}
|
|
if !reflect.DeepEqual(prompt.Items, []PlanItem{{Collection: "shell:zsh:normal", Template: "zsh"}}) ||
|
|
len(prompt.Files) != 0 || prompt.Placement["machine:account-home"] != "/home/op" {
|
|
t.Fatalf("prompt's plan is %+v: its item, by template, and the placement its template names", prompt)
|
|
}
|
|
// The old form on the same machine is not placed, and said so.
|
|
if len(c.Unplaced) != 1 || !strings.Contains(c.Unplaced[0], "aliases's shell:zsh:normal is not placed") {
|
|
t.Fatalf("unplaced: %v", c.Unplaced)
|
|
}
|
|
}
|
|
|
|
// A collector filled the old way holds the old forms and each moved contributor's item, rendered from the text the
|
|
// mesh holds as its old form was (design 57 L2, issue 681), so the file loses no line where nothing is handed; a
|
|
// collection of the new form stays empty.
|
|
func TestACollectorFilledTheOldWayHoldsTheOldFormsAndEachHeldItem(t *testing.T) {
|
|
c, got := composeWith(t, collectionsOn(t), Rendering{ArtifactStore: "store:5000"})
|
|
if c.Plans != nil {
|
|
t.Fatalf("handed on a machine that cannot take it: %v", c.Plans)
|
|
}
|
|
if !strings.Contains(got, `"content":"# zsh\n# aliases\nalias ll='ls -l'\n# prompt\nsource /home/op/.p10k.zsh\n"`) {
|
|
t.Fatalf("the old way does not hold the old forms and the held item in module order: %s", got)
|
|
}
|
|
if len(c.Unplaced) != 0 {
|
|
t.Fatalf("unplaced: %v", c.Unplaced)
|
|
}
|
|
}
|
|
|
|
// An item the controller cannot render the old way (it names a value but a machine fact) is said as not placed.
|
|
func TestAHeldItemNamingMoreThanAFactIsSaidNotPlacedTheOldWay(t *testing.T) {
|
|
zsh := held(t, collectorZsh, builtWith("zsh", map[string]string{"zshrc": zshrcText}))
|
|
if _, ok := heldItemText(Manifest{Module: "p", Items: []Item{{Collection: "shell:zsh:normal",
|
|
Content: "export THEME=${config:theme}\n"}}}, "shell:zsh:normal", map[string]string{}); ok {
|
|
t.Fatal("an item naming a config value was rendered by the controller")
|
|
}
|
|
if _, ok := heldItemText(Manifest{Module: "p", Items: []Item{{Collection: "shell:zsh:normal",
|
|
Content: "cd ${machine:account-home}\n"}}}, "shell:zsh:normal", map[string]string{}); ok {
|
|
t.Fatal("an item naming a fact this machine lacks was rendered")
|
|
}
|
|
if _, ok := heldItemText(Manifest{Module: "p", Items: []Item{{Collection: "widgets", Content: "x\n"}}},
|
|
"widgets", nil); ok {
|
|
t.Fatal("an item of a collection of the new form was rendered the old way")
|
|
}
|
|
left := itemsLeftOut([]Manifest{zsh, {Module: "p", Items: []Item{{Collection: "shell:zsh:normal",
|
|
Content: "export THEME=${config:theme}\n"}}}}, zsh, "shell:zsh:normal", map[string]string{})
|
|
if len(left) != 1 || !strings.Contains(left[0], "p's item of shell:zsh:normal is not placed") {
|
|
t.Fatalf("left out: %v", left)
|
|
}
|
|
}
|
|
|
|
// Each old namespace L2 moves renders a moved contributor's item exactly as its old form did, where the collector is
|
|
// not handed: the same contributor written both ways composes the same bytes (design 57 L2, issue 681).
|
|
func TestAMovedContributorsItemRendersAsItsOldFormDid(t *testing.T) {
|
|
code := "# two lines\nalias a=b"
|
|
asOld := Manifest{Module: "laptop", Shell: []ShellCode{{For: "zsh", Slot: "normal", Code: code}},
|
|
Contributions: []SeatContribution{{Seat: HotkeysSeat, Kind: "trigger", Content: "KEY_F21 1 touchpad\n"}}}
|
|
asItem := Manifest{Module: "laptop", Moved: true, Items: []Item{{Collection: "shell:zsh:normal", Content: code},
|
|
{Collection: "contribution:node-hotkeys:trigger", Content: "KEY_F21 1 touchpad\n"}}}
|
|
other := Manifest{Module: "zz-other", Shell: []ShellCode{{For: "zsh", Slot: "normal", Code: "x=1\n"}},
|
|
Contributions: []SeatContribution{{Seat: HotkeysSeat, Kind: "trigger", Content: "KEY_MUTE 1 mute\n"}}}
|
|
first := Manifest{Module: "aa-first", Shell: []ShellCode{{For: "zsh", Slot: "normal", Code: "y=2\n"}}}
|
|
for _, mods := range [][]Manifest{{other, first}, {}} {
|
|
was := append(append([]Manifest(nil), mods...), asOld)
|
|
is := append(append([]Manifest(nil), mods...), asItem)
|
|
if a, b := shellCodeOn(was, "zsh", "normal", nil), shellCodeOn(is, "zsh", "normal", nil); a != b || a == "" {
|
|
t.Errorf("shell: the old form made %q, the item %q", a, b)
|
|
}
|
|
a, _, errA := seatContributions(was, hotkeysHolder(), "node-hotkeys:trigger", Rendering{}, nil, nil)
|
|
b, left, errB := seatContributions(is, hotkeysHolder(), "node-hotkeys:trigger", Rendering{}, nil, nil)
|
|
if errA != nil || errB != nil || a != b || a == "" || len(left) != 0 {
|
|
t.Errorf("hotkeys: the old form made %q, the item %q (%v %v %v)", a, b, errA, errB, left)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCollectionsAndItemsAreJudged(t *testing.T) {
|
|
for name, c := range map[string]struct{ raw, says string }{
|
|
"an item of a module not moved": {`{"module":"m","version":"1",
|
|
"items":[{"collection":"shell:zsh:normal","template":"files/x"}],
|
|
"build":{"artifacts":[{"name":"files","kind":"archive","from":"files"}]}}`, "is marked moved"},
|
|
"two items to one collection": {`{"module":"m","version":"1","moved":true,
|
|
"items":[{"collection":"a","template":"files/x"},{"collection":"a","template":"files/y"}],
|
|
"build":{"artifacts":[{"name":"files","kind":"archive","from":"files"}]}}`, "contributes to a twice"},
|
|
"an item to no slot": {`{"module":"m","version":"1","moved":true,
|
|
"items":[{"collection":"shell:zsh:middle","template":"files/x"}],
|
|
"build":{"artifacts":[{"name":"files","kind":"archive","from":"files"}]}}`, "is no slot"},
|
|
"an item outside the templates": {`{"module":"m","version":"1","moved":true,
|
|
"items":[{"collection":"a","template":"x"}],
|
|
"build":{"artifacts":[{"name":"files","kind":"archive","from":"files"}]}}`, "is not a file under files/"},
|
|
"an item naming a secret": {`{"module":"m","version":"1",
|
|
"items":[{"collection":"a","content":"t=${secret:token}"}]}`, "where no secret is"},
|
|
"a collection not declared": {`{"module":"m","version":"1",
|
|
"resources":[{"id":"f","type":"file","path":"/f","content":"${collected:a}"}]}`, "does not collect"},
|
|
"an old namespace declared": {`{"module":"m","version":"1","collections":[{"name":"shell:zsh:normal"}],
|
|
"resources":[{"id":"f","type":"file","path":"/f","content":"x"}]}`, "read from its placeholder"},
|
|
"a collection placed nowhere": {`{"module":"m","version":"1","collections":[{"name":"a"}],
|
|
"resources":[{"id":"f","type":"file","path":"/f","content":"x"}]}`, "no file of its places it"},
|
|
"a collection in a path": {`{"module":"m","version":"1","collections":[{"name":"a"}],
|
|
"resources":[{"id":"f","type":"file","path":"/${collected:a}","content":"${collected:a}"}]}`,
|
|
"only in a file's content"},
|
|
} {
|
|
_, err := ParseManifest([]byte(c.raw))
|
|
if err == nil || !strings.Contains(err.Error(), c.says) {
|
|
t.Errorf("%s: %v, want it to say %q", name, err, c.says)
|
|
}
|
|
}
|
|
if _, err := ParseManifest([]byte(collectorZsh)); err != nil {
|
|
t.Errorf("a collector: %v", err)
|
|
}
|
|
}
|