Files
mesh-catalog/modules/mesh-config/cmd/mesh-config/manifest_test.go
T

103 lines
4.1 KiB
Go

package main
import (
"encoding/json"
"os"
"path/filepath"
"slices"
"strings"
"testing"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// Every state, log and read the manifest declares has a tool that reads it, and every act the module takes by itself
// a tool that starts it (novox/hq ADR 0565 §15): the verb config's actions, and the switch's tools.
func TestEveryStateAndActHasItsTool(t *testing.T) {
raw, err := os.ReadFile(filepath.Join("..", "..", "module.json"))
if err != nil {
t.Fatal(err)
}
var m struct {
State []string `json:"state"`
Packages map[string]string `json:"packages"`
Logs []string `json:"logs"`
Reads []string `json:"reads"`
Tools []string `json:"tools"`
Claims []struct {
Name string `json:"name"`
Serves []string `json:"serves"`
} `json:"claims"`
}
if err := json.Unmarshal(raw, &m); err != nil {
t.Fatal(err)
}
// The builder's keys are read through its published package, taken by its series (ADR 0634 §1).
if m.Packages["builds"] != "0.1" {
t.Errorf("packages %v: want builds of series 0.1", m.Packages)
}
via := map[string]string{
ValuesState: "config list", ResolvedState: "config list", PredefinedState: "config list",
ProposalsState: "config proposals", PullsState: "config list", KeptState: "config list", HistoryLog: "config history",
DeclaredState: DeclaredTool,
PlacementRead: "config list", WantsRead: "config list", BuildsRead: "config list", ModulesRead: DeclaredTool,
ManifestsRead: DeclaredTool, IndexerPredefinedRead: "config list", CandidatesRead: ResyncTool,
"a resolution": ResyncTool, "the indexer's candidates taken": ResyncTool,
// design 32: each new state with the tool that reads it, each act with the tool that starts it.
RenamesState: RenamesTool, RetiringState: RetiringTool, FindingsState: "config_renames and config_retiring",
"a move refused": RenameAgainTool, "a window dropped": RenameCloseTool, "an ask again": RetiringTool,
"the owners' first views": FirstViewsTool, "a first view asked again": FirstViewAgainTool,
}
served := map[string]bool{}
for _, tool := range Tools(&Config{}) {
served[tool.Name] = true
}
if len(m.Claims) != 1 || m.Claims[0].Name != Seat || strings.Join(m.Claims[0].Serves, ",") != strings.Join(SeatVerbs, ",") {
t.Errorf("claims %+v, want %s serving %v", m.Claims, Seat, SeatVerbs)
}
// The stream and its events are declared as the module emits them, and the manifest decodes whole.
if dm, err := catalogue.Decode(raw); err != nil {
t.Errorf("the manifest does not decode: %v", err)
} else {
// An event goes to one place (novox/hq ADR 0363 §2): config-changed to EVENTS, the rename window's to the stream.
if !slices.Equal(dm.Emits, []string{ConfigChanged}) {
t.Errorf("emits %v, want only %s: the stream carries the others", dm.Emits, ConfigChanged)
}
if len(dm.Streams) != 1 || dm.Streams[0].Name != StreamName || dm.Streams[0].Days() != 7 || !dm.Streams[0].Carries(EventRenamed) ||
!dm.Streams[0].Carries(EventRetiring) || !dm.Streams[0].Carries(EventRetired) || dm.Streams[0].Carries(ConfigChanged) {
t.Errorf("streams %+v: want %s, seven days, carrying renamed, retiring and retired but not config-changed", dm.Streams, StreamName)
}
}
for _, verb := range SeatVerbs {
if !served[Seat+"."+verb] {
t.Errorf("the seat's verb %s is not served", verb)
}
}
for _, name := range m.Tools {
if !served[name] {
t.Errorf("the manifest lists the tool %s, which is not served", name)
}
}
// The delivery owners' state is read through their tools and views (ADR 0615 §1): only the builder's builds, which has
// no tool yet, is still a read.
if len(m.Reads) != 1 || m.Reads[0] != BuildsRead {
t.Errorf("reads %v, want the builder's builds alone", m.Reads)
}
for _, list := range [][]string{m.State, m.Logs, m.Reads} {
for _, s := range list {
if _, ok := via[s]; !ok {
t.Errorf("%s has no tool that reads it", s)
}
}
}
for what, tool := range via {
name, _, _ := strings.Cut(tool, " ")
if name == "config" {
name = Seat + "." + Verb
}
if !served[name] {
t.Errorf("%s is read or started by %s, which is not served", what, tool)
}
}
}