diff --git a/modules/mesh-grants/grants_test.go b/modules/mesh-grants/grants_test.go index 0aec273e..b138b314 100644 --- a/modules/mesh-grants/grants_test.go +++ b/modules/mesh-grants/grants_test.go @@ -2542,6 +2542,42 @@ func TestGrants(t *testing.T) { if !strings.Contains(refused, "manifest of mod-x: it waits for the seat list") { t.Errorf("another module is not held: %v", p.Last().Refused) } + + // Issue 1966: the assignments view unanswered, the indexer placed by its have alone (its real manifest, claiming + // mesh-catalog and serving seat-definitions) is composed to serve the seat's verbs, in the list and its membership, + // while the seat list stays unread: the bootstrap reaches the verb that reads the list without opening the gate. + indexer, err := os.ReadFile("../mesh-delivery-indexer/module.json") + if err != nil { + t.Fatal(err) + } + fb := fixture() + fb.refused[grants.ReadAssignments] = true + fb.manifestOf("mesh-delivery-indexer", string(indexer)) + fb.put(grants.ReadHave, "novox.node", map[string]any{"v": 1}) + fb.put(grants.ReadHave, "novox.mesh-delivery-indexer", nodeengine.HaveByNodeModuleValue{V: keys.Version, Phase: nodeengineclient.PhaseRunning, Health: nodeengineclient.HealthOK}) + gate := &seatGate{} + fp := partOn(fb) + fp.SeatList = gate + res := fp.Compose() + if strings.Contains(strings.Join(res.Refused, "\n"), "manifest of mesh-delivery-indexer:") { + t.Fatalf("the indexer is held in a pass placed by the haves: %v", res.Refused) + } + listRecs, _ := grants.ListRecords(grants.ReadInputs(fb, &grants.Manifests{})) + users, err := grants.ComposeUsers(listRecs) + if err != nil { + t.Fatal(err) + } + at := slices.IndexFunc(users, func(u grants.User) bool { return u.User == "novox.mesh-delivery-indexer" }) + if at < 0 || !slices.ContainsFunc(users[at].Subscribe, func(s string) bool { return strings.HasPrefix(s, "mesh.seat.mesh-catalog.") }) { + t.Fatalf("novox.mesh-delivery-indexer is not composed to hear the seat's verbs: %+v", users) + } + raw := fb.own[grants.StateMemberships]["novox.mesh-delivery-indexer"] + if !slices.Contains(res.Published, "novox.mesh-delivery-indexer") || !strings.Contains(string(raw), "seat-definitions") { + t.Errorf("the indexer's membership serving seat-definitions was not published: %v, %s", res.Published, raw) + } + if !strings.Contains(strings.Join(res.Refused, "\n"), "manifest of mod-x: it waits for the seat list") { + t.Errorf("the seat list was opened by a pass placed by the haves: %v", res.Refused) + } }) // DLV-G1, 1966/AC32-AC33 (novox/hq ADR 0595 §1, §7; design 25 § 12.2): the bus module's created writes the binding into