package catalogue import ( "strings" "testing" ) // A served verb is written as a bare name or in full, and both read into one type (novox/hq ADR 0132). func TestAServedVerbIsANameOrADefinition(t *testing.T) { m, err := ParseManifest([]byte(`{"module":"till","version":"1","tools":["price","refund"],` + `"seats":[{"name":"shop-till","serves":["price",{"name":"refund","description":"give it back",` + `"input":{"type":"object","properties":{"order":{"type":"string"}}}}]}],` + `"claims":[{"name":"shop-till","scope":"mesh"}]}`)) if err != nil { t.Fatal(err) } got := m.DefinesSeats[0].Serves if len(got) != 2 || got[0].Name != "price" || got[1].Name != "refund" || got[1].Description != "give it back" { t.Fatalf("verbs not read: %+v", got) } if got[1].Input["type"] != "object" { t.Fatalf("the schema did not travel with the verb: %+v", got[1].Input) } } // A misspelt key inside a verb's definition is refused, like one anywhere else in the manifest. func TestAVerbWithAnUnknownKeyIsRefused(t *testing.T) { _, err := ParseManifest([]byte(`{"module":"till","version":"1",` + `"seats":[{"name":"shop-till","serves":[{"name":"price","descripton":"typo"}]}]}`)) if err == nil || !strings.Contains(err.Error(), "descripton") { t.Fatalf("a verb with a misspelt key was accepted: %v", err) } } // Holding a mesh seat that serves verbs requires serving them, and the refusal names the verbs. func TestHoldingAMeshSeatRequiresServingItsVerbs(t *testing.T) { was := Seats() t.Cleanup(func() { UseSeats(was) }) UseSeats([]Seat{{Name: "mesh-controller", Scope: ScopeMesh, Decision: "test", Serves: []Verb{{Name: "status"}, {Name: "push"}}}}) seat, _ := SeatNamed("mesh-controller") partial := Manifest{Module: "a-controller", Tools: []string{"status"}, Claims: []Claim{{Name: "mesh-controller", Scope: ScopeMesh}}} err := CanHold(partial, seat) if err == nil || !strings.Contains(err.Error(), "does not serve push") { t.Fatalf("a holder missing a verb was not refused by name: %v", err) } whole := Manifest{Module: "a-controller", Tools: []string{"status", "push"}, Claims: []Claim{{Name: "mesh-controller", Scope: ScopeMesh}}} if err := CanHold(whole, seat); err != nil { t.Fatalf("a holder serving every verb was refused: %v", err) } } // The mesh's own verbs are declared in full: an agent cannot call a name without a schema. func TestEveryControllerVerbIsDescribedWithASchema(t *testing.T) { seen := map[string]bool{} for _, v := range ControllerVerbs { if v.Description == "" || v.Input == nil || v.Input["type"] != "object" { t.Errorf("%s: no description or no object schema", v.Name) } if seen[v.Name] { t.Errorf("%s declared twice", v.Name) } seen[v.Name] = true } seat, _ := SeatNamed(ControllerSeatName) if len(seat.Serves) != len(ControllerVerbs) { t.Fatalf("the compiled mesh-controller seat serves %d verbs, the table has %d", len(seat.Serves), len(ControllerVerbs)) } }