123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "remoting/signaling/ftl_messaging_client.h"
- #include <algorithm>
- #include <memory>
- #include <string>
- #include <utility>
- #include <vector>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/check.h"
- #include "base/memory/raw_ptr.h"
- #include "base/notreached.h"
- #include "base/run_loop.h"
- #include "base/task/thread_pool.h"
- #include "base/test/bind.h"
- #include "base/test/mock_callback.h"
- #include "base/test/task_environment.h"
- #include "remoting/base/fake_oauth_token_getter.h"
- #include "remoting/base/protobuf_http_client.h"
- #include "remoting/base/protobuf_http_status.h"
- #include "remoting/base/protobuf_http_test_responder.h"
- #include "remoting/base/scoped_protobuf_http_request.h"
- #include "remoting/proto/ftl/v1/ftl_messages.pb.h"
- #include "remoting/signaling/ftl_services_context.h"
- #include "remoting/signaling/message_reception_channel.h"
- #include "remoting/signaling/registration_manager.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace remoting {
- namespace {
- using ::testing::_;
- using ::testing::Invoke;
- using ::testing::Property;
- using ::testing::Return;
- using ::testing::Truly;
- constexpr char kFakeServerEndpoint[] = "test.com";
- constexpr char kFakeSenderId[] = "fake_sender@gmail.com";
- constexpr char kFakeSenderRegId[] = "fake_sender_reg_id";
- constexpr char kFakeReceiverId[] = "fake_receiver@gmail.com";
- constexpr char kMessage1Id[] = "msg_1";
- constexpr char kMessage2Id[] = "msg_2";
- constexpr char kMessage1Text[] = "Message 1";
- constexpr char kMessage2Text[] = "Message 2";
- MATCHER(IsFakeSenderId, "") {
- return arg.id() == kFakeSenderId;
- }
- ftl::ChromotingMessage CreateXmppMessage(const std::string& message_text) {
- ftl::ChromotingMessage crd_message;
- crd_message.mutable_xmpp()->set_stanza(message_text);
- return crd_message;
- }
- ftl::InboxMessage CreateInboxMessage(const std::string& message_id,
- const std::string& message_text) {
- ftl::InboxMessage message;
- message.mutable_sender_id()->set_id(kFakeSenderId);
- message.mutable_receiver_id()->set_id(kFakeReceiverId);
- message.set_sender_registration_id(kFakeSenderRegId);
- message.set_message_type(ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE);
- message.set_message_id(message_id);
- ftl::ChromotingMessage crd_message = CreateXmppMessage(message_text);
- std::string serialized_message;
- bool succeeded = crd_message.SerializeToString(&serialized_message);
- EXPECT_TRUE(succeeded);
- message.set_message(serialized_message);
- return message;
- }
- base::OnceCallback<void(const ProtobufHttpStatus&)>
- CheckStatusThenQuitRunLoopCallback(
- const base::Location& from_here,
- ProtobufHttpStatus::Code expected_status_code,
- base::RunLoop* run_loop) {
- return base::BindLambdaForTesting([=](const ProtobufHttpStatus& status) {
- ASSERT_EQ(expected_status_code, status.error_code())
- << "Incorrect status code. Location: " << from_here.ToString();
- run_loop->QuitWhenIdle();
- });
- }
- std::string GetChromotingMessageText(const ftl::InboxMessage& message) {
- EXPECT_EQ(ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE,
- message.message_type());
- ftl::ChromotingMessage chromoting_message;
- chromoting_message.ParseFromString(message.message());
- return chromoting_message.xmpp().stanza();
- }
- class MockMessageReceptionChannel : public MessageReceptionChannel {
- public:
- MockMessageReceptionChannel() = default;
- MockMessageReceptionChannel(const MockMessageReceptionChannel&) = delete;
- MockMessageReceptionChannel& operator=(const MockMessageReceptionChannel&) =
- delete;
- ~MockMessageReceptionChannel() override = default;
- // MessageReceptionChannel implementations.
- void Initialize(const StreamOpener& stream_opener,
- const MessageCallback& on_incoming_msg) override {
- stream_opener_ = stream_opener;
- on_incoming_msg_ = on_incoming_msg;
- }
- MOCK_METHOD2(StartReceivingMessages, void(base::OnceClosure, DoneCallback));
- MOCK_METHOD0(StopReceivingMessages, void());
- MOCK_CONST_METHOD0(IsReceivingMessages, bool());
- StreamOpener* stream_opener() { return &stream_opener_; }
- MessageCallback* on_incoming_msg() { return &on_incoming_msg_; }
- private:
- StreamOpener stream_opener_;
- MessageCallback on_incoming_msg_;
- };
- class MockRegistrationManager : public RegistrationManager {
- public:
- MockRegistrationManager() = default;
- ~MockRegistrationManager() override = default;
- MOCK_METHOD1(SignInGaia, void(DoneCallback));
- MOCK_METHOD0(SignOut, void());
- MOCK_CONST_METHOD0(IsSignedIn, bool());
- MOCK_CONST_METHOD0(GetRegistrationId, std::string());
- MOCK_CONST_METHOD0(GetFtlAuthToken, std::string());
- };
- decltype(auto) StanzaTextMatches(const std::string& expected_stanza) {
- return Truly([=](const ftl::ChromotingMessage& message) {
- return expected_stanza == message.xmpp().stanza();
- });
- }
- } // namespace
- class FtlMessagingClientTest : public testing::Test {
- public:
- void SetUp() override;
- void TearDown() override;
- protected:
- ProtobufHttpTestResponder test_responder_;
- FakeOAuthTokenGetter token_getter_{OAuthTokenGetter::Status::SUCCESS, "", ""};
- std::unique_ptr<FtlMessagingClient> messaging_client_;
- raw_ptr<MockMessageReceptionChannel> mock_message_reception_channel_;
- private:
- base::test::TaskEnvironment task_environment_;
- MockRegistrationManager mock_registration_manager_;
- };
- void FtlMessagingClientTest::SetUp() {
- EXPECT_CALL(mock_registration_manager_, GetFtlAuthToken())
- .WillRepeatedly(Return("fake_auth_token"));
- auto channel = std::make_unique<MockMessageReceptionChannel>();
- mock_message_reception_channel_ = channel.get();
- messaging_client_ = std::unique_ptr<FtlMessagingClient>(
- new FtlMessagingClient(std::make_unique<ProtobufHttpClient>(
- kFakeServerEndpoint, &token_getter_,
- test_responder_.GetUrlLoaderFactory()),
- &mock_registration_manager_, std::move(channel)));
- }
- void FtlMessagingClientTest::TearDown() {
- messaging_client_.reset();
- }
- TEST_F(FtlMessagingClientTest, TestSendMessage_Unauthenticated) {
- base::RunLoop run_loop;
- messaging_client_->SendMessage(
- kFakeReceiverId, kFakeSenderRegId, CreateXmppMessage(kMessage1Text),
- CheckStatusThenQuitRunLoopCallback(
- FROM_HERE, ProtobufHttpStatus::Code::UNAUTHENTICATED, &run_loop));
- test_responder_.AddErrorToMostRecentRequestUrl(ProtobufHttpStatus(
- ProtobufHttpStatus::Code::UNAUTHENTICATED, "Unauthenticated"));
- run_loop.Run();
- }
- TEST_F(FtlMessagingClientTest, TestSendMessage_SendOneMessageWithoutRegId) {
- base::RunLoop run_loop;
- messaging_client_->SendMessage(
- kFakeReceiverId, "", CreateXmppMessage(kMessage1Text),
- CheckStatusThenQuitRunLoopCallback(
- FROM_HERE, ProtobufHttpStatus::Code::OK, &run_loop));
- ftl::InboxSendRequest request;
- ASSERT_TRUE(test_responder_.GetMostRecentRequestMessage(&request));
- EXPECT_EQ(0, request.dest_registration_ids_size());
- EXPECT_LT(0, request.time_to_live());
- EXPECT_EQ(kFakeReceiverId, request.dest_id().id());
- EXPECT_FALSE(request.message().message_id().empty());
- EXPECT_EQ(kMessage1Text, GetChromotingMessageText(request.message()));
- test_responder_.AddResponseToMostRecentRequestUrl(ftl::InboxSendResponse());
- run_loop.Run();
- }
- TEST_F(FtlMessagingClientTest, TestSendMessage_SendOneMessageWithRegId) {
- base::RunLoop run_loop;
- messaging_client_->SendMessage(
- kFakeReceiverId, kFakeSenderRegId, CreateXmppMessage(kMessage1Text),
- CheckStatusThenQuitRunLoopCallback(
- FROM_HERE, ProtobufHttpStatus::Code::OK, &run_loop));
- ftl::InboxSendRequest request;
- ASSERT_TRUE(test_responder_.GetMostRecentRequestMessage(&request));
- EXPECT_EQ(1, request.dest_registration_ids_size());
- EXPECT_EQ(kFakeSenderRegId, request.dest_registration_ids(0));
- EXPECT_LT(0, request.time_to_live());
- EXPECT_EQ(kFakeReceiverId, request.dest_id().id());
- EXPECT_FALSE(request.message().message_id().empty());
- EXPECT_EQ(kMessage1Text, GetChromotingMessageText(request.message()));
- test_responder_.AddResponseToMostRecentRequestUrl(ftl::InboxSendResponse());
- run_loop.Run();
- }
- TEST_F(FtlMessagingClientTest, TestStartReceivingMessages_CallbacksForwarded) {
- base::RunLoop run_loop;
- EXPECT_CALL(*mock_message_reception_channel_, StartReceivingMessages(_, _))
- .WillOnce(Invoke([&](base::OnceClosure on_ready,
- FtlMessagingClient::DoneCallback on_closed) {
- std::move(on_ready).Run();
- std::move(on_closed).Run(
- ProtobufHttpStatus(ProtobufHttpStatus::Code::UNAUTHENTICATED, ""));
- }));
- base::MockCallback<base::OnceClosure> mock_on_ready_closure;
- EXPECT_CALL(mock_on_ready_closure, Run()).WillOnce(Return());
- messaging_client_->StartReceivingMessages(
- mock_on_ready_closure.Get(),
- base::BindLambdaForTesting([&](const ProtobufHttpStatus& status) {
- ASSERT_EQ(ProtobufHttpStatus::Code::UNAUTHENTICATED,
- status.error_code());
- run_loop.Quit();
- }));
- run_loop.Run();
- }
- TEST_F(FtlMessagingClientTest, TestStopReceivingMessages_CallForwarded) {
- EXPECT_CALL(*mock_message_reception_channel_, StopReceivingMessages())
- .WillOnce(Return());
- messaging_client_->StopReceivingMessages();
- }
- TEST_F(FtlMessagingClientTest,
- TestStreamOpener_StreamsTwoMessagesThenCloseByServer) {
- base::RunLoop run_loop;
- std::unique_ptr<ScopedProtobufHttpRequest> scoped_stream;
- ftl::ReceiveMessagesResponse response_1;
- response_1.mutable_inbox_message()->set_message_id(kMessage1Id);
- ftl::ReceiveMessagesResponse response_2;
- response_2.mutable_pong();
- base::MockCallback<base::RepeatingCallback<void(
- std::unique_ptr<ftl::ReceiveMessagesResponse>)>>
- mock_on_incoming_msg;
- EXPECT_CALL(mock_on_incoming_msg, Run(_))
- .WillOnce([&](std::unique_ptr<ftl::ReceiveMessagesResponse> response) {
- ASSERT_EQ(kMessage1Id, response->inbox_message().message_id());
- })
- .WillOnce([&](std::unique_ptr<ftl::ReceiveMessagesResponse> response) {
- ASSERT_TRUE(response->has_pong());
- });
- base::MockCallback<base::OnceClosure> on_channel_ready;
- EXPECT_CALL(on_channel_ready, Run()).Times(1);
- scoped_stream = mock_message_reception_channel_->stream_opener()->Run(
- on_channel_ready.Get(), mock_on_incoming_msg.Get(),
- CheckStatusThenQuitRunLoopCallback(
- FROM_HERE, ProtobufHttpStatus::Code::OK, &run_loop));
- test_responder_.AddStreamResponseToMostRecentRequestUrl(
- {&response_1, &response_2}, ProtobufHttpStatus::OK());
- run_loop.Run();
- }
- TEST_F(FtlMessagingClientTest,
- TestOnMessageReceived_MessagePassedToSubscriberAndAcked) {
- base::RunLoop run_loop;
- base::MockCallback<FtlMessagingClient::MessageCallback> mock_on_incoming_msg;
- EXPECT_CALL(mock_on_incoming_msg, Run(IsFakeSenderId(), kFakeSenderRegId,
- StanzaTextMatches(kMessage1Text)))
- .WillOnce([&](const ftl::Id&, const std::string&,
- const ftl::ChromotingMessage&) { run_loop.Quit(); });
- auto subscription =
- messaging_client_->RegisterMessageCallback(mock_on_incoming_msg.Get());
- ftl::InboxMessage message = CreateInboxMessage(kMessage1Id, kMessage1Text);
- mock_message_reception_channel_->on_incoming_msg()->Run(message);
- ftl::BatchAckMessagesRequest request;
- ASSERT_TRUE(test_responder_.GetMostRecentRequestMessage(&request));
- EXPECT_EQ(1, request.message_ids_size());
- EXPECT_EQ(kMessage1Id, request.message_ids(0));
- test_responder_.AddResponseToMostRecentRequestUrl(
- ftl::BatchAckMessagesResponse());
- run_loop.Run();
- }
- TEST_F(FtlMessagingClientTest, ReceivedDuplicatedMessage_AckAndDrop) {
- base::RunLoop run_loop;
- base::MockCallback<FtlMessagingClient::MessageCallback> mock_on_incoming_msg;
- EXPECT_CALL(mock_on_incoming_msg, Run(IsFakeSenderId(), kFakeSenderRegId, _))
- .WillOnce([](const ftl::Id&, const std::string&,
- const ftl::ChromotingMessage& message) {
- EXPECT_EQ(kMessage1Text, message.xmpp().stanza());
- })
- .WillOnce([](const ftl::Id&, const std::string&,
- const ftl::ChromotingMessage& message) {
- EXPECT_EQ(kMessage2Text, message.xmpp().stanza());
- });
- EXPECT_CALL(test_responder_.GetMockInterceptor(), Run(_))
- .WillOnce([](const network::ResourceRequest& request) {
- ftl::BatchAckMessagesRequest message;
- ProtobufHttpTestResponder::ParseRequestMessage(request, &message);
- EXPECT_EQ(1, message.message_ids_size());
- EXPECT_EQ(kMessage1Id, message.message_ids(0));
- })
- .WillOnce([](const network::ResourceRequest& request) {
- ftl::BatchAckMessagesRequest message;
- ProtobufHttpTestResponder::ParseRequestMessage(request, &message);
- EXPECT_EQ(1, message.message_ids_size());
- EXPECT_EQ(kMessage1Id, message.message_ids(0));
- })
- .WillOnce([&](const network::ResourceRequest& request) {
- ftl::BatchAckMessagesRequest message;
- ProtobufHttpTestResponder::ParseRequestMessage(request, &message);
- EXPECT_EQ(1, message.message_ids_size());
- EXPECT_EQ(kMessage2Id, message.message_ids(0));
- run_loop.Quit();
- });
- auto subscription =
- messaging_client_->RegisterMessageCallback(mock_on_incoming_msg.Get());
- ftl::InboxMessage message_1 = CreateInboxMessage(kMessage1Id, kMessage1Text);
- mock_message_reception_channel_->on_incoming_msg()->Run(message_1);
- ftl::InboxMessage message_2 = CreateInboxMessage(kMessage1Id, kMessage1Text);
- mock_message_reception_channel_->on_incoming_msg()->Run(message_2);
- ftl::InboxMessage message_3 = CreateInboxMessage(kMessage2Id, kMessage2Text);
- mock_message_reception_channel_->on_incoming_msg()->Run(message_3);
- run_loop.Run();
- }
- } // namespace remoting
|