Update ASan/Android runtime and setup script to LLVM r200682.
[chromium-blink-merge.git] / google_apis / gcm / engine / mcs_client_unittest.cc
blob6bdce132b68b065fd6260ea024c6944691456840
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
3 // found in the LICENSE file.
5 #include "google_apis/gcm/engine/mcs_client.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/test/simple_test_clock.h"
12 #include "components/webdata/encryptor/encryptor.h"
13 #include "google_apis/gcm/base/mcs_util.h"
14 #include "google_apis/gcm/engine/fake_connection_factory.h"
15 #include "google_apis/gcm/engine/fake_connection_handler.h"
16 #include "google_apis/gcm/engine/gcm_store_impl.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace gcm {
21 namespace {
23 const uint64 kAndroidId = 54321;
24 const uint64 kSecurityToken = 12345;
26 // Number of messages to send when testing batching.
27 // Note: must be even for tests that split batches in half.
28 const int kMessageBatchSize = 6;
30 // The number of unacked messages the client will receive before sending a
31 // stream ack.
32 // TODO(zea): get this (and other constants) directly from the mcs client.
33 const int kAckLimitSize = 10;
35 // TTL value for reliable messages.
36 const int kTTLValue = 5 * 60; // 5 minutes.
38 // Helper for building arbitrary data messages.
39 MCSMessage BuildDataMessage(const std::string& from,
40 const std::string& category,
41 const std::string& message_id,
42 int last_stream_id_received,
43 const std::string& persistent_id,
44 int ttl,
45 uint64 sent,
46 int queued) {
47 mcs_proto::DataMessageStanza data_message;
48 data_message.set_id(message_id);
49 data_message.set_from(from);
50 data_message.set_category(category);
51 data_message.set_last_stream_id_received(last_stream_id_received);
52 if (!persistent_id.empty())
53 data_message.set_persistent_id(persistent_id);
54 data_message.set_ttl(ttl);
55 data_message.set_sent(sent);
56 data_message.set_queued(queued);
57 return MCSMessage(kDataMessageStanzaTag, data_message);
60 // MCSClient with overriden exposed persistent id logic.
61 class TestMCSClient : public MCSClient {
62 public:
63 TestMCSClient(base::Clock* clock,
64 ConnectionFactory* connection_factory,
65 GCMStore* gcm_store)
66 : MCSClient(clock, connection_factory, gcm_store),
67 next_id_(0) {
70 virtual std::string GetNextPersistentId() OVERRIDE {
71 return base::UintToString(++next_id_);
74 private:
75 uint32 next_id_;
78 class MCSClientTest : public testing::Test {
79 public:
80 MCSClientTest();
81 virtual ~MCSClientTest();
83 void BuildMCSClient();
84 void InitializeClient();
85 void StoreCredentials();
86 void LoginClient(const std::vector<std::string>& acknowledged_ids);
88 base::SimpleTestClock* clock() { return &clock_; }
89 TestMCSClient* mcs_client() const { return mcs_client_.get(); }
90 FakeConnectionFactory* connection_factory() {
91 return &connection_factory_;
93 bool init_success() const { return init_success_; }
94 std::vector<int64> user_serial_numbers() const {
95 std::vector<int64> user_serial_numbers;
96 user_serial_numbers.push_back(1LL);
97 return user_serial_numbers;
99 uint64 restored_android_id() const { return restored_android_id_; }
100 uint64 restored_security_token() const { return restored_security_token_; }
101 MCSMessage* received_message() const { return received_message_.get(); }
102 std::string sent_message_id() const { return sent_message_id_;}
103 MCSClient::MessageSendStatus message_send_status() const {
104 return message_send_status_;
107 void SetDeviceCredentialsCallback(bool success);
109 FakeConnectionHandler* GetFakeHandler() const;
111 void WaitForMCSEvent();
112 void PumpLoop();
114 private:
115 void ErrorCallback();
116 void MessageReceivedCallback(const MCSMessage& message);
117 void MessageSentCallback(int64 user_serial_number,
118 const std::string& app_id,
119 const std::string& message_id,
120 MCSClient::MessageSendStatus status);
122 base::SimpleTestClock clock_;
124 base::ScopedTempDir temp_directory_;
125 base::MessageLoop message_loop_;
126 scoped_ptr<base::RunLoop> run_loop_;
127 scoped_ptr<GCMStore> gcm_store_;
129 FakeConnectionFactory connection_factory_;
130 scoped_ptr<TestMCSClient> mcs_client_;
131 bool init_success_;
132 uint64 restored_android_id_;
133 uint64 restored_security_token_;
134 scoped_ptr<MCSMessage> received_message_;
135 std::string sent_message_id_;
136 MCSClient::MessageSendStatus message_send_status_;
139 MCSClientTest::MCSClientTest()
140 : run_loop_(new base::RunLoop()),
141 init_success_(true),
142 restored_android_id_(0),
143 restored_security_token_(0),
144 message_send_status_(MCSClient::SENT) {
145 EXPECT_TRUE(temp_directory_.CreateUniqueTempDir());
146 run_loop_.reset(new base::RunLoop());
148 // On OSX, prevent the Keychain permissions popup during unit tests.
149 #if defined(OS_MACOSX)
150 Encryptor::UseMockKeychain(true);
151 #endif
153 // Advance the clock to a non-zero time.
154 clock_.Advance(base::TimeDelta::FromSeconds(1));
157 MCSClientTest::~MCSClientTest() {}
159 void MCSClientTest::BuildMCSClient() {
160 gcm_store_.reset(new GCMStoreImpl(true,
161 temp_directory_.path(),
162 message_loop_.message_loop_proxy()));
163 mcs_client_.reset(new TestMCSClient(&clock_,
164 &connection_factory_,
165 gcm_store_.get()));
168 void MCSClientTest::InitializeClient() {
169 gcm_store_->Load(base::Bind(
170 &MCSClient::Initialize,
171 base::Unretained(mcs_client_.get()),
172 base::Bind(&MCSClientTest::ErrorCallback,
173 base::Unretained(this)),
174 base::Bind(&MCSClientTest::MessageReceivedCallback,
175 base::Unretained(this)),
176 base::Bind(&MCSClientTest::MessageSentCallback, base::Unretained(this))));
177 run_loop_->RunUntilIdle();
178 run_loop_.reset(new base::RunLoop());
181 void MCSClientTest::LoginClient(
182 const std::vector<std::string>& acknowledged_ids) {
183 scoped_ptr<mcs_proto::LoginRequest> login_request =
184 BuildLoginRequest(kAndroidId, kSecurityToken, user_serial_numbers());
185 for (size_t i = 0; i < acknowledged_ids.size(); ++i)
186 login_request->add_received_persistent_id(acknowledged_ids[i]);
187 GetFakeHandler()->ExpectOutgoingMessage(
188 MCSMessage(kLoginRequestTag,
189 login_request.PassAs<const google::protobuf::MessageLite>()));
190 mcs_client_->Login(kAndroidId, kSecurityToken, user_serial_numbers());
191 run_loop_->Run();
192 run_loop_.reset(new base::RunLoop());
195 void MCSClientTest::StoreCredentials() {
196 gcm_store_->SetDeviceCredentials(
197 kAndroidId, kSecurityToken,
198 base::Bind(&MCSClientTest::SetDeviceCredentialsCallback,
199 base::Unretained(this)));
200 run_loop_->Run();
201 run_loop_.reset(new base::RunLoop());
204 FakeConnectionHandler* MCSClientTest::GetFakeHandler() const {
205 return reinterpret_cast<FakeConnectionHandler*>(
206 connection_factory_.GetConnectionHandler());
209 void MCSClientTest::WaitForMCSEvent() {
210 run_loop_->Run();
211 run_loop_.reset(new base::RunLoop());
214 void MCSClientTest::PumpLoop() {
215 run_loop_->RunUntilIdle();
216 run_loop_.reset(new base::RunLoop());
219 void MCSClientTest::ErrorCallback() {
220 init_success_ = false;
221 DVLOG(1) << "Error callback invoked, killing loop.";
222 run_loop_->Quit();
225 void MCSClientTest::MessageReceivedCallback(const MCSMessage& message) {
226 received_message_.reset(new MCSMessage(message));
227 DVLOG(1) << "Message received callback invoked, killing loop.";
228 run_loop_->Quit();
231 void MCSClientTest::MessageSentCallback(int64 user_serial_number,
232 const std::string& app_id,
233 const std::string& message_id,
234 MCSClient::MessageSendStatus status) {
235 DVLOG(1) << "Message sent callback invoked, killing loop.";
236 sent_message_id_ = message_id;
237 message_send_status_ = status;
238 run_loop_->Quit();
241 void MCSClientTest::SetDeviceCredentialsCallback(bool success) {
242 ASSERT_TRUE(success);
243 run_loop_->Quit();
246 // Initialize a new client.
247 TEST_F(MCSClientTest, InitializeNew) {
248 BuildMCSClient();
249 InitializeClient();
250 EXPECT_TRUE(init_success());
253 // Initialize a new client, shut it down, then restart the client. Should
254 // reload the existing device credentials.
255 TEST_F(MCSClientTest, InitializeExisting) {
256 BuildMCSClient();
257 InitializeClient();
258 LoginClient(std::vector<std::string>());
260 // Rebuild the client, to reload from the GCM store.
261 StoreCredentials();
262 BuildMCSClient();
263 InitializeClient();
264 EXPECT_TRUE(init_success());
267 // Log in successfully to the MCS endpoint.
268 TEST_F(MCSClientTest, LoginSuccess) {
269 BuildMCSClient();
270 InitializeClient();
271 LoginClient(std::vector<std::string>());
272 EXPECT_TRUE(connection_factory()->IsEndpointReachable());
273 EXPECT_TRUE(init_success());
274 ASSERT_TRUE(received_message());
275 EXPECT_EQ(kLoginResponseTag, received_message()->tag());
278 // Encounter a server error during the login attempt.
279 TEST_F(MCSClientTest, FailLogin) {
280 BuildMCSClient();
281 InitializeClient();
282 GetFakeHandler()->set_fail_login(true);
283 LoginClient(std::vector<std::string>());
284 EXPECT_FALSE(connection_factory()->IsEndpointReachable());
285 EXPECT_FALSE(init_success());
286 EXPECT_FALSE(received_message());
289 // Send a message without RMQ support.
290 TEST_F(MCSClientTest, SendMessageNoRMQ) {
291 BuildMCSClient();
292 InitializeClient();
293 LoginClient(std::vector<std::string>());
294 MCSMessage message(BuildDataMessage("from", "category", "X", 1, "", 0, 1, 0));
295 GetFakeHandler()->ExpectOutgoingMessage(message);
296 mcs_client()->SendMessage(message);
297 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
300 // Send a message without RMQ support while disconnected. Message send should
301 // fail immediately, invoking callback.
302 TEST_F(MCSClientTest, SendMessageNoRMQWhileDisconnected) {
303 BuildMCSClient();
304 InitializeClient();
306 EXPECT_TRUE(sent_message_id().empty());
307 MCSMessage message(BuildDataMessage("from", "category", "X", 1, "", 0, 1, 0));
308 mcs_client()->SendMessage(message);
310 // Message sent callback should be invoked, but no message should actually
311 // be sent.
312 EXPECT_EQ("X", sent_message_id());
313 EXPECT_EQ(MCSClient::NO_CONNECTION_ON_ZERO_TTL, message_send_status());
314 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
317 // Send a message with RMQ support.
318 TEST_F(MCSClientTest, SendMessageRMQ) {
319 BuildMCSClient();
320 InitializeClient();
321 LoginClient(std::vector<std::string>());
322 MCSMessage message(
323 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0));
324 GetFakeHandler()->ExpectOutgoingMessage(message);
325 mcs_client()->SendMessage(message);
326 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
329 // Send a message with RMQ support while disconnected. On reconnect, the message
330 // should be resent.
331 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) {
332 BuildMCSClient();
333 InitializeClient();
334 LoginClient(std::vector<std::string>());
335 GetFakeHandler()->set_fail_send(true);
336 MCSMessage message(
337 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0));
339 // The initial (failed) send.
340 GetFakeHandler()->ExpectOutgoingMessage(message);
341 // The login request.
342 GetFakeHandler()->ExpectOutgoingMessage(
343 MCSMessage(
344 kLoginRequestTag,
345 BuildLoginRequest(kAndroidId, kSecurityToken, user_serial_numbers()).
346 PassAs<const google::protobuf::MessageLite>()));
347 // The second (re)send.
348 MCSMessage message2(BuildDataMessage("from",
349 "category",
350 "X",
352 "1",
353 kTTLValue,
355 kTTLValue - 1));
356 GetFakeHandler()->ExpectOutgoingMessage(message2);
357 mcs_client()->SendMessage(message);
358 PumpLoop(); // Wait for the queuing to happen.
359 EXPECT_EQ(MCSClient::QUEUED, message_send_status());
360 EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived());
361 GetFakeHandler()->set_fail_send(false);
362 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1));
363 connection_factory()->Connect();
364 WaitForMCSEvent(); // Wait for the login to finish.
365 PumpLoop(); // Wait for the send to happen.
366 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
369 // Send a message with RMQ support without receiving an acknowledgement. On
370 // restart the message should be resent.
371 TEST_F(MCSClientTest, SendMessageRMQOnRestart) {
372 BuildMCSClient();
373 InitializeClient();
374 LoginClient(std::vector<std::string>());
375 GetFakeHandler()->set_fail_send(true);
376 MCSMessage message(
377 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0));
379 // The initial (failed) send.
380 GetFakeHandler()->ExpectOutgoingMessage(message);
381 GetFakeHandler()->set_fail_send(false);
382 mcs_client()->SendMessage(message);
383 PumpLoop();
384 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
386 // Rebuild the client, which should resend the old message.
387 StoreCredentials();
388 BuildMCSClient();
389 InitializeClient();
391 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue - 1));
392 MCSMessage message2(BuildDataMessage("from",
393 "category",
394 "X",
396 "1",
397 kTTLValue,
399 kTTLValue - 1));
400 LoginClient(std::vector<std::string>());
401 GetFakeHandler()->ExpectOutgoingMessage(message2);
402 PumpLoop();
403 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
406 // Send messages with RMQ support, followed by receiving a stream ack. On
407 // restart nothing should be recent.
408 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) {
409 BuildMCSClient();
410 InitializeClient();
411 LoginClient(std::vector<std::string>());
413 // Send some messages.
414 for (int i = 1; i <= kMessageBatchSize; ++i) {
415 MCSMessage message(
416 BuildDataMessage("from",
417 "category",
418 "X",
420 base::IntToString(i),
421 kTTLValue,
423 0));
424 GetFakeHandler()->ExpectOutgoingMessage(message);
425 mcs_client()->SendMessage(message);
426 PumpLoop();
428 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
430 // Receive the ack.
431 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck();
432 ack->set_last_stream_id_received(kMessageBatchSize + 1);
433 GetFakeHandler()->ReceiveMessage(
434 MCSMessage(kIqStanzaTag,
435 ack.PassAs<const google::protobuf::MessageLite>()));
436 WaitForMCSEvent();
438 // Reconnect and ensure no messages are resent.
439 StoreCredentials();
440 BuildMCSClient();
441 InitializeClient();
442 LoginClient(std::vector<std::string>());
443 PumpLoop();
446 // Send messages with RMQ support. On restart, receive a SelectiveAck with
447 // the login response. No messages should be resent.
448 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) {
449 BuildMCSClient();
450 InitializeClient();
451 LoginClient(std::vector<std::string>());
453 // Send some messages.
454 std::vector<std::string> id_list;
455 for (int i = 1; i <= kMessageBatchSize; ++i) {
456 id_list.push_back(base::IntToString(i));
457 MCSMessage message(
458 BuildDataMessage("from",
459 "category",
460 id_list.back(),
462 id_list.back(),
463 kTTLValue,
465 0));
466 GetFakeHandler()->ExpectOutgoingMessage(message);
467 mcs_client()->SendMessage(message);
468 PumpLoop();
470 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
472 // Rebuild the client, and receive an acknowledgment for the messages as
473 // part of the login response.
474 StoreCredentials();
475 BuildMCSClient();
476 InitializeClient();
477 LoginClient(std::vector<std::string>());
478 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(id_list));
479 GetFakeHandler()->ReceiveMessage(
480 MCSMessage(kIqStanzaTag,
481 ack.PassAs<const google::protobuf::MessageLite>()));
482 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
485 // Send messages with RMQ support. On restart, receive a SelectiveAck with
486 // the login response that only acks some messages. The unacked messages should
487 // be resent.
488 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) {
489 BuildMCSClient();
490 InitializeClient();
491 LoginClient(std::vector<std::string>());
493 // Send some messages.
494 std::vector<std::string> id_list;
495 for (int i = 1; i <= kMessageBatchSize; ++i) {
496 id_list.push_back(base::IntToString(i));
497 MCSMessage message(
498 BuildDataMessage("from",
499 "category",
500 id_list.back(),
502 id_list.back(),
503 kTTLValue,
505 0));
506 GetFakeHandler()->ExpectOutgoingMessage(message);
507 mcs_client()->SendMessage(message);
508 PumpLoop();
510 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
512 // Rebuild the client, and receive an acknowledgment for the messages as
513 // part of the login response.
514 StoreCredentials();
515 BuildMCSClient();
516 InitializeClient();
517 LoginClient(std::vector<std::string>());
519 std::vector<std::string> acked_ids, remaining_ids;
520 acked_ids.insert(acked_ids.end(),
521 id_list.begin(),
522 id_list.begin() + kMessageBatchSize / 2);
523 remaining_ids.insert(remaining_ids.end(),
524 id_list.begin() + kMessageBatchSize / 2,
525 id_list.end());
526 for (int i = 1; i <= kMessageBatchSize / 2; ++i) {
527 MCSMessage message(
528 BuildDataMessage("from",
529 "category",
530 remaining_ids[i - 1],
532 remaining_ids[i - 1],
533 kTTLValue,
534 1, 0));
535 GetFakeHandler()->ExpectOutgoingMessage(message);
537 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids));
538 GetFakeHandler()->ReceiveMessage(
539 MCSMessage(kIqStanzaTag,
540 ack.PassAs<const google::protobuf::MessageLite>()));
541 WaitForMCSEvent();
542 PumpLoop();
543 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
546 // Receive some messages. On restart, the login request should contain the
547 // appropriate acknowledged ids.
548 TEST_F(MCSClientTest, AckOnLogin) {
549 BuildMCSClient();
550 InitializeClient();
551 LoginClient(std::vector<std::string>());
553 // Receive some messages.
554 std::vector<std::string> id_list;
555 for (int i = 1; i <= kMessageBatchSize; ++i) {
556 id_list.push_back(base::IntToString(i));
557 MCSMessage message(
558 BuildDataMessage("from",
559 "category",
560 "X",
562 id_list.back(),
563 kTTLValue,
565 0));
566 GetFakeHandler()->ReceiveMessage(message);
567 WaitForMCSEvent();
568 PumpLoop();
571 // Restart the client.
572 StoreCredentials();
573 BuildMCSClient();
574 InitializeClient();
575 LoginClient(id_list);
578 // Receive some messages. On the next send, the outgoing message should contain
579 // the appropriate last stream id received field to ack the received messages.
580 TEST_F(MCSClientTest, AckOnSend) {
581 BuildMCSClient();
582 InitializeClient();
583 LoginClient(std::vector<std::string>());
585 // Receive some messages.
586 std::vector<std::string> id_list;
587 for (int i = 1; i <= kMessageBatchSize; ++i) {
588 id_list.push_back(base::IntToString(i));
589 MCSMessage message(
590 BuildDataMessage("from",
591 "category",
592 id_list.back(),
594 id_list.back(),
595 kTTLValue,
597 0));
598 GetFakeHandler()->ReceiveMessage(message);
599 PumpLoop();
602 // Trigger a message send, which should acknowledge via stream ack.
603 MCSMessage message(
604 BuildDataMessage("from",
605 "category",
606 "X",
607 kMessageBatchSize + 1,
608 "1",
609 kTTLValue,
610 1, 0));
611 GetFakeHandler()->ExpectOutgoingMessage(message);
612 mcs_client()->SendMessage(message);
613 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
616 // Receive the ack limit in messages, which should trigger an automatic
617 // stream ack. Receive a heartbeat to confirm the ack.
618 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) {
619 BuildMCSClient();
620 InitializeClient();
621 LoginClient(std::vector<std::string>());
623 // The stream ack.
624 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck();
625 ack->set_last_stream_id_received(kAckLimitSize + 1);
626 GetFakeHandler()->ExpectOutgoingMessage(
627 MCSMessage(kIqStanzaTag,
628 ack.PassAs<const google::protobuf::MessageLite>()));
630 // Receive some messages.
631 std::vector<std::string> id_list;
632 for (int i = 1; i <= kAckLimitSize; ++i) {
633 id_list.push_back(base::IntToString(i));
634 MCSMessage message(
635 BuildDataMessage("from",
636 "category",
637 id_list.back(),
639 id_list.back(),
640 kTTLValue,
642 0));
643 GetFakeHandler()->ReceiveMessage(message);
644 WaitForMCSEvent();
645 PumpLoop();
647 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
649 // Receive a heartbeat confirming the ack (and receive the heartbeat ack).
650 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat(
651 new mcs_proto::HeartbeatPing());
652 heartbeat->set_last_stream_id_received(2);
654 scoped_ptr<mcs_proto::HeartbeatAck> heartbeat_ack(
655 new mcs_proto::HeartbeatAck());
656 heartbeat_ack->set_last_stream_id_received(kAckLimitSize + 2);
657 GetFakeHandler()->ExpectOutgoingMessage(
658 MCSMessage(kHeartbeatAckTag,
659 heartbeat_ack.PassAs<const google::protobuf::MessageLite>()));
661 GetFakeHandler()->ReceiveMessage(
662 MCSMessage(kHeartbeatPingTag,
663 heartbeat.PassAs<const google::protobuf::MessageLite>()));
664 PumpLoop();
665 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
667 // Rebuild the client. Nothing should be sent on login.
668 StoreCredentials();
669 BuildMCSClient();
670 InitializeClient();
671 LoginClient(std::vector<std::string>());
672 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
675 // If a message's TTL has expired by the time it reaches the front of the send
676 // queue, it should be dropped.
677 TEST_F(MCSClientTest, ExpiredTTLOnSend) {
678 BuildMCSClient();
679 InitializeClient();
680 LoginClient(std::vector<std::string>());
681 MCSMessage message(
682 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0));
684 // Advance time to after the TTL.
685 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2));
686 EXPECT_TRUE(sent_message_id().empty());
687 mcs_client()->SendMessage(message);
689 // No messages should be sent, but the callback should still be invoked.
690 EXPECT_EQ("X", sent_message_id());
691 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status());
692 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
695 TEST_F(MCSClientTest, ExpiredTTLOnRestart) {
696 BuildMCSClient();
697 InitializeClient();
698 LoginClient(std::vector<std::string>());
699 GetFakeHandler()->set_fail_send(true);
700 MCSMessage message(
701 BuildDataMessage("from", "category", "X", 1, "1", kTTLValue, 1, 0));
703 // The initial (failed) send.
704 GetFakeHandler()->ExpectOutgoingMessage(message);
705 GetFakeHandler()->set_fail_send(false);
706 mcs_client()->SendMessage(message);
707 PumpLoop();
708 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
710 // Move the clock forward and rebuild the client, which should fail the
711 // message send on restart.
712 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2));
713 StoreCredentials();
714 BuildMCSClient();
715 InitializeClient();
716 LoginClient(std::vector<std::string>());
717 PumpLoop();
718 EXPECT_EQ("X", sent_message_id());
719 EXPECT_EQ(MCSClient::TTL_EXCEEDED, message_send_status());
720 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived());
723 } // namespace
725 } // namespace gcm