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