| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "google_apis/gcm/engine/mcs_client.h" | 5 #include "google_apis/gcm/engine/mcs_client.h" |
| 6 | 6 |
| 7 #include "base/files/scoped_temp_dir.h" | 7 #include "base/files/scoped_temp_dir.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/test/simple_test_clock.h" |
| 11 #include "components/webdata/encryptor/encryptor.h" | 12 #include "components/webdata/encryptor/encryptor.h" |
| 12 #include "google_apis/gcm/base/mcs_util.h" | 13 #include "google_apis/gcm/base/mcs_util.h" |
| 13 #include "google_apis/gcm/engine/fake_connection_factory.h" | 14 #include "google_apis/gcm/engine/fake_connection_factory.h" |
| 14 #include "google_apis/gcm/engine/fake_connection_handler.h" | 15 #include "google_apis/gcm/engine/fake_connection_handler.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 17 |
| 17 namespace gcm { | 18 namespace gcm { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 const uint64 kAndroidId = 54321; | 22 const uint64 kAndroidId = 54321; |
| 22 const uint64 kSecurityToken = 12345; | 23 const uint64 kSecurityToken = 12345; |
| 23 | 24 |
| 24 // Number of messages to send when testing batching. | 25 // Number of messages to send when testing batching. |
| 25 // Note: must be even for tests that split batches in half. | 26 // Note: must be even for tests that split batches in half. |
| 26 const int kMessageBatchSize = 6; | 27 const int kMessageBatchSize = 6; |
| 27 | 28 |
| 28 // The number of unacked messages the client will receive before sending a | 29 // The number of unacked messages the client will receive before sending a |
| 29 // stream ack. | 30 // stream ack. |
| 30 // TODO(zea): get this (and other constants) directly from the mcs client. | 31 // TODO(zea): get this (and other constants) directly from the mcs client. |
| 31 const int kAckLimitSize = 10; | 32 const int kAckLimitSize = 10; |
| 32 | 33 |
| 34 // TTL value for reliable messages. |
| 35 const int kTTLValue = 5 * 60; // 5 minutes. |
| 36 |
| 33 // Helper for building arbitrary data messages. | 37 // Helper for building arbitrary data messages. |
| 34 MCSMessage BuildDataMessage(const std::string& from, | 38 MCSMessage BuildDataMessage(const std::string& from, |
| 35 const std::string& category, | 39 const std::string& category, |
| 36 int last_stream_id_received, | 40 int last_stream_id_received, |
| 37 const std::string persistent_id) { | 41 const std::string persistent_id, |
| 42 int ttl, |
| 43 uint64 sent) { |
| 38 mcs_proto::DataMessageStanza data_message; | 44 mcs_proto::DataMessageStanza data_message; |
| 39 data_message.set_from(from); | 45 data_message.set_from(from); |
| 40 data_message.set_category(category); | 46 data_message.set_category(category); |
| 41 data_message.set_last_stream_id_received(last_stream_id_received); | 47 data_message.set_last_stream_id_received(last_stream_id_received); |
| 42 if (!persistent_id.empty()) | 48 if (!persistent_id.empty()) |
| 43 data_message.set_persistent_id(persistent_id); | 49 data_message.set_persistent_id(persistent_id); |
| 50 data_message.set_ttl(ttl); |
| 51 data_message.set_sent(sent); |
| 44 return MCSMessage(kDataMessageStanzaTag, data_message); | 52 return MCSMessage(kDataMessageStanzaTag, data_message); |
| 45 } | 53 } |
| 46 | 54 |
| 47 // MCSClient with overriden exposed persistent id logic. | 55 // MCSClient with overriden exposed persistent id logic. |
| 48 class TestMCSClient : public MCSClient { | 56 class TestMCSClient : public MCSClient { |
| 49 public: | 57 public: |
| 50 TestMCSClient(ConnectionFactory* connection_factory, | 58 TestMCSClient(base::Clock* clock, |
| 59 ConnectionFactory* connection_factory, |
| 51 RMQStore* rmq_store) | 60 RMQStore* rmq_store) |
| 52 : MCSClient(connection_factory, rmq_store), | 61 : MCSClient(clock, connection_factory, rmq_store), |
| 53 next_id_(0) { | 62 next_id_(0) { |
| 54 } | 63 } |
| 55 | 64 |
| 56 virtual std::string GetNextPersistentId() OVERRIDE { | 65 virtual std::string GetNextPersistentId() OVERRIDE { |
| 57 return base::UintToString(++next_id_); | 66 return base::UintToString(++next_id_); |
| 58 } | 67 } |
| 59 | 68 |
| 60 private: | 69 private: |
| 61 uint32 next_id_; | 70 uint32 next_id_; |
| 62 }; | 71 }; |
| 63 | 72 |
| 64 class MCSClientTest : public testing::Test { | 73 class MCSClientTest : public testing::Test { |
| 65 public: | 74 public: |
| 66 MCSClientTest(); | 75 MCSClientTest(); |
| 67 virtual ~MCSClientTest(); | 76 virtual ~MCSClientTest(); |
| 68 | 77 |
| 69 void BuildMCSClient(); | 78 void BuildMCSClient(); |
| 70 void InitializeClient(); | 79 void InitializeClient(); |
| 71 void LoginClient(const std::vector<std::string>& acknowledged_ids); | 80 void LoginClient(const std::vector<std::string>& acknowledged_ids); |
| 72 | 81 |
| 82 base::SimpleTestClock* clock() { return &clock_; } |
| 73 TestMCSClient* mcs_client() const { return mcs_client_.get(); } | 83 TestMCSClient* mcs_client() const { return mcs_client_.get(); } |
| 74 FakeConnectionFactory* connection_factory() { | 84 FakeConnectionFactory* connection_factory() { |
| 75 return &connection_factory_; | 85 return &connection_factory_; |
| 76 } | 86 } |
| 77 bool init_success() const { return init_success_; } | 87 bool init_success() const { return init_success_; } |
| 78 uint64 restored_android_id() const { return restored_android_id_; } | 88 uint64 restored_android_id() const { return restored_android_id_; } |
| 79 uint64 restored_security_token() const { return restored_security_token_; } | 89 uint64 restored_security_token() const { return restored_security_token_; } |
| 80 MCSMessage* received_message() const { return received_message_.get(); } | 90 MCSMessage* received_message() const { return received_message_.get(); } |
| 81 std::string sent_message_id() const { return sent_message_id_;} | 91 std::string sent_message_id() const { return sent_message_id_;} |
| 82 | 92 |
| 83 FakeConnectionHandler* GetFakeHandler() const; | 93 FakeConnectionHandler* GetFakeHandler() const; |
| 84 | 94 |
| 85 void WaitForMCSEvent(); | 95 void WaitForMCSEvent(); |
| 86 void PumpLoop(); | 96 void PumpLoop(); |
| 87 | 97 |
| 88 private: | 98 private: |
| 89 void InitializationCallback(bool success, | 99 void InitializationCallback(bool success, |
| 90 uint64 restored_android_id, | 100 uint64 restored_android_id, |
| 91 uint64 restored_security_token); | 101 uint64 restored_security_token); |
| 92 void MessageReceivedCallback(const MCSMessage& message); | 102 void MessageReceivedCallback(const MCSMessage& message); |
| 93 void MessageSentCallback(const std::string& message_id); | 103 void MessageSentCallback(const std::string& message_id); |
| 94 | 104 |
| 105 base::SimpleTestClock clock_; |
| 106 |
| 95 base::ScopedTempDir temp_directory_; | 107 base::ScopedTempDir temp_directory_; |
| 96 base::MessageLoop message_loop_; | 108 base::MessageLoop message_loop_; |
| 97 scoped_ptr<base::RunLoop> run_loop_; | 109 scoped_ptr<base::RunLoop> run_loop_; |
| 98 scoped_ptr<RMQStore> rmq_store_; | 110 scoped_ptr<RMQStore> rmq_store_; |
| 99 | 111 |
| 100 FakeConnectionFactory connection_factory_; | 112 FakeConnectionFactory connection_factory_; |
| 101 scoped_ptr<TestMCSClient> mcs_client_; | 113 scoped_ptr<TestMCSClient> mcs_client_; |
| 102 bool init_success_; | 114 bool init_success_; |
| 103 uint64 restored_android_id_; | 115 uint64 restored_android_id_; |
| 104 uint64 restored_security_token_; | 116 uint64 restored_security_token_; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 118 #if defined(OS_MACOSX) | 130 #if defined(OS_MACOSX) |
| 119 Encryptor::UseMockKeychain(true); | 131 Encryptor::UseMockKeychain(true); |
| 120 #endif | 132 #endif |
| 121 } | 133 } |
| 122 | 134 |
| 123 MCSClientTest::~MCSClientTest() {} | 135 MCSClientTest::~MCSClientTest() {} |
| 124 | 136 |
| 125 void MCSClientTest::BuildMCSClient() { | 137 void MCSClientTest::BuildMCSClient() { |
| 126 rmq_store_.reset(new RMQStore(temp_directory_.path(), | 138 rmq_store_.reset(new RMQStore(temp_directory_.path(), |
| 127 message_loop_.message_loop_proxy())); | 139 message_loop_.message_loop_proxy())); |
| 128 mcs_client_.reset(new TestMCSClient(&connection_factory_, rmq_store_.get())); | 140 mcs_client_.reset(new TestMCSClient(&clock_, |
| 141 &connection_factory_, |
| 142 rmq_store_.get())); |
| 129 } | 143 } |
| 130 | 144 |
| 131 void MCSClientTest::InitializeClient() { | 145 void MCSClientTest::InitializeClient() { |
| 132 rmq_store_->Load( | 146 rmq_store_->Load( |
| 133 base::Bind(&MCSClient::Initialize, | 147 base::Bind(&MCSClient::Initialize, |
| 134 base::Unretained(mcs_client_.get()), | 148 base::Unretained(mcs_client_.get()), |
| 135 base::Bind(&MCSClientTest::InitializationCallback, | 149 base::Bind(&MCSClientTest::InitializationCallback, |
| 136 base::Unretained(this)), | 150 base::Unretained(this)), |
| 137 base::Bind(&MCSClientTest::MessageReceivedCallback, | 151 base::Bind(&MCSClientTest::MessageReceivedCallback, |
| 138 base::Unretained(this)), | 152 base::Unretained(this)), |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 } | 196 } |
| 183 | 197 |
| 184 void MCSClientTest::MessageReceivedCallback(const MCSMessage& message) { | 198 void MCSClientTest::MessageReceivedCallback(const MCSMessage& message) { |
| 185 received_message_.reset(new MCSMessage(message)); | 199 received_message_.reset(new MCSMessage(message)); |
| 186 DVLOG(1) << "Message received callback invoked, killing loop."; | 200 DVLOG(1) << "Message received callback invoked, killing loop."; |
| 187 run_loop_->Quit(); | 201 run_loop_->Quit(); |
| 188 } | 202 } |
| 189 | 203 |
| 190 void MCSClientTest::MessageSentCallback(const std::string& message_id) { | 204 void MCSClientTest::MessageSentCallback(const std::string& message_id) { |
| 191 DVLOG(1) << "Message sent callback invoked, killing loop."; | 205 DVLOG(1) << "Message sent callback invoked, killing loop."; |
| 206 sent_message_id_ = message_id; |
| 192 run_loop_->Quit(); | 207 run_loop_->Quit(); |
| 193 } | 208 } |
| 194 | 209 |
| 195 // Initialize a new client. | 210 // Initialize a new client. |
| 196 TEST_F(MCSClientTest, InitializeNew) { | 211 TEST_F(MCSClientTest, InitializeNew) { |
| 197 BuildMCSClient(); | 212 BuildMCSClient(); |
| 198 InitializeClient(); | 213 InitializeClient(); |
| 199 EXPECT_EQ(0U, restored_android_id()); | 214 EXPECT_EQ(0U, restored_android_id()); |
| 200 EXPECT_EQ(0U, restored_security_token()); | 215 EXPECT_EQ(0U, restored_security_token()); |
| 201 EXPECT_TRUE(init_success()); | 216 EXPECT_TRUE(init_success()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 EXPECT_FALSE(connection_factory()->IsEndpointReachable()); | 251 EXPECT_FALSE(connection_factory()->IsEndpointReachable()); |
| 237 EXPECT_FALSE(init_success()); | 252 EXPECT_FALSE(init_success()); |
| 238 EXPECT_FALSE(received_message()); | 253 EXPECT_FALSE(received_message()); |
| 239 } | 254 } |
| 240 | 255 |
| 241 // Send a message without RMQ support. | 256 // Send a message without RMQ support. |
| 242 TEST_F(MCSClientTest, SendMessageNoRMQ) { | 257 TEST_F(MCSClientTest, SendMessageNoRMQ) { |
| 243 BuildMCSClient(); | 258 BuildMCSClient(); |
| 244 InitializeClient(); | 259 InitializeClient(); |
| 245 LoginClient(std::vector<std::string>()); | 260 LoginClient(std::vector<std::string>()); |
| 246 MCSMessage message(BuildDataMessage("from", "category", 1, "")); | 261 MCSMessage message(BuildDataMessage("from", "category", 1, "", 0, 1)); |
| 247 GetFakeHandler()->ExpectOutgoingMessage(message); | 262 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 248 mcs_client()->SendMessage(message, false); | 263 mcs_client()->SendMessage(message); |
| 249 EXPECT_TRUE(GetFakeHandler()-> | 264 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 250 AllOutgoingMessagesReceived()); | 265 } |
| 266 |
| 267 // Send a message without RMQ support while disconnected. Message send should |
| 268 // fail immediately, invoking callback. |
| 269 TEST_F(MCSClientTest, SendMessageNoRMQWhileDisconnected) { |
| 270 BuildMCSClient(); |
| 271 InitializeClient(); |
| 272 |
| 273 EXPECT_TRUE(sent_message_id().empty()); |
| 274 MCSMessage message(BuildDataMessage("from", "category", 1, "", 0, 1)); |
| 275 mcs_client()->SendMessage(message); |
| 276 |
| 277 // Message sent callback should be invoked, but no message should actually |
| 278 // be sent. |
| 279 EXPECT_FALSE(sent_message_id().empty()); |
| 280 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 251 } | 281 } |
| 252 | 282 |
| 253 // Send a message with RMQ support. | 283 // Send a message with RMQ support. |
| 254 TEST_F(MCSClientTest, SendMessageRMQ) { | 284 TEST_F(MCSClientTest, SendMessageRMQ) { |
| 255 BuildMCSClient(); | 285 BuildMCSClient(); |
| 256 InitializeClient(); | 286 InitializeClient(); |
| 257 LoginClient(std::vector<std::string>()); | 287 LoginClient(std::vector<std::string>()); |
| 258 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 288 MCSMessage message( |
| 289 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
| 259 GetFakeHandler()->ExpectOutgoingMessage(message); | 290 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 260 mcs_client()->SendMessage(message, true); | 291 mcs_client()->SendMessage(message); |
| 261 EXPECT_TRUE(GetFakeHandler()-> | 292 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 262 AllOutgoingMessagesReceived()); | |
| 263 } | 293 } |
| 264 | 294 |
| 265 // Send a message with RMQ support while disconnected. On reconnect, the message | 295 // Send a message with RMQ support while disconnected. On reconnect, the message |
| 266 // should be resent. | 296 // should be resent. |
| 267 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { | 297 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { |
| 268 BuildMCSClient(); | 298 BuildMCSClient(); |
| 269 InitializeClient(); | 299 InitializeClient(); |
| 270 LoginClient(std::vector<std::string>()); | 300 LoginClient(std::vector<std::string>()); |
| 271 GetFakeHandler()->set_fail_send(true); | 301 GetFakeHandler()->set_fail_send(true); |
| 272 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 302 MCSMessage message( |
| 303 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
| 273 | 304 |
| 274 // The initial (failed) send. | 305 // The initial (failed) send. |
| 275 GetFakeHandler()->ExpectOutgoingMessage(message); | 306 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 276 // The login request. | 307 // The login request. |
| 277 GetFakeHandler()->ExpectOutgoingMessage( | 308 GetFakeHandler()->ExpectOutgoingMessage( |
| 278 MCSMessage(kLoginRequestTag, | 309 MCSMessage(kLoginRequestTag, |
| 279 BuildLoginRequest(kAndroidId, kSecurityToken). | 310 BuildLoginRequest(kAndroidId, kSecurityToken). |
| 280 PassAs<const google::protobuf::MessageLite>())); | 311 PassAs<const google::protobuf::MessageLite>())); |
| 281 // The second (re)send. | 312 // The second (re)send. |
| 282 GetFakeHandler()->ExpectOutgoingMessage(message); | 313 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 283 mcs_client()->SendMessage(message, true); | 314 mcs_client()->SendMessage(message); |
| 284 EXPECT_FALSE(GetFakeHandler()-> | 315 EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 285 AllOutgoingMessagesReceived()); | |
| 286 GetFakeHandler()->set_fail_send(false); | 316 GetFakeHandler()->set_fail_send(false); |
| 287 connection_factory()->Connect(); | 317 connection_factory()->Connect(); |
| 288 WaitForMCSEvent(); // Wait for the login to finish. | 318 WaitForMCSEvent(); // Wait for the login to finish. |
| 289 PumpLoop(); // Wait for the send to happen. | 319 PumpLoop(); // Wait for the send to happen. |
| 290 EXPECT_TRUE(GetFakeHandler()-> | 320 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 291 AllOutgoingMessagesReceived()); | |
| 292 } | 321 } |
| 293 | 322 |
| 294 // Send a message with RMQ support without receiving an acknowledgement. On | 323 // Send a message with RMQ support without receiving an acknowledgement. On |
| 295 // restart the message should be resent. | 324 // restart the message should be resent. |
| 296 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { | 325 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { |
| 297 BuildMCSClient(); | 326 BuildMCSClient(); |
| 298 InitializeClient(); | 327 InitializeClient(); |
| 299 LoginClient(std::vector<std::string>()); | 328 LoginClient(std::vector<std::string>()); |
| 300 GetFakeHandler()->set_fail_send(true); | 329 GetFakeHandler()->set_fail_send(true); |
| 301 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 330 MCSMessage message( |
| 331 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
| 302 | 332 |
| 303 // The initial (failed) send. | 333 // The initial (failed) send. |
| 304 GetFakeHandler()->ExpectOutgoingMessage(message); | 334 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 305 GetFakeHandler()->set_fail_send(false); | 335 GetFakeHandler()->set_fail_send(false); |
| 306 mcs_client()->SendMessage(message, true); | 336 mcs_client()->SendMessage(message); |
| 307 EXPECT_TRUE(GetFakeHandler()-> | 337 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 308 AllOutgoingMessagesReceived()); | |
| 309 | 338 |
| 310 // Rebuild the client, which should resend the old message. | 339 // Rebuild the client, which should resend the old message. |
| 311 BuildMCSClient(); | 340 BuildMCSClient(); |
| 312 InitializeClient(); | 341 InitializeClient(); |
| 313 LoginClient(std::vector<std::string>()); | 342 LoginClient(std::vector<std::string>()); |
| 314 GetFakeHandler()->ExpectOutgoingMessage(message); | 343 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 315 PumpLoop(); | 344 PumpLoop(); |
| 316 EXPECT_TRUE(GetFakeHandler()-> | 345 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 317 AllOutgoingMessagesReceived()); | |
| 318 } | 346 } |
| 319 | 347 |
| 320 // Send messages with RMQ support, followed by receiving a stream ack. On | 348 // Send messages with RMQ support, followed by receiving a stream ack. On |
| 321 // restart nothing should be recent. | 349 // restart nothing should be recent. |
| 322 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { | 350 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { |
| 323 BuildMCSClient(); | 351 BuildMCSClient(); |
| 324 InitializeClient(); | 352 InitializeClient(); |
| 325 LoginClient(std::vector<std::string>()); | 353 LoginClient(std::vector<std::string>()); |
| 326 | 354 |
| 327 // Send some messages. | 355 // Send some messages. |
| 328 for (int i = 1; i <= kMessageBatchSize; ++i) { | 356 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 329 MCSMessage message( | 357 MCSMessage message( |
| 330 BuildDataMessage("from", "category", 1, base::IntToString(i))); | 358 BuildDataMessage("from", |
| 359 "category", |
| 360 1, |
| 361 base::IntToString(i), |
| 362 kTTLValue, |
| 363 1)); |
| 331 GetFakeHandler()->ExpectOutgoingMessage(message); | 364 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 332 mcs_client()->SendMessage(message, true); | 365 mcs_client()->SendMessage(message); |
| 333 } | 366 } |
| 334 EXPECT_TRUE(GetFakeHandler()-> | 367 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 335 AllOutgoingMessagesReceived()); | |
| 336 | 368 |
| 337 // Receive the ack. | 369 // Receive the ack. |
| 338 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 370 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
| 339 ack->set_last_stream_id_received(kMessageBatchSize + 1); | 371 ack->set_last_stream_id_received(kMessageBatchSize + 1); |
| 340 GetFakeHandler()->ReceiveMessage( | 372 GetFakeHandler()->ReceiveMessage( |
| 341 MCSMessage(kIqStanzaTag, | 373 MCSMessage(kIqStanzaTag, |
| 342 ack.PassAs<const google::protobuf::MessageLite>())); | 374 ack.PassAs<const google::protobuf::MessageLite>())); |
| 343 WaitForMCSEvent(); | 375 WaitForMCSEvent(); |
| 344 | 376 |
| 345 // Reconnect and ensure no messages are resent. | 377 // Reconnect and ensure no messages are resent. |
| 346 BuildMCSClient(); | 378 BuildMCSClient(); |
| 347 InitializeClient(); | 379 InitializeClient(); |
| 348 LoginClient(std::vector<std::string>()); | 380 LoginClient(std::vector<std::string>()); |
| 349 PumpLoop(); | 381 PumpLoop(); |
| 350 } | 382 } |
| 351 | 383 |
| 352 // Send messages with RMQ support. On restart, receive a SelectiveAck with | 384 // Send messages with RMQ support. On restart, receive a SelectiveAck with |
| 353 // the login response. No messages should be resent. | 385 // the login response. No messages should be resent. |
| 354 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { | 386 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { |
| 355 BuildMCSClient(); | 387 BuildMCSClient(); |
| 356 InitializeClient(); | 388 InitializeClient(); |
| 357 LoginClient(std::vector<std::string>()); | 389 LoginClient(std::vector<std::string>()); |
| 358 | 390 |
| 359 // Send some messages. | 391 // Send some messages. |
| 360 std::vector<std::string> id_list; | 392 std::vector<std::string> id_list; |
| 361 for (int i = 1; i <= kMessageBatchSize; ++i) { | 393 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 362 id_list.push_back(base::IntToString(i)); | 394 id_list.push_back(base::IntToString(i)); |
| 363 MCSMessage message( | 395 MCSMessage message( |
| 364 BuildDataMessage("from", "category", 1, id_list.back())); | 396 BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 1)); |
| 365 GetFakeHandler()->ExpectOutgoingMessage(message); | 397 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 366 mcs_client()->SendMessage(message, true); | 398 mcs_client()->SendMessage(message); |
| 367 } | 399 } |
| 368 EXPECT_TRUE(GetFakeHandler()-> | 400 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 369 AllOutgoingMessagesReceived()); | |
| 370 | 401 |
| 371 // Rebuild the client, and receive an acknowledgment for the messages as | 402 // Rebuild the client, and receive an acknowledgment for the messages as |
| 372 // part of the login response. | 403 // part of the login response. |
| 373 BuildMCSClient(); | 404 BuildMCSClient(); |
| 374 InitializeClient(); | 405 InitializeClient(); |
| 375 LoginClient(std::vector<std::string>()); | 406 LoginClient(std::vector<std::string>()); |
| 376 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(id_list)); | 407 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(id_list)); |
| 377 GetFakeHandler()->ReceiveMessage( | 408 GetFakeHandler()->ReceiveMessage( |
| 378 MCSMessage(kIqStanzaTag, | 409 MCSMessage(kIqStanzaTag, |
| 379 ack.PassAs<const google::protobuf::MessageLite>())); | 410 ack.PassAs<const google::protobuf::MessageLite>())); |
| 380 WaitForMCSEvent(); | 411 WaitForMCSEvent(); |
| 381 EXPECT_TRUE(GetFakeHandler()-> | 412 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 382 AllOutgoingMessagesReceived()); | |
| 383 } | 413 } |
| 384 | 414 |
| 385 // Send messages with RMQ support. On restart, receive a SelectiveAck with | 415 // Send messages with RMQ support. On restart, receive a SelectiveAck with |
| 386 // the login response that only acks some messages. The unacked messages should | 416 // the login response that only acks some messages. The unacked messages should |
| 387 // be resent. | 417 // be resent. |
| 388 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { | 418 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { |
| 389 BuildMCSClient(); | 419 BuildMCSClient(); |
| 390 InitializeClient(); | 420 InitializeClient(); |
| 391 LoginClient(std::vector<std::string>()); | 421 LoginClient(std::vector<std::string>()); |
| 392 | 422 |
| 393 // Send some messages. | 423 // Send some messages. |
| 394 std::vector<std::string> id_list; | 424 std::vector<std::string> id_list; |
| 395 for (int i = 1; i <= kMessageBatchSize; ++i) { | 425 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 396 id_list.push_back(base::IntToString(i)); | 426 id_list.push_back(base::IntToString(i)); |
| 397 MCSMessage message( | 427 MCSMessage message( |
| 398 BuildDataMessage("from", "category", 1, id_list.back())); | 428 BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 1)); |
| 399 GetFakeHandler()->ExpectOutgoingMessage(message); | 429 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 400 mcs_client()->SendMessage(message, true); | 430 mcs_client()->SendMessage(message); |
| 401 } | 431 } |
| 402 EXPECT_TRUE(GetFakeHandler()-> | 432 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 403 AllOutgoingMessagesReceived()); | |
| 404 | 433 |
| 405 // Rebuild the client, and receive an acknowledgment for the messages as | 434 // Rebuild the client, and receive an acknowledgment for the messages as |
| 406 // part of the login response. | 435 // part of the login response. |
| 407 BuildMCSClient(); | 436 BuildMCSClient(); |
| 408 InitializeClient(); | 437 InitializeClient(); |
| 409 LoginClient(std::vector<std::string>()); | 438 LoginClient(std::vector<std::string>()); |
| 410 | 439 |
| 411 std::vector<std::string> acked_ids, remaining_ids; | 440 std::vector<std::string> acked_ids, remaining_ids; |
| 412 acked_ids.insert(acked_ids.end(), | 441 acked_ids.insert(acked_ids.end(), |
| 413 id_list.begin(), | 442 id_list.begin(), |
| 414 id_list.begin() + kMessageBatchSize / 2); | 443 id_list.begin() + kMessageBatchSize / 2); |
| 415 remaining_ids.insert(remaining_ids.end(), | 444 remaining_ids.insert(remaining_ids.end(), |
| 416 id_list.begin() + kMessageBatchSize / 2, | 445 id_list.begin() + kMessageBatchSize / 2, |
| 417 id_list.end()); | 446 id_list.end()); |
| 418 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { | 447 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { |
| 419 MCSMessage message( | 448 MCSMessage message( |
| 420 BuildDataMessage("from", | 449 BuildDataMessage("from", |
| 421 "category", | 450 "category", |
| 422 2, | 451 2, |
| 423 remaining_ids[i - 1])); | 452 remaining_ids[i - 1], |
| 453 kTTLValue, |
| 454 1)); |
| 424 GetFakeHandler()->ExpectOutgoingMessage(message); | 455 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 425 } | 456 } |
| 426 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); | 457 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); |
| 427 GetFakeHandler()->ReceiveMessage( | 458 GetFakeHandler()->ReceiveMessage( |
| 428 MCSMessage(kIqStanzaTag, | 459 MCSMessage(kIqStanzaTag, |
| 429 ack.PassAs<const google::protobuf::MessageLite>())); | 460 ack.PassAs<const google::protobuf::MessageLite>())); |
| 430 WaitForMCSEvent(); | 461 WaitForMCSEvent(); |
| 431 EXPECT_TRUE(GetFakeHandler()-> | 462 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 432 AllOutgoingMessagesReceived()); | |
| 433 } | 463 } |
| 434 | 464 |
| 435 // Receive some messages. On restart, the login request should contain the | 465 // Receive some messages. On restart, the login request should contain the |
| 436 // appropriate acknowledged ids. | 466 // appropriate acknowledged ids. |
| 437 TEST_F(MCSClientTest, AckOnLogin) { | 467 TEST_F(MCSClientTest, AckOnLogin) { |
| 438 BuildMCSClient(); | 468 BuildMCSClient(); |
| 439 InitializeClient(); | 469 InitializeClient(); |
| 440 LoginClient(std::vector<std::string>()); | 470 LoginClient(std::vector<std::string>()); |
| 441 | 471 |
| 442 // Receive some messages. | 472 // Receive some messages. |
| 443 std::vector<std::string> id_list; | 473 std::vector<std::string> id_list; |
| 444 for (int i = 1; i <= kMessageBatchSize; ++i) { | 474 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 445 id_list.push_back(base::IntToString(i)); | 475 id_list.push_back(base::IntToString(i)); |
| 446 MCSMessage message( | 476 MCSMessage message( |
| 447 BuildDataMessage("from", "category", i, id_list.back())); | 477 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 1)); |
| 448 GetFakeHandler()->ReceiveMessage(message); | 478 GetFakeHandler()->ReceiveMessage(message); |
| 449 WaitForMCSEvent(); | 479 WaitForMCSEvent(); |
| 450 PumpLoop(); | 480 PumpLoop(); |
| 451 } | 481 } |
| 452 | 482 |
| 453 // Restart the client. | 483 // Restart the client. |
| 454 BuildMCSClient(); | 484 BuildMCSClient(); |
| 455 InitializeClient(); | 485 InitializeClient(); |
| 456 LoginClient(id_list); | 486 LoginClient(id_list); |
| 457 } | 487 } |
| 458 | 488 |
| 459 // Receive some messages. On the next send, the outgoing message should contain | 489 // Receive some messages. On the next send, the outgoing message should contain |
| 460 // the appropriate last stream id received field to ack the received messages. | 490 // the appropriate last stream id received field to ack the received messages. |
| 461 TEST_F(MCSClientTest, AckOnSend) { | 491 TEST_F(MCSClientTest, AckOnSend) { |
| 462 BuildMCSClient(); | 492 BuildMCSClient(); |
| 463 InitializeClient(); | 493 InitializeClient(); |
| 464 LoginClient(std::vector<std::string>()); | 494 LoginClient(std::vector<std::string>()); |
| 465 | 495 |
| 466 // Receive some messages. | 496 // Receive some messages. |
| 467 std::vector<std::string> id_list; | 497 std::vector<std::string> id_list; |
| 468 for (int i = 1; i <= kMessageBatchSize; ++i) { | 498 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 469 id_list.push_back(base::IntToString(i)); | 499 id_list.push_back(base::IntToString(i)); |
| 470 MCSMessage message( | 500 MCSMessage message( |
| 471 BuildDataMessage("from", "category", i, id_list.back())); | 501 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 1)); |
| 472 GetFakeHandler()->ReceiveMessage(message); | 502 GetFakeHandler()->ReceiveMessage(message); |
| 473 WaitForMCSEvent(); | 503 WaitForMCSEvent(); |
| 474 PumpLoop(); | 504 PumpLoop(); |
| 475 } | 505 } |
| 476 | 506 |
| 477 // Trigger a message send, which should acknowledge via stream ack. | 507 // Trigger a message send, which should acknowledge via stream ack. |
| 478 MCSMessage message( | 508 MCSMessage message( |
| 479 BuildDataMessage("from", "category", kMessageBatchSize + 1, "1")); | 509 BuildDataMessage("from", |
| 510 "category", |
| 511 kMessageBatchSize + 1, |
| 512 "1", |
| 513 kTTLValue, |
| 514 1)); |
| 480 GetFakeHandler()->ExpectOutgoingMessage(message); | 515 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 481 mcs_client()->SendMessage(message, true); | 516 mcs_client()->SendMessage(message); |
| 482 EXPECT_TRUE(GetFakeHandler()-> | 517 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 483 AllOutgoingMessagesReceived()); | |
| 484 } | 518 } |
| 485 | 519 |
| 486 // Receive the ack limit in messages, which should trigger an automatic | 520 // Receive the ack limit in messages, which should trigger an automatic |
| 487 // stream ack. Receive a heartbeat to confirm the ack. | 521 // stream ack. Receive a heartbeat to confirm the ack. |
| 488 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { | 522 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { |
| 489 BuildMCSClient(); | 523 BuildMCSClient(); |
| 490 InitializeClient(); | 524 InitializeClient(); |
| 491 LoginClient(std::vector<std::string>()); | 525 LoginClient(std::vector<std::string>()); |
| 492 | 526 |
| 493 // The stream ack. | 527 // The stream ack. |
| 494 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 528 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
| 495 ack->set_last_stream_id_received(kAckLimitSize + 1); | 529 ack->set_last_stream_id_received(kAckLimitSize + 1); |
| 496 GetFakeHandler()->ExpectOutgoingMessage( | 530 GetFakeHandler()->ExpectOutgoingMessage( |
| 497 MCSMessage(kIqStanzaTag, | 531 MCSMessage(kIqStanzaTag, |
| 498 ack.PassAs<const google::protobuf::MessageLite>())); | 532 ack.PassAs<const google::protobuf::MessageLite>())); |
| 499 | 533 |
| 500 // Receive some messages. | 534 // Receive some messages. |
| 501 std::vector<std::string> id_list; | 535 std::vector<std::string> id_list; |
| 502 for (int i = 1; i <= kAckLimitSize; ++i) { | 536 for (int i = 1; i <= kAckLimitSize; ++i) { |
| 503 id_list.push_back(base::IntToString(i)); | 537 id_list.push_back(base::IntToString(i)); |
| 504 MCSMessage message( | 538 MCSMessage message( |
| 505 BuildDataMessage("from", "category", i, id_list.back())); | 539 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 1)); |
| 506 GetFakeHandler()->ReceiveMessage(message); | 540 GetFakeHandler()->ReceiveMessage(message); |
| 507 WaitForMCSEvent(); | 541 WaitForMCSEvent(); |
| 508 PumpLoop(); | 542 PumpLoop(); |
| 509 } | 543 } |
| 510 EXPECT_TRUE(GetFakeHandler()-> | 544 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 511 AllOutgoingMessagesReceived()); | |
| 512 | 545 |
| 513 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). | 546 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). |
| 514 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( | 547 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( |
| 515 new mcs_proto::HeartbeatPing()); | 548 new mcs_proto::HeartbeatPing()); |
| 516 heartbeat->set_last_stream_id_received(2); | 549 heartbeat->set_last_stream_id_received(2); |
| 517 | 550 |
| 518 scoped_ptr<mcs_proto::HeartbeatAck> heartbeat_ack( | 551 scoped_ptr<mcs_proto::HeartbeatAck> heartbeat_ack( |
| 519 new mcs_proto::HeartbeatAck()); | 552 new mcs_proto::HeartbeatAck()); |
| 520 heartbeat_ack->set_last_stream_id_received(kAckLimitSize + 2); | 553 heartbeat_ack->set_last_stream_id_received(kAckLimitSize + 2); |
| 521 GetFakeHandler()->ExpectOutgoingMessage( | 554 GetFakeHandler()->ExpectOutgoingMessage( |
| 522 MCSMessage(kHeartbeatAckTag, | 555 MCSMessage(kHeartbeatAckTag, |
| 523 heartbeat_ack.PassAs<const google::protobuf::MessageLite>())); | 556 heartbeat_ack.PassAs<const google::protobuf::MessageLite>())); |
| 524 | 557 |
| 525 GetFakeHandler()->ReceiveMessage( | 558 GetFakeHandler()->ReceiveMessage( |
| 526 MCSMessage(kHeartbeatPingTag, | 559 MCSMessage(kHeartbeatPingTag, |
| 527 heartbeat.PassAs<const google::protobuf::MessageLite>())); | 560 heartbeat.PassAs<const google::protobuf::MessageLite>())); |
| 528 WaitForMCSEvent(); | 561 WaitForMCSEvent(); |
| 529 EXPECT_TRUE(GetFakeHandler()-> | 562 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 530 AllOutgoingMessagesReceived()); | |
| 531 | 563 |
| 532 // Rebuild the client. Nothing should be sent on login. | 564 // Rebuild the client. Nothing should be sent on login. |
| 533 BuildMCSClient(); | 565 BuildMCSClient(); |
| 534 InitializeClient(); | 566 InitializeClient(); |
| 535 LoginClient(std::vector<std::string>()); | 567 LoginClient(std::vector<std::string>()); |
| 536 EXPECT_TRUE(GetFakeHandler()-> | 568 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 537 AllOutgoingMessagesReceived()); | 569 } |
| 570 |
| 571 // If a message's TTL has expired by the time it reaches the front of the send |
| 572 // queue, it should be dropped. |
| 573 TEST_F(MCSClientTest, ExpiredTTLOnSend) { |
| 574 BuildMCSClient(); |
| 575 InitializeClient(); |
| 576 LoginClient(std::vector<std::string>()); |
| 577 MCSMessage message( |
| 578 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
| 579 |
| 580 // Advance time to after the TTL. |
| 581 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); |
| 582 EXPECT_TRUE(sent_message_id().empty()); |
| 583 mcs_client()->SendMessage(message); |
| 584 |
| 585 // No messages should be sent, but the callback should still be invoked. |
| 586 EXPECT_FALSE(sent_message_id().empty()); |
| 587 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 588 } |
| 589 |
| 590 TEST_F(MCSClientTest, ExpiredTTLOnRestart) { |
| 591 BuildMCSClient(); |
| 592 InitializeClient(); |
| 593 LoginClient(std::vector<std::string>()); |
| 594 GetFakeHandler()->set_fail_send(true); |
| 595 MCSMessage message( |
| 596 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
| 597 |
| 598 // The initial (failed) send. |
| 599 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 600 GetFakeHandler()->set_fail_send(false); |
| 601 mcs_client()->SendMessage(message); |
| 602 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 603 |
| 604 // Move the clock forward and rebuild the client, which should fail the |
| 605 // message send on restart. |
| 606 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); |
| 607 BuildMCSClient(); |
| 608 InitializeClient(); |
| 609 LoginClient(std::vector<std::string>()); |
| 610 PumpLoop(); |
| 611 EXPECT_FALSE(sent_message_id().empty()); |
| 612 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 538 } | 613 } |
| 539 | 614 |
| 540 } // namespace | 615 } // namespace |
| 541 | 616 |
| 542 } // namespace gcm | 617 } // namespace gcm |
| OLD | NEW |