ftl_messaging_client_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "remoting/signaling/ftl_messaging_client.h"
  5. #include <algorithm>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/bind.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/check.h"
  13. #include "base/memory/raw_ptr.h"
  14. #include "base/notreached.h"
  15. #include "base/run_loop.h"
  16. #include "base/task/thread_pool.h"
  17. #include "base/test/bind.h"
  18. #include "base/test/mock_callback.h"
  19. #include "base/test/task_environment.h"
  20. #include "remoting/base/fake_oauth_token_getter.h"
  21. #include "remoting/base/protobuf_http_client.h"
  22. #include "remoting/base/protobuf_http_status.h"
  23. #include "remoting/base/protobuf_http_test_responder.h"
  24. #include "remoting/base/scoped_protobuf_http_request.h"
  25. #include "remoting/proto/ftl/v1/ftl_messages.pb.h"
  26. #include "remoting/signaling/ftl_services_context.h"
  27. #include "remoting/signaling/message_reception_channel.h"
  28. #include "remoting/signaling/registration_manager.h"
  29. #include "testing/gmock/include/gmock/gmock.h"
  30. #include "testing/gtest/include/gtest/gtest.h"
  31. namespace remoting {
  32. namespace {
  33. using ::testing::_;
  34. using ::testing::Invoke;
  35. using ::testing::Property;
  36. using ::testing::Return;
  37. using ::testing::Truly;
  38. constexpr char kFakeServerEndpoint[] = "test.com";
  39. constexpr char kFakeSenderId[] = "fake_sender@gmail.com";
  40. constexpr char kFakeSenderRegId[] = "fake_sender_reg_id";
  41. constexpr char kFakeReceiverId[] = "fake_receiver@gmail.com";
  42. constexpr char kMessage1Id[] = "msg_1";
  43. constexpr char kMessage2Id[] = "msg_2";
  44. constexpr char kMessage1Text[] = "Message 1";
  45. constexpr char kMessage2Text[] = "Message 2";
  46. MATCHER(IsFakeSenderId, "") {
  47. return arg.id() == kFakeSenderId;
  48. }
  49. ftl::ChromotingMessage CreateXmppMessage(const std::string& message_text) {
  50. ftl::ChromotingMessage crd_message;
  51. crd_message.mutable_xmpp()->set_stanza(message_text);
  52. return crd_message;
  53. }
  54. ftl::InboxMessage CreateInboxMessage(const std::string& message_id,
  55. const std::string& message_text) {
  56. ftl::InboxMessage message;
  57. message.mutable_sender_id()->set_id(kFakeSenderId);
  58. message.mutable_receiver_id()->set_id(kFakeReceiverId);
  59. message.set_sender_registration_id(kFakeSenderRegId);
  60. message.set_message_type(ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE);
  61. message.set_message_id(message_id);
  62. ftl::ChromotingMessage crd_message = CreateXmppMessage(message_text);
  63. std::string serialized_message;
  64. bool succeeded = crd_message.SerializeToString(&serialized_message);
  65. EXPECT_TRUE(succeeded);
  66. message.set_message(serialized_message);
  67. return message;
  68. }
  69. base::OnceCallback<void(const ProtobufHttpStatus&)>
  70. CheckStatusThenQuitRunLoopCallback(
  71. const base::Location& from_here,
  72. ProtobufHttpStatus::Code expected_status_code,
  73. base::RunLoop* run_loop) {
  74. return base::BindLambdaForTesting([=](const ProtobufHttpStatus& status) {
  75. ASSERT_EQ(expected_status_code, status.error_code())
  76. << "Incorrect status code. Location: " << from_here.ToString();
  77. run_loop->QuitWhenIdle();
  78. });
  79. }
  80. std::string GetChromotingMessageText(const ftl::InboxMessage& message) {
  81. EXPECT_EQ(ftl::InboxMessage_MessageType_CHROMOTING_MESSAGE,
  82. message.message_type());
  83. ftl::ChromotingMessage chromoting_message;
  84. chromoting_message.ParseFromString(message.message());
  85. return chromoting_message.xmpp().stanza();
  86. }
  87. class MockMessageReceptionChannel : public MessageReceptionChannel {
  88. public:
  89. MockMessageReceptionChannel() = default;
  90. MockMessageReceptionChannel(const MockMessageReceptionChannel&) = delete;
  91. MockMessageReceptionChannel& operator=(const MockMessageReceptionChannel&) =
  92. delete;
  93. ~MockMessageReceptionChannel() override = default;
  94. // MessageReceptionChannel implementations.
  95. void Initialize(const StreamOpener& stream_opener,
  96. const MessageCallback& on_incoming_msg) override {
  97. stream_opener_ = stream_opener;
  98. on_incoming_msg_ = on_incoming_msg;
  99. }
  100. MOCK_METHOD2(StartReceivingMessages, void(base::OnceClosure, DoneCallback));
  101. MOCK_METHOD0(StopReceivingMessages, void());
  102. MOCK_CONST_METHOD0(IsReceivingMessages, bool());
  103. StreamOpener* stream_opener() { return &stream_opener_; }
  104. MessageCallback* on_incoming_msg() { return &on_incoming_msg_; }
  105. private:
  106. StreamOpener stream_opener_;
  107. MessageCallback on_incoming_msg_;
  108. };
  109. class MockRegistrationManager : public RegistrationManager {
  110. public:
  111. MockRegistrationManager() = default;
  112. ~MockRegistrationManager() override = default;
  113. MOCK_METHOD1(SignInGaia, void(DoneCallback));
  114. MOCK_METHOD0(SignOut, void());
  115. MOCK_CONST_METHOD0(IsSignedIn, bool());
  116. MOCK_CONST_METHOD0(GetRegistrationId, std::string());
  117. MOCK_CONST_METHOD0(GetFtlAuthToken, std::string());
  118. };
  119. decltype(auto) StanzaTextMatches(const std::string& expected_stanza) {
  120. return Truly([=](const ftl::ChromotingMessage& message) {
  121. return expected_stanza == message.xmpp().stanza();
  122. });
  123. }
  124. } // namespace
  125. class FtlMessagingClientTest : public testing::Test {
  126. public:
  127. void SetUp() override;
  128. void TearDown() override;
  129. protected:
  130. ProtobufHttpTestResponder test_responder_;
  131. FakeOAuthTokenGetter token_getter_{OAuthTokenGetter::Status::SUCCESS, "", ""};
  132. std::unique_ptr<FtlMessagingClient> messaging_client_;
  133. raw_ptr<MockMessageReceptionChannel> mock_message_reception_channel_;
  134. private:
  135. base::test::TaskEnvironment task_environment_;
  136. MockRegistrationManager mock_registration_manager_;
  137. };
  138. void FtlMessagingClientTest::SetUp() {
  139. EXPECT_CALL(mock_registration_manager_, GetFtlAuthToken())
  140. .WillRepeatedly(Return("fake_auth_token"));
  141. auto channel = std::make_unique<MockMessageReceptionChannel>();
  142. mock_message_reception_channel_ = channel.get();
  143. messaging_client_ = std::unique_ptr<FtlMessagingClient>(
  144. new FtlMessagingClient(std::make_unique<ProtobufHttpClient>(
  145. kFakeServerEndpoint, &token_getter_,
  146. test_responder_.GetUrlLoaderFactory()),
  147. &mock_registration_manager_, std::move(channel)));
  148. }
  149. void FtlMessagingClientTest::TearDown() {
  150. messaging_client_.reset();
  151. }
  152. TEST_F(FtlMessagingClientTest, TestSendMessage_Unauthenticated) {
  153. base::RunLoop run_loop;
  154. messaging_client_->SendMessage(
  155. kFakeReceiverId, kFakeSenderRegId, CreateXmppMessage(kMessage1Text),
  156. CheckStatusThenQuitRunLoopCallback(
  157. FROM_HERE, ProtobufHttpStatus::Code::UNAUTHENTICATED, &run_loop));
  158. test_responder_.AddErrorToMostRecentRequestUrl(ProtobufHttpStatus(
  159. ProtobufHttpStatus::Code::UNAUTHENTICATED, "Unauthenticated"));
  160. run_loop.Run();
  161. }
  162. TEST_F(FtlMessagingClientTest, TestSendMessage_SendOneMessageWithoutRegId) {
  163. base::RunLoop run_loop;
  164. messaging_client_->SendMessage(
  165. kFakeReceiverId, "", CreateXmppMessage(kMessage1Text),
  166. CheckStatusThenQuitRunLoopCallback(
  167. FROM_HERE, ProtobufHttpStatus::Code::OK, &run_loop));
  168. ftl::InboxSendRequest request;
  169. ASSERT_TRUE(test_responder_.GetMostRecentRequestMessage(&request));
  170. EXPECT_EQ(0, request.dest_registration_ids_size());
  171. EXPECT_LT(0, request.time_to_live());
  172. EXPECT_EQ(kFakeReceiverId, request.dest_id().id());
  173. EXPECT_FALSE(request.message().message_id().empty());
  174. EXPECT_EQ(kMessage1Text, GetChromotingMessageText(request.message()));
  175. test_responder_.AddResponseToMostRecentRequestUrl(ftl::InboxSendResponse());
  176. run_loop.Run();
  177. }
  178. TEST_F(FtlMessagingClientTest, TestSendMessage_SendOneMessageWithRegId) {
  179. base::RunLoop run_loop;
  180. messaging_client_->SendMessage(
  181. kFakeReceiverId, kFakeSenderRegId, CreateXmppMessage(kMessage1Text),
  182. CheckStatusThenQuitRunLoopCallback(
  183. FROM_HERE, ProtobufHttpStatus::Code::OK, &run_loop));
  184. ftl::InboxSendRequest request;
  185. ASSERT_TRUE(test_responder_.GetMostRecentRequestMessage(&request));
  186. EXPECT_EQ(1, request.dest_registration_ids_size());
  187. EXPECT_EQ(kFakeSenderRegId, request.dest_registration_ids(0));
  188. EXPECT_LT(0, request.time_to_live());
  189. EXPECT_EQ(kFakeReceiverId, request.dest_id().id());
  190. EXPECT_FALSE(request.message().message_id().empty());
  191. EXPECT_EQ(kMessage1Text, GetChromotingMessageText(request.message()));
  192. test_responder_.AddResponseToMostRecentRequestUrl(ftl::InboxSendResponse());
  193. run_loop.Run();
  194. }
  195. TEST_F(FtlMessagingClientTest, TestStartReceivingMessages_CallbacksForwarded) {
  196. base::RunLoop run_loop;
  197. EXPECT_CALL(*mock_message_reception_channel_, StartReceivingMessages(_, _))
  198. .WillOnce(Invoke([&](base::OnceClosure on_ready,
  199. FtlMessagingClient::DoneCallback on_closed) {
  200. std::move(on_ready).Run();
  201. std::move(on_closed).Run(
  202. ProtobufHttpStatus(ProtobufHttpStatus::Code::UNAUTHENTICATED, ""));
  203. }));
  204. base::MockCallback<base::OnceClosure> mock_on_ready_closure;
  205. EXPECT_CALL(mock_on_ready_closure, Run()).WillOnce(Return());
  206. messaging_client_->StartReceivingMessages(
  207. mock_on_ready_closure.Get(),
  208. base::BindLambdaForTesting([&](const ProtobufHttpStatus& status) {
  209. ASSERT_EQ(ProtobufHttpStatus::Code::UNAUTHENTICATED,
  210. status.error_code());
  211. run_loop.Quit();
  212. }));
  213. run_loop.Run();
  214. }
  215. TEST_F(FtlMessagingClientTest, TestStopReceivingMessages_CallForwarded) {
  216. EXPECT_CALL(*mock_message_reception_channel_, StopReceivingMessages())
  217. .WillOnce(Return());
  218. messaging_client_->StopReceivingMessages();
  219. }
  220. TEST_F(FtlMessagingClientTest,
  221. TestStreamOpener_StreamsTwoMessagesThenCloseByServer) {
  222. base::RunLoop run_loop;
  223. std::unique_ptr<ScopedProtobufHttpRequest> scoped_stream;
  224. ftl::ReceiveMessagesResponse response_1;
  225. response_1.mutable_inbox_message()->set_message_id(kMessage1Id);
  226. ftl::ReceiveMessagesResponse response_2;
  227. response_2.mutable_pong();
  228. base::MockCallback<base::RepeatingCallback<void(
  229. std::unique_ptr<ftl::ReceiveMessagesResponse>)>>
  230. mock_on_incoming_msg;
  231. EXPECT_CALL(mock_on_incoming_msg, Run(_))
  232. .WillOnce([&](std::unique_ptr<ftl::ReceiveMessagesResponse> response) {
  233. ASSERT_EQ(kMessage1Id, response->inbox_message().message_id());
  234. })
  235. .WillOnce([&](std::unique_ptr<ftl::ReceiveMessagesResponse> response) {
  236. ASSERT_TRUE(response->has_pong());
  237. });
  238. base::MockCallback<base::OnceClosure> on_channel_ready;
  239. EXPECT_CALL(on_channel_ready, Run()).Times(1);
  240. scoped_stream = mock_message_reception_channel_->stream_opener()->Run(
  241. on_channel_ready.Get(), mock_on_incoming_msg.Get(),
  242. CheckStatusThenQuitRunLoopCallback(
  243. FROM_HERE, ProtobufHttpStatus::Code::OK, &run_loop));
  244. test_responder_.AddStreamResponseToMostRecentRequestUrl(
  245. {&response_1, &response_2}, ProtobufHttpStatus::OK());
  246. run_loop.Run();
  247. }
  248. TEST_F(FtlMessagingClientTest,
  249. TestOnMessageReceived_MessagePassedToSubscriberAndAcked) {
  250. base::RunLoop run_loop;
  251. base::MockCallback<FtlMessagingClient::MessageCallback> mock_on_incoming_msg;
  252. EXPECT_CALL(mock_on_incoming_msg, Run(IsFakeSenderId(), kFakeSenderRegId,
  253. StanzaTextMatches(kMessage1Text)))
  254. .WillOnce([&](const ftl::Id&, const std::string&,
  255. const ftl::ChromotingMessage&) { run_loop.Quit(); });
  256. auto subscription =
  257. messaging_client_->RegisterMessageCallback(mock_on_incoming_msg.Get());
  258. ftl::InboxMessage message = CreateInboxMessage(kMessage1Id, kMessage1Text);
  259. mock_message_reception_channel_->on_incoming_msg()->Run(message);
  260. ftl::BatchAckMessagesRequest request;
  261. ASSERT_TRUE(test_responder_.GetMostRecentRequestMessage(&request));
  262. EXPECT_EQ(1, request.message_ids_size());
  263. EXPECT_EQ(kMessage1Id, request.message_ids(0));
  264. test_responder_.AddResponseToMostRecentRequestUrl(
  265. ftl::BatchAckMessagesResponse());
  266. run_loop.Run();
  267. }
  268. TEST_F(FtlMessagingClientTest, ReceivedDuplicatedMessage_AckAndDrop) {
  269. base::RunLoop run_loop;
  270. base::MockCallback<FtlMessagingClient::MessageCallback> mock_on_incoming_msg;
  271. EXPECT_CALL(mock_on_incoming_msg, Run(IsFakeSenderId(), kFakeSenderRegId, _))
  272. .WillOnce([](const ftl::Id&, const std::string&,
  273. const ftl::ChromotingMessage& message) {
  274. EXPECT_EQ(kMessage1Text, message.xmpp().stanza());
  275. })
  276. .WillOnce([](const ftl::Id&, const std::string&,
  277. const ftl::ChromotingMessage& message) {
  278. EXPECT_EQ(kMessage2Text, message.xmpp().stanza());
  279. });
  280. EXPECT_CALL(test_responder_.GetMockInterceptor(), Run(_))
  281. .WillOnce([](const network::ResourceRequest& request) {
  282. ftl::BatchAckMessagesRequest message;
  283. ProtobufHttpTestResponder::ParseRequestMessage(request, &message);
  284. EXPECT_EQ(1, message.message_ids_size());
  285. EXPECT_EQ(kMessage1Id, message.message_ids(0));
  286. })
  287. .WillOnce([](const network::ResourceRequest& request) {
  288. ftl::BatchAckMessagesRequest message;
  289. ProtobufHttpTestResponder::ParseRequestMessage(request, &message);
  290. EXPECT_EQ(1, message.message_ids_size());
  291. EXPECT_EQ(kMessage1Id, message.message_ids(0));
  292. })
  293. .WillOnce([&](const network::ResourceRequest& request) {
  294. ftl::BatchAckMessagesRequest message;
  295. ProtobufHttpTestResponder::ParseRequestMessage(request, &message);
  296. EXPECT_EQ(1, message.message_ids_size());
  297. EXPECT_EQ(kMessage2Id, message.message_ids(0));
  298. run_loop.Quit();
  299. });
  300. auto subscription =
  301. messaging_client_->RegisterMessageCallback(mock_on_incoming_msg.Get());
  302. ftl::InboxMessage message_1 = CreateInboxMessage(kMessage1Id, kMessage1Text);
  303. mock_message_reception_channel_->on_incoming_msg()->Run(message_1);
  304. ftl::InboxMessage message_2 = CreateInboxMessage(kMessage1Id, kMessage1Text);
  305. mock_message_reception_channel_->on_incoming_msg()->Run(message_2);
  306. ftl::InboxMessage message_3 = CreateInboxMessage(kMessage2Id, kMessage2Text);
  307. mock_message_reception_channel_->on_incoming_msg()->Run(message_3);
  308. run_loop.Run();
  309. }
  310. } // namespace remoting