//go:build integration package main import ( "context" "encoding/json" "strings" "testing" "github.com/nats-io/nats.go" "github.com/novox/mesh-controller/internal/broker" "github.com/novox/mesh-controller/internal/link" "github.com/novox/mesh-controller/internal/testbus" ) func TestTheServingControllerLendsItsOwnConnection(t *testing.T) { bus := testbus.Start(t) serving, err := broker.Dial(bus.ClientURL()) if err != nil { t.Fatal(err) } defer serving.Close() if err := serving.EnsureControllerBuckets(); err != nil { t.Fatal(err) } was := servingBus.Load() servingBus.Store(serving) defer servingBus.Store(was) t.Setenv(broker.NATSVar, bus.ClientURL()) before, _ := bus.Varz(nil) lent, err := aBus() if err != nil { t.Fatal(err) } lent.Close() if !serving.Conn().IsConnected() { t.Fatal("closing a lent connection closed the serving controller's") } if err := onTheBus(func(*nats.Conn) error { return nil }); err != nil { t.Fatal(err) } handlers, _, err := seatToolHandlers() if err != nil { t.Fatal(err) } answer, err := handlers["hand-acts"](context.Background(), json.RawMessage(`{}`)) if err != nil { t.Fatal(err) } if a := answer.(verbAnswer); !a.OK || a.Answer == nil { t.Fatalf("hand-acts answered %+v", a) } _, _ = handlers["queue"](context.Background(), json.RawMessage(`{}`)) after, _ := bus.Varz(nil) if opened := after.TotalConnections - before.TotalConnections; opened != 0 { t.Fatalf("the serving controller opened %d connection(s) of its own", opened) } } func TestAVerbsOwnProcessNamesItsConnection(t *testing.T) { bus := testbus.Start(t) setup, err := broker.Dial(bus.ClientURL()) if err != nil { t.Fatal(err) } if err := setup.EnsureControllerBuckets(); err != nil { t.Fatal(err) } setup.Close() asAProcess(t, bus.ClientURL()) handlers, _, err := seatToolHandlers() if err != nil { t.Fatal(err) } // A silence acts, so it is still its own process; it dials, and finds no such condition. _, _ = handlers["conditions"](context.Background(), json.RawMessage(`{"silence":"bus.nothing.here","for":"1h","why":"a test"}`)) names := closedNames(t, bus, "mesh-controller verb conditions") found := false for _, n := range names { found = found || n == "mesh-controller verb conditions" } if !found { t.Fatalf("the verb's connection was named %q", names) } } func TestTheBusModuleIsAskedWhoClosedConnections(t *testing.T) { bus := testbus.Start(t) conn, err := nats.Connect(bus.ClientURL()) if err != nil { t.Fatal(err) } defer conn.Close() sub, err := conn.Subscribe(link.ModuleToolOn("nats", "nats_closed_connections", "anchor"), func(m *nats.Msg) { _ = m.Respond([]byte(`{"result":{"hours":1,"reaches":true,"users":[{"user":"controller","closed":2,"dropped":0}]}}`)) }) if err != nil { t.Fatal(err) } defer func() { _ = sub.Unsubscribe() }() read, err := askClosed(context.Background(), conn, "anchor") if err != nil { t.Fatal(err) } if len(read.Users) != 1 || read.Users[0].Closed != 2 { t.Fatalf("%+v", read) } } func TestAnOlderBusModuleIsPassedOverQuietly(t *testing.T) { bus := testbus.Start(t) conn, err := nats.Connect(bus.ClientURL()) if err != nil { t.Fatal(err) } defer conn.Close() found, err := reconnectsOn(context.Background(), conn, "anchor") if err != nil || len(found) != 0 { t.Fatalf("a bus module without the tool: %v %v", found, err) } } func TestAFlagErrorIsSaidInTheAnswer(t *testing.T) { bus := testbus.Start(t) serving, err := broker.Dial(bus.ClientURL()) if err != nil { t.Fatal(err) } defer serving.Close() was := servingBus.Load() servingBus.Store(serving) defer servingBus.Store(was) answer, read := readHere(context.Background(), []string{"hand-acts", "--bogus"}) if !read || answer.OK || !strings.Contains(answer.Output, "flag provided but not defined") { t.Fatalf("answered %+v", answer) } }