OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "google_apis/gcm/engine/mcs_client.h" | 5 #include "google_apis/gcm/engine/mcs_client.h" |
6 | 6 |
7 #include "base/files/scoped_temp_dir.h" | 7 #include "base/files/scoped_temp_dir.h" |
8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/test/simple_test_clock.h" |
11 #include "components/webdata/encryptor/encryptor.h" | 12 #include "components/webdata/encryptor/encryptor.h" |
12 #include "google_apis/gcm/base/mcs_util.h" | 13 #include "google_apis/gcm/base/mcs_util.h" |
13 #include "google_apis/gcm/engine/fake_connection_factory.h" | 14 #include "google_apis/gcm/engine/fake_connection_factory.h" |
14 #include "google_apis/gcm/engine/fake_connection_handler.h" | 15 #include "google_apis/gcm/engine/fake_connection_handler.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
16 | 17 |
17 namespace gcm { | 18 namespace gcm { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 const uint64 kAndroidId = 54321; | 22 const uint64 kAndroidId = 54321; |
22 const uint64 kSecurityToken = 12345; | 23 const uint64 kSecurityToken = 12345; |
23 | 24 |
24 // Number of messages to send when testing batching. | 25 // Number of messages to send when testing batching. |
25 // Note: must be even for tests that split batches in half. | 26 // Note: must be even for tests that split batches in half. |
26 const int kMessageBatchSize = 6; | 27 const int kMessageBatchSize = 6; |
27 | 28 |
28 // The number of unacked messages the client will receive before sending a | 29 // The number of unacked messages the client will receive before sending a |
29 // stream ack. | 30 // stream ack. |
30 // TODO(zea): get this (and other constants) directly from the mcs client. | 31 // TODO(zea): get this (and other constants) directly from the mcs client. |
31 const int kAckLimitSize = 10; | 32 const int kAckLimitSize = 10; |
32 | 33 |
| 34 // TTL value for reliable messages. |
| 35 const int kTTLValue = 5 * 60; // 5 minutes. |
| 36 |
33 // Helper for building arbitrary data messages. | 37 // Helper for building arbitrary data messages. |
34 MCSMessage BuildDataMessage(const std::string& from, | 38 MCSMessage BuildDataMessage(const std::string& from, |
35 const std::string& category, | 39 const std::string& category, |
36 int last_stream_id_received, | 40 int last_stream_id_received, |
37 const std::string persistent_id) { | 41 const std::string persistent_id, |
| 42 int ttl, |
| 43 uint64 sent) { |
38 mcs_proto::DataMessageStanza data_message; | 44 mcs_proto::DataMessageStanza data_message; |
39 data_message.set_from(from); | 45 data_message.set_from(from); |
40 data_message.set_category(category); | 46 data_message.set_category(category); |
41 data_message.set_last_stream_id_received(last_stream_id_received); | 47 data_message.set_last_stream_id_received(last_stream_id_received); |
42 if (!persistent_id.empty()) | 48 if (!persistent_id.empty()) |
43 data_message.set_persistent_id(persistent_id); | 49 data_message.set_persistent_id(persistent_id); |
| 50 data_message.set_ttl(ttl); |
| 51 data_message.set_sent(sent); |
44 return MCSMessage(kDataMessageStanzaTag, data_message); | 52 return MCSMessage(kDataMessageStanzaTag, data_message); |
45 } | 53 } |
46 | 54 |
47 // MCSClient with overriden exposed persistent id logic. | 55 // MCSClient with overriden exposed persistent id logic. |
48 class TestMCSClient : public MCSClient { | 56 class TestMCSClient : public MCSClient { |
49 public: | 57 public: |
50 TestMCSClient(ConnectionFactory* connection_factory, | 58 TestMCSClient(base::Clock* clock, |
| 59 ConnectionFactory* connection_factory, |
51 RMQStore* rmq_store) | 60 RMQStore* rmq_store) |
52 : MCSClient(connection_factory, rmq_store), | 61 : MCSClient(clock, connection_factory, rmq_store), |
53 next_id_(0) { | 62 next_id_(0) { |
54 } | 63 } |
55 | 64 |
56 virtual std::string GetNextPersistentId() OVERRIDE { | 65 virtual std::string GetNextPersistentId() OVERRIDE { |
57 return base::UintToString(++next_id_); | 66 return base::UintToString(++next_id_); |
58 } | 67 } |
59 | 68 |
60 private: | 69 private: |
61 uint32 next_id_; | 70 uint32 next_id_; |
62 }; | 71 }; |
63 | 72 |
64 class MCSClientTest : public testing::Test { | 73 class MCSClientTest : public testing::Test { |
65 public: | 74 public: |
66 MCSClientTest(); | 75 MCSClientTest(); |
67 virtual ~MCSClientTest(); | 76 virtual ~MCSClientTest(); |
68 | 77 |
69 void BuildMCSClient(); | 78 void BuildMCSClient(); |
70 void InitializeClient(); | 79 void InitializeClient(); |
71 void LoginClient(const std::vector<std::string>& acknowledged_ids); | 80 void LoginClient(const std::vector<std::string>& acknowledged_ids); |
72 | 81 |
| 82 base::SimpleTestClock* clock() { return &clock_; } |
73 TestMCSClient* mcs_client() const { return mcs_client_.get(); } | 83 TestMCSClient* mcs_client() const { return mcs_client_.get(); } |
74 FakeConnectionFactory* connection_factory() { | 84 FakeConnectionFactory* connection_factory() { |
75 return &connection_factory_; | 85 return &connection_factory_; |
76 } | 86 } |
77 bool init_success() const { return init_success_; } | 87 bool init_success() const { return init_success_; } |
78 uint64 restored_android_id() const { return restored_android_id_; } | 88 uint64 restored_android_id() const { return restored_android_id_; } |
79 uint64 restored_security_token() const { return restored_security_token_; } | 89 uint64 restored_security_token() const { return restored_security_token_; } |
80 MCSMessage* received_message() const { return received_message_.get(); } | 90 MCSMessage* received_message() const { return received_message_.get(); } |
81 std::string sent_message_id() const { return sent_message_id_;} | 91 std::string sent_message_id() const { return sent_message_id_;} |
82 | 92 |
83 FakeConnectionHandler* GetFakeHandler() const; | 93 FakeConnectionHandler* GetFakeHandler() const; |
84 | 94 |
85 void WaitForMCSEvent(); | 95 void WaitForMCSEvent(); |
86 void PumpLoop(); | 96 void PumpLoop(); |
87 | 97 |
88 private: | 98 private: |
89 void InitializationCallback(bool success, | 99 void InitializationCallback(bool success, |
90 uint64 restored_android_id, | 100 uint64 restored_android_id, |
91 uint64 restored_security_token); | 101 uint64 restored_security_token); |
92 void MessageReceivedCallback(const MCSMessage& message); | 102 void MessageReceivedCallback(const MCSMessage& message); |
93 void MessageSentCallback(const std::string& message_id); | 103 void MessageSentCallback(const std::string& message_id); |
94 | 104 |
| 105 base::SimpleTestClock clock_; |
| 106 |
95 base::ScopedTempDir temp_directory_; | 107 base::ScopedTempDir temp_directory_; |
96 base::MessageLoop message_loop_; | 108 base::MessageLoop message_loop_; |
97 scoped_ptr<base::RunLoop> run_loop_; | 109 scoped_ptr<base::RunLoop> run_loop_; |
98 scoped_ptr<RMQStore> rmq_store_; | 110 scoped_ptr<RMQStore> rmq_store_; |
99 | 111 |
100 FakeConnectionFactory connection_factory_; | 112 FakeConnectionFactory connection_factory_; |
101 scoped_ptr<TestMCSClient> mcs_client_; | 113 scoped_ptr<TestMCSClient> mcs_client_; |
102 bool init_success_; | 114 bool init_success_; |
103 uint64 restored_android_id_; | 115 uint64 restored_android_id_; |
104 uint64 restored_security_token_; | 116 uint64 restored_security_token_; |
(...skipping 13 matching lines...) Expand all Loading... |
118 #if defined(OS_MACOSX) | 130 #if defined(OS_MACOSX) |
119 Encryptor::UseMockKeychain(true); | 131 Encryptor::UseMockKeychain(true); |
120 #endif | 132 #endif |
121 } | 133 } |
122 | 134 |
123 MCSClientTest::~MCSClientTest() {} | 135 MCSClientTest::~MCSClientTest() {} |
124 | 136 |
125 void MCSClientTest::BuildMCSClient() { | 137 void MCSClientTest::BuildMCSClient() { |
126 rmq_store_.reset(new RMQStore(temp_directory_.path(), | 138 rmq_store_.reset(new RMQStore(temp_directory_.path(), |
127 message_loop_.message_loop_proxy())); | 139 message_loop_.message_loop_proxy())); |
128 mcs_client_.reset(new TestMCSClient(&connection_factory_, rmq_store_.get())); | 140 mcs_client_.reset(new TestMCSClient(&clock_, |
| 141 &connection_factory_, |
| 142 rmq_store_.get())); |
129 } | 143 } |
130 | 144 |
131 void MCSClientTest::InitializeClient() { | 145 void MCSClientTest::InitializeClient() { |
132 rmq_store_->Load( | 146 rmq_store_->Load( |
133 base::Bind(&MCSClient::Initialize, | 147 base::Bind(&MCSClient::Initialize, |
134 base::Unretained(mcs_client_.get()), | 148 base::Unretained(mcs_client_.get()), |
135 base::Bind(&MCSClientTest::InitializationCallback, | 149 base::Bind(&MCSClientTest::InitializationCallback, |
136 base::Unretained(this)), | 150 base::Unretained(this)), |
137 base::Bind(&MCSClientTest::MessageReceivedCallback, | 151 base::Bind(&MCSClientTest::MessageReceivedCallback, |
138 base::Unretained(this)), | 152 base::Unretained(this)), |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 } | 196 } |
183 | 197 |
184 void MCSClientTest::MessageReceivedCallback(const MCSMessage& message) { | 198 void MCSClientTest::MessageReceivedCallback(const MCSMessage& message) { |
185 received_message_.reset(new MCSMessage(message)); | 199 received_message_.reset(new MCSMessage(message)); |
186 DVLOG(1) << "Message received callback invoked, killing loop."; | 200 DVLOG(1) << "Message received callback invoked, killing loop."; |
187 run_loop_->Quit(); | 201 run_loop_->Quit(); |
188 } | 202 } |
189 | 203 |
190 void MCSClientTest::MessageSentCallback(const std::string& message_id) { | 204 void MCSClientTest::MessageSentCallback(const std::string& message_id) { |
191 DVLOG(1) << "Message sent callback invoked, killing loop."; | 205 DVLOG(1) << "Message sent callback invoked, killing loop."; |
| 206 sent_message_id_ = message_id; |
192 run_loop_->Quit(); | 207 run_loop_->Quit(); |
193 } | 208 } |
194 | 209 |
195 // Initialize a new client. | 210 // Initialize a new client. |
196 TEST_F(MCSClientTest, InitializeNew) { | 211 TEST_F(MCSClientTest, InitializeNew) { |
197 BuildMCSClient(); | 212 BuildMCSClient(); |
198 InitializeClient(); | 213 InitializeClient(); |
199 EXPECT_EQ(0U, restored_android_id()); | 214 EXPECT_EQ(0U, restored_android_id()); |
200 EXPECT_EQ(0U, restored_security_token()); | 215 EXPECT_EQ(0U, restored_security_token()); |
201 EXPECT_TRUE(init_success()); | 216 EXPECT_TRUE(init_success()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 EXPECT_FALSE(connection_factory()->IsEndpointReachable()); | 251 EXPECT_FALSE(connection_factory()->IsEndpointReachable()); |
237 EXPECT_FALSE(init_success()); | 252 EXPECT_FALSE(init_success()); |
238 EXPECT_FALSE(received_message()); | 253 EXPECT_FALSE(received_message()); |
239 } | 254 } |
240 | 255 |
241 // Send a message without RMQ support. | 256 // Send a message without RMQ support. |
242 TEST_F(MCSClientTest, SendMessageNoRMQ) { | 257 TEST_F(MCSClientTest, SendMessageNoRMQ) { |
243 BuildMCSClient(); | 258 BuildMCSClient(); |
244 InitializeClient(); | 259 InitializeClient(); |
245 LoginClient(std::vector<std::string>()); | 260 LoginClient(std::vector<std::string>()); |
246 MCSMessage message(BuildDataMessage("from", "category", 1, "")); | 261 MCSMessage message(BuildDataMessage("from", "category", 1, "", 0, 1)); |
247 GetFakeHandler()->ExpectOutgoingMessage(message); | 262 GetFakeHandler()->ExpectOutgoingMessage(message); |
248 mcs_client()->SendMessage(message, false); | 263 mcs_client()->SendMessage(message); |
249 EXPECT_TRUE(GetFakeHandler()-> | 264 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
250 AllOutgoingMessagesReceived()); | 265 } |
| 266 |
| 267 // Send a message without RMQ support while disconnected. Message send should |
| 268 // fail immediately, invoking callback. |
| 269 TEST_F(MCSClientTest, SendMessageNoRMQWhileDisconnected) { |
| 270 BuildMCSClient(); |
| 271 InitializeClient(); |
| 272 |
| 273 EXPECT_TRUE(sent_message_id().empty()); |
| 274 MCSMessage message(BuildDataMessage("from", "category", 1, "", 0, 1)); |
| 275 mcs_client()->SendMessage(message); |
| 276 |
| 277 // Message sent callback should be invoked, but no message should actually |
| 278 // be sent. |
| 279 EXPECT_FALSE(sent_message_id().empty()); |
| 280 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
251 } | 281 } |
252 | 282 |
253 // Send a message with RMQ support. | 283 // Send a message with RMQ support. |
254 TEST_F(MCSClientTest, SendMessageRMQ) { | 284 TEST_F(MCSClientTest, SendMessageRMQ) { |
255 BuildMCSClient(); | 285 BuildMCSClient(); |
256 InitializeClient(); | 286 InitializeClient(); |
257 LoginClient(std::vector<std::string>()); | 287 LoginClient(std::vector<std::string>()); |
258 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 288 MCSMessage message( |
| 289 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
259 GetFakeHandler()->ExpectOutgoingMessage(message); | 290 GetFakeHandler()->ExpectOutgoingMessage(message); |
260 mcs_client()->SendMessage(message, true); | 291 mcs_client()->SendMessage(message); |
261 EXPECT_TRUE(GetFakeHandler()-> | 292 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
262 AllOutgoingMessagesReceived()); | |
263 } | 293 } |
264 | 294 |
265 // Send a message with RMQ support while disconnected. On reconnect, the message | 295 // Send a message with RMQ support while disconnected. On reconnect, the message |
266 // should be resent. | 296 // should be resent. |
267 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { | 297 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { |
268 BuildMCSClient(); | 298 BuildMCSClient(); |
269 InitializeClient(); | 299 InitializeClient(); |
270 LoginClient(std::vector<std::string>()); | 300 LoginClient(std::vector<std::string>()); |
271 GetFakeHandler()->set_fail_send(true); | 301 GetFakeHandler()->set_fail_send(true); |
272 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 302 MCSMessage message( |
| 303 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
273 | 304 |
274 // The initial (failed) send. | 305 // The initial (failed) send. |
275 GetFakeHandler()->ExpectOutgoingMessage(message); | 306 GetFakeHandler()->ExpectOutgoingMessage(message); |
276 // The login request. | 307 // The login request. |
277 GetFakeHandler()->ExpectOutgoingMessage( | 308 GetFakeHandler()->ExpectOutgoingMessage( |
278 MCSMessage(kLoginRequestTag, | 309 MCSMessage(kLoginRequestTag, |
279 BuildLoginRequest(kAndroidId, kSecurityToken). | 310 BuildLoginRequest(kAndroidId, kSecurityToken). |
280 PassAs<const google::protobuf::MessageLite>())); | 311 PassAs<const google::protobuf::MessageLite>())); |
281 // The second (re)send. | 312 // The second (re)send. |
282 GetFakeHandler()->ExpectOutgoingMessage(message); | 313 GetFakeHandler()->ExpectOutgoingMessage(message); |
283 mcs_client()->SendMessage(message, true); | 314 mcs_client()->SendMessage(message); |
284 EXPECT_FALSE(GetFakeHandler()-> | 315 EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
285 AllOutgoingMessagesReceived()); | |
286 GetFakeHandler()->set_fail_send(false); | 316 GetFakeHandler()->set_fail_send(false); |
287 connection_factory()->Connect(); | 317 connection_factory()->Connect(); |
288 WaitForMCSEvent(); // Wait for the login to finish. | 318 WaitForMCSEvent(); // Wait for the login to finish. |
289 PumpLoop(); // Wait for the send to happen. | 319 PumpLoop(); // Wait for the send to happen. |
290 EXPECT_TRUE(GetFakeHandler()-> | 320 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
291 AllOutgoingMessagesReceived()); | |
292 } | 321 } |
293 | 322 |
294 // Send a message with RMQ support without receiving an acknowledgement. On | 323 // Send a message with RMQ support without receiving an acknowledgement. On |
295 // restart the message should be resent. | 324 // restart the message should be resent. |
296 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { | 325 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { |
297 BuildMCSClient(); | 326 BuildMCSClient(); |
298 InitializeClient(); | 327 InitializeClient(); |
299 LoginClient(std::vector<std::string>()); | 328 LoginClient(std::vector<std::string>()); |
300 GetFakeHandler()->set_fail_send(true); | 329 GetFakeHandler()->set_fail_send(true); |
301 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 330 MCSMessage message( |
| 331 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
302 | 332 |
303 // The initial (failed) send. | 333 // The initial (failed) send. |
304 GetFakeHandler()->ExpectOutgoingMessage(message); | 334 GetFakeHandler()->ExpectOutgoingMessage(message); |
305 GetFakeHandler()->set_fail_send(false); | 335 GetFakeHandler()->set_fail_send(false); |
306 mcs_client()->SendMessage(message, true); | 336 mcs_client()->SendMessage(message); |
307 EXPECT_TRUE(GetFakeHandler()-> | 337 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
308 AllOutgoingMessagesReceived()); | |
309 | 338 |
310 // Rebuild the client, which should resend the old message. | 339 // Rebuild the client, which should resend the old message. |
311 BuildMCSClient(); | 340 BuildMCSClient(); |
312 InitializeClient(); | 341 InitializeClient(); |
313 LoginClient(std::vector<std::string>()); | 342 LoginClient(std::vector<std::string>()); |
314 GetFakeHandler()->ExpectOutgoingMessage(message); | 343 GetFakeHandler()->ExpectOutgoingMessage(message); |
315 PumpLoop(); | 344 PumpLoop(); |
316 EXPECT_TRUE(GetFakeHandler()-> | 345 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
317 AllOutgoingMessagesReceived()); | |
318 } | 346 } |
319 | 347 |
320 // Send messages with RMQ support, followed by receiving a stream ack. On | 348 // Send messages with RMQ support, followed by receiving a stream ack. On |
321 // restart nothing should be recent. | 349 // restart nothing should be recent. |
322 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { | 350 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { |
323 BuildMCSClient(); | 351 BuildMCSClient(); |
324 InitializeClient(); | 352 InitializeClient(); |
325 LoginClient(std::vector<std::string>()); | 353 LoginClient(std::vector<std::string>()); |
326 | 354 |
327 // Send some messages. | 355 // Send some messages. |
328 for (int i = 1; i <= kMessageBatchSize; ++i) { | 356 for (int i = 1; i <= kMessageBatchSize; ++i) { |
329 MCSMessage message( | 357 MCSMessage message( |
330 BuildDataMessage("from", "category", 1, base::IntToString(i))); | 358 BuildDataMessage("from", |
| 359 "category", |
| 360 1, |
| 361 base::IntToString(i), |
| 362 kTTLValue, |
| 363 1)); |
331 GetFakeHandler()->ExpectOutgoingMessage(message); | 364 GetFakeHandler()->ExpectOutgoingMessage(message); |
332 mcs_client()->SendMessage(message, true); | 365 mcs_client()->SendMessage(message); |
333 } | 366 } |
334 EXPECT_TRUE(GetFakeHandler()-> | 367 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
335 AllOutgoingMessagesReceived()); | |
336 | 368 |
337 // Receive the ack. | 369 // Receive the ack. |
338 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 370 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
339 ack->set_last_stream_id_received(kMessageBatchSize + 1); | 371 ack->set_last_stream_id_received(kMessageBatchSize + 1); |
340 GetFakeHandler()->ReceiveMessage( | 372 GetFakeHandler()->ReceiveMessage( |
341 MCSMessage(kIqStanzaTag, | 373 MCSMessage(kIqStanzaTag, |
342 ack.PassAs<const google::protobuf::MessageLite>())); | 374 ack.PassAs<const google::protobuf::MessageLite>())); |
343 WaitForMCSEvent(); | 375 WaitForMCSEvent(); |
344 | 376 |
345 // Reconnect and ensure no messages are resent. | 377 // Reconnect and ensure no messages are resent. |
346 BuildMCSClient(); | 378 BuildMCSClient(); |
347 InitializeClient(); | 379 InitializeClient(); |
348 LoginClient(std::vector<std::string>()); | 380 LoginClient(std::vector<std::string>()); |
349 PumpLoop(); | 381 PumpLoop(); |
350 } | 382 } |
351 | 383 |
352 // Send messages with RMQ support. On restart, receive a SelectiveAck with | 384 // Send messages with RMQ support. On restart, receive a SelectiveAck with |
353 // the login response. No messages should be resent. | 385 // the login response. No messages should be resent. |
354 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { | 386 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { |
355 BuildMCSClient(); | 387 BuildMCSClient(); |
356 InitializeClient(); | 388 InitializeClient(); |
357 LoginClient(std::vector<std::string>()); | 389 LoginClient(std::vector<std::string>()); |
358 | 390 |
359 // Send some messages. | 391 // Send some messages. |
360 std::vector<std::string> id_list; | 392 std::vector<std::string> id_list; |
361 for (int i = 1; i <= kMessageBatchSize; ++i) { | 393 for (int i = 1; i <= kMessageBatchSize; ++i) { |
362 id_list.push_back(base::IntToString(i)); | 394 id_list.push_back(base::IntToString(i)); |
363 MCSMessage message( | 395 MCSMessage message( |
364 BuildDataMessage("from", "category", 1, id_list.back())); | 396 BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 1)); |
365 GetFakeHandler()->ExpectOutgoingMessage(message); | 397 GetFakeHandler()->ExpectOutgoingMessage(message); |
366 mcs_client()->SendMessage(message, true); | 398 mcs_client()->SendMessage(message); |
367 } | 399 } |
368 EXPECT_TRUE(GetFakeHandler()-> | 400 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
369 AllOutgoingMessagesReceived()); | |
370 | 401 |
371 // Rebuild the client, and receive an acknowledgment for the messages as | 402 // Rebuild the client, and receive an acknowledgment for the messages as |
372 // part of the login response. | 403 // part of the login response. |
373 BuildMCSClient(); | 404 BuildMCSClient(); |
374 InitializeClient(); | 405 InitializeClient(); |
375 LoginClient(std::vector<std::string>()); | 406 LoginClient(std::vector<std::string>()); |
376 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(id_list)); | 407 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(id_list)); |
377 GetFakeHandler()->ReceiveMessage( | 408 GetFakeHandler()->ReceiveMessage( |
378 MCSMessage(kIqStanzaTag, | 409 MCSMessage(kIqStanzaTag, |
379 ack.PassAs<const google::protobuf::MessageLite>())); | 410 ack.PassAs<const google::protobuf::MessageLite>())); |
380 WaitForMCSEvent(); | 411 WaitForMCSEvent(); |
381 EXPECT_TRUE(GetFakeHandler()-> | 412 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
382 AllOutgoingMessagesReceived()); | |
383 } | 413 } |
384 | 414 |
385 // Send messages with RMQ support. On restart, receive a SelectiveAck with | 415 // Send messages with RMQ support. On restart, receive a SelectiveAck with |
386 // the login response that only acks some messages. The unacked messages should | 416 // the login response that only acks some messages. The unacked messages should |
387 // be resent. | 417 // be resent. |
388 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { | 418 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { |
389 BuildMCSClient(); | 419 BuildMCSClient(); |
390 InitializeClient(); | 420 InitializeClient(); |
391 LoginClient(std::vector<std::string>()); | 421 LoginClient(std::vector<std::string>()); |
392 | 422 |
393 // Send some messages. | 423 // Send some messages. |
394 std::vector<std::string> id_list; | 424 std::vector<std::string> id_list; |
395 for (int i = 1; i <= kMessageBatchSize; ++i) { | 425 for (int i = 1; i <= kMessageBatchSize; ++i) { |
396 id_list.push_back(base::IntToString(i)); | 426 id_list.push_back(base::IntToString(i)); |
397 MCSMessage message( | 427 MCSMessage message( |
398 BuildDataMessage("from", "category", 1, id_list.back())); | 428 BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 1)); |
399 GetFakeHandler()->ExpectOutgoingMessage(message); | 429 GetFakeHandler()->ExpectOutgoingMessage(message); |
400 mcs_client()->SendMessage(message, true); | 430 mcs_client()->SendMessage(message); |
401 } | 431 } |
402 EXPECT_TRUE(GetFakeHandler()-> | 432 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
403 AllOutgoingMessagesReceived()); | |
404 | 433 |
405 // Rebuild the client, and receive an acknowledgment for the messages as | 434 // Rebuild the client, and receive an acknowledgment for the messages as |
406 // part of the login response. | 435 // part of the login response. |
407 BuildMCSClient(); | 436 BuildMCSClient(); |
408 InitializeClient(); | 437 InitializeClient(); |
409 LoginClient(std::vector<std::string>()); | 438 LoginClient(std::vector<std::string>()); |
410 | 439 |
411 std::vector<std::string> acked_ids, remaining_ids; | 440 std::vector<std::string> acked_ids, remaining_ids; |
412 acked_ids.insert(acked_ids.end(), | 441 acked_ids.insert(acked_ids.end(), |
413 id_list.begin(), | 442 id_list.begin(), |
414 id_list.begin() + kMessageBatchSize / 2); | 443 id_list.begin() + kMessageBatchSize / 2); |
415 remaining_ids.insert(remaining_ids.end(), | 444 remaining_ids.insert(remaining_ids.end(), |
416 id_list.begin() + kMessageBatchSize / 2, | 445 id_list.begin() + kMessageBatchSize / 2, |
417 id_list.end()); | 446 id_list.end()); |
418 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { | 447 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { |
419 MCSMessage message( | 448 MCSMessage message( |
420 BuildDataMessage("from", | 449 BuildDataMessage("from", |
421 "category", | 450 "category", |
422 2, | 451 2, |
423 remaining_ids[i - 1])); | 452 remaining_ids[i - 1], |
| 453 kTTLValue, |
| 454 1)); |
424 GetFakeHandler()->ExpectOutgoingMessage(message); | 455 GetFakeHandler()->ExpectOutgoingMessage(message); |
425 } | 456 } |
426 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); | 457 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); |
427 GetFakeHandler()->ReceiveMessage( | 458 GetFakeHandler()->ReceiveMessage( |
428 MCSMessage(kIqStanzaTag, | 459 MCSMessage(kIqStanzaTag, |
429 ack.PassAs<const google::protobuf::MessageLite>())); | 460 ack.PassAs<const google::protobuf::MessageLite>())); |
430 WaitForMCSEvent(); | 461 WaitForMCSEvent(); |
431 EXPECT_TRUE(GetFakeHandler()-> | 462 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
432 AllOutgoingMessagesReceived()); | |
433 } | 463 } |
434 | 464 |
435 // Receive some messages. On restart, the login request should contain the | 465 // Receive some messages. On restart, the login request should contain the |
436 // appropriate acknowledged ids. | 466 // appropriate acknowledged ids. |
437 TEST_F(MCSClientTest, AckOnLogin) { | 467 TEST_F(MCSClientTest, AckOnLogin) { |
438 BuildMCSClient(); | 468 BuildMCSClient(); |
439 InitializeClient(); | 469 InitializeClient(); |
440 LoginClient(std::vector<std::string>()); | 470 LoginClient(std::vector<std::string>()); |
441 | 471 |
442 // Receive some messages. | 472 // Receive some messages. |
443 std::vector<std::string> id_list; | 473 std::vector<std::string> id_list; |
444 for (int i = 1; i <= kMessageBatchSize; ++i) { | 474 for (int i = 1; i <= kMessageBatchSize; ++i) { |
445 id_list.push_back(base::IntToString(i)); | 475 id_list.push_back(base::IntToString(i)); |
446 MCSMessage message( | 476 MCSMessage message( |
447 BuildDataMessage("from", "category", i, id_list.back())); | 477 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 1)); |
448 GetFakeHandler()->ReceiveMessage(message); | 478 GetFakeHandler()->ReceiveMessage(message); |
449 WaitForMCSEvent(); | 479 WaitForMCSEvent(); |
450 PumpLoop(); | 480 PumpLoop(); |
451 } | 481 } |
452 | 482 |
453 // Restart the client. | 483 // Restart the client. |
454 BuildMCSClient(); | 484 BuildMCSClient(); |
455 InitializeClient(); | 485 InitializeClient(); |
456 LoginClient(id_list); | 486 LoginClient(id_list); |
457 } | 487 } |
458 | 488 |
459 // Receive some messages. On the next send, the outgoing message should contain | 489 // Receive some messages. On the next send, the outgoing message should contain |
460 // the appropriate last stream id received field to ack the received messages. | 490 // the appropriate last stream id received field to ack the received messages. |
461 TEST_F(MCSClientTest, AckOnSend) { | 491 TEST_F(MCSClientTest, AckOnSend) { |
462 BuildMCSClient(); | 492 BuildMCSClient(); |
463 InitializeClient(); | 493 InitializeClient(); |
464 LoginClient(std::vector<std::string>()); | 494 LoginClient(std::vector<std::string>()); |
465 | 495 |
466 // Receive some messages. | 496 // Receive some messages. |
467 std::vector<std::string> id_list; | 497 std::vector<std::string> id_list; |
468 for (int i = 1; i <= kMessageBatchSize; ++i) { | 498 for (int i = 1; i <= kMessageBatchSize; ++i) { |
469 id_list.push_back(base::IntToString(i)); | 499 id_list.push_back(base::IntToString(i)); |
470 MCSMessage message( | 500 MCSMessage message( |
471 BuildDataMessage("from", "category", i, id_list.back())); | 501 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 1)); |
472 GetFakeHandler()->ReceiveMessage(message); | 502 GetFakeHandler()->ReceiveMessage(message); |
473 WaitForMCSEvent(); | 503 WaitForMCSEvent(); |
474 PumpLoop(); | 504 PumpLoop(); |
475 } | 505 } |
476 | 506 |
477 // Trigger a message send, which should acknowledge via stream ack. | 507 // Trigger a message send, which should acknowledge via stream ack. |
478 MCSMessage message( | 508 MCSMessage message( |
479 BuildDataMessage("from", "category", kMessageBatchSize + 1, "1")); | 509 BuildDataMessage("from", |
| 510 "category", |
| 511 kMessageBatchSize + 1, |
| 512 "1", |
| 513 kTTLValue, |
| 514 1)); |
480 GetFakeHandler()->ExpectOutgoingMessage(message); | 515 GetFakeHandler()->ExpectOutgoingMessage(message); |
481 mcs_client()->SendMessage(message, true); | 516 mcs_client()->SendMessage(message); |
482 EXPECT_TRUE(GetFakeHandler()-> | 517 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
483 AllOutgoingMessagesReceived()); | |
484 } | 518 } |
485 | 519 |
486 // Receive the ack limit in messages, which should trigger an automatic | 520 // Receive the ack limit in messages, which should trigger an automatic |
487 // stream ack. Receive a heartbeat to confirm the ack. | 521 // stream ack. Receive a heartbeat to confirm the ack. |
488 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { | 522 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { |
489 BuildMCSClient(); | 523 BuildMCSClient(); |
490 InitializeClient(); | 524 InitializeClient(); |
491 LoginClient(std::vector<std::string>()); | 525 LoginClient(std::vector<std::string>()); |
492 | 526 |
493 // The stream ack. | 527 // The stream ack. |
494 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 528 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
495 ack->set_last_stream_id_received(kAckLimitSize + 1); | 529 ack->set_last_stream_id_received(kAckLimitSize + 1); |
496 GetFakeHandler()->ExpectOutgoingMessage( | 530 GetFakeHandler()->ExpectOutgoingMessage( |
497 MCSMessage(kIqStanzaTag, | 531 MCSMessage(kIqStanzaTag, |
498 ack.PassAs<const google::protobuf::MessageLite>())); | 532 ack.PassAs<const google::protobuf::MessageLite>())); |
499 | 533 |
500 // Receive some messages. | 534 // Receive some messages. |
501 std::vector<std::string> id_list; | 535 std::vector<std::string> id_list; |
502 for (int i = 1; i <= kAckLimitSize; ++i) { | 536 for (int i = 1; i <= kAckLimitSize; ++i) { |
503 id_list.push_back(base::IntToString(i)); | 537 id_list.push_back(base::IntToString(i)); |
504 MCSMessage message( | 538 MCSMessage message( |
505 BuildDataMessage("from", "category", i, id_list.back())); | 539 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 1)); |
506 GetFakeHandler()->ReceiveMessage(message); | 540 GetFakeHandler()->ReceiveMessage(message); |
507 WaitForMCSEvent(); | 541 WaitForMCSEvent(); |
508 PumpLoop(); | 542 PumpLoop(); |
509 } | 543 } |
510 EXPECT_TRUE(GetFakeHandler()-> | 544 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
511 AllOutgoingMessagesReceived()); | |
512 | 545 |
513 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). | 546 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). |
514 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( | 547 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( |
515 new mcs_proto::HeartbeatPing()); | 548 new mcs_proto::HeartbeatPing()); |
516 heartbeat->set_last_stream_id_received(2); | 549 heartbeat->set_last_stream_id_received(2); |
517 | 550 |
518 scoped_ptr<mcs_proto::HeartbeatAck> heartbeat_ack( | 551 scoped_ptr<mcs_proto::HeartbeatAck> heartbeat_ack( |
519 new mcs_proto::HeartbeatAck()); | 552 new mcs_proto::HeartbeatAck()); |
520 heartbeat_ack->set_last_stream_id_received(kAckLimitSize + 2); | 553 heartbeat_ack->set_last_stream_id_received(kAckLimitSize + 2); |
521 GetFakeHandler()->ExpectOutgoingMessage( | 554 GetFakeHandler()->ExpectOutgoingMessage( |
522 MCSMessage(kHeartbeatAckTag, | 555 MCSMessage(kHeartbeatAckTag, |
523 heartbeat_ack.PassAs<const google::protobuf::MessageLite>())); | 556 heartbeat_ack.PassAs<const google::protobuf::MessageLite>())); |
524 | 557 |
525 GetFakeHandler()->ReceiveMessage( | 558 GetFakeHandler()->ReceiveMessage( |
526 MCSMessage(kHeartbeatPingTag, | 559 MCSMessage(kHeartbeatPingTag, |
527 heartbeat.PassAs<const google::protobuf::MessageLite>())); | 560 heartbeat.PassAs<const google::protobuf::MessageLite>())); |
528 WaitForMCSEvent(); | 561 WaitForMCSEvent(); |
529 EXPECT_TRUE(GetFakeHandler()-> | 562 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
530 AllOutgoingMessagesReceived()); | |
531 | 563 |
532 // Rebuild the client. Nothing should be sent on login. | 564 // Rebuild the client. Nothing should be sent on login. |
533 BuildMCSClient(); | 565 BuildMCSClient(); |
534 InitializeClient(); | 566 InitializeClient(); |
535 LoginClient(std::vector<std::string>()); | 567 LoginClient(std::vector<std::string>()); |
536 EXPECT_TRUE(GetFakeHandler()-> | 568 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
537 AllOutgoingMessagesReceived()); | 569 } |
| 570 |
| 571 // If a message's TTL has expired by the time it reaches the front of the send |
| 572 // queue, it should be dropped. |
| 573 TEST_F(MCSClientTest, ExpiredTTLOnSend) { |
| 574 BuildMCSClient(); |
| 575 InitializeClient(); |
| 576 LoginClient(std::vector<std::string>()); |
| 577 MCSMessage message( |
| 578 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
| 579 |
| 580 // Advance time to after the TTL. |
| 581 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); |
| 582 EXPECT_TRUE(sent_message_id().empty()); |
| 583 mcs_client()->SendMessage(message); |
| 584 |
| 585 // No messages should be sent, but the callback should still be invoked. |
| 586 EXPECT_FALSE(sent_message_id().empty()); |
| 587 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 588 } |
| 589 |
| 590 TEST_F(MCSClientTest, ExpiredTTLOnRestart) { |
| 591 BuildMCSClient(); |
| 592 InitializeClient(); |
| 593 LoginClient(std::vector<std::string>()); |
| 594 GetFakeHandler()->set_fail_send(true); |
| 595 MCSMessage message( |
| 596 BuildDataMessage("from", "category", 1, "1", kTTLValue, 1)); |
| 597 |
| 598 // The initial (failed) send. |
| 599 GetFakeHandler()->ExpectOutgoingMessage(message); |
| 600 GetFakeHandler()->set_fail_send(false); |
| 601 mcs_client()->SendMessage(message); |
| 602 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
| 603 |
| 604 // Move the clock forward and rebuild the client, which should fail the |
| 605 // message send on restart. |
| 606 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 2)); |
| 607 BuildMCSClient(); |
| 608 InitializeClient(); |
| 609 LoginClient(std::vector<std::string>()); |
| 610 PumpLoop(); |
| 611 EXPECT_FALSE(sent_message_id().empty()); |
| 612 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
538 } | 613 } |
539 | 614 |
540 } // namespace | 615 } // namespace |
541 | 616 |
542 } // namespace gcm | 617 } // namespace gcm |
OLD | NEW |