package botlink import ( "fmt" "net" "testing" "time" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" botlinkv1 "scrabble/pkg/proto/botlink/v1" telegramv1 "scrabble/pkg/proto/telegram/v1" ) // testLinkServer registers one bot, pushes a single Notify command, and records the // Ack the client returns. type testLinkServer struct { botlinkv1.UnimplementedBotLinkServer acks chan *botlinkv1.Ack } func (s *testLinkServer) Link(stream grpc.BidiStreamingServer[botlinkv1.FromBot, botlinkv1.ToBot]) error { hello, err := stream.Recv() if err != nil { return err } if hello.GetHello() == nil { return fmt.Errorf("first message was not Hello") } if err := stream.Send(&botlinkv1.ToBot{Command: &botlinkv1.Command{ CommandId: "c1", Payload: &botlinkv1.Command_Notify{Notify: &telegramv1.NotifyRequest{ ExternalId: "12345", Kind: "your_turn", Payload: yourTurnPayload("7c9e6679-7425-40de-944b-e07fc1f90ae7"), Language: "en", }}, }}); err != nil { return err } for { msg, err := stream.Recv() if err != nil { return err } if ack := msg.GetAck(); ack != nil { s.acks <- ack return nil } } } // TestClientServesCommands verifies the bot client dials, registers, executes a // pushed command through the executor, and acks it. func TestClientServesCommands(t *testing.T) { lis, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatalf("listen: %v", err) } ts := &testLinkServer{acks: make(chan *botlinkv1.Ack, 1)} srv := grpc.NewServer() botlinkv1.RegisterBotLinkServer(srv, ts) go func() { _ = srv.Serve(lis) }() t.Cleanup(srv.Stop) sender := &fakeSender{} client := NewClient(ClientConfig{ GatewayAddr: lis.Addr().String(), InstanceID: "test", Creds: insecure.NewCredentials(), ReconnectDelay: 50 * time.Millisecond, }, NewExecutor(sender, 0, nil), nil) go func() { _ = client.Run(t.Context()) }() select { case ack := <-ts.acks: if ack.GetCommandId() != "c1" || !ack.GetDelivered() { t.Errorf("ack = %+v, want command_id c1 delivered=true", ack) } case <-time.After(2 * time.Second): t.Fatal("server received no ack") } // The channel receive above happens-after the client wrote the sender call. if len(sender.notify) != 1 || sender.notify[0].chatID != 12345 { t.Errorf("sender notify calls = %+v, want one call to chat 12345", sender.notify) } }