package link import ( "fmt" "os" "strings" "testing" "time" "github.com/nats-io/nats.go" ) // **A reader's own consumer gone is not a consumer lost**: every bucket watch and stream read-back // makes and deletes one, many a minute, and the bus says so each time (found running the controller // against a real bus: five a tick). func TestOnlyTheMeshsOwnConsumersAreSaidLost(t *testing.T) { deleted := func(stream, consumer string) bool { _, ok := ReadAdvisory("$JS.EVENT.ADVISORY.CONSUMER.DELETED."+stream+"."+consumer, []byte(`{"type":"io.nats.jetstream.advisory.v1.consumer_action","stream":"`+stream+`","consumer":"`+consumer+`","action":"delete"}`)) return ok } for _, c := range [][2]string{{"EVENTS", "controller"}, {"CONTROL", "controller"}, {"NODES", "anchor"}, {"EVENTS", "anchor_shop"}, {"SEAT_NODE_BUILD_AGENT", "SEAT_NODE_BUILD_AGENT_worker"}} { if !deleted(c[0], c[1]) { t.Errorf("%s on %s deleted is not said", c[1], c[0]) } } for _, c := range [][2]string{{"KV_mesh-controller_conditions", "381UWW5Y"}, {"EVENTS", "E7vVYoe6"}, {"SEAT_NODE_BUILD_AGENT", "Rcnt6jla"}, {"ASSIGNMENTS", "x"}} { if deleted(c[0], c[1]) { t.Errorf("a reader's own consumer %s on %s is said lost", c[1], c[0]) } } a, ok := ReadAdvisory("$JS.EVENT.ADVISORY.CONSUMER.MAX_DELIVERIES.EVENTS.anchor_shop", []byte(`{"stream":"EVENTS","consumer":"anchor_shop","stream_seq":7,"deliveries":5}`)) if !ok || a.Kind != AdvisoryMaxDeliveries || a.ID != "EVENTS.anchor_shop" || a.Said != "how shop on anchor hears what it consumes handed message 7 over 5 times and gave up on it: "+ "it will not be delivered again, and what it asked for was not done" { t.Fatalf("%+v", a) } } // **A question the bus refuses is answered as refused at once**, not after its timeout: against a // server whose only user may not publish where it asks. func TestNatsARefusedQuestionIsSaidAtOnce(t *testing.T) { url := os.Getenv("MESH_TEST_NATS_REFUSING") if url == "" { t.Skip("MESH_TEST_NATS_REFUSING unset: a server whose user may not publish mesh.seat.>") } conn, err := nats.Connect(url) if err != nil { t.Fatal(err) } defer conn.Close() started := time.Now() _, err = AskSeatTool(t.Context(), conn, "node-intrusion-prevention", "banned", "anchor", map[string]any{}, 10*time.Second) if err == nil || !strings.Contains(err.Error(), "the bus refused") { t.Fatalf("answered %v", err) } if took := time.Since(started); took > 3*time.Second { t.Fatalf("a refusal took %s to be known", took) } } // The refusal reaches whoever waits on that subject, and only them. func TestNatsARefusalReachesItsWaiter(t *testing.T) { url := os.Getenv("MESH_TEST_NATS") if url == "" { t.Skip("MESH_TEST_NATS unset") } conn, err := nats.Connect(url) if err != nil { t.Fatal(err) } defer conn.Close() mine, stop := refusalsOf(conn, "mesh.seat.s.tool.v.anchor") defer stop() other, stopOther := refusalsOf(conn, "mesh.seat.s.tool.v.laptop") defer stopOther() conn.ErrorHandler()(conn, nil, fmt.Errorf("%w: Permissions Violation for Publish to %q", nats.ErrPermissionViolation, "mesh.seat.s.tool.v.anchor")) select { case <-mine: case <-time.After(time.Second): t.Fatal("the waiter was not told") } select { case <-other: t.Fatal("another subject's waiter was told") default: } }