| 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( | 344 MCSMessage( |
| 339 kLoginRequestTag, | 345 kLoginRequestTag, |
| 340 BuildLoginRequest(kAndroidId, kSecurityToken). | 346 BuildLoginRequest(kAndroidId, kSecurityToken). |
| 341 PassAs<const google::protobuf::MessageLite>())); | 347 PassAs<const google::protobuf::MessageLite>())); |
| 342 // The second (re)send. | 348 // The second (re)send. |
| 343 MCSMessage message2(BuildDataMessage("from", | 349 MCSMessage message2(BuildDataMessage( |
| 344 "category", | 350 "from", "category", "X", 1, "1", kTTLValue, 1, kTTLValue - 1, "", 0)); |
| 345 "X", | |
| 346 1, | |
| 347 "1", | |
| 348 kTTLValue, | |
| 349 1, | |
| 350 kTTLValue - 1)); | |
| 351 GetFakeHandler()->ExpectOutgoingMessage(message2); | 351 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 352 mcs_client()->SendMessage(message); | 352 mcs_client()->SendMessage(message); |
| 353 PumpLoop(); // Wait for the queuing to happen. | 353 PumpLoop(); // Wait for the queuing to happen. |
| 354 EXPECT_EQ(MCSClient::QUEUED, message_send_status()); | 354 EXPECT_EQ(MCSClient::QUEUED, message_send_status()); |
| 355 EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 355 EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 356 GetFakeHandler()->set_fail_send(false); | 356 GetFakeHandler()->set_fail_send(false); |
| 357 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1)); | 357 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1)); |
| 358 connection_factory()->Connect(); | 358 connection_factory()->Connect(); |
| 359 WaitForMCSEvent(); // Wait for the login to finish. | 359 WaitForMCSEvent(); // Wait for the login to finish. |
| 360 PumpLoop(); // Wait for the send to happen. | 360 PumpLoop(); // Wait for the send to happen. |
| 361 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 361 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 362 } | 362 } |
| 363 | 363 |
| 364 // Send a message with RMQ support without receiving an acknowledgement. On | 364 // Send a message with RMQ support without receiving an acknowledgement. On |
| 365 // restart the message should be resent. | 365 // restart the message should be resent. |
| 366 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { | 366 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { |
| 367 BuildMCSClient(); | 367 BuildMCSClient(); |
| 368 InitializeClient(); | 368 InitializeClient(); |
| 369 LoginClient(std::vector<std::string>()); | 369 LoginClient(std::vector<std::string>()); |
| 370 GetFakeHandler()->set_fail_send(true); | 370 GetFakeHandler()->set_fail_send(true); |
| 371 MCSMessage message( | 371 MCSMessage message(BuildDataMessage( |
| 372 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0)); | 372 "from", "category", "X", 1, "1", kTTLValue, 1, 0, "", 0)); |
| 373 | 373 |
| 374 // The initial (failed) send. | 374 // The initial (failed) send. |
| 375 GetFakeHandler()->ExpectOutgoingMessage(message); | 375 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 376 GetFakeHandler()->set_fail_send(false); | 376 GetFakeHandler()->set_fail_send(false); |
| 377 mcs_client()->SendMessage(message); | 377 mcs_client()->SendMessage(message); |
| 378 PumpLoop(); | 378 PumpLoop(); |
| 379 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 379 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 380 | 380 |
| 381 // Rebuild the client, which should resend the old message. | 381 // Rebuild the client, which should resend the old message. |
| 382 StoreCredentials(); | 382 StoreCredentials(); |
| 383 BuildMCSClient(); | 383 BuildMCSClient(); |
| 384 InitializeClient(); | 384 InitializeClient(); |
| 385 | 385 |
| 386 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1)); | 386 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1)); |
| 387 MCSMessage message2(BuildDataMessage("from", | 387 MCSMessage message2(BuildDataMessage( |
| 388 "category", | 388 "from", "category", "X", 1, "1", kTTLValue, 1, kTTLValue - 1, "", 0)); |
| 389 "X", | |
| 390 1, | |
| 391 "1", | |
| 392 kTTLValue, | |
| 393 1, | |
| 394 kTTLValue - 1)); | |
| 395 LoginClient(std::vector<std::string>()); | 389 LoginClient(std::vector<std::string>()); |
| 396 GetFakeHandler()->ExpectOutgoingMessage(message2); | 390 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 397 PumpLoop(); | 391 PumpLoop(); |
| 398 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 392 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 399 } | 393 } |
| 400 | 394 |
| 401 // Send messages with RMQ support, followed by receiving a stream ack. On | 395 // Send messages with RMQ support, followed by receiving a stream ack. On |
| 402 // restart nothing should be recent. | 396 // restart nothing should be recent. |
| 403 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { | 397 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { |
| 404 BuildMCSClient(); | 398 BuildMCSClient(); |
| 405 InitializeClient(); | 399 InitializeClient(); |
| 406 LoginClient(std::vector<std::string>()); | 400 LoginClient(std::vector<std::string>()); |
| 407 | 401 |
| 408 // Send some messages. | 402 // Send some messages. |
| 409 for (int i = 1; i <= kMessageBatchSize; ++i) { | 403 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 410 MCSMessage message( | 404 MCSMessage message(BuildDataMessage("from", |
| 411 BuildDataMessage("from", | 405 "category", |
| 412 "category", | 406 "X", |
| 413 "X", | 407 1, |
| 414 1, | 408 base::IntToString(i), |
| 415 base::IntToString(i), | 409 kTTLValue, |
| 416 kTTLValue, | 410 1, |
| 417 1, | 411 0, |
| 418 0)); | 412 "", |
| 413 0)); |
| 419 GetFakeHandler()->ExpectOutgoingMessage(message); | 414 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 420 mcs_client()->SendMessage(message); | 415 mcs_client()->SendMessage(message); |
| 421 PumpLoop(); | 416 PumpLoop(); |
| 422 } | 417 } |
| 423 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 418 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 424 | 419 |
| 425 // Receive the ack. | 420 // Receive the ack. |
| 426 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 421 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
| 427 ack->set_last_stream_id_received(kMessageBatchSize + 1); | 422 ack->set_last_stream_id_received(kMessageBatchSize + 1); |
| 428 GetFakeHandler()->ReceiveMessage( | 423 GetFakeHandler()->ReceiveMessage( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 442 // the login response. No messages should be resent. | 437 // the login response. No messages should be resent. |
| 443 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { | 438 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { |
| 444 BuildMCSClient(); | 439 BuildMCSClient(); |
| 445 InitializeClient(); | 440 InitializeClient(); |
| 446 LoginClient(std::vector<std::string>()); | 441 LoginClient(std::vector<std::string>()); |
| 447 | 442 |
| 448 // Send some messages. | 443 // Send some messages. |
| 449 std::vector<std::string> id_list; | 444 std::vector<std::string> id_list; |
| 450 for (int i = 1; i <= kMessageBatchSize; ++i) { | 445 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 451 id_list.push_back(base::IntToString(i)); | 446 id_list.push_back(base::IntToString(i)); |
| 452 MCSMessage message( | 447 MCSMessage message(BuildDataMessage("from", |
| 453 BuildDataMessage("from", | 448 "category", |
| 454 "category", | 449 id_list.back(), |
| 455 id_list.back(), | 450 1, |
| 456 1, | 451 id_list.back(), |
| 457 id_list.back(), | 452 kTTLValue, |
| 458 kTTLValue, | 453 1, |
| 459 1, | 454 0, |
| 460 0)); | 455 "", |
| 456 0)); |
| 461 GetFakeHandler()->ExpectOutgoingMessage(message); | 457 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 462 mcs_client()->SendMessage(message); | 458 mcs_client()->SendMessage(message); |
| 463 PumpLoop(); | 459 PumpLoop(); |
| 464 } | 460 } |
| 465 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 461 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 466 | 462 |
| 467 // Rebuild the client, and receive an acknowledgment for the messages as | 463 // Rebuild the client, and receive an acknowledgment for the messages as |
| 468 // part of the login response. | 464 // part of the login response. |
| 469 StoreCredentials(); | 465 StoreCredentials(); |
| 470 BuildMCSClient(); | 466 BuildMCSClient(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 482 // be resent. | 478 // be resent. |
| 483 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { | 479 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { |
| 484 BuildMCSClient(); | 480 BuildMCSClient(); |
| 485 InitializeClient(); | 481 InitializeClient(); |
| 486 LoginClient(std::vector<std::string>()); | 482 LoginClient(std::vector<std::string>()); |
| 487 | 483 |
| 488 // Send some messages. | 484 // Send some messages. |
| 489 std::vector<std::string> id_list; | 485 std::vector<std::string> id_list; |
| 490 for (int i = 1; i <= kMessageBatchSize; ++i) { | 486 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 491 id_list.push_back(base::IntToString(i)); | 487 id_list.push_back(base::IntToString(i)); |
| 492 MCSMessage message( | 488 MCSMessage message(BuildDataMessage("from", |
| 493 BuildDataMessage("from", | 489 "category", |
| 494 "category", | 490 id_list.back(), |
| 495 id_list.back(), | 491 1, |
| 496 1, | 492 id_list.back(), |
| 497 id_list.back(), | 493 kTTLValue, |
| 498 kTTLValue, | 494 1, |
| 499 1, | 495 0, |
| 500 0)); | 496 "", |
| 497 0)); |
| 501 GetFakeHandler()->ExpectOutgoingMessage(message); | 498 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 502 mcs_client()->SendMessage(message); | 499 mcs_client()->SendMessage(message); |
| 503 PumpLoop(); | 500 PumpLoop(); |
| 504 } | 501 } |
| 505 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 502 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 506 | 503 |
| 507 // Rebuild the client, and receive an acknowledgment for the messages as | 504 // Rebuild the client, and receive an acknowledgment for the messages as |
| 508 // part of the login response. | 505 // part of the login response. |
| 509 StoreCredentials(); | 506 StoreCredentials(); |
| 510 BuildMCSClient(); | 507 BuildMCSClient(); |
| 511 InitializeClient(); | 508 InitializeClient(); |
| 512 LoginClient(std::vector<std::string>()); | 509 LoginClient(std::vector<std::string>()); |
| 513 | 510 |
| 514 std::vector<std::string> acked_ids, remaining_ids; | 511 std::vector<std::string> acked_ids, remaining_ids; |
| 515 acked_ids.insert(acked_ids.end(), | 512 acked_ids.insert(acked_ids.end(), |
| 516 id_list.begin(), | 513 id_list.begin(), |
| 517 id_list.begin() + kMessageBatchSize / 2); | 514 id_list.begin() + kMessageBatchSize / 2); |
| 518 remaining_ids.insert(remaining_ids.end(), | 515 remaining_ids.insert(remaining_ids.end(), |
| 519 id_list.begin() + kMessageBatchSize / 2, | 516 id_list.begin() + kMessageBatchSize / 2, |
| 520 id_list.end()); | 517 id_list.end()); |
| 521 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { | 518 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { |
| 522 MCSMessage message( | 519 MCSMessage message(BuildDataMessage("from", |
| 523 BuildDataMessage("from", | 520 "category", |
| 524 "category", | 521 remaining_ids[i - 1], |
| 525 remaining_ids[i - 1], | 522 2, |
| 526 2, | 523 remaining_ids[i - 1], |
| 527 remaining_ids[i - 1], | 524 kTTLValue, |
| 528 kTTLValue, | 525 1, |
| 529 1, 0)); | 526 0, |
| 527 "", |
| 528 0)); |
| 530 GetFakeHandler()->ExpectOutgoingMessage(message); | 529 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 531 } | 530 } |
| 532 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); | 531 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); |
| 533 GetFakeHandler()->ReceiveMessage( | 532 GetFakeHandler()->ReceiveMessage( |
| 534 MCSMessage(kIqStanzaTag, | 533 MCSMessage(kIqStanzaTag, |
| 535 ack.PassAs<const google::protobuf::MessageLite>())); | 534 ack.PassAs<const google::protobuf::MessageLite>())); |
| 536 WaitForMCSEvent(); | 535 WaitForMCSEvent(); |
| 537 PumpLoop(); | 536 PumpLoop(); |
| 538 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 537 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 539 } | 538 } |
| 540 | 539 |
| 541 // Receive some messages. On restart, the login request should contain the | 540 // Receive some messages. On restart, the login request should contain the |
| 542 // appropriate acknowledged ids. | 541 // appropriate acknowledged ids. |
| 543 TEST_F(MCSClientTest, AckOnLogin) { | 542 TEST_F(MCSClientTest, AckOnLogin) { |
| 544 BuildMCSClient(); | 543 BuildMCSClient(); |
| 545 InitializeClient(); | 544 InitializeClient(); |
| 546 LoginClient(std::vector<std::string>()); | 545 LoginClient(std::vector<std::string>()); |
| 547 | 546 |
| 548 // Receive some messages. | 547 // Receive some messages. |
| 549 std::vector<std::string> id_list; | 548 std::vector<std::string> id_list; |
| 550 for (int i = 1; i <= kMessageBatchSize; ++i) { | 549 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 551 id_list.push_back(base::IntToString(i)); | 550 id_list.push_back(base::IntToString(i)); |
| 552 MCSMessage message( | 551 MCSMessage message(BuildDataMessage( |
| 553 BuildDataMessage("from", | 552 "from", "category", "X", 1, id_list.back(), kTTLValue, 1, 0, "", 0)); |
| 554 "category", | |
| 555 "X", | |
| 556 1, | |
| 557 id_list.back(), | |
| 558 kTTLValue, | |
| 559 1, | |
| 560 0)); | |
| 561 GetFakeHandler()->ReceiveMessage(message); | 553 GetFakeHandler()->ReceiveMessage(message); |
| 562 WaitForMCSEvent(); | 554 WaitForMCSEvent(); |
| 563 PumpLoop(); | 555 PumpLoop(); |
| 564 } | 556 } |
| 565 | 557 |
| 566 // Restart the client. | 558 // Restart the client. |
| 567 StoreCredentials(); | 559 StoreCredentials(); |
| 568 BuildMCSClient(); | 560 BuildMCSClient(); |
| 569 InitializeClient(); | 561 InitializeClient(); |
| 570 LoginClient(id_list); | 562 LoginClient(id_list); |
| 571 } | 563 } |
| 572 | 564 |
| 573 // Receive some messages. On the next send, the outgoing message should contain | 565 // Receive some messages. On the next send, the outgoing message should contain |
| 574 // the appropriate last stream id received field to ack the received messages. | 566 // the appropriate last stream id received field to ack the received messages. |
| 575 TEST_F(MCSClientTest, AckOnSend) { | 567 TEST_F(MCSClientTest, AckOnSend) { |
| 576 BuildMCSClient(); | 568 BuildMCSClient(); |
| 577 InitializeClient(); | 569 InitializeClient(); |
| 578 LoginClient(std::vector<std::string>()); | 570 LoginClient(std::vector<std::string>()); |
| 579 | 571 |
| 580 // Receive some messages. | 572 // Receive some messages. |
| 581 std::vector<std::string> id_list; | 573 std::vector<std::string> id_list; |
| 582 for (int i = 1; i <= kMessageBatchSize; ++i) { | 574 for (int i = 1; i <= kMessageBatchSize; ++i) { |
| 583 id_list.push_back(base::IntToString(i)); | 575 id_list.push_back(base::IntToString(i)); |
| 584 MCSMessage message( | 576 MCSMessage message(BuildDataMessage("from", |
| 585 BuildDataMessage("from", | 577 "category", |
| 586 "category", | 578 id_list.back(), |
| 587 id_list.back(), | 579 1, |
| 588 1, | 580 id_list.back(), |
| 589 id_list.back(), | 581 kTTLValue, |
| 590 kTTLValue, | 582 1, |
| 591 1, | 583 0, |
| 592 0)); | 584 "", |
| 585 0)); |
| 593 GetFakeHandler()->ReceiveMessage(message); | 586 GetFakeHandler()->ReceiveMessage(message); |
| 594 PumpLoop(); | 587 PumpLoop(); |
| 595 } | 588 } |
| 596 | 589 |
| 597 // Trigger a message send, which should acknowledge via stream ack. | 590 // Trigger a message send, which should acknowledge via stream ack. |
| 598 MCSMessage message( | 591 MCSMessage message(BuildDataMessage("from", |
| 599 BuildDataMessage("from", | 592 "category", |
| 600 "category", | 593 "X", |
| 601 "X", | 594 kMessageBatchSize + 1, |
| 602 kMessageBatchSize + 1, | 595 "1", |
| 603 "1", | 596 kTTLValue, |
| 604 kTTLValue, | 597 1, |
| 605 1, 0)); | 598 0, |
| 599 "", |
| 600 0)); |
| 606 GetFakeHandler()->ExpectOutgoingMessage(message); | 601 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 607 mcs_client()->SendMessage(message); | 602 mcs_client()->SendMessage(message); |
| 608 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 603 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 609 } | 604 } |
| 610 | 605 |
| 611 // Receive the ack limit in messages, which should trigger an automatic | 606 // Receive the ack limit in messages, which should trigger an automatic |
| 612 // stream ack. Receive a heartbeat to confirm the ack. | 607 // stream ack. Receive a heartbeat to confirm the ack. |
| 613 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { | 608 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { |
| 614 BuildMCSClient(); | 609 BuildMCSClient(); |
| 615 InitializeClient(); | 610 InitializeClient(); |
| 616 LoginClient(std::vector<std::string>()); | 611 LoginClient(std::vector<std::string>()); |
| 617 | 612 |
| 618 // The stream ack. | 613 // The stream ack. |
| 619 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 614 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
| 620 ack->set_last_stream_id_received(kAckLimitSize + 1); | 615 ack->set_last_stream_id_received(kAckLimitSize + 1); |
| 621 GetFakeHandler()->ExpectOutgoingMessage( | 616 GetFakeHandler()->ExpectOutgoingMessage( |
| 622 MCSMessage(kIqStanzaTag, | 617 MCSMessage(kIqStanzaTag, |
| 623 ack.PassAs<const google::protobuf::MessageLite>())); | 618 ack.PassAs<const google::protobuf::MessageLite>())); |
| 624 | 619 |
| 625 // Receive some messages. | 620 // Receive some messages. |
| 626 std::vector<std::string> id_list; | 621 std::vector<std::string> id_list; |
| 627 for (int i = 1; i <= kAckLimitSize; ++i) { | 622 for (int i = 1; i <= kAckLimitSize; ++i) { |
| 628 id_list.push_back(base::IntToString(i)); | 623 id_list.push_back(base::IntToString(i)); |
| 629 MCSMessage message( | 624 MCSMessage message(BuildDataMessage("from", |
| 630 BuildDataMessage("from", | 625 "category", |
| 631 "category", | 626 id_list.back(), |
| 632 id_list.back(), | 627 1, |
| 633 1, | 628 id_list.back(), |
| 634 id_list.back(), | 629 kTTLValue, |
| 635 kTTLValue, | 630 1, |
| 636 1, | 631 0, |
| 637 0)); | 632 "", |
| 633 0)); |
| 638 GetFakeHandler()->ReceiveMessage(message); | 634 GetFakeHandler()->ReceiveMessage(message); |
| 639 WaitForMCSEvent(); | 635 WaitForMCSEvent(); |
| 640 PumpLoop(); | 636 PumpLoop(); |
| 641 } | 637 } |
| 642 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 638 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 643 | 639 |
| 644 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). | 640 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). |
| 645 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( | 641 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( |
| 646 new mcs_proto::HeartbeatPing()); | 642 new mcs_proto::HeartbeatPing()); |
| 647 heartbeat->set_last_stream_id_received(2); | 643 heartbeat->set_last_stream_id_received(2); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 666 LoginClient(std::vector<std::string>()); | 662 LoginClient(std::vector<std::string>()); |
| 667 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 663 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 668 } | 664 } |
| 669 | 665 |
| 670 // If a message's TTL has expired by the time it reaches the front of the send | 666 // If a message's TTL has expired by the time it reaches the front of the send |
| 671 // queue, it should be dropped. | 667 // queue, it should be dropped. |
| 672 TEST_F(MCSClientTest, ExpiredTTLOnSend) { | 668 TEST_F(MCSClientTest, ExpiredTTLOnSend) { |
| 673 BuildMCSClient(); | 669 BuildMCSClient(); |
| 674 InitializeClient(); | 670 InitializeClient(); |
| 675 LoginClient(std::vector<std::string>()); | 671 LoginClient(std::vector<std::string>()); |
| 676 MCSMessage message( | 672 MCSMessage message(BuildDataMessage( |
| 677 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0)); | 673 "from", "category", "X", 1, "1", kTTLValue, 1, 0, "", 0)); |
| 678 | 674 |
| 679 // Advance time to after the TTL. | 675 // Advance time to after the TTL. |
| 680 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); | 676 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); |
| 681 EXPECT_TRUE(sent_message_id().empty()); | 677 EXPECT_TRUE(sent_message_id().empty()); |
| 682 mcs_client()->SendMessage(message); | 678 mcs_client()->SendMessage(message); |
| 683 | 679 |
| 684 // No messages should be sent, but the callback should still be invoked. | 680 // No messages should be sent, but the callback should still be invoked. |
| 685 EXPECT_EQ("X", sent_message_id()); | 681 EXPECT_EQ("X", sent_message_id()); |
| 686 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status()); | 682 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status()); |
| 687 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 683 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 688 } | 684 } |
| 689 | 685 |
| 690 TEST_F(MCSClientTest, ExpiredTTLOnRestart) { | 686 TEST_F(MCSClientTest, ExpiredTTLOnRestart) { |
| 691 BuildMCSClient(); | 687 BuildMCSClient(); |
| 692 InitializeClient(); | 688 InitializeClient(); |
| 693 LoginClient(std::vector<std::string>()); | 689 LoginClient(std::vector<std::string>()); |
| 694 GetFakeHandler()->set_fail_send(true); | 690 GetFakeHandler()->set_fail_send(true); |
| 695 MCSMessage message( | 691 MCSMessage message(BuildDataMessage( |
| 696 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0)); | 692 "from", "category", "X", 1, "1", kTTLValue, 1, 0, "", 0)); |
| 697 | 693 |
| 698 // The initial (failed) send. | 694 // The initial (failed) send. |
| 699 GetFakeHandler()->ExpectOutgoingMessage(message); | 695 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 700 GetFakeHandler()->set_fail_send(false); | 696 GetFakeHandler()->set_fail_send(false); |
| 701 mcs_client()->SendMessage(message); | 697 mcs_client()->SendMessage(message); |
| 702 PumpLoop(); | 698 PumpLoop(); |
| 703 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 699 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 704 | 700 |
| 705 // Move the clock forward and rebuild the client, which should fail the | 701 // Move the clock forward and rebuild the client, which should fail the |
| 706 // message send on restart. | 702 // message send on restart. |
| 707 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); | 703 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); |
| 708 StoreCredentials(); | 704 StoreCredentials(); |
| 709 BuildMCSClient(); | 705 BuildMCSClient(); |
| 710 InitializeClient(); | 706 InitializeClient(); |
| 711 LoginClient(std::vector<std::string>()); | 707 LoginClient(std::vector<std::string>()); |
| 712 PumpLoop(); | 708 PumpLoop(); |
| 713 EXPECT_EQ("X", sent_message_id()); | 709 EXPECT_EQ("X", sent_message_id()); |
| 714 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status()); | 710 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status()); |
| 715 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | 711 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 716 } | 712 } |
| 717 | 713 |
| 714 // Sending two messages with the same collapse key and same app id while |
| 715 // disconnected should only send the latter of the two on reconnection. |
| 716 TEST_F(MCSClientTest, CollapseKeysSameApp) { |
| 717 BuildMCSClient(); |
| 718 InitializeClient(); |
| 719 MCSMessage message(BuildDataMessage( |
| 720 "from", "app", "message id 1", 1, "1", kTTLValue, 1, 0, "token", 0)); |
| 721 mcs_client()->SendMessage(message); |
| 722 |
| 723 MCSMessage message2(BuildDataMessage( |
| 724 "from", "app", "message id 2", 1, "1", kTTLValue, 1, 0, "token", 0)); |
| 725 mcs_client()->SendMessage(message2); |
| 726 |
| 727 LoginClient(std::vector<std::string>()); |
| 728 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 729 PumpLoop(); |
| 730 } |
| 731 |
| 732 // Sending two messages with the same collapse key and different app id while |
| 733 // disconnected should not perform any collapsing. |
| 734 TEST_F(MCSClientTest, CollapseKeysDifferentApp) { |
| 735 BuildMCSClient(); |
| 736 InitializeClient(); |
| 737 MCSMessage message(BuildDataMessage( |
| 738 "from", "app", "message id 1", 1, "1", kTTLValue, 1, 0, "token", 0)); |
| 739 mcs_client()->SendMessage(message); |
| 740 |
| 741 MCSMessage message2(BuildDataMessage("from", |
| 742 "app 2", |
| 743 "message id 2", |
| 744 1, |
| 745 "2", |
| 746 kTTLValue, |
| 747 1, |
| 748 0, |
| 749 "token", |
| 750 0)); |
| 751 mcs_client()->SendMessage(message2); |
| 752 |
| 753 LoginClient(std::vector<std::string>()); |
| 754 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 755 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 756 PumpLoop(); |
| 757 } |
| 758 |
| 759 // Sending two messages with the same collapse key and app id, but different |
| 760 // user, while disconnected, should not perform any collapsing. |
| 761 TEST_F(MCSClientTest, CollapseKeysDifferentUser) { |
| 762 BuildMCSClient(); |
| 763 InitializeClient(); |
| 764 MCSMessage message(BuildDataMessage( |
| 765 "from", "app", "message id 1", 1, "1", kTTLValue, 1, 0, "token", 0)); |
| 766 mcs_client()->SendMessage(message); |
| 767 |
| 768 MCSMessage message2(BuildDataMessage("from", |
| 769 "app", |
| 770 "message id 2", |
| 771 1, |
| 772 "2", |
| 773 kTTLValue, |
| 774 1, |
| 775 0, |
| 776 "token", |
| 777 1)); |
| 778 mcs_client()->SendMessage(message2); |
| 779 |
| 780 LoginClient(std::vector<std::string>()); |
| 781 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 782 GetFakeHandler()->ExpectOutgoingMessage(message2); |
| 783 PumpLoop(); |
| 784 } |
| 785 |
| 718 } // namespace | 786 } // namespace |
| 719 | 787 |
| 720 } // namespace gcm | 788 } // namespace gcm |
| OLD | NEW |