package main // manifest_kit_test.go is the same file in each workstation module: it reads the module's // definition so the module's own tests can hold it to what it says. import ( "encoding/json" "os" "path/filepath" "sort" "strings" "testing" ) type manifest struct { Module string `json:"module"` Capabilities []string `json:"capabilities"` Claims []any `json:"claims"` Seats []any `json:"seats"` Tools []string `json:"tools"` Resources []map[string]any `json:"resources"` Build struct { Artifacts []map[string]any `json:"artifacts"` } `json:"build"` } func readManifest(t *testing.T) manifest { t.Helper() raw, err := os.ReadFile(filepath.Join("..", "..", "module.json")) if err != nil { t.Fatal(err) } var m manifest if err := json.Unmarshal(raw, &m); err != nil { t.Fatalf("module.json: %v", err) } return m } func (m manifest) resource(id string) map[string]any { for _, r := range m.Resources { if r["id"] == id { return r } } return nil } // packages are the packages the module installs, sorted. func (m manifest) packages() []string { out := []string{} for _, r := range m.Resources { if r["type"] == "package" && r["absent"] != true { out = append(out, r["package"].(string)) } } sort.Strings(out) return out } // services are the units the module declares, by unit name. func (m manifest) services() map[string]map[string]any { out := map[string]map[string]any{} for _, r := range m.Resources { if r["type"] == "service" { out[r["unit"].(string)] = r } } return out } // holdsTheBundle holds the manifest to the Go bundle this directory builds: every tool registered // is listed and nothing else, each named _…, and the artifact builds this command. func holdsTheBundle(t *testing.T, m manifest, prefix string) { t.Helper() registered := []string{} for _, tool := range tools() { registered = append(registered, tool.Name) if !strings.HasPrefix(tool.Name, prefix+"_") { t.Errorf("tool %s is not named %s_…", tool.Name, prefix) } if tool.Description == "" || tool.Run == nil || tool.Input == nil { t.Errorf("tool %s is not described, runnable and given an input schema", tool.Name) } } if strings.Join(registered, ",") != strings.Join(m.Tools, ",") { t.Errorf("registered %v, listed %v", registered, m.Tools) } if len(m.Build.Artifacts) != 1 { t.Fatalf("one artifact, got %d", len(m.Build.Artifacts)) } cwd, _ := os.Getwd() binary := filepath.Base(cwd) a := m.Build.Artifacts[0] want := map[string]any{"kind": "bundle", "language": "go", "system": "arch", "from": "cmd/" + binary, "binary": binary} for k, v := range want { if a[k] != v { t.Errorf("artifact %s = %v, want %v", k, a[k], v) } } if loads, _ := a["loads"].([]any); len(loads) != 1 || loads[0] != binary { t.Errorf("artifact loads %v, want [%s]", a["loads"], binary) } if m.Claims != nil || m.Seats != nil { t.Errorf("claims %v, seats %v: this module holds no seat", m.Claims, m.Seats) } }