| 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" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 const int kTTLValue = 5 * 60; // 5 minutes. | 36 const int kTTLValue = 5 * 60; // 5 minutes. |
| 37 | 37 |
| 38 // Helper for building arbitrary data messages. | 38 // Helper for building arbitrary data messages. |
| 39 MCSMessage BuildDataMessage(const std::string& from, | 39 MCSMessage BuildDataMessage(const std::string& from, |
| 40 const std::string& category, | 40 const std::string& category, |
| 41 const std::string& message_id, | 41 const std::string& message_id, |
| 42 int last_stream_id_received, | 42 int last_stream_id_received, |
| 43 const std::string& persistent_id, | 43 const std::string& persistent_id, |
| 44 int ttl, | 44 int ttl, |
| 45 uint64 sent, | 45 uint64 sent, |
| 46 int queued) { | 46 int queued, |
| 47 const std::string& token, |
| 48 const uint64& user_id) { |
| 47 mcs_proto::DataMessageStanza data_message; | 49 mcs_proto::DataMessageStanza data_message; |
| 48 data_message.set_id(message_id); | 50 data_message.set_id(message_id); |
| 49 data_message.set_from(from); | 51 data_message.set_from(from); |
| 50 data_message.set_category(category); | 52 data_message.set_category(category); |
| 51 data_message.set_last_stream_id_received(last_stream_id_received); | 53 data_message.set_last_stream_id_received(last_stream_id_received); |
| 52 if (!persistent_id.empty()) | 54 if (!persistent_id.empty()) |
| 53 data_message.set_persistent_id(persistent_id); | 55 data_message.set_persistent_id(persistent_id); |
| 54 data_message.set_ttl(ttl); | 56 data_message.set_ttl(ttl); |
| 55 data_message.set_sent(sent); | 57 data_message.set_sent(sent); |
| 56 data_message.set_queued(queued); | 58 data_message.set_queued(queued); |
| 59 data_message.set_token(token); |
| 60 data_message.set_device_user_id(user_id); |
| 57 return MCSMessage(kDataMessageStanzaTag, data_message); | 61 return MCSMessage(kDataMessageStanzaTag, data_message); |
| 58 } | 62 } |
| 59 | 63 |
| 60 // MCSClient with overriden exposed persistent id logic. | 64 // MCSClient with overriden exposed persistent id logic. |
| 61 class TestMCSClient : public MCSClient { | 65 class TestMCSClient : public MCSClient { |
| 62 public: | 66 public: |
| 63 TestMCSClient(base::Clock* clock, | 67 TestMCSClient(base::Clock* clock, |
| 64 ConnectionFactory* connection_factory, | 68 ConnectionFactory* connection_factory, |
| 65 GCMStore* gcm_store) | 69 GCMStore* gcm_store) |
| 66 : MCSClient(clock, connection_factory, gcm_store), | 70 : MCSClient(clock, connection_factory, gcm_store), |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 EXPECT_FALSE(connection_factory()->IsEndpointReachable()); | 283 EXPECT_FALSE(connection_factory()->IsEndpointReachable()); |
| 280 EXPECT_FALSE(init_success()); | 284 EXPECT_FALSE(init_success()); |
| 281 EXPECT_FALSE(received_message()); | 285 EXPECT_FALSE(received_message()); |
| 282 } | 286 } |
| 283 | 287 |
| 284 // Send a message without RMQ support. | 288 // Send a message without RMQ support. |
| 285 TEST_F(MCSClientTest, SendMessageNoRMQ) { | 289 TEST_F(MCSClientTest, SendMessageNoRMQ) { |
| 286 BuildMCSClient(); | 290 BuildMCSClient(); |
| 287 InitializeClient(); | 291 InitializeClient(); |
| 288 LoginClient(std::vector<std::string>()); | 292 LoginClient(std::vector<std::string>()); |
| 289 MCSMessage message(BuildDataMessage("from", "category", "X", 1, "", 0, 1, 0)); | 293 MCSMessage message( |
| 294 BuildDataMessage("from", "category", "X", 1, "", 0, 1, 0, "", 0)); |
| 290 GetFakeHandler()->ExpectOutgoingMessage(message); | 295 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 291 mcs_client()->SendMessage(message); | 296 mcs_client()->SendMessage(message); |
| 292 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 297 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 293 } | 298 } |
| 294 | 299 |
| 295 // Send a message without RMQ support while disconnected. Message send should | 300 // Send a message without RMQ support while disconnected. Message send should |
| 296 // fail immediately, invoking callback. | 301 // fail immediately, invoking callback. |
| 297 TEST_F(MCSClientTest, SendMessageNoRMQWhileDisconnected) { | 302 TEST_F(MCSClientTest, SendMessageNoRMQWhileDisconnected) { |
| 298 BuildMCSClient(); | 303 BuildMCSClient(); |
| 299 InitializeClient(); | 304 InitializeClient(); |
| 300 | 305 |
| 301 EXPECT_TRUE(sent_message_id().empty()); | 306 EXPECT_TRUE(sent_message_id().empty()); |
| 302 MCSMessage message(BuildDataMessage("from", "category", "X", 1, "", 0, 1, 0)); | 307 MCSMessage message( |
| 308 BuildDataMessage("from", "category", "X", 1, "", 0, 1, 0, "", 0)); |
| 303 mcs_client()->SendMessage(message); | 309 mcs_client()->SendMessage(message); |
| 304 | 310 |
| 305 // Message sent callback should be invoked, but no message should actually | 311 // Message sent callback should be invoked, but no message should actually |
| 306 // be sent. | 312 // be sent. |
| 307 EXPECT_EQ("X", sent_message_id()); | 313 EXPECT_EQ("X", sent_message_id()); |
| 308 EXPECT_EQ(MCSClient::NO_CONNECTION_ON_ZERO_TTL, message_send_status()); | 314 EXPECT_EQ(MCSClient::NO_CONNECTION_ON_ZERO_TTL, message_send_status()); |
| 309 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 315 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 310 } | 316 } |
| 311 | 317 |
| 312 // Send a message with RMQ support. | 318 // Send a message with RMQ support. |
| 313 TEST_F(MCSClientTest, SendMessageRMQ) { | 319 TEST_F(MCSClientTest, SendMessageRMQ) { |
| 314 BuildMCSClient(); | 320 BuildMCSClient(); |
| 315 InitializeClient(); | 321 InitializeClient(); |
| 316 LoginClient(std::vector<std::string>()); | 322 LoginClient(std::vector<std::string>()); |
| 317 MCSMessage message( | 323 MCSMessage message(BuildDataMessage( |
| 318 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0)); | 324 "from", "category", "X", 1, "1", kTTLValue, 1, 0, "", 0)); |
| 319 GetFakeHandler()->ExpectOutgoingMessage(message); | 325 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 320 mcs_client()->SendMessage(message); | 326 mcs_client()->SendMessage(message); |
| 321 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 327 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 322 } | 328 } |
| 323 | 329 |
| 324 // Send a message with RMQ support while disconnected. On reconnect, the message | 330 // Send a message with RMQ support while disconnected. On reconnect, the message |
| 325 // should be resent. | 331 // should be resent. |
| 326 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { | 332 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { |
| 327 BuildMCSClient(); | 333 BuildMCSClient(); |
| 328 InitializeClient(); | 334 InitializeClient(); |
| 329 LoginClient(std::vector<std::string>()); | 335 LoginClient(std::vector<std::string>()); |
| 330 GetFakeHandler()->set_fail_send(true); | 336 GetFakeHandler()->set_fail_send(true); |
| 331 MCSMessage message( | 337 MCSMessage message(BuildDataMessage( |
| 332 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0)); | 338 "from", "category", "X", 1, "1", kTTLValue, 1, 0, "", 0)); |
| 333 | 339 |
| 334 // The initial (failed) send. | 340 // The initial (failed) send. |
| 335 GetFakeHandler()->ExpectOutgoingMessage(message); | 341 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 336 // The login request. | 342 // The login request. |
| 337 GetFakeHandler()->ExpectOutgoingMessage( | 343 GetFakeHandler()->ExpectOutgoingMessage( |
| 338 MCSMessage(kLoginRequestTag, | 344 MCSMessage(kLoginRequestTag, |
| 339 BuildLoginRequest(kAndroidId, kSecurityToken). | 345 BuildLoginRequest(kAndroidId, kSecurityToken). |
| 340 PassAs<const google::protobuf::MessageLite>())); | 346 PassAs<const google::protobuf::MessageLite>())); |
| 341 // The second (re)send. | 347 // The second (re)send. |
| 342 MCSMessage message2(BuildDataMessage("from", | 348 MCSMessage message2(BuildDataMessage( |
| 343 "category", | 349 "from", "category", "X", 1, "1", kTTLValue, 1, kTTLValue - 1, "", 0)); |
| 344 "X", | |
| 345 1, | |
| 346 "1", | |
| 347 kTTLValue, | |
| 348 1, | |
| 349 kTTLValue - 1)); | |
| 350 GetFakeHandler()->ExpectOutgoingMessage(message2); | 350 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 351 mcs_client()->SendMessage(message); | 351 mcs_client()->SendMessage(message); |
| 352 EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 352 EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 353 GetFakeHandler()->set_fail_send(false); | 353 GetFakeHandler()->set_fail_send(false); |
| 354 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1)); | 354 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1)); |
| 355 connection_factory()->Connect(); | 355 connection_factory()->Connect(); |
| 356 WaitForMCSEvent(); // Wait for the login to finish. | 356 WaitForMCSEvent(); // Wait for the login to finish. |
| 357 PumpLoop(); // Wait for the send to happen. | 357 PumpLoop(); // Wait for the send to happen. |
| 358 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 358 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 359 } | 359 } |
| 360 | 360 |
| 361 // Send a message with RMQ support without receiving an acknowledgement. On | 361 // Send a message with RMQ support without receiving an acknowledgement. On |
| 362 // restart the message should be resent. | 362 // restart the message should be resent. |
| 363 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { | 363 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { |
| 364 BuildMCSClient(); | 364 BuildMCSClient(); |
| 365 InitializeClient(); | 365 InitializeClient(); |
| 366 LoginClient(std::vector<std::string>()); | 366 LoginClient(std::vector<std::string>()); |
| 367 GetFakeHandler()->set_fail_send(true); | 367 GetFakeHandler()->set_fail_send(true); |
| 368 MCSMessage message( | 368 MCSMessage message(BuildDataMessage( |
| 369 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0)); | 369 "from", "category", "X", 1, "1", kTTLValue, 1, 0, "", 0)); |
| 370 | 370 |
| 371 // The initial (failed) send. | 371 // The initial (failed) send. |
| 372 GetFakeHandler()->ExpectOutgoingMessage(message); | 372 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 373 GetFakeHandler()->set_fail_send(false); | 373 GetFakeHandler()->set_fail_send(false); |
| 374 mcs_client()->SendMessage(message); | 374 mcs_client()->SendMessage(message); |
| 375 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 375 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 376 | 376 |
| 377 // Rebuild the client, which should resend the old message. | 377 // Rebuild the client, which should resend the old message. |
| 378 StoreCredentials(); | 378 StoreCredentials(); |
| 379 BuildMCSClient(); | 379 BuildMCSClient(); |
| 380 InitializeClient(); | 380 InitializeClient(); |
| 381 | 381 |
| 382 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1)); | 382 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1)); |
| 383 MCSMessage message2(BuildDataMessage("from", | 383 MCSMessage message2(BuildDataMessage( |
| 384 "category", | 384 "from", "category", "X", 1, "1", kTTLValue, 1, kTTLValue - 1, "", 0)); |
| 385 "X", | |
| 386 1, | |
| 387 "1", | |
| 388 kTTLValue, | |
| 389 1, | |
| 390 kTTLValue - 1)); | |
| 391 LoginClient(std::vector<std::string>()); | 385 LoginClient(std::vector<std::string>()); |
| 392 GetFakeHandler()->ExpectOutgoingMessage(message2); | 386 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 393 PumpLoop(); | 387 PumpLoop(); |
| 394 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 388 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 395 } | 389 } |
| 396 | 390 |
| 397 // Send messages with RMQ support, followed by receiving a stream ack. On | 391 // Send messages with RMQ support, followed by receiving a stream ack. On |
| 398 // restart nothing should be recent. | 392 // restart nothing should be recent. |
| 399 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { | 393 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { |
| 400 BuildMCSClient(); | 394 BuildMCSClient(); |
| 401 InitializeClient(); | 395 InitializeClient(); |
| 402 LoginClient(std::vector<std::string>()); | 396 LoginClient(std::vector<std::string>()); |
| 403 | 397 |
| 404 // Send some messages. | 398 // Send some messages. |
| 405 for (int i = 1; i <= kMessageBatchSize; ++i) { | 399 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 406 MCSMessage message( | 400 MCSMessage message(BuildDataMessage("from", |
| 407 BuildDataMessage("from", | 401 "category", |
| 408 "category", | 402 "X", |
| 409 "X", | 403 1, |
| 410 1, | 404 base::IntToString(i), |
| 411 base::IntToString(i), | 405 kTTLValue, |
| 412 kTTLValue, | 406 1, |
| 413 1, | 407 0, |
| 414 0)); | 408 "", |
| 409 0)); |
| 415 GetFakeHandler()->ExpectOutgoingMessage(message); | 410 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 416 mcs_client()->SendMessage(message); | 411 mcs_client()->SendMessage(message); |
| 417 } | 412 } |
| 418 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 413 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 419 | 414 |
| 420 // Receive the ack. | 415 // Receive the ack. |
| 421 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 416 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
| 422 ack->set_last_stream_id_received(kMessageBatchSize + 1); | 417 ack->set_last_stream_id_received(kMessageBatchSize + 1); |
| 423 GetFakeHandler()->ReceiveMessage( | 418 GetFakeHandler()->ReceiveMessage( |
| 424 MCSMessage(kIqStanzaTag, | 419 MCSMessage(kIqStanzaTag, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 437 // the login response. No messages should be resent. | 432 // the login response. No messages should be resent. |
| 438 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { | 433 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { |
| 439 BuildMCSClient(); | 434 BuildMCSClient(); |
| 440 InitializeClient(); | 435 InitializeClient(); |
| 441 LoginClient(std::vector<std::string>()); | 436 LoginClient(std::vector<std::string>()); |
| 442 | 437 |
| 443 // Send some messages. | 438 // Send some messages. |
| 444 std::vector<std::string> id_list; | 439 std::vector<std::string> id_list; |
| 445 for (int i = 1; i <= kMessageBatchSize; ++i) { | 440 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 446 id_list.push_back(base::IntToString(i)); | 441 id_list.push_back(base::IntToString(i)); |
| 447 MCSMessage message( | 442 MCSMessage message(BuildDataMessage("from", |
| 448 BuildDataMessage("from", | 443 "category", |
| 449 "category", | 444 id_list.back(), |
| 450 id_list.back(), | 445 1, |
| 451 1, | 446 id_list.back(), |
| 452 id_list.back(), | 447 kTTLValue, |
| 453 kTTLValue, | 448 1, |
| 454 1, | 449 0, |
| 455 0)); | 450 "", |
| 451 0)); |
| 456 GetFakeHandler()->ExpectOutgoingMessage(message); | 452 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 457 mcs_client()->SendMessage(message); | 453 mcs_client()->SendMessage(message); |
| 458 } | 454 } |
| 459 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 455 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 460 | 456 |
| 461 // Rebuild the client, and receive an acknowledgment for the messages as | 457 // Rebuild the client, and receive an acknowledgment for the messages as |
| 462 // part of the login response. | 458 // part of the login response. |
| 463 StoreCredentials(); | 459 StoreCredentials(); |
| 464 BuildMCSClient(); | 460 BuildMCSClient(); |
| 465 InitializeClient(); | 461 InitializeClient(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 476 // be resent. | 472 // be resent. |
| 477 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { | 473 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { |
| 478 BuildMCSClient(); | 474 BuildMCSClient(); |
| 479 InitializeClient(); | 475 InitializeClient(); |
| 480 LoginClient(std::vector<std::string>()); | 476 LoginClient(std::vector<std::string>()); |
| 481 | 477 |
| 482 // Send some messages. | 478 // Send some messages. |
| 483 std::vector<std::string> id_list; | 479 std::vector<std::string> id_list; |
| 484 for (int i = 1; i <= kMessageBatchSize; ++i) { | 480 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 485 id_list.push_back(base::IntToString(i)); | 481 id_list.push_back(base::IntToString(i)); |
| 486 MCSMessage message( | 482 MCSMessage message(BuildDataMessage("from", |
| 487 BuildDataMessage("from", | 483 "category", |
| 488 "category", | 484 id_list.back(), |
| 489 id_list.back(), | 485 1, |
| 490 1, | 486 id_list.back(), |
| 491 id_list.back(), | 487 kTTLValue, |
| 492 kTTLValue, | 488 1, |
| 493 1, | 489 0, |
| 494 0)); | 490 "", |
| 491 0)); |
| 495 GetFakeHandler()->ExpectOutgoingMessage(message); | 492 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 496 mcs_client()->SendMessage(message); | 493 mcs_client()->SendMessage(message); |
| 497 } | 494 } |
| 498 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 495 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 499 | 496 |
| 500 // Rebuild the client, and receive an acknowledgment for the messages as | 497 // Rebuild the client, and receive an acknowledgment for the messages as |
| 501 // part of the login response. | 498 // part of the login response. |
| 502 StoreCredentials(); | 499 StoreCredentials(); |
| 503 BuildMCSClient(); | 500 BuildMCSClient(); |
| 504 InitializeClient(); | 501 InitializeClient(); |
| 505 LoginClient(std::vector<std::string>()); | 502 LoginClient(std::vector<std::string>()); |
| 506 | 503 |
| 507 std::vector<std::string> acked_ids, remaining_ids; | 504 std::vector<std::string> acked_ids, remaining_ids; |
| 508 acked_ids.insert(acked_ids.end(), | 505 acked_ids.insert(acked_ids.end(), |
| 509 id_list.begin(), | 506 id_list.begin(), |
| 510 id_list.begin() + kMessageBatchSize / 2); | 507 id_list.begin() + kMessageBatchSize / 2); |
| 511 remaining_ids.insert(remaining_ids.end(), | 508 remaining_ids.insert(remaining_ids.end(), |
| 512 id_list.begin() + kMessageBatchSize / 2, | 509 id_list.begin() + kMessageBatchSize / 2, |
| 513 id_list.end()); | 510 id_list.end()); |
| 514 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { | 511 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { |
| 515 MCSMessage message( | 512 MCSMessage message(BuildDataMessage("from", |
| 516 BuildDataMessage("from", | 513 "category", |
| 517 "category", | 514 remaining_ids[i - 1], |
| 518 remaining_ids[i - 1], | 515 2, |
| 519 2, | 516 remaining_ids[i - 1], |
| 520 remaining_ids[i - 1], | 517 kTTLValue, |
| 521 kTTLValue, | 518 1, |
| 522 1, 0)); | 519 0, |
| 520 "", |
| 521 0)); |
| 523 GetFakeHandler()->ExpectOutgoingMessage(message); | 522 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 524 } | 523 } |
| 525 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); | 524 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); |
| 526 GetFakeHandler()->ReceiveMessage( | 525 GetFakeHandler()->ReceiveMessage( |
| 527 MCSMessage(kIqStanzaTag, | 526 MCSMessage(kIqStanzaTag, |
| 528 ack.PassAs<const google::protobuf::MessageLite>())); | 527 ack.PassAs<const google::protobuf::MessageLite>())); |
| 529 WaitForMCSEvent(); | 528 WaitForMCSEvent(); |
| 530 PumpLoop(); | 529 PumpLoop(); |
| 531 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 530 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 532 } | 531 } |
| 533 | 532 |
| 534 // Receive some messages. On restart, the login request should contain the | 533 // Receive some messages. On restart, the login request should contain the |
| 535 // appropriate acknowledged ids. | 534 // appropriate acknowledged ids. |
| 536 TEST_F(MCSClientTest, AckOnLogin) { | 535 TEST_F(MCSClientTest, AckOnLogin) { |
| 537 BuildMCSClient(); | 536 BuildMCSClient(); |
| 538 InitializeClient(); | 537 InitializeClient(); |
| 539 LoginClient(std::vector<std::string>()); | 538 LoginClient(std::vector<std::string>()); |
| 540 | 539 |
| 541 // Receive some messages. | 540 // Receive some messages. |
| 542 std::vector<std::string> id_list; | 541 std::vector<std::string> id_list; |
| 543 for (int i = 1; i <= kMessageBatchSize; ++i) { | 542 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 544 id_list.push_back(base::IntToString(i)); | 543 id_list.push_back(base::IntToString(i)); |
| 545 MCSMessage message( | 544 MCSMessage message(BuildDataMessage( |
| 546 BuildDataMessage("from", | 545 "from", "category", "X", 1, id_list.back(), kTTLValue, 1, 0, "", 0)); |
| 547 "category", | |
| 548 "X", | |
| 549 1, | |
| 550 id_list.back(), | |
| 551 kTTLValue, | |
| 552 1, | |
| 553 0)); | |
| 554 GetFakeHandler()->ReceiveMessage(message); | 546 GetFakeHandler()->ReceiveMessage(message); |
| 555 WaitForMCSEvent(); | 547 WaitForMCSEvent(); |
| 556 PumpLoop(); | 548 PumpLoop(); |
| 557 } | 549 } |
| 558 | 550 |
| 559 // Restart the client. | 551 // Restart the client. |
| 560 StoreCredentials(); | 552 StoreCredentials(); |
| 561 BuildMCSClient(); | 553 BuildMCSClient(); |
| 562 InitializeClient(); | 554 InitializeClient(); |
| 563 LoginClient(id_list); | 555 LoginClient(id_list); |
| 564 } | 556 } |
| 565 | 557 |
| 566 // Receive some messages. On the next send, the outgoing message should contain | 558 // Receive some messages. On the next send, the outgoing message should contain |
| 567 // the appropriate last stream id received field to ack the received messages. | 559 // the appropriate last stream id received field to ack the received messages. |
| 568 TEST_F(MCSClientTest, AckOnSend) { | 560 TEST_F(MCSClientTest, AckOnSend) { |
| 569 BuildMCSClient(); | 561 BuildMCSClient(); |
| 570 InitializeClient(); | 562 InitializeClient(); |
| 571 LoginClient(std::vector<std::string>()); | 563 LoginClient(std::vector<std::string>()); |
| 572 | 564 |
| 573 // Receive some messages. | 565 // Receive some messages. |
| 574 std::vector<std::string> id_list; | 566 std::vector<std::string> id_list; |
| 575 for (int i = 1; i <= kMessageBatchSize; ++i) { | 567 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 576 id_list.push_back(base::IntToString(i)); | 568 id_list.push_back(base::IntToString(i)); |
| 577 MCSMessage message( | 569 MCSMessage message(BuildDataMessage("from", |
| 578 BuildDataMessage("from", | 570 "category", |
| 579 "category", | 571 id_list.back(), |
| 580 id_list.back(), | 572 1, |
| 581 1, | 573 id_list.back(), |
| 582 id_list.back(), | 574 kTTLValue, |
| 583 kTTLValue, | 575 1, |
| 584 1, | 576 0, |
| 585 0)); | 577 "", |
| 578 0)); |
| 586 GetFakeHandler()->ReceiveMessage(message); | 579 GetFakeHandler()->ReceiveMessage(message); |
| 587 PumpLoop(); | 580 PumpLoop(); |
| 588 } | 581 } |
| 589 | 582 |
| 590 // Trigger a message send, which should acknowledge via stream ack. | 583 // Trigger a message send, which should acknowledge via stream ack. |
| 591 MCSMessage message( | 584 MCSMessage message(BuildDataMessage("from", |
| 592 BuildDataMessage("from", | 585 "category", |
| 593 "category", | 586 "X", |
| 594 "X", | 587 kMessageBatchSize + 1, |
| 595 kMessageBatchSize + 1, | 588 "1", |
| 596 "1", | 589 kTTLValue, |
| 597 kTTLValue, | 590 1, |
| 598 1, 0)); | 591 0, |
| 592 "", |
| 593 0)); |
| 599 GetFakeHandler()->ExpectOutgoingMessage(message); | 594 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 600 mcs_client()->SendMessage(message); | 595 mcs_client()->SendMessage(message); |
| 601 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 596 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 602 } | 597 } |
| 603 | 598 |
| 604 // Receive the ack limit in messages, which should trigger an automatic | 599 // Receive the ack limit in messages, which should trigger an automatic |
| 605 // stream ack. Receive a heartbeat to confirm the ack. | 600 // stream ack. Receive a heartbeat to confirm the ack. |
| 606 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { | 601 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { |
| 607 BuildMCSClient(); | 602 BuildMCSClient(); |
| 608 InitializeClient(); | 603 InitializeClient(); |
| 609 LoginClient(std::vector<std::string>()); | 604 LoginClient(std::vector<std::string>()); |
| 610 | 605 |
| 611 // The stream ack. | 606 // The stream ack. |
| 612 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 607 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
| 613 ack->set_last_stream_id_received(kAckLimitSize + 1); | 608 ack->set_last_stream_id_received(kAckLimitSize + 1); |
| 614 GetFakeHandler()->ExpectOutgoingMessage( | 609 GetFakeHandler()->ExpectOutgoingMessage( |
| 615 MCSMessage(kIqStanzaTag, | 610 MCSMessage(kIqStanzaTag, |
| 616 ack.PassAs<const google::protobuf::MessageLite>())); | 611 ack.PassAs<const google::protobuf::MessageLite>())); |
| 617 | 612 |
| 618 // Receive some messages. | 613 // Receive some messages. |
| 619 std::vector<std::string> id_list; | 614 std::vector<std::string> id_list; |
| 620 for (int i = 1; i <= kAckLimitSize; ++i) { | 615 for (int i = 1; i <= kAckLimitSize; ++i) { |
| 621 id_list.push_back(base::IntToString(i)); | 616 id_list.push_back(base::IntToString(i)); |
| 622 MCSMessage message( | 617 MCSMessage message(BuildDataMessage("from", |
| 623 BuildDataMessage("from", | 618 "category", |
| 624 "category", | 619 id_list.back(), |
| 625 id_list.back(), | 620 1, |
| 626 1, | 621 id_list.back(), |
| 627 id_list.back(), | 622 kTTLValue, |
| 628 kTTLValue, | 623 1, |
| 629 1, | 624 0, |
| 630 0)); | 625 "", |
| 626 0)); |
| 631 GetFakeHandler()->ReceiveMessage(message); | 627 GetFakeHandler()->ReceiveMessage(message); |
| 632 WaitForMCSEvent(); | 628 WaitForMCSEvent(); |
| 633 PumpLoop(); | 629 PumpLoop(); |
| 634 } | 630 } |
| 635 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 631 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 636 | 632 |
| 637 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). | 633 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). |
| 638 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( | 634 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( |
| 639 new mcs_proto::HeartbeatPing()); | 635 new mcs_proto::HeartbeatPing()); |
| 640 heartbeat->set_last_stream_id_received(2); | 636 heartbeat->set_last_stream_id_received(2); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 659 LoginClient(std::vector<std::string>()); | 655 LoginClient(std::vector<std::string>()); |
| 660 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 656 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 661 } | 657 } |
| 662 | 658 |
| 663 // If a message's TTL has expired by the time it reaches the front of the send | 659 // If a message's TTL has expired by the time it reaches the front of the send |
| 664 // queue, it should be dropped. | 660 // queue, it should be dropped. |
| 665 TEST_F(MCSClientTest, ExpiredTTLOnSend) { | 661 TEST_F(MCSClientTest, ExpiredTTLOnSend) { |
| 666 BuildMCSClient(); | 662 BuildMCSClient(); |
| 667 InitializeClient(); | 663 InitializeClient(); |
| 668 LoginClient(std::vector<std::string>()); | 664 LoginClient(std::vector<std::string>()); |
| 669 MCSMessage message( | 665 MCSMessage message(BuildDataMessage( |
| 670 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0)); | 666 "from", "category", "X", 1, "1", kTTLValue, 1, 0, "", 0)); |
| 671 | 667 |
| 672 // Advance time to after the TTL. | 668 // Advance time to after the TTL. |
| 673 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); | 669 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); |
| 674 EXPECT_TRUE(sent_message_id().empty()); | 670 EXPECT_TRUE(sent_message_id().empty()); |
| 675 mcs_client()->SendMessage(message); | 671 mcs_client()->SendMessage(message); |
| 676 | 672 |
| 677 // No messages should be sent, but the callback should still be invoked. | 673 // No messages should be sent, but the callback should still be invoked. |
| 678 EXPECT_EQ("X", sent_message_id()); | 674 EXPECT_EQ("X", sent_message_id()); |
| 679 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status()); | 675 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status()); |
| 680 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 676 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 681 } | 677 } |
| 682 | 678 |
| 683 TEST_F(MCSClientTest, ExpiredTTLOnRestart) { | 679 TEST_F(MCSClientTest, ExpiredTTLOnRestart) { |
| 684 BuildMCSClient(); | 680 BuildMCSClient(); |
| 685 InitializeClient(); | 681 InitializeClient(); |
| 686 LoginClient(std::vector<std::string>()); | 682 LoginClient(std::vector<std::string>()); |
| 687 GetFakeHandler()->set_fail_send(true); | 683 GetFakeHandler()->set_fail_send(true); |
| 688 MCSMessage message( | 684 MCSMessage message(BuildDataMessage( |
| 689 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0)); | 685 "from", "category", "X", 1, "1", kTTLValue, 1, 0, "", 0)); |
| 690 | 686 |
| 691 // The initial (failed) send. | 687 // The initial (failed) send. |
| 692 GetFakeHandler()->ExpectOutgoingMessage(message); | 688 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 693 GetFakeHandler()->set_fail_send(false); | 689 GetFakeHandler()->set_fail_send(false); |
| 694 mcs_client()->SendMessage(message); | 690 mcs_client()->SendMessage(message); |
| 695 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 691 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 696 | 692 |
| 697 // Move the clock forward and rebuild the client, which should fail the | 693 // Move the clock forward and rebuild the client, which should fail the |
| 698 // message send on restart. | 694 // message send on restart. |
| 699 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); | 695 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); |
| 700 StoreCredentials(); | 696 StoreCredentials(); |
| 701 BuildMCSClient(); | 697 BuildMCSClient(); |
| 702 InitializeClient(); | 698 InitializeClient(); |
| 703 LoginClient(std::vector<std::string>()); | 699 LoginClient(std::vector<std::string>()); |
| 704 PumpLoop(); | 700 PumpLoop(); |
| 705 EXPECT_EQ("X", sent_message_id()); | 701 EXPECT_EQ("X", sent_message_id()); |
| 706 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status()); | 702 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status()); |
| 707 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 703 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 708 } | 704 } |
| 709 | 705 |
| 706 // Sending two messages with the same collapse key and same app id while |
| 707 // disconnected should only send the latter of the two on reconnection. |
| 708 TEST_F(MCSClientTest, CollapseKeysSameApp) { |
| 709 BuildMCSClient(); |
| 710 InitializeClient(); |
| 711 MCSMessage message(BuildDataMessage( |
| 712 "from", "app", "message id 1", 1, "1", kTTLValue, 1, 0, "token", 0)); |
| 713 mcs_client()->SendMessage(message); |
| 714 |
| 715 MCSMessage message2(BuildDataMessage( |
| 716 "from", "app", "message id 2", 1, "1", kTTLValue, 1, 0, "token", 0)); |
| 717 mcs_client()->SendMessage(message2); |
| 718 |
| 719 LoginClient(std::vector<std::string>()); |
| 720 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 721 PumpLoop(); |
| 722 } |
| 723 |
| 724 // Sending two messages with the same collapse key and different app id while |
| 725 // disconnected should not perform any collapsing. |
| 726 TEST_F(MCSClientTest, CollapseKeysDifferentApp) { |
| 727 BuildMCSClient(); |
| 728 InitializeClient(); |
| 729 MCSMessage message(BuildDataMessage( |
| 730 "from", "app", "message id 1", 1, "1", kTTLValue, 1, 0, "token", 0)); |
| 731 mcs_client()->SendMessage(message); |
| 732 |
| 733 MCSMessage message2(BuildDataMessage("from", |
| 734 "app 2", |
| 735 "message id 2", |
| 736 1, |
| 737 "2", |
| 738 kTTLValue, |
| 739 1, |
| 740 0, |
| 741 "token", |
| 742 0)); |
| 743 mcs_client()->SendMessage(message2); |
| 744 |
| 745 LoginClient(std::vector<std::string>()); |
| 746 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 747 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 748 PumpLoop(); |
| 749 } |
| 750 |
| 751 // Sending two messages with the same collapse key and app id, but different |
| 752 // user, while disconnected, should not perform any collapsing. |
| 753 TEST_F(MCSClientTest, CollapseKeysDifferentUser) { |
| 754 BuildMCSClient(); |
| 755 InitializeClient(); |
| 756 MCSMessage message(BuildDataMessage( |
| 757 "from", "app", "message id 1", 1, "1", kTTLValue, 1, 0, "token", 0)); |
| 758 mcs_client()->SendMessage(message); |
| 759 |
| 760 MCSMessage message2(BuildDataMessage("from", |
| 761 "app", |
| 762 "message id 2", |
| 763 1, |
| 764 "2", |
| 765 kTTLValue, |
| 766 1, |
| 767 0, |
| 768 "token", |
| 769 1)); |
| 770 mcs_client()->SendMessage(message2); |
| 771 |
| 772 LoginClient(std::vector<std::string>()); |
| 773 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 774 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 775 PumpLoop(); |
| 776 } |
| 777 |
| 710 } // namespace | 778 } // namespace |
| 711 | 779 |
| 712 } // namespace gcm | 780 } // namespace gcm |
| OLD | NEW |