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, 0)); |
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()); | |
251 } | 265 } |
252 | 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, 0)); | |
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()); | |
281 } | |
282 | |
jianli
2014/01/02 18:52:58
nit: empty line not needed
Nicolas Zea
2014/01/02 21:39:08
Done.
| |
283 | |
253 // Send a message with RMQ support. | 284 // Send a message with RMQ support. |
254 TEST_F(MCSClientTest, SendMessageRMQ) { | 285 TEST_F(MCSClientTest, SendMessageRMQ) { |
255 BuildMCSClient(); | 286 BuildMCSClient(); |
256 InitializeClient(); | 287 InitializeClient(); |
257 LoginClient(std::vector<std::string>()); | 288 LoginClient(std::vector<std::string>()); |
258 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 289 MCSMessage message( |
290 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
259 GetFakeHandler()->ExpectOutgoingMessage(message); | 291 GetFakeHandler()->ExpectOutgoingMessage(message); |
260 mcs_client()->SendMessage(message, true); | 292 mcs_client()->SendMessage(message); |
261 EXPECT_TRUE(GetFakeHandler()-> | 293 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
262 AllOutgoingMessagesReceived()); | |
263 } | 294 } |
264 | 295 |
265 // Send a message with RMQ support while disconnected. On reconnect, the message | 296 // Send a message with RMQ support while disconnected. On reconnect, the message |
266 // should be resent. | 297 // should be resent. |
267 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { | 298 TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { |
268 BuildMCSClient(); | 299 BuildMCSClient(); |
269 InitializeClient(); | 300 InitializeClient(); |
270 LoginClient(std::vector<std::string>()); | 301 LoginClient(std::vector<std::string>()); |
271 GetFakeHandler()->set_fail_send(true); | 302 GetFakeHandler()->set_fail_send(true); |
272 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 303 MCSMessage message( |
304 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
273 | 305 |
274 // The initial (failed) send. | 306 // The initial (failed) send. |
275 GetFakeHandler()->ExpectOutgoingMessage(message); | 307 GetFakeHandler()->ExpectOutgoingMessage(message); |
276 // The login request. | 308 // The login request. |
277 GetFakeHandler()->ExpectOutgoingMessage( | 309 GetFakeHandler()->ExpectOutgoingMessage( |
278 MCSMessage(kLoginRequestTag, | 310 MCSMessage(kLoginRequestTag, |
279 BuildLoginRequest(kAndroidId, kSecurityToken). | 311 BuildLoginRequest(kAndroidId, kSecurityToken). |
280 PassAs<const google::protobuf::MessageLite>())); | 312 PassAs<const google::protobuf::MessageLite>())); |
281 // The second (re)send. | 313 // The second (re)send. |
282 GetFakeHandler()->ExpectOutgoingMessage(message); | 314 GetFakeHandler()->ExpectOutgoingMessage(message); |
283 mcs_client()->SendMessage(message, true); | 315 mcs_client()->SendMessage(message); |
284 EXPECT_FALSE(GetFakeHandler()-> | 316 EXPECT_FALSE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
285 AllOutgoingMessagesReceived()); | |
286 GetFakeHandler()->set_fail_send(false); | 317 GetFakeHandler()->set_fail_send(false); |
287 connection_factory()->Connect(); | 318 connection_factory()->Connect(); |
288 WaitForMCSEvent(); // Wait for the login to finish. | 319 WaitForMCSEvent(); // Wait for the login to finish. |
289 PumpLoop(); // Wait for the send to happen. | 320 PumpLoop(); // Wait for the send to happen. |
290 EXPECT_TRUE(GetFakeHandler()-> | 321 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
291 AllOutgoingMessagesReceived()); | |
292 } | 322 } |
293 | 323 |
294 // Send a message with RMQ support without receiving an acknowledgement. On | 324 // Send a message with RMQ support without receiving an acknowledgement. On |
295 // restart the message should be resent. | 325 // restart the message should be resent. |
296 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { | 326 TEST_F(MCSClientTest, SendMessageRMQOnRestart) { |
297 BuildMCSClient(); | 327 BuildMCSClient(); |
298 InitializeClient(); | 328 InitializeClient(); |
299 LoginClient(std::vector<std::string>()); | 329 LoginClient(std::vector<std::string>()); |
300 GetFakeHandler()->set_fail_send(true); | 330 GetFakeHandler()->set_fail_send(true); |
301 MCSMessage message(BuildDataMessage("from", "category", 1, "1")); | 331 MCSMessage message( |
332 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
302 | 333 |
303 // The initial (failed) send. | 334 // The initial (failed) send. |
304 GetFakeHandler()->ExpectOutgoingMessage(message); | 335 GetFakeHandler()->ExpectOutgoingMessage(message); |
305 GetFakeHandler()->set_fail_send(false); | 336 GetFakeHandler()->set_fail_send(false); |
306 mcs_client()->SendMessage(message, true); | 337 mcs_client()->SendMessage(message); |
307 EXPECT_TRUE(GetFakeHandler()-> | 338 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
308 AllOutgoingMessagesReceived()); | |
309 | 339 |
310 // Rebuild the client, which should resend the old message. | 340 // Rebuild the client, which should resend the old message. |
311 BuildMCSClient(); | 341 BuildMCSClient(); |
312 InitializeClient(); | 342 InitializeClient(); |
313 LoginClient(std::vector<std::string>()); | 343 LoginClient(std::vector<std::string>()); |
314 GetFakeHandler()->ExpectOutgoingMessage(message); | 344 GetFakeHandler()->ExpectOutgoingMessage(message); |
315 PumpLoop(); | 345 PumpLoop(); |
316 EXPECT_TRUE(GetFakeHandler()-> | 346 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
317 AllOutgoingMessagesReceived()); | |
318 } | 347 } |
319 | 348 |
320 // Send messages with RMQ support, followed by receiving a stream ack. On | 349 // Send messages with RMQ support, followed by receiving a stream ack. On |
321 // restart nothing should be recent. | 350 // restart nothing should be recent. |
322 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { | 351 TEST_F(MCSClientTest, SendMessageRMQWithStreamAck) { |
323 BuildMCSClient(); | 352 BuildMCSClient(); |
324 InitializeClient(); | 353 InitializeClient(); |
325 LoginClient(std::vector<std::string>()); | 354 LoginClient(std::vector<std::string>()); |
326 | 355 |
327 // Send some messages. | 356 // Send some messages. |
328 for (int i = 1; i <= kMessageBatchSize; ++i) { | 357 for (int i = 1; i <= kMessageBatchSize; ++i) { |
329 MCSMessage message( | 358 MCSMessage message( |
330 BuildDataMessage("from", "category", 1, base::IntToString(i))); | 359 BuildDataMessage("from", |
360 "category", | |
361 1, | |
362 base::IntToString(i), | |
363 kTTLValue, | |
364 0)); | |
331 GetFakeHandler()->ExpectOutgoingMessage(message); | 365 GetFakeHandler()->ExpectOutgoingMessage(message); |
332 mcs_client()->SendMessage(message, true); | 366 mcs_client()->SendMessage(message); |
333 } | 367 } |
334 EXPECT_TRUE(GetFakeHandler()-> | 368 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
335 AllOutgoingMessagesReceived()); | |
336 | 369 |
337 // Receive the ack. | 370 // Receive the ack. |
338 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 371 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
339 ack->set_last_stream_id_received(kMessageBatchSize + 1); | 372 ack->set_last_stream_id_received(kMessageBatchSize + 1); |
340 GetFakeHandler()->ReceiveMessage( | 373 GetFakeHandler()->ReceiveMessage( |
341 MCSMessage(kIqStanzaTag, | 374 MCSMessage(kIqStanzaTag, |
342 ack.PassAs<const google::protobuf::MessageLite>())); | 375 ack.PassAs<const google::protobuf::MessageLite>())); |
343 WaitForMCSEvent(); | 376 WaitForMCSEvent(); |
344 | 377 |
345 // Reconnect and ensure no messages are resent. | 378 // Reconnect and ensure no messages are resent. |
346 BuildMCSClient(); | 379 BuildMCSClient(); |
347 InitializeClient(); | 380 InitializeClient(); |
348 LoginClient(std::vector<std::string>()); | 381 LoginClient(std::vector<std::string>()); |
349 PumpLoop(); | 382 PumpLoop(); |
350 } | 383 } |
351 | 384 |
352 // Send messages with RMQ support. On restart, receive a SelectiveAck with | 385 // Send messages with RMQ support. On restart, receive a SelectiveAck with |
353 // the login response. No messages should be resent. | 386 // the login response. No messages should be resent. |
354 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { | 387 TEST_F(MCSClientTest, SendMessageRMQAckOnReconnect) { |
355 BuildMCSClient(); | 388 BuildMCSClient(); |
356 InitializeClient(); | 389 InitializeClient(); |
357 LoginClient(std::vector<std::string>()); | 390 LoginClient(std::vector<std::string>()); |
358 | 391 |
359 // Send some messages. | 392 // Send some messages. |
360 std::vector<std::string> id_list; | 393 std::vector<std::string> id_list; |
361 for (int i = 1; i <= kMessageBatchSize; ++i) { | 394 for (int i = 1; i <= kMessageBatchSize; ++i) { |
362 id_list.push_back(base::IntToString(i)); | 395 id_list.push_back(base::IntToString(i)); |
363 MCSMessage message( | 396 MCSMessage message( |
364 BuildDataMessage("from", "category", 1, id_list.back())); | 397 BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 0)); |
365 GetFakeHandler()->ExpectOutgoingMessage(message); | 398 GetFakeHandler()->ExpectOutgoingMessage(message); |
366 mcs_client()->SendMessage(message, true); | 399 mcs_client()->SendMessage(message); |
367 } | 400 } |
368 EXPECT_TRUE(GetFakeHandler()-> | 401 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
369 AllOutgoingMessagesReceived()); | |
370 | 402 |
371 // Rebuild the client, and receive an acknowledgment for the messages as | 403 // Rebuild the client, and receive an acknowledgment for the messages as |
372 // part of the login response. | 404 // part of the login response. |
373 BuildMCSClient(); | 405 BuildMCSClient(); |
374 InitializeClient(); | 406 InitializeClient(); |
375 LoginClient(std::vector<std::string>()); | 407 LoginClient(std::vector<std::string>()); |
376 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(id_list)); | 408 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(id_list)); |
377 GetFakeHandler()->ReceiveMessage( | 409 GetFakeHandler()->ReceiveMessage( |
378 MCSMessage(kIqStanzaTag, | 410 MCSMessage(kIqStanzaTag, |
379 ack.PassAs<const google::protobuf::MessageLite>())); | 411 ack.PassAs<const google::protobuf::MessageLite>())); |
380 WaitForMCSEvent(); | 412 WaitForMCSEvent(); |
381 EXPECT_TRUE(GetFakeHandler()-> | 413 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
382 AllOutgoingMessagesReceived()); | |
383 } | 414 } |
384 | 415 |
385 // Send messages with RMQ support. On restart, receive a SelectiveAck with | 416 // Send messages with RMQ support. On restart, receive a SelectiveAck with |
386 // the login response that only acks some messages. The unacked messages should | 417 // the login response that only acks some messages. The unacked messages should |
387 // be resent. | 418 // be resent. |
388 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { | 419 TEST_F(MCSClientTest, SendMessageRMQPartialAckOnReconnect) { |
389 BuildMCSClient(); | 420 BuildMCSClient(); |
390 InitializeClient(); | 421 InitializeClient(); |
391 LoginClient(std::vector<std::string>()); | 422 LoginClient(std::vector<std::string>()); |
392 | 423 |
393 // Send some messages. | 424 // Send some messages. |
394 std::vector<std::string> id_list; | 425 std::vector<std::string> id_list; |
395 for (int i = 1; i <= kMessageBatchSize; ++i) { | 426 for (int i = 1; i <= kMessageBatchSize; ++i) { |
396 id_list.push_back(base::IntToString(i)); | 427 id_list.push_back(base::IntToString(i)); |
397 MCSMessage message( | 428 MCSMessage message( |
398 BuildDataMessage("from", "category", 1, id_list.back())); | 429 BuildDataMessage("from", "category", 1, id_list.back(), kTTLValue, 0)); |
399 GetFakeHandler()->ExpectOutgoingMessage(message); | 430 GetFakeHandler()->ExpectOutgoingMessage(message); |
400 mcs_client()->SendMessage(message, true); | 431 mcs_client()->SendMessage(message); |
401 } | 432 } |
402 EXPECT_TRUE(GetFakeHandler()-> | 433 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
403 AllOutgoingMessagesReceived()); | |
404 | 434 |
405 // Rebuild the client, and receive an acknowledgment for the messages as | 435 // Rebuild the client, and receive an acknowledgment for the messages as |
406 // part of the login response. | 436 // part of the login response. |
407 BuildMCSClient(); | 437 BuildMCSClient(); |
408 InitializeClient(); | 438 InitializeClient(); |
409 LoginClient(std::vector<std::string>()); | 439 LoginClient(std::vector<std::string>()); |
410 | 440 |
411 std::vector<std::string> acked_ids, remaining_ids; | 441 std::vector<std::string> acked_ids, remaining_ids; |
412 acked_ids.insert(acked_ids.end(), | 442 acked_ids.insert(acked_ids.end(), |
413 id_list.begin(), | 443 id_list.begin(), |
414 id_list.begin() + kMessageBatchSize / 2); | 444 id_list.begin() + kMessageBatchSize / 2); |
415 remaining_ids.insert(remaining_ids.end(), | 445 remaining_ids.insert(remaining_ids.end(), |
416 id_list.begin() + kMessageBatchSize / 2, | 446 id_list.begin() + kMessageBatchSize / 2, |
417 id_list.end()); | 447 id_list.end()); |
418 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { | 448 for (int i = 1; i <= kMessageBatchSize / 2; ++i) { |
419 MCSMessage message( | 449 MCSMessage message( |
420 BuildDataMessage("from", | 450 BuildDataMessage("from", |
421 "category", | 451 "category", |
422 2, | 452 2, |
423 remaining_ids[i - 1])); | 453 remaining_ids[i - 1], |
454 kTTLValue, | |
455 0)); | |
424 GetFakeHandler()->ExpectOutgoingMessage(message); | 456 GetFakeHandler()->ExpectOutgoingMessage(message); |
425 } | 457 } |
426 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); | 458 scoped_ptr<mcs_proto::IqStanza> ack(BuildSelectiveAck(acked_ids)); |
427 GetFakeHandler()->ReceiveMessage( | 459 GetFakeHandler()->ReceiveMessage( |
428 MCSMessage(kIqStanzaTag, | 460 MCSMessage(kIqStanzaTag, |
429 ack.PassAs<const google::protobuf::MessageLite>())); | 461 ack.PassAs<const google::protobuf::MessageLite>())); |
430 WaitForMCSEvent(); | 462 WaitForMCSEvent(); |
431 EXPECT_TRUE(GetFakeHandler()-> | 463 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
432 AllOutgoingMessagesReceived()); | |
433 } | 464 } |
434 | 465 |
435 // Receive some messages. On restart, the login request should contain the | 466 // Receive some messages. On restart, the login request should contain the |
436 // appropriate acknowledged ids. | 467 // appropriate acknowledged ids. |
437 TEST_F(MCSClientTest, AckOnLogin) { | 468 TEST_F(MCSClientTest, AckOnLogin) { |
438 BuildMCSClient(); | 469 BuildMCSClient(); |
439 InitializeClient(); | 470 InitializeClient(); |
440 LoginClient(std::vector<std::string>()); | 471 LoginClient(std::vector<std::string>()); |
441 | 472 |
442 // Receive some messages. | 473 // Receive some messages. |
443 std::vector<std::string> id_list; | 474 std::vector<std::string> id_list; |
444 for (int i = 1; i <= kMessageBatchSize; ++i) { | 475 for (int i = 1; i <= kMessageBatchSize; ++i) { |
445 id_list.push_back(base::IntToString(i)); | 476 id_list.push_back(base::IntToString(i)); |
446 MCSMessage message( | 477 MCSMessage message( |
447 BuildDataMessage("from", "category", i, id_list.back())); | 478 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 0)); |
448 GetFakeHandler()->ReceiveMessage(message); | 479 GetFakeHandler()->ReceiveMessage(message); |
449 WaitForMCSEvent(); | 480 WaitForMCSEvent(); |
450 PumpLoop(); | 481 PumpLoop(); |
451 } | 482 } |
452 | 483 |
453 // Restart the client. | 484 // Restart the client. |
454 BuildMCSClient(); | 485 BuildMCSClient(); |
455 InitializeClient(); | 486 InitializeClient(); |
456 LoginClient(id_list); | 487 LoginClient(id_list); |
457 } | 488 } |
458 | 489 |
459 // Receive some messages. On the next send, the outgoing message should contain | 490 // 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. | 491 // the appropriate last stream id received field to ack the received messages. |
461 TEST_F(MCSClientTest, AckOnSend) { | 492 TEST_F(MCSClientTest, AckOnSend) { |
462 BuildMCSClient(); | 493 BuildMCSClient(); |
463 InitializeClient(); | 494 InitializeClient(); |
464 LoginClient(std::vector<std::string>()); | 495 LoginClient(std::vector<std::string>()); |
465 | 496 |
466 // Receive some messages. | 497 // Receive some messages. |
467 std::vector<std::string> id_list; | 498 std::vector<std::string> id_list; |
468 for (int i = 1; i <= kMessageBatchSize; ++i) { | 499 for (int i = 1; i <= kMessageBatchSize; ++i) { |
469 id_list.push_back(base::IntToString(i)); | 500 id_list.push_back(base::IntToString(i)); |
470 MCSMessage message( | 501 MCSMessage message( |
471 BuildDataMessage("from", "category", i, id_list.back())); | 502 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 0)); |
472 GetFakeHandler()->ReceiveMessage(message); | 503 GetFakeHandler()->ReceiveMessage(message); |
473 WaitForMCSEvent(); | 504 WaitForMCSEvent(); |
474 PumpLoop(); | 505 PumpLoop(); |
475 } | 506 } |
476 | 507 |
477 // Trigger a message send, which should acknowledge via stream ack. | 508 // Trigger a message send, which should acknowledge via stream ack. |
478 MCSMessage message( | 509 MCSMessage message( |
479 BuildDataMessage("from", "category", kMessageBatchSize + 1, "1")); | 510 BuildDataMessage("from", |
511 "category", | |
512 kMessageBatchSize + 1, | |
513 "1", | |
514 kTTLValue, | |
515 0)); | |
480 GetFakeHandler()->ExpectOutgoingMessage(message); | 516 GetFakeHandler()->ExpectOutgoingMessage(message); |
481 mcs_client()->SendMessage(message, true); | 517 mcs_client()->SendMessage(message); |
482 EXPECT_TRUE(GetFakeHandler()-> | 518 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
483 AllOutgoingMessagesReceived()); | |
484 } | 519 } |
485 | 520 |
486 // Receive the ack limit in messages, which should trigger an automatic | 521 // Receive the ack limit in messages, which should trigger an automatic |
487 // stream ack. Receive a heartbeat to confirm the ack. | 522 // stream ack. Receive a heartbeat to confirm the ack. |
488 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { | 523 TEST_F(MCSClientTest, AckWhenLimitReachedWithHeartbeat) { |
489 BuildMCSClient(); | 524 BuildMCSClient(); |
490 InitializeClient(); | 525 InitializeClient(); |
491 LoginClient(std::vector<std::string>()); | 526 LoginClient(std::vector<std::string>()); |
492 | 527 |
493 // The stream ack. | 528 // The stream ack. |
494 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); | 529 scoped_ptr<mcs_proto::IqStanza> ack = BuildStreamAck(); |
495 ack->set_last_stream_id_received(kAckLimitSize + 1); | 530 ack->set_last_stream_id_received(kAckLimitSize + 1); |
496 GetFakeHandler()->ExpectOutgoingMessage( | 531 GetFakeHandler()->ExpectOutgoingMessage( |
497 MCSMessage(kIqStanzaTag, | 532 MCSMessage(kIqStanzaTag, |
498 ack.PassAs<const google::protobuf::MessageLite>())); | 533 ack.PassAs<const google::protobuf::MessageLite>())); |
499 | 534 |
500 // Receive some messages. | 535 // Receive some messages. |
501 std::vector<std::string> id_list; | 536 std::vector<std::string> id_list; |
502 for (int i = 1; i <= kAckLimitSize; ++i) { | 537 for (int i = 1; i <= kAckLimitSize; ++i) { |
503 id_list.push_back(base::IntToString(i)); | 538 id_list.push_back(base::IntToString(i)); |
504 MCSMessage message( | 539 MCSMessage message( |
505 BuildDataMessage("from", "category", i, id_list.back())); | 540 BuildDataMessage("from", "category", i, id_list.back(), kTTLValue, 0)); |
506 GetFakeHandler()->ReceiveMessage(message); | 541 GetFakeHandler()->ReceiveMessage(message); |
507 WaitForMCSEvent(); | 542 WaitForMCSEvent(); |
508 PumpLoop(); | 543 PumpLoop(); |
509 } | 544 } |
510 EXPECT_TRUE(GetFakeHandler()-> | 545 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
511 AllOutgoingMessagesReceived()); | |
512 | 546 |
513 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). | 547 // Receive a heartbeat confirming the ack (and receive the heartbeat ack). |
514 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( | 548 scoped_ptr<mcs_proto::HeartbeatPing> heartbeat( |
515 new mcs_proto::HeartbeatPing()); | 549 new mcs_proto::HeartbeatPing()); |
516 heartbeat->set_last_stream_id_received(2); | 550 heartbeat->set_last_stream_id_received(2); |
517 | 551 |
518 scoped_ptr<mcs_proto::HeartbeatAck> heartbeat_ack( | 552 scoped_ptr<mcs_proto::HeartbeatAck> heartbeat_ack( |
519 new mcs_proto::HeartbeatAck()); | 553 new mcs_proto::HeartbeatAck()); |
520 heartbeat_ack->set_last_stream_id_received(kAckLimitSize + 2); | 554 heartbeat_ack->set_last_stream_id_received(kAckLimitSize + 2); |
521 GetFakeHandler()->ExpectOutgoingMessage( | 555 GetFakeHandler()->ExpectOutgoingMessage( |
522 MCSMessage(kHeartbeatAckTag, | 556 MCSMessage(kHeartbeatAckTag, |
523 heartbeat_ack.PassAs<const google::protobuf::MessageLite>())); | 557 heartbeat_ack.PassAs<const google::protobuf::MessageLite>())); |
524 | 558 |
525 GetFakeHandler()->ReceiveMessage( | 559 GetFakeHandler()->ReceiveMessage( |
526 MCSMessage(kHeartbeatPingTag, | 560 MCSMessage(kHeartbeatPingTag, |
527 heartbeat.PassAs<const google::protobuf::MessageLite>())); | 561 heartbeat.PassAs<const google::protobuf::MessageLite>())); |
528 WaitForMCSEvent(); | 562 WaitForMCSEvent(); |
529 EXPECT_TRUE(GetFakeHandler()-> | 563 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
530 AllOutgoingMessagesReceived()); | |
531 | 564 |
532 // Rebuild the client. Nothing should be sent on login. | 565 // Rebuild the client. Nothing should be sent on login. |
533 BuildMCSClient(); | 566 BuildMCSClient(); |
534 InitializeClient(); | 567 InitializeClient(); |
535 LoginClient(std::vector<std::string>()); | 568 LoginClient(std::vector<std::string>()); |
536 EXPECT_TRUE(GetFakeHandler()-> | 569 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); |
537 AllOutgoingMessagesReceived()); | 570 } |
571 | |
572 // If a message's TTL has expired by the time it reaches the front of the send | |
573 // queue, it should be dropped. | |
574 TEST_F(MCSClientTest, ExpiredTTLOnSend) { | |
575 BuildMCSClient(); | |
576 InitializeClient(); | |
577 LoginClient(std::vector<std::string>()); | |
578 MCSMessage message( | |
579 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
580 | |
581 // Advance time to after the TTL. | |
582 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 1)); | |
583 EXPECT_TRUE(sent_message_id().empty()); | |
584 mcs_client()->SendMessage(message); | |
585 | |
586 // No messages should be sent, but the callback should still be invoked. | |
587 EXPECT_FALSE(sent_message_id().empty()); | |
588 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | |
589 } | |
590 | |
591 TEST_F(MCSClientTest, ExpiredTTLOnRestart) { | |
592 BuildMCSClient(); | |
593 InitializeClient(); | |
594 LoginClient(std::vector<std::string>()); | |
595 GetFakeHandler()->set_fail_send(true); | |
596 MCSMessage message( | |
597 BuildDataMessage("from", "category", 1, "1", kTTLValue, 0)); | |
598 | |
599 // The initial (failed) send. | |
600 GetFakeHandler()->ExpectOutgoingMessage(message); | |
601 GetFakeHandler()->set_fail_send(false); | |
602 mcs_client()->SendMessage(message); | |
603 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | |
604 | |
605 // Move the clock forward and rebuild the client, which should fail the | |
606 // message send on restart. | |
607 clock()->Advance(base::TimeDelta::FromSeconds(kTTLValue + 1)); | |
608 BuildMCSClient(); | |
609 InitializeClient(); | |
610 LoginClient(std::vector<std::string>()); | |
611 PumpLoop(); | |
612 EXPECT_FALSE(sent_message_id().empty()); | |
613 EXPECT_TRUE(GetFakeHandler()->AllOutgoingMessagesReceived()); | |
538 } | 614 } |
539 | 615 |
540 } // namespace | 616 } // namespace |
541 | 617 |
542 } // namespace gcm | 618 } // namespace gcm |
OLD | NEW |