package bus_test import ( "encoding/json" "strings" "sync/atomic" "testing" "time" "github.com/nats-io/nats.go" "github.com/novox/mesh-tools/node-tools/internal/bus" "github.com/novox/mesh-tools/node-tools/internal/meshtest" ) // **A call the controller refused because it is handing over is asked once more** (novox/hq issue 289): // the controller being replaced did nothing and marked its refusal, and the one after it answers. A // refusal not so marked is final, and a second handover refusal is said, not asked a third time. func TestAHandoverRefusalIsAskedOnceMore(t *testing.T) { was := bus.HandoverPause bus.HandoverPause = 10 * time.Millisecond t.Cleanup(func() { bus.HandoverPause = was }) url := meshtest.URL(t) seat, err := nats.Connect(url) if err != nil { t.Fatal(err) } defer seat.Close() c, err := bus.Connect(bus.Credential{URL: url, Module: "console", Node: "anchor"}) if err != nil { t.Fatal(err) } defer c.Close() serve := func(t *testing.T, verb string, answers ...map[string]any) *atomic.Int32 { t.Helper() var asked atomic.Int32 sub, err := seat.Subscribe(bus.SeatToolSubject("mesh-controller", verb, "", ""), func(m *nats.Msg) { n := int(asked.Add(1)) - 1 if n >= len(answers) { n = len(answers) - 1 } body, _ := json.Marshal(answers[n]) _ = m.Respond(body) }) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = sub.Unsubscribe() }) _ = seat.Flush() return &asked } handingOver := map[string]any{"error": "the controller is handing over to the next one; nothing was done, ask again", "retry": bus.RetryHandingOver} asked := serve(t, "rotate", handingOver, map[string]any{"result": "rotated"}) got, err := c.Ask("seat:mesh-controller.rotate", map[string]any{}, "") if err != nil || string(got.Result) != `"rotated"` || asked.Load() != 2 { t.Fatalf("after a handover refusal: %s %v, asked %d times", got.Result, err, asked.Load()) } asked = serve(t, "push", map[string]any{"error": "refused for its own reason"}) if _, err := c.Ask("seat:mesh-controller.push", map[string]any{}, ""); err == nil || asked.Load() != 1 { t.Fatalf("an unmarked refusal was asked again: %v, asked %d times", err, asked.Load()) } asked = serve(t, "status", handingOver) _, err = c.Ask("seat:mesh-controller.status", map[string]any{}, "") if err == nil || asked.Load() != 2 || !strings.Contains(err.Error(), "both times refused as a handover") { t.Fatalf("two handover refusals: %v, asked %d times", err, asked.Load()) } }