package resolution import ( "encoding/json" "strings" "testing" mcat "git.novox.be/novox/mesh-sdk/go/catalogue" ) const barTemplate = `{{if eq .shows "battery"}}[[block]] block = "battery" {{with .options}}{{with .device}}device = {{quote .}} {{end}}{{end}}{{else if eq .shows "command"}}[[block]] block = "custom" command = {{quote .options.command}} interval = {{.options.interval}} {{else if eq .shows "state"}}[[block]] block = "custom" command = {{quote (printf "show %s %s" .options.state (or .options.key .machine))}} {{end}}` func barHolder() mcat.Manifest { place := func(bar string) string { return "own-first\n${contribution:node-bar:block:bar=" + bar + ",place=resources}" + "own-middle\n${contribution:node-bar:block:bar=" + bar + ",place=status}own-last\n" } return mcat.Manifest{Module: "a-bar", Claims: []mcat.Claim{{Name: mcat.BarSeat, Renders: map[string]string{mcat.BarKindBlock: barTemplate}}}, Resources: []map[string]any{ {"id": "bottom", "type": "file", "path": "/b", "content": place("bottom")}, {"id": "top", "type": "file", "path": "/t", "content": place("top")}, }} } func block(data string) mcat.SeatContribution { var d map[string]any if err := json.Unmarshal([]byte(data), &d); err != nil { panic(err) } return mcat.SeatContribution{Seat: mcat.BarSeat, Kind: mcat.BarKindBlock, Data: d} } func composedFile(t *testing.T, r mcat.Resolution, id string) string { t.Helper() out, err := Declaration(r, mcat.Rendering{}) if err != nil { t.Fatal(err) } for _, res := range out { if res["id"] == id { return res["content"].(string) } } t.Fatalf("%s was not composed", id) return "" } func TestResolveCarriesTheMachinesCapabilities(t *testing.T) { node := workstation() node.Capabilities["battery"] = true r, err := Resolve(shelf(mcat.Manifest{Module: "a"}), []string{"a"}, node, mcat.World{}) if err != nil { t.Fatal(err) } if !r.Capabilities["battery"] || !r.Capabilities["seat"] { t.Fatalf("the resolution carries %v, not the node's %v", r.Capabilities, node.Capabilities) } } func TestAPieceTheHolderCannotRenderIsLeftOutAndNamedNotTheMachine(t *testing.T) { // A shows the shape gained after the holder's template was written: built here, past the check. power := mcat.Manifest{Module: "power", Contributions: []mcat.SeatContribution{ block(`{"bar":"bottom","place":"status","shows":"gpu"}`), block(`{"bar":"bottom","place":"status","shows":"battery"}`), }} r := mcat.Resolution{Node: "n", Account: "op", Modules: []mcat.Manifest{barHolder(), power}} c, err := Compose(r, mcat.Rendering{}) if err != nil { t.Fatalf("one piece failed the whole machine: %v", err) } if len(c.Unplaced) != 1 || !strings.Contains(c.Unplaced[0], "power's node-bar:block") || !strings.Contains(c.Unplaced[0], "shows=gpu") || !strings.Contains(c.Unplaced[0], "renders nothing") { t.Fatalf("unplaced: %v", c.Unplaced) } for _, res := range c.Resources { if res["id"] == "a-bar.bottom" && !strings.Contains(res["content"].(string), `block = "battery"`) { t.Fatalf("the piece beside it was lost too: %s", res["content"]) } } } func TestAnOfferedBlockMakesNoDependencyOnTheBar(t *testing.T) { power := mcat.Manifest{Module: "power", Contributions: []mcat.SeatContribution{ block(`{"bar":"bottom","place":"status","shows":"battery"}`), {Seat: mcat.HotkeysSeat, Kind: "trigger", Content: "x"}, }} for _, seat := range DependsOn(nil, power) { if seat == mcat.BarSeat { t.Fatalf("a block made the power module depend on the bar: %v", DependsOn(nil, power)) } } // And on a machine with no bar it is placed nowhere, and nothing fails. r := mcat.Resolution{Node: "server", Account: "op", Capabilities: map[string]bool{"battery": true}, Modules: []mcat.Manifest{hotkeysHolder(), power}} if _, err := Declaration(r, mcat.Rendering{}); err != nil { t.Fatal(err) } }