Chromium Code Reviews| 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, 0)); |
| 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()); | |
| 251 } | 265 } |
| 252 | 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, 0)); | |
| 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()); | |
| 281 } | |
| 282 | |
|
jianli
2014/01/02 18:52:58
nit: empty line not needed
Nicolas Zea
2014/01/02 21:39:08
Done.
| |
| 283 | |
| 253 // Send a message with RMQ support. | 284 // Send a message with RMQ support. |
| 254 TEST_F(MCSClientTest, SendMessageRMQ) { | 285 TEST_F(MCSClientTest, SendMessageRMQ) { |
| 255 BuildMCSClient(); | 286 BuildMCSClient(); |
| 256 InitializeClient(); | 287 InitializeClient(); |
| 257 LoginClient(std::vector<std::string>()); | 288 LoginClient(std::vector<std::string>()); |
| 258 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 289 MCSMessage message( |
| 290 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
| 259 GetFakeHandler()->ExpectOutgoingMessage(message); | 291 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 260 mcs_client()->SendMessage(message, true); | 292 mcs_client()->SendMessage(message); |
| 261 EXPECT_TRUE(GetFakeHandler()-> | 293 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 262 AllOutgoingMessagesReceived()); | |
| 263 } | 294 } |
| 264 | 295 |
| 265 // Send a message with RMQ support while disconnected. On reconnect, the message | 296 // Send a message with RMQ support while disconnected. On reconnect, the message |
| 266 // should be resent. | 297 // should be resent. |
| 267 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { | 298 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { |
| 268 BuildMCSClient(); | 299 BuildMCSClient(); |
| 269 InitializeClient(); | 300 InitializeClient(); |
| 270 LoginClient(std::vector<std::string>()); | 301 LoginClient(std::vector<std::string>()); |
| 271 GetFakeHandler()->set_fail_send(true); | 302 GetFakeHandler()->set_fail_send(true); |
| 272 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 303 MCSMessage message( |
| 304 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
| 273 | 305 |
| 274 // The initial (failed) send. | 306 // The initial (failed) send. |
| 275 GetFakeHandler()->ExpectOutgoingMessage(message); | 307 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 276 // The login request. | 308 // The login request. |
| 277 GetFakeHandler()->ExpectOutgoingMessage( | 309 GetFakeHandler()->ExpectOutgoingMessage( |
| 278 MCSMessage(kLoginRequestTag, | 310 MCSMessage(kLoginRequestTag, |
| 279 BuildLoginRequest(kAndroidId, kSecurityToken). | 311 BuildLoginRequest(kAndroidId, kSecurityToken). |
| 280 PassAs<const google::protobuf::MessageLite>())); | 312 PassAs<const google::protobuf::MessageLite>())); |
| 281 // The second (re)send. | 313 // The second (re)send. |
| 282 GetFakeHandler()->ExpectOutgoingMessage(message); | 314 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 283 mcs_client()->SendMessage(message, true); | 315 mcs_client()->SendMessage(message); |
| 284 EXPECT_FALSE(GetFakeHandler()-> | 316 EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 285 AllOutgoingMessagesReceived()); | |
| 286 GetFakeHandler()->set_fail_send(false); | 317 GetFakeHandler()->set_fail_send(false); |
| 287 connection_factory()->Connect(); | 318 connection_factory()->Connect(); |
| 288 WaitForMCSEvent(); // Wait for the login to finish. | 319 WaitForMCSEvent(); // Wait for the login to finish. |
| 289 PumpLoop(); // Wait for the send to happen. | 320 PumpLoop(); // Wait for the send to happen. |
| 290 EXPECT_TRUE(GetFakeHandler()-> | 321 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 291 AllOutgoingMessagesReceived()); | |
| 292 } | 322 } |
| 293 | 323 |
| 294 // Send a message with RMQ support without receiving an acknowledgement. On | 324 // Send a message with RMQ support without receiving an acknowledgement. On |
| 295 // restart the message should be resent. | 325 // restart the message should be resent. |
| 296 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { | 326 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { |
| 297 BuildMCSClient(); | 327 BuildMCSClient(); |
| 298 InitializeClient(); | 328 InitializeClient(); |
| 299 LoginClient(std::vector<std::string>()); | 329 LoginClient(std::vector<std::string>()); |
| 300 GetFakeHandler()->set_fail_send(true); | 330 GetFakeHandler()->set_fail_send(true); |
| 301 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 331 MCSMessage message( |
| 332 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
| 302 | 333 |
| 303 // The initial (failed) send. | 334 // The initial (failed) send. |
| 304 GetFakeHandler()->ExpectOutgoingMessage(message); | 335 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 305 GetFakeHandler()->set_fail_send(false); | 336 GetFakeHandler()->set_fail_send(false); |
| 306 mcs_client()->SendMessage(message, true); | 337 mcs_client()->SendMessage(message); |
| 307 EXPECT_TRUE(GetFakeHandler()-> | 338 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 308 AllOutgoingMessagesReceived()); | |
| 309 | 339 |
| 310 // Rebuild the client, which should resend the old message. | 340 // Rebuild the client, which should resend the old message. |
| 311 BuildMCSClient(); | 341 BuildMCSClient(); |
| 312 InitializeClient(); | 342 InitializeClient(); |
| 313 LoginClient(std::vector<std::string>()); | 343 LoginClient(std::vector<std::string>()); |
| 314 GetFakeHandler()->ExpectOutgoingMessage(message); | 344 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 315 PumpLoop(); | 345 PumpLoop(); |
| 316 EXPECT_TRUE(GetFakeHandler()-> | 346 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 317 AllOutgoingMessagesReceived()); | |
| 318 } | 347 } |
| 319 | 348 |
| 320 // Send messages with RMQ support, followed by receiving a stream ack. On | 349 // Send messages with RMQ support, followed by receiving a stream ack. On |
| 321 // restart nothing should be recent. | 350 // restart nothing should be recent. |
| 322 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { | 351 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { |
| 323 BuildMCSClient(); | 352 BuildMCSClient(); |
| 324 InitializeClient(); | 353 InitializeClient(); |
| 325 LoginClient(std::vector<std::string>()); | 354 LoginClient(std::vector<std::string>()); |
| 326 | 355 |
| 327 // Send some messages. | 356 // Send some messages. |
| 328 for (int i = 1; i <= kMessageBatchSize; ++i) { | 357 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 329 MCSMessage message( | 358 MCSMessage message( |
| 330 BuildDataMessage("from", "category", 1, base::IntToString(i))); | 359 BuildDataMessage("from", |
| 360 "category", | |
| 361 1, | |
| 362 base::IntToString(i), | |
| 363 kTTLValue, | |
| 364 0)); | |
| 331 GetFakeHandler()->ExpectOutgoingMessage(message); | 365 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 332 mcs_client()->SendMessage(message, true); | 366 mcs_client()->SendMessage(message); |
| 333 } | 367 } |
| 334 EXPECT_TRUE(GetFakeHandler()-> | 368 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 335 AllOutgoingMessagesReceived()); | |
| 336 | 369 |
| 337 // Receive the ack. | 370 // Receive the ack. |
| 338 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 371 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
| 339 ack->set_last_stream_id_received(kMessageBatchSize + 1); | 372 ack->set_last_stream_id_received(kMessageBatchSize + 1); |
| 340 GetFakeHandler()->ReceiveMessage( | 373 GetFakeHandler()->ReceiveMessage( |
| 341 MCSMessage(kIqStanzaTag, | 374 MCSMessage(kIqStanzaTag, |
| 342 ack.PassAs<const google::protobuf::MessageLite>())); | 375 ack.PassAs<const google::protobuf::MessageLite>())); |
| 343 WaitForMCSEvent(); | 376 WaitForMCSEvent(); |
| 344 | 377 |
| 345 // Reconnect and ensure no messages are resent. | 378 // Reconnect and ensure no messages are resent. |
| 346 BuildMCSClient(); | 379 BuildMCSClient(); |
| 347 InitializeClient(); | 380 InitializeClient(); |
| 348 LoginClient(std::vector<std::string>()); | 381 LoginClient(std::vector<std::string>()); |
| 349 PumpLoop(); | 382 PumpLoop(); |
| 350 } | 383 } |
| 351 | 384 |
| 352 // Send messages with RMQ support. On restart, receive a SelectiveAck with | 385 // Send messages with RMQ support. On restart, receive a SelectiveAck with |
| 353 // the login response. No messages should be resent. | 386 // the login response. No messages should be resent. |
| 354 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { | 387 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { |
| 355 BuildMCSClient(); | 388 BuildMCSClient(); |
| 356 InitializeClient(); | 389 InitializeClient(); |
| 357 LoginClient(std::vector<std::string>()); | 390 LoginClient(std::vector<std::string>()); |
| 358 | 391 |
| 359 // Send some messages. | 392 // Send some messages. |
| 360 std::vector<std::string> id_list; | 393 std::vector<std::string> id_list; |
| 361 for (int i = 1; i <= kMessageBatchSize; ++i) { | 394 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 362 id_list.push_back(base::IntToString(i)); | 395 id_list.push_back(base::IntToString(i)); |
| 363 MCSMessage message( | 396 MCSMessage message( |
| 364 BuildDataMessage("from", "category", 1, id_list.back())); | 397 BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 0)); |
| 365 GetFakeHandler()->ExpectOutgoingMessage(message); | 398 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 366 mcs_client()->SendMessage(message, true); | 399 mcs_client()->SendMessage(message); |
| 367 } | 400 } |
| 368 EXPECT_TRUE(GetFakeHandler()-> | 401 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 369 AllOutgoingMessagesReceived()); | |
| 370 | 402 |
| 371 // Rebuild the client, and receive an acknowledgment for the messages as | 403 // Rebuild the client, and receive an acknowledgment for the messages as |
| 372 // part of the login response. | 404 // part of the login response. |
| 373 BuildMCSClient(); | 405 BuildMCSClient(); |
| 374 InitializeClient(); | 406 InitializeClient(); |
| 375 LoginClient(std::vector<std::string>()); | 407 LoginClient(std::vector<std::string>()); |
| 376 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(id_list)); | 408 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(id_list)); |
| 377 GetFakeHandler()->ReceiveMessage( | 409 GetFakeHandler()->ReceiveMessage( |
| 378 MCSMessage(kIqStanzaTag, | 410 MCSMessage(kIqStanzaTag, |
| 379 ack.PassAs<const google::protobuf::MessageLite>())); | 411 ack.PassAs<const google::protobuf::MessageLite>())); |
| 380 WaitForMCSEvent(); | 412 WaitForMCSEvent(); |
| 381 EXPECT_TRUE(GetFakeHandler()-> | 413 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 382 AllOutgoingMessagesReceived()); | |
| 383 } | 414 } |
| 384 | 415 |
| 385 // Send messages with RMQ support. On restart, receive a SelectiveAck with | 416 // Send messages with RMQ support. On restart, receive a SelectiveAck with |
| 386 // the login response that only acks some messages. The unacked messages should | 417 // the login response that only acks some messages. The unacked messages should |
| 387 // be resent. | 418 // be resent. |
| 388 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { | 419 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { |
| 389 BuildMCSClient(); | 420 BuildMCSClient(); |
| 390 InitializeClient(); | 421 InitializeClient(); |
| 391 LoginClient(std::vector<std::string>()); | 422 LoginClient(std::vector<std::string>()); |
| 392 | 423 |
| 393 // Send some messages. | 424 // Send some messages. |
| 394 std::vector<std::string> id_list; | 425 std::vector<std::string> id_list; |
| 395 for (int i = 1; i <= kMessageBatchSize; ++i) { | 426 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 396 id_list.push_back(base::IntToString(i)); | 427 id_list.push_back(base::IntToString(i)); |
| 397 MCSMessage message( | 428 MCSMessage message( |
| 398 BuildDataMessage("from", "category", 1, id_list.back())); | 429 BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 0)); |
| 399 GetFakeHandler()->ExpectOutgoingMessage(message); | 430 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 400 mcs_client()->SendMessage(message, true); | 431 mcs_client()->SendMessage(message); |
| 401 } | 432 } |
| 402 EXPECT_TRUE(GetFakeHandler()-> | 433 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 403 AllOutgoingMessagesReceived()); | |
| 404 | 434 |
| 405 // Rebuild the client, and receive an acknowledgment for the messages as | 435 // Rebuild the client, and receive an acknowledgment for the messages as |
| 406 // part of the login response. | 436 // part of the login response. |
| 407 BuildMCSClient(); | 437 BuildMCSClient(); |
| 408 InitializeClient(); | 438 InitializeClient(); |
| 409 LoginClient(std::vector<std::string>()); | 439 LoginClient(std::vector<std::string>()); |
| 410 | 440 |
| 411 std::vector<std::string> acked_ids, remaining_ids; | 441 std::vector<std::string> acked_ids, remaining_ids; |
| 412 acked_ids.insert(acked_ids.end(), | 442 acked_ids.insert(acked_ids.end(), |
| 413 id_list.begin(), | 443 id_list.begin(), |
| 414 id_list.begin() + kMessageBatchSize / 2); | 444 id_list.begin() + kMessageBatchSize / 2); |
| 415 remaining_ids.insert(remaining_ids.end(), | 445 remaining_ids.insert(remaining_ids.end(), |
| 416 id_list.begin() + kMessageBatchSize / 2, | 446 id_list.begin() + kMessageBatchSize / 2, |
| 417 id_list.end()); | 447 id_list.end()); |
| 418 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { | 448 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { |
| 419 MCSMessage message( | 449 MCSMessage message( |
| 420 BuildDataMessage("from", | 450 BuildDataMessage("from", |
| 421 "category", | 451 "category", |
| 422 2, | 452 2, |
| 423 remaining_ids[i - 1])); | 453 remaining_ids[i - 1], |
| 454 kTTLValue, | |
| 455 0)); | |
| 424 GetFakeHandler()->ExpectOutgoingMessage(message); | 456 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 425 } | 457 } |
| 426 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); | 458 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); |
| 427 GetFakeHandler()->ReceiveMessage( | 459 GetFakeHandler()->ReceiveMessage( |
| 428 MCSMessage(kIqStanzaTag, | 460 MCSMessage(kIqStanzaTag, |
| 429 ack.PassAs<const google::protobuf::MessageLite>())); | 461 ack.PassAs<const google::protobuf::MessageLite>())); |
| 430 WaitForMCSEvent(); | 462 WaitForMCSEvent(); |
| 431 EXPECT_TRUE(GetFakeHandler()-> | 463 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 432 AllOutgoingMessagesReceived()); | |
| 433 } | 464 } |
| 434 | 465 |
| 435 // Receive some messages. On restart, the login request should contain the | 466 // Receive some messages. On restart, the login request should contain the |
| 436 // appropriate acknowledged ids. | 467 // appropriate acknowledged ids. |
| 437 TEST_F(MCSClientTest, AckOnLogin) { | 468 TEST_F(MCSClientTest, AckOnLogin) { |
| 438 BuildMCSClient(); | 469 BuildMCSClient(); |
| 439 InitializeClient(); | 470 InitializeClient(); |
| 440 LoginClient(std::vector<std::string>()); | 471 LoginClient(std::vector<std::string>()); |
| 441 | 472 |
| 442 // Receive some messages. | 473 // Receive some messages. |
| 443 std::vector<std::string> id_list; | 474 std::vector<std::string> id_list; |
| 444 for (int i = 1; i <= kMessageBatchSize; ++i) { | 475 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 445 id_list.push_back(base::IntToString(i)); | 476 id_list.push_back(base::IntToString(i)); |
| 446 MCSMessage message( | 477 MCSMessage message( |
| 447 BuildDataMessage("from", "category", i, id_list.back())); | 478 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 0)); |
| 448 GetFakeHandler()->ReceiveMessage(message); | 479 GetFakeHandler()->ReceiveMessage(message); |
| 449 WaitForMCSEvent(); | 480 WaitForMCSEvent(); |
| 450 PumpLoop(); | 481 PumpLoop(); |
| 451 } | 482 } |
| 452 | 483 |
| 453 // Restart the client. | 484 // Restart the client. |
| 454 BuildMCSClient(); | 485 BuildMCSClient(); |
| 455 InitializeClient(); | 486 InitializeClient(); |
| 456 LoginClient(id_list); | 487 LoginClient(id_list); |
| 457 } | 488 } |
| 458 | 489 |
| 459 // Receive some messages. On the next send, the outgoing message should contain | 490 // 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. | 491 // the appropriate last stream id received field to ack the received messages. |
| 461 TEST_F(MCSClientTest, AckOnSend) { | 492 TEST_F(MCSClientTest, AckOnSend) { |
| 462 BuildMCSClient(); | 493 BuildMCSClient(); |
| 463 InitializeClient(); | 494 InitializeClient(); |
| 464 LoginClient(std::vector<std::string>()); | 495 LoginClient(std::vector<std::string>()); |
| 465 | 496 |
| 466 // Receive some messages. | 497 // Receive some messages. |
| 467 std::vector<std::string> id_list; | 498 std::vector<std::string> id_list; |
| 468 for (int i = 1; i <= kMessageBatchSize; ++i) { | 499 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 469 id_list.push_back(base::IntToString(i)); | 500 id_list.push_back(base::IntToString(i)); |
| 470 MCSMessage message( | 501 MCSMessage message( |
| 471 BuildDataMessage("from", "category", i, id_list.back())); | 502 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 0)); |
| 472 GetFakeHandler()->ReceiveMessage(message); | 503 GetFakeHandler()->ReceiveMessage(message); |
| 473 WaitForMCSEvent(); | 504 WaitForMCSEvent(); |
| 474 PumpLoop(); | 505 PumpLoop(); |
| 475 } | 506 } |
| 476 | 507 |
| 477 // Trigger a message send, which should acknowledge via stream ack. | 508 // Trigger a message send, which should acknowledge via stream ack. |
| 478 MCSMessage message( | 509 MCSMessage message( |
| 479 BuildDataMessage("from", "category", kMessageBatchSize + 1, "1")); | 510 BuildDataMessage("from", |
| 511 "category", | |
| 512 kMessageBatchSize + 1, | |
| 513 "1", | |
| 514 kTTLValue, | |
| 515 0)); | |
| 480 GetFakeHandler()->ExpectOutgoingMessage(message); | 516 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 481 mcs_client()->SendMessage(message, true); | 517 mcs_client()->SendMessage(message); |
| 482 EXPECT_TRUE(GetFakeHandler()-> | 518 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 483 AllOutgoingMessagesReceived()); | |
| 484 } | 519 } |
| 485 | 520 |
| 486 // Receive the ack limit in messages, which should trigger an automatic | 521 // Receive the ack limit in messages, which should trigger an automatic |
| 487 // stream ack. Receive a heartbeat to confirm the ack. | 522 // stream ack. Receive a heartbeat to confirm the ack. |
| 488 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { | 523 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { |
| 489 BuildMCSClient(); | 524 BuildMCSClient(); |
| 490 InitializeClient(); | 525 InitializeClient(); |
| 491 LoginClient(std::vector<std::string>()); | 526 LoginClient(std::vector<std::string>()); |
| 492 | 527 |
| 493 // The stream ack. | 528 // The stream ack. |
| 494 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 529 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
| 495 ack->set_last_stream_id_received(kAckLimitSize + 1); | 530 ack->set_last_stream_id_received(kAckLimitSize + 1); |
| 496 GetFakeHandler()->ExpectOutgoingMessage( | 531 GetFakeHandler()->ExpectOutgoingMessage( |
| 497 MCSMessage(kIqStanzaTag, | 532 MCSMessage(kIqStanzaTag, |
| 498 ack.PassAs<const google::protobuf::MessageLite>())); | 533 ack.PassAs<const google::protobuf::MessageLite>())); |
| 499 | 534 |
| 500 // Receive some messages. | 535 // Receive some messages. |
| 501 std::vector<std::string> id_list; | 536 std::vector<std::string> id_list; |
| 502 for (int i = 1; i <= kAckLimitSize; ++i) { | 537 for (int i = 1; i <= kAckLimitSize; ++i) { |
| 503 id_list.push_back(base::IntToString(i)); | 538 id_list.push_back(base::IntToString(i)); |
| 504 MCSMessage message( | 539 MCSMessage message( |
| 505 BuildDataMessage("from", "category", i, id_list.back())); | 540 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 0)); |
| 506 GetFakeHandler()->ReceiveMessage(message); | 541 GetFakeHandler()->ReceiveMessage(message); |
| 507 WaitForMCSEvent(); | 542 WaitForMCSEvent(); |
| 508 PumpLoop(); | 543 PumpLoop(); |
| 509 } | 544 } |
| 510 EXPECT_TRUE(GetFakeHandler()-> | 545 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 511 AllOutgoingMessagesReceived()); | |
| 512 | 546 |
| 513 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). | 547 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). |
| 514 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( | 548 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( |
| 515 new mcs_proto::HeartbeatPing()); | 549 new mcs_proto::HeartbeatPing()); |
| 516 heartbeat->set_last_stream_id_received(2); | 550 heartbeat->set_last_stream_id_received(2); |
| 517 | 551 |
| 518 scoped_ptr<mcs_proto::HeartbeatAck> heartbeat_ack( | 552 scoped_ptr<mcs_proto::HeartbeatAck> heartbeat_ack( |
| 519 new mcs_proto::HeartbeatAck()); | 553 new mcs_proto::HeartbeatAck()); |
| 520 heartbeat_ack->set_last_stream_id_received(kAckLimitSize + 2); | 554 heartbeat_ack->set_last_stream_id_received(kAckLimitSize + 2); |
| 521 GetFakeHandler()->ExpectOutgoingMessage( | 555 GetFakeHandler()->ExpectOutgoingMessage( |
| 522 MCSMessage(kHeartbeatAckTag, | 556 MCSMessage(kHeartbeatAckTag, |
| 523 heartbeat_ack.PassAs<const google::protobuf::MessageLite>())); | 557 heartbeat_ack.PassAs<const google::protobuf::MessageLite>())); |
| 524 | 558 |
| 525 GetFakeHandler()->ReceiveMessage( | 559 GetFakeHandler()->ReceiveMessage( |
| 526 MCSMessage(kHeartbeatPingTag, | 560 MCSMessage(kHeartbeatPingTag, |
| 527 heartbeat.PassAs<const google::protobuf::MessageLite>())); | 561 heartbeat.PassAs<const google::protobuf::MessageLite>())); |
| 528 WaitForMCSEvent(); | 562 WaitForMCSEvent(); |
| 529 EXPECT_TRUE(GetFakeHandler()-> | 563 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 530 AllOutgoingMessagesReceived()); | |
| 531 | 564 |
| 532 // Rebuild the client. Nothing should be sent on login. | 565 // Rebuild the client. Nothing should be sent on login. |
| 533 BuildMCSClient(); | 566 BuildMCSClient(); |
| 534 InitializeClient(); | 567 InitializeClient(); |
| 535 LoginClient(std::vector<std::string>()); | 568 LoginClient(std::vector<std::string>()); |
| 536 EXPECT_TRUE(GetFakeHandler()-> | 569 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 537 AllOutgoingMessagesReceived()); | 570 } |
| 571 | |
| 572 // If a message's TTL has expired by the time it reaches the front of the send | |
| 573 // queue, it should be dropped. | |
| 574 TEST_F(MCSClientTest, ExpiredTTLOnSend) { | |
| 575 BuildMCSClient(); | |
| 576 InitializeClient(); | |
| 577 LoginClient(std::vector<std::string>()); | |
| 578 MCSMessage message( | |
| 579 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
| 580 | |
| 581 // Advance time to after the TTL. | |
| 582 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 1)); | |
| 583 EXPECT_TRUE(sent_message_id().empty()); | |
| 584 mcs_client()->SendMessage(message); | |
| 585 | |
| 586 // No messages should be sent, but the callback should still be invoked. | |
| 587 EXPECT_FALSE(sent_message_id().empty()); | |
| 588 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | |
| 589 } | |
| 590 | |
| 591 TEST_F(MCSClientTest, ExpiredTTLOnRestart) { | |
| 592 BuildMCSClient(); | |
| 593 InitializeClient(); | |
| 594 LoginClient(std::vector<std::string>()); | |
| 595 GetFakeHandler()->set_fail_send(true); | |
| 596 MCSMessage message( | |
| 597 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
| 598 | |
| 599 // The initial (failed) send. | |
| 600 GetFakeHandler()->ExpectOutgoingMessage(message); | |
| 601 GetFakeHandler()->set_fail_send(false); | |
| 602 mcs_client()->SendMessage(message); | |
| 603 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | |
| 604 | |
| 605 // Move the clock forward and rebuild the client, which should fail the | |
| 606 // message send on restart. | |
| 607 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 1)); | |
| 608 BuildMCSClient(); | |
| 609 InitializeClient(); | |
| 610 LoginClient(std::vector<std::string>()); | |
| 611 PumpLoop(); | |
| 612 EXPECT_FALSE(sent_message_id().empty()); | |
| 613 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | |
| 538 } | 614 } |
| 539 | 615 |
| 540 } // namespace | 616 } // namespace |
| 541 | 617 |
| 542 } // namespace gcm | 618 } // namespace gcm |
| OLD | NEW |