package manifest import ( "bytes" "encoding/json" "io/fs" "os" "path/filepath" "reflect" "slices" "strings" "testing" ) // The controller's manifest reader is mesh-controller internal/catalogue (ParseManifest), an internal package of another // repository, which this module cannot import. These tests therefore decode the manifest strictly into the fields its // Manifest type names (DisallowUnknownFields, as its parseManifest does) and check the rules the issue names. // **The merge gate's module check is what proves the controller takes this manifest (1135/AC6); these tests hold the // rules so a unit run catches a refusal early.** type state struct { Name string `json:"name"` History int `json:"history,omitempty"` KeyTTL bool `json:"key-ttl,omitempty"` } type artifact struct { Name string `json:"name"` Kind string `json:"kind"` Language string `json:"language"` System string `json:"system"` From string `json:"from"` Binary string `json:"binary"` Context *struct { Repository string `json:"repository"` } `json:"context"` } type manifest struct { Module string `json:"module"` Moved bool `json:"moved"` Version string `json:"version"` Slug string `json:"slug"` Reads []string `json:"reads"` State []state `json:"state"` OwnSecrets map[string]string `json:"own-secrets"` SecretsOwner string `json:"secrets-owner"` Resources []map[string]any `json:"resources"` Build struct { Artifacts []artifact `json:"artifacts"` } `json:"build"` } func load(t *testing.T) (manifest, map[string]json.RawMessage) { t.Helper() raw, err := os.ReadFile("module.json") if err != nil { t.Fatal(err) } var m manifest dec := json.NewDecoder(bytes.NewReader(raw)) dec.DisallowUnknownFields() if err := dec.Decode(&m); err != nil { t.Fatalf("the controller's reader refuses a key this manifest has: %v", err) } var top map[string]json.RawMessage if err := json.Unmarshal(raw, &top); err != nil { t.Fatal(err) } return m, top } func TestManifestStateAndReads(t *testing.T) { // 1135/AC6 m, top := load(t) if m.Module != "mesh-delivery-watchman" || m.Moved || m.Slug != "watchman" { t.Errorf("module %q moved %v (it has no template, so it is not moved) slug %q", m.Module, m.Moved, m.Slug) } want := []state{{Name: "presence", History: 20}, {Name: "pulse", KeyTTL: true}, {Name: "stuck", History: 20}} if !reflect.DeepEqual(m.State, want) { t.Errorf("state = %+v, want %+v", m.State, want) } reads := slices.Clone(m.Reads) slices.Sort(reads) if !reflect.DeepEqual(reads, []string{"mesh-controller.checks-running"}) { t.Errorf("reads = %v", reads) } for _, k := range []string{"emits", "context", "items", "consumes", "provides", "claims"} { if _, ok := top[k]; ok { t.Errorf("the manifest declares %q: the watchman has none", k) } } if b, ok := m.OwnSecrets["broker"]; !ok || len(m.OwnSecrets) != 1 || b != "${dir:state}/broker" { t.Errorf("own-secrets = %v, want exactly broker", m.OwnSecrets) } if m.SecretsOwner != "mesh-delivery-watchman" { t.Errorf("secrets-owner = %q", m.SecretsOwner) } } func TestManifestIsWholeInItsRepository(t *testing.T) { // 1135/AC6 m, _ := load(t) if len(m.Build.Artifacts) != 1 { t.Fatalf("artifacts = %+v, want the one bundle program", m.Build.Artifacts) } a := m.Build.Artifacts[0] if a.Name != "program" || a.Kind != "bundle" || a.Language != "go" || a.System != "arch" || a.Context != nil { t.Errorf("artifact = %+v", a) } if st, err := os.Stat(a.From); err != nil || !st.IsDir() { t.Errorf("the artifact builds from %q, which is not a directory of this module", a.From) } if a.Binary != "mesh-delivery-watchman" || !strings.HasSuffix(a.From, a.Binary) { t.Errorf("binary %q from %q", a.Binary, a.From) } } func TestManifestResources(t *testing.T) { // 1135/AC6 m, _ := load(t) byType := map[string][]map[string]any{} for _, r := range m.Resources { ty, _ := r["type"].(string) byType[ty] = append(byType[ty], r) } for _, ty := range []string{"user", "directory", "process"} { if len(byType[ty]) == 0 { t.Fatalf("no %s resource", ty) } } user := byType["user"][0]["name"] if user != "mesh-delivery-watchman" { t.Errorf("user = %v", user) } p := byType["process"][0] if p["user"] != user || p["artifact"] != "program" { t.Errorf("process = %v", p) } env, _ := p["env"].(map[string]any) if env["MESH_BROKER_FILE"] != "${dir:state}/broker" { t.Errorf("the process reads %v", env["MESH_BROKER_FILE"]) } if h, _ := p["health"].(map[string]any); h["kind"] != "unit" { t.Errorf("health = %v", p["health"]) } d := byType["directory"][0] if d["id"] != "state" || d["mode"] != "0700" || d["owner"] != user { t.Errorf("state directory = %v", d) } } func TestNoTickerTimerOrSleep(t *testing.T) { // 1135/AC7 forbidden := []string{"time.Tick", "time.NewTicker", "time.Sleep", "time.After", "time.NewTimer", "time.AfterFunc"} var files int for _, root := range []string{"cmd", "internal"} { err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { if err != nil || d.IsDir() || !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") { return err } files++ src, err := os.ReadFile(path) if err != nil { return err } for _, f := range forbidden { if strings.Contains(string(src), f) { t.Errorf("%s holds %s: the program holds no timer", path, f) } } return nil }) if err != nil { t.Fatal(err) } } if files < 3 { t.Fatalf("read %d source files, want the program's", files) } }