package catalogue import ( "strings" "testing" ) // 1943/AC4: the controller's seat no longer offers a verb that starts, stops, retries, follows or reads a delivery // plan, nor a push: each is a row with no input whose description refuses it by name and names its replacement, and // each is in the removed list the holder answers from. upgrade keeps its policy and drops the plan's backlog. func TestTheControllerSeatHasNoPlanVerbs(t *testing.T) { rows := map[string]Verb{} for _, v := range ControllerVerbs { rows[v.Name] = v } gone := []string{"plans", "plan", "push", "deliver", "delivery-stop", "delivery-backups-again", "delivery-walks", "delivery-order"} for _, name := range gone { v, ok := rows[name] if !ok { t.Errorf("%s is not in the table, so a caller is not answered by name", name) continue } replacement, removed := RemovedControllerVerbs[name] if !removed || replacement == "" { t.Errorf("%s is not in the removed list with its replacement", name) } if !strings.HasPrefix(v.Description, "Removed in R6 (ADR 0539): refused by name") || !strings.Contains(v.Description, replacement) { t.Errorf("%s = %q, want refused by name, naming %q", name, v.Description, replacement) } if props, _ := v.Input["properties"].(map[string]any); len(props) > 0 { t.Errorf("%s still takes %v", name, props) } } props, _ := rows["upgrade"].Input["properties"].(map[string]any) for _, arg := range []string{"together", "backlog", "release-backlog", "cause"} { if _, has := props[arg]; has { t.Errorf("upgrade still takes %s, a plan's", arg) } } for _, arg := range []string{"module", "policy", "why"} { if _, has := props[arg]; !has { t.Errorf("upgrade no longer takes %s", arg) } } for _, word := range []string{"rolled", "gate", "backlog", "push"} { if strings.Contains(rows["upgrade"].Description, word) { t.Errorf("upgrade's description still speaks of %q: %q", word, rows["upgrade"].Description) } } if !strings.Contains(rows["bus"].Description, "want") { t.Errorf("bus does not say the operator writes the bus's want: %q", rows["bus"].Description) } for name := range RemovedControllerVerbs { if v := rows[name]; !strings.HasPrefix(v.Description, "Removed in R6") { t.Errorf("%s is in the removed list and its row says %q", name, v.Description) } } } // 1943/AC4: the delivery seat keeps the merge's verbs and no longer offers times, what-if, release, stop or // retire-history: each is a row with no input, optional so the holder of before and the holder of release 6 both hold // the seat, refusing it by name; mark-ready, served by nobody since issue 1022, is gone. func TestTheDeliverySeatHasNoPlanVerbs(t *testing.T) { seat, ok := SeatNamed(DeliverySeat) if !ok { t.Fatal("the delivery seat is not in the set") } rows := map[string]Verb{} for _, v := range seat.Serves { rows[v.Name] = v } for _, name := range []string{"times", "what-if", "release", "stop", "retire-history"} { v, ok := rows[name] replacement, removed := RemovedDeliveryVerbs[name] if !ok || !removed || replacement == "" { t.Errorf("%s: in the table %v, in the removed list %v", name, ok, removed) continue } if !strings.HasPrefix(v.Description, "Removed in R6 (ADR 0539): refused by name") || !strings.Contains(v.Description, replacement) || !v.Optional { t.Errorf("%s = %q (optional %v), want an optional row refusing it by name", name, v.Description, v.Optional) } if props, _ := v.Input["properties"].(map[string]any); len(props) > 0 { t.Errorf("%s still takes %v", name, props) } } if _, ok := rows["mark-ready"]; ok { t.Errorf("mark-ready is still promised") } for _, kept := range []string{"deliveries", "show", "groups", "checks", "table", "recheck", "close", "stalled", "settle"} { if v, ok := rows[kept]; !ok || strings.HasPrefix(v.Description, "Removed") { t.Errorf("%s is not kept (ADR 0539 clause 17)", kept) } } gate := Manifest{Module: "mesh-delivery", Claims: []Claim{{Name: DeliverySeat, Scope: ScopeMesh, Serves: []string{"deliveries", "show", "groups", "checks", "table", "stalled", "recheck", "close"}}}} if err := CanHold(gate, seat); err != nil { t.Errorf("the gate of release 6 cannot hold the seat: %v", err) } gate.Claims[0].Serves = append(gate.Claims[0].Serves, "times", "what-if", "release", "stop", "retire-history") if err := CanHold(gate, seat); err != nil { t.Errorf("the gate of release 5 cannot hold the seat: %v", err) } } // 1943 (for 1945/AC14): the controller's seat says a bucket it deleted at its first start as its event, bucket-deleted // (ADR 0539 clause 13). func TestTheControllerSaysABucketItDeleted(t *testing.T) { seat, ok := SeatNamed(ControllerSeatName) if !ok { t.Fatal("no controller seat") } if !SeatSays(seat.Emits, "bucket-deleted") { t.Errorf("the controller's seat does not emit bucket-deleted: %v", seat.Emits) } }