OLD | NEW |
| (Empty) |
1 // Copyright 2014 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. | |
4 | |
5 #include "google_apis/gcm/gcm_client_impl.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "base/files/scoped_temp_dir.h" | |
9 #include "base/message_loop/message_loop.h" | |
10 #include "base/run_loop.h" | |
11 #include "base/strings/string_number_conversions.h" | |
12 #include "base/time/clock.h" | |
13 #include "google_apis/gcm/base/fake_encryptor.h" | |
14 #include "google_apis/gcm/base/mcs_message.h" | |
15 #include "google_apis/gcm/base/mcs_util.h" | |
16 #include "google_apis/gcm/engine/fake_connection_factory.h" | |
17 #include "google_apis/gcm/engine/fake_connection_handler.h" | |
18 #include "google_apis/gcm/engine/gservices_settings.h" | |
19 #include "google_apis/gcm/monitoring/gcm_stats_recorder.h" | |
20 #include "google_apis/gcm/protocol/android_checkin.pb.h" | |
21 #include "google_apis/gcm/protocol/checkin.pb.h" | |
22 #include "google_apis/gcm/protocol/mcs.pb.h" | |
23 #include "net/url_request/test_url_fetcher_factory.h" | |
24 #include "net/url_request/url_fetcher_delegate.h" | |
25 #include "net/url_request/url_request_test_util.h" | |
26 #include "testing/gtest/include/gtest/gtest.h" | |
27 | |
28 namespace gcm { | |
29 | |
30 namespace { | |
31 | |
32 enum LastEvent { | |
33 NONE, | |
34 LOADING_COMPLETED, | |
35 REGISTRATION_COMPLETED, | |
36 UNREGISTRATION_COMPLETED, | |
37 MESSAGE_SEND_ERROR, | |
38 MESSAGE_RECEIVED, | |
39 MESSAGES_DELETED, | |
40 }; | |
41 | |
42 const uint64 kDeviceAndroidId = 54321; | |
43 const uint64 kDeviceSecurityToken = 12345; | |
44 const int64 kSettingsCheckinInterval = 16 * 60 * 60; | |
45 const char kAppId[] = "app_id"; | |
46 const char kSender[] = "project_id"; | |
47 const char kSender2[] = "project_id2"; | |
48 const char kSender3[] = "project_id3"; | |
49 const char kRegistrationResponsePrefix[] = "token="; | |
50 const char kUnregistrationResponsePrefix[] = "deleted="; | |
51 | |
52 // Helper for building arbitrary data messages. | |
53 MCSMessage BuildDownstreamMessage( | |
54 const std::string& project_id, | |
55 const std::string& app_id, | |
56 const std::map<std::string, std::string>& data) { | |
57 mcs_proto::DataMessageStanza data_message; | |
58 data_message.set_from(project_id); | |
59 data_message.set_category(app_id); | |
60 for (std::map<std::string, std::string>::const_iterator iter = data.begin(); | |
61 iter != data.end(); | |
62 ++iter) { | |
63 mcs_proto::AppData* app_data = data_message.add_app_data(); | |
64 app_data->set_key(iter->first); | |
65 app_data->set_value(iter->second); | |
66 } | |
67 return MCSMessage(kDataMessageStanzaTag, data_message); | |
68 } | |
69 | |
70 class FakeMCSClient : public MCSClient { | |
71 public: | |
72 FakeMCSClient(base::Clock* clock, | |
73 ConnectionFactory* connection_factory, | |
74 GCMStore* gcm_store, | |
75 GCMStatsRecorder* recorder); | |
76 virtual ~FakeMCSClient(); | |
77 virtual void Login(uint64 android_id, uint64 security_token) OVERRIDE; | |
78 virtual void SendMessage(const MCSMessage& message) OVERRIDE; | |
79 | |
80 uint64 last_android_id() const { return last_android_id_; } | |
81 uint64 last_security_token() const { return last_security_token_; } | |
82 uint8 last_message_tag() const { return last_message_tag_; } | |
83 const mcs_proto::DataMessageStanza& last_data_message_stanza() const { | |
84 return last_data_message_stanza_; | |
85 } | |
86 | |
87 private: | |
88 uint64 last_android_id_; | |
89 uint64 last_security_token_; | |
90 uint8 last_message_tag_; | |
91 mcs_proto::DataMessageStanza last_data_message_stanza_; | |
92 }; | |
93 | |
94 FakeMCSClient::FakeMCSClient(base::Clock* clock, | |
95 ConnectionFactory* connection_factory, | |
96 GCMStore* gcm_store, | |
97 GCMStatsRecorder* recorder) | |
98 : MCSClient("", clock, connection_factory, gcm_store, recorder), | |
99 last_android_id_(0u), | |
100 last_security_token_(0u), | |
101 last_message_tag_(kNumProtoTypes) { | |
102 } | |
103 | |
104 FakeMCSClient::~FakeMCSClient() { | |
105 } | |
106 | |
107 void FakeMCSClient::Login(uint64 android_id, uint64 security_token) { | |
108 last_android_id_ = android_id; | |
109 last_security_token_ = security_token; | |
110 } | |
111 | |
112 void FakeMCSClient::SendMessage(const MCSMessage& message) { | |
113 last_message_tag_ = message.tag(); | |
114 if (last_message_tag_ == kDataMessageStanzaTag) { | |
115 last_data_message_stanza_.CopyFrom( | |
116 reinterpret_cast<const mcs_proto::DataMessageStanza&>( | |
117 message.GetProtobuf())); | |
118 } | |
119 } | |
120 | |
121 class AutoAdvancingTestClock : public base::Clock { | |
122 public: | |
123 explicit AutoAdvancingTestClock(base::TimeDelta auto_increment_time_delta); | |
124 virtual ~AutoAdvancingTestClock(); | |
125 | |
126 virtual base::Time Now() OVERRIDE; | |
127 void Advance(TimeDelta delta); | |
128 int call_count() const { return call_count_; } | |
129 | |
130 private: | |
131 int call_count_; | |
132 base::TimeDelta auto_increment_time_delta_; | |
133 base::Time now_; | |
134 | |
135 DISALLOW_COPY_AND_ASSIGN(AutoAdvancingTestClock); | |
136 }; | |
137 | |
138 AutoAdvancingTestClock::AutoAdvancingTestClock( | |
139 base::TimeDelta auto_increment_time_delta) | |
140 : call_count_(0), auto_increment_time_delta_(auto_increment_time_delta) { | |
141 } | |
142 | |
143 AutoAdvancingTestClock::~AutoAdvancingTestClock() { | |
144 } | |
145 | |
146 base::Time AutoAdvancingTestClock::Now() { | |
147 call_count_++; | |
148 now_ += auto_increment_time_delta_; | |
149 return now_; | |
150 } | |
151 | |
152 void AutoAdvancingTestClock::Advance(base::TimeDelta delta) { | |
153 now_ += delta; | |
154 } | |
155 | |
156 class FakeGCMInternalsBuilder : public GCMInternalsBuilder { | |
157 public: | |
158 FakeGCMInternalsBuilder(base::TimeDelta clock_step); | |
159 virtual ~FakeGCMInternalsBuilder(); | |
160 | |
161 virtual scoped_ptr<base::Clock> BuildClock() OVERRIDE; | |
162 virtual scoped_ptr<MCSClient> BuildMCSClient( | |
163 const std::string& version, | |
164 base::Clock* clock, | |
165 ConnectionFactory* connection_factory, | |
166 GCMStore* gcm_store, | |
167 GCMStatsRecorder* recorder) OVERRIDE; | |
168 virtual scoped_ptr<ConnectionFactory> BuildConnectionFactory( | |
169 const std::vector<GURL>& endpoints, | |
170 const net::BackoffEntry::Policy& backoff_policy, | |
171 scoped_refptr<net::HttpNetworkSession> network_session, | |
172 net::NetLog* net_log, | |
173 GCMStatsRecorder* recorder) OVERRIDE; | |
174 | |
175 private: | |
176 base::TimeDelta clock_step_; | |
177 }; | |
178 | |
179 FakeGCMInternalsBuilder::FakeGCMInternalsBuilder(base::TimeDelta clock_step) | |
180 : clock_step_(clock_step) { | |
181 } | |
182 | |
183 FakeGCMInternalsBuilder::~FakeGCMInternalsBuilder() {} | |
184 | |
185 scoped_ptr<base::Clock> FakeGCMInternalsBuilder::BuildClock() { | |
186 return make_scoped_ptr<base::Clock>(new AutoAdvancingTestClock(clock_step_)); | |
187 } | |
188 | |
189 scoped_ptr<MCSClient> FakeGCMInternalsBuilder::BuildMCSClient( | |
190 const std::string& version, | |
191 base::Clock* clock, | |
192 ConnectionFactory* connection_factory, | |
193 GCMStore* gcm_store, | |
194 GCMStatsRecorder* recorder) { | |
195 return make_scoped_ptr<MCSClient>(new FakeMCSClient(clock, | |
196 connection_factory, | |
197 gcm_store, | |
198 recorder)); | |
199 } | |
200 | |
201 scoped_ptr<ConnectionFactory> FakeGCMInternalsBuilder::BuildConnectionFactory( | |
202 const std::vector<GURL>& endpoints, | |
203 const net::BackoffEntry::Policy& backoff_policy, | |
204 scoped_refptr<net::HttpNetworkSession> network_session, | |
205 net::NetLog* net_log, | |
206 GCMStatsRecorder* recorder) { | |
207 return make_scoped_ptr<ConnectionFactory>(new FakeConnectionFactory()); | |
208 } | |
209 | |
210 } // namespace | |
211 | |
212 class GCMClientImplTest : public testing::Test, | |
213 public GCMClient::Delegate { | |
214 public: | |
215 GCMClientImplTest(); | |
216 virtual ~GCMClientImplTest(); | |
217 | |
218 virtual void SetUp() OVERRIDE; | |
219 | |
220 void BuildGCMClient(base::TimeDelta clock_step); | |
221 void InitializeGCMClient(); | |
222 void ReceiveMessageFromMCS(const MCSMessage& message); | |
223 void CompleteCheckin(uint64 android_id, | |
224 uint64 security_token, | |
225 const std::string& digest, | |
226 const std::map<std::string, std::string>& settings); | |
227 void CompleteRegistration(const std::string& registration_id); | |
228 void CompleteUnregistration(const std::string& app_id); | |
229 | |
230 bool ExistsRegistration(const std::string& app_id) const; | |
231 void AddRegistration(const std::string& app_id, | |
232 const std::vector<std::string>& sender_ids, | |
233 const std::string& registration_id); | |
234 | |
235 // GCMClient::Delegate overrides (for verification). | |
236 virtual void OnRegisterFinished(const std::string& app_id, | |
237 const std::string& registration_id, | |
238 GCMClient::Result result) OVERRIDE; | |
239 virtual void OnUnregisterFinished(const std::string& app_id, | |
240 GCMClient::Result result) OVERRIDE; | |
241 virtual void OnSendFinished(const std::string& app_id, | |
242 const std::string& message_id, | |
243 GCMClient::Result result) OVERRIDE {} | |
244 virtual void OnMessageReceived(const std::string& registration_id, | |
245 const GCMClient::IncomingMessage& message) | |
246 OVERRIDE; | |
247 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE; | |
248 virtual void OnMessageSendError( | |
249 const std::string& app_id, | |
250 const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE; | |
251 virtual void OnGCMReady() OVERRIDE; | |
252 virtual void OnActivityRecorded() OVERRIDE {} | |
253 | |
254 GCMClientImpl* gcm_client() const { return gcm_client_.get(); } | |
255 FakeMCSClient* mcs_client() const { | |
256 return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get()); | |
257 } | |
258 ConnectionFactory* connection_factory() const { | |
259 return gcm_client_->connection_factory_.get(); | |
260 } | |
261 | |
262 void reset_last_event() { | |
263 last_event_ = NONE; | |
264 last_app_id_.clear(); | |
265 last_registration_id_.clear(); | |
266 last_message_id_.clear(); | |
267 last_result_ = GCMClient::UNKNOWN_ERROR; | |
268 } | |
269 | |
270 LastEvent last_event() const { return last_event_; } | |
271 const std::string& last_app_id() const { return last_app_id_; } | |
272 const std::string& last_registration_id() const { | |
273 return last_registration_id_; | |
274 } | |
275 const std::string& last_message_id() const { return last_message_id_; } | |
276 GCMClient::Result last_result() const { return last_result_; } | |
277 const GCMClient::IncomingMessage& last_message() const { | |
278 return last_message_; | |
279 } | |
280 const GCMClient::SendErrorDetails& last_error_details() const { | |
281 return last_error_details_; | |
282 } | |
283 | |
284 const GServicesSettings& gservices_settings() const { | |
285 return gcm_client_->gservices_settings_; | |
286 } | |
287 | |
288 int64 CurrentTime(); | |
289 | |
290 // Tooling. | |
291 void PumpLoop(); | |
292 void PumpLoopUntilIdle(); | |
293 void QuitLoop(); | |
294 void InitializeLoop(); | |
295 bool CreateUniqueTempDir(); | |
296 AutoAdvancingTestClock* clock() const { | |
297 return reinterpret_cast<AutoAdvancingTestClock*>(gcm_client_->clock_.get()); | |
298 } | |
299 | |
300 private: | |
301 // Variables used for verification. | |
302 LastEvent last_event_; | |
303 std::string last_app_id_; | |
304 std::string last_registration_id_; | |
305 std::string last_message_id_; | |
306 GCMClient::Result last_result_; | |
307 GCMClient::IncomingMessage last_message_; | |
308 GCMClient::SendErrorDetails last_error_details_; | |
309 | |
310 scoped_ptr<GCMClientImpl> gcm_client_; | |
311 | |
312 base::MessageLoop message_loop_; | |
313 scoped_ptr<base::RunLoop> run_loop_; | |
314 net::TestURLFetcherFactory url_fetcher_factory_; | |
315 | |
316 // Injected to GCM client: | |
317 base::ScopedTempDir temp_directory_; | |
318 scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_; | |
319 }; | |
320 | |
321 GCMClientImplTest::GCMClientImplTest() | |
322 : last_event_(NONE), | |
323 last_result_(GCMClient::UNKNOWN_ERROR), | |
324 url_request_context_getter_(new net::TestURLRequestContextGetter( | |
325 message_loop_.message_loop_proxy())) { | |
326 } | |
327 | |
328 GCMClientImplTest::~GCMClientImplTest() {} | |
329 | |
330 void GCMClientImplTest::SetUp() { | |
331 testing::Test::SetUp(); | |
332 ASSERT_TRUE(CreateUniqueTempDir()); | |
333 InitializeLoop(); | |
334 BuildGCMClient(base::TimeDelta()); | |
335 InitializeGCMClient(); | |
336 CompleteCheckin(kDeviceAndroidId, | |
337 kDeviceSecurityToken, | |
338 std::string(), | |
339 std::map<std::string, std::string>()); | |
340 } | |
341 | |
342 void GCMClientImplTest::PumpLoop() { | |
343 run_loop_->Run(); | |
344 run_loop_.reset(new base::RunLoop()); | |
345 } | |
346 | |
347 void GCMClientImplTest::PumpLoopUntilIdle() { | |
348 run_loop_->RunUntilIdle(); | |
349 run_loop_.reset(new base::RunLoop()); | |
350 } | |
351 | |
352 void GCMClientImplTest::QuitLoop() { | |
353 if (run_loop_ && run_loop_->running()) | |
354 run_loop_->Quit(); | |
355 } | |
356 | |
357 void GCMClientImplTest::InitializeLoop() { | |
358 run_loop_.reset(new base::RunLoop); | |
359 } | |
360 | |
361 bool GCMClientImplTest::CreateUniqueTempDir() { | |
362 return temp_directory_.CreateUniqueTempDir(); | |
363 } | |
364 | |
365 void GCMClientImplTest::BuildGCMClient(base::TimeDelta clock_step) { | |
366 gcm_client_.reset(new GCMClientImpl(make_scoped_ptr<GCMInternalsBuilder>( | |
367 new FakeGCMInternalsBuilder(clock_step)))); | |
368 } | |
369 | |
370 void GCMClientImplTest::CompleteCheckin( | |
371 uint64 android_id, | |
372 uint64 security_token, | |
373 const std::string& digest, | |
374 const std::map<std::string, std::string>& settings) { | |
375 checkin_proto::AndroidCheckinResponse response; | |
376 response.set_stats_ok(true); | |
377 response.set_android_id(android_id); | |
378 response.set_security_token(security_token); | |
379 | |
380 // For testing G-services settings. | |
381 if (!digest.empty()) { | |
382 response.set_digest(digest); | |
383 for (std::map<std::string, std::string>::const_iterator it = | |
384 settings.begin(); | |
385 it != settings.end(); | |
386 ++it) { | |
387 checkin_proto::GservicesSetting* setting = response.add_setting(); | |
388 setting->set_name(it->first); | |
389 setting->set_value(it->second); | |
390 } | |
391 response.set_settings_diff(false); | |
392 } | |
393 | |
394 std::string response_string; | |
395 response.SerializeToString(&response_string); | |
396 | |
397 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); | |
398 ASSERT_TRUE(fetcher); | |
399 fetcher->set_response_code(net::HTTP_OK); | |
400 fetcher->SetResponseString(response_string); | |
401 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
402 url_fetcher_factory_.RemoveFetcherFromMap(0); | |
403 } | |
404 | |
405 void GCMClientImplTest::CompleteRegistration( | |
406 const std::string& registration_id) { | |
407 std::string response(kRegistrationResponsePrefix); | |
408 response.append(registration_id); | |
409 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); | |
410 ASSERT_TRUE(fetcher); | |
411 fetcher->set_response_code(net::HTTP_OK); | |
412 fetcher->SetResponseString(response); | |
413 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
414 url_fetcher_factory_.RemoveFetcherFromMap(0); | |
415 } | |
416 | |
417 void GCMClientImplTest::CompleteUnregistration( | |
418 const std::string& app_id) { | |
419 std::string response(kUnregistrationResponsePrefix); | |
420 response.append(app_id); | |
421 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); | |
422 ASSERT_TRUE(fetcher); | |
423 fetcher->set_response_code(net::HTTP_OK); | |
424 fetcher->SetResponseString(response); | |
425 fetcher->delegate()->OnURLFetchComplete(fetcher); | |
426 url_fetcher_factory_.RemoveFetcherFromMap(0); | |
427 } | |
428 | |
429 bool GCMClientImplTest::ExistsRegistration(const std::string& app_id) const { | |
430 return gcm_client_->registrations_.count(app_id) > 0; | |
431 } | |
432 | |
433 void GCMClientImplTest::AddRegistration( | |
434 const std::string& app_id, | |
435 const std::vector<std::string>& sender_ids, | |
436 const std::string& registration_id) { | |
437 linked_ptr<RegistrationInfo> registration(new RegistrationInfo); | |
438 registration->sender_ids = sender_ids; | |
439 registration->registration_id = registration_id; | |
440 gcm_client_->registrations_[app_id] = registration; | |
441 } | |
442 | |
443 void GCMClientImplTest::InitializeGCMClient() { | |
444 clock()->Advance(base::TimeDelta::FromMilliseconds(1)); | |
445 | |
446 // Actual initialization. | |
447 GCMClient::ChromeBuildInfo chrome_build_info; | |
448 gcm_client_->Initialize(chrome_build_info, | |
449 temp_directory_.path(), | |
450 std::vector<std::string>(), | |
451 message_loop_.message_loop_proxy(), | |
452 url_request_context_getter_, | |
453 make_scoped_ptr<Encryptor>(new FakeEncryptor), | |
454 this); | |
455 | |
456 // Start loading and check-in. | |
457 gcm_client_->Start(); | |
458 | |
459 PumpLoopUntilIdle(); | |
460 } | |
461 | |
462 void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) { | |
463 gcm_client_->OnMessageReceivedFromMCS(message); | |
464 } | |
465 | |
466 void GCMClientImplTest::OnGCMReady() { | |
467 last_event_ = LOADING_COMPLETED; | |
468 QuitLoop(); | |
469 } | |
470 | |
471 void GCMClientImplTest::OnMessageReceived( | |
472 const std::string& registration_id, | |
473 const GCMClient::IncomingMessage& message) { | |
474 last_event_ = MESSAGE_RECEIVED; | |
475 last_app_id_ = registration_id; | |
476 last_message_ = message; | |
477 QuitLoop(); | |
478 } | |
479 | |
480 void GCMClientImplTest::OnRegisterFinished(const std::string& app_id, | |
481 const std::string& registration_id, | |
482 GCMClient::Result result) { | |
483 last_event_ = REGISTRATION_COMPLETED; | |
484 last_app_id_ = app_id; | |
485 last_registration_id_ = registration_id; | |
486 last_result_ = result; | |
487 } | |
488 | |
489 void GCMClientImplTest::OnUnregisterFinished(const std::string& app_id, | |
490 GCMClient::Result result) { | |
491 last_event_ = UNREGISTRATION_COMPLETED; | |
492 last_app_id_ = app_id; | |
493 last_result_ = result; | |
494 } | |
495 | |
496 void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) { | |
497 last_event_ = MESSAGES_DELETED; | |
498 last_app_id_ = app_id; | |
499 } | |
500 | |
501 void GCMClientImplTest::OnMessageSendError( | |
502 const std::string& app_id, | |
503 const gcm::GCMClient::SendErrorDetails& send_error_details) { | |
504 last_event_ = MESSAGE_SEND_ERROR; | |
505 last_app_id_ = app_id; | |
506 last_error_details_ = send_error_details; | |
507 } | |
508 | |
509 int64 GCMClientImplTest::CurrentTime() { | |
510 return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond; | |
511 } | |
512 | |
513 TEST_F(GCMClientImplTest, LoadingCompleted) { | |
514 EXPECT_EQ(LOADING_COMPLETED, last_event()); | |
515 EXPECT_EQ(kDeviceAndroidId, mcs_client()->last_android_id()); | |
516 EXPECT_EQ(kDeviceSecurityToken, mcs_client()->last_security_token()); | |
517 } | |
518 | |
519 TEST_F(GCMClientImplTest, CheckOut) { | |
520 EXPECT_TRUE(mcs_client()); | |
521 EXPECT_TRUE(connection_factory()); | |
522 gcm_client()->CheckOut(); | |
523 EXPECT_FALSE(mcs_client()); | |
524 EXPECT_FALSE(connection_factory()); | |
525 } | |
526 | |
527 TEST_F(GCMClientImplTest, RegisterApp) { | |
528 EXPECT_FALSE(ExistsRegistration(kAppId)); | |
529 | |
530 std::vector<std::string> senders; | |
531 senders.push_back("sender"); | |
532 gcm_client()->Register(kAppId, senders); | |
533 CompleteRegistration("reg_id"); | |
534 | |
535 EXPECT_EQ(REGISTRATION_COMPLETED, last_event()); | |
536 EXPECT_EQ(kAppId, last_app_id()); | |
537 EXPECT_EQ("reg_id", last_registration_id()); | |
538 EXPECT_EQ(GCMClient::SUCCESS, last_result()); | |
539 EXPECT_TRUE(ExistsRegistration(kAppId)); | |
540 } | |
541 | |
542 TEST_F(GCMClientImplTest, DISABLED_RegisterAppFromCache) { | |
543 EXPECT_FALSE(ExistsRegistration(kAppId)); | |
544 | |
545 std::vector<std::string> senders; | |
546 senders.push_back("sender"); | |
547 gcm_client()->Register(kAppId, senders); | |
548 CompleteRegistration("reg_id"); | |
549 EXPECT_TRUE(ExistsRegistration(kAppId)); | |
550 | |
551 EXPECT_EQ(kAppId, last_app_id()); | |
552 EXPECT_EQ("reg_id", last_registration_id()); | |
553 EXPECT_EQ(GCMClient::SUCCESS, last_result()); | |
554 EXPECT_EQ(REGISTRATION_COMPLETED, last_event()); | |
555 | |
556 // Recreate GCMClient in order to load from the persistent store. | |
557 BuildGCMClient(base::TimeDelta()); | |
558 InitializeGCMClient(); | |
559 | |
560 EXPECT_TRUE(ExistsRegistration(kAppId)); | |
561 } | |
562 | |
563 TEST_F(GCMClientImplTest, UnregisterApp) { | |
564 EXPECT_FALSE(ExistsRegistration(kAppId)); | |
565 | |
566 std::vector<std::string> senders; | |
567 senders.push_back("sender"); | |
568 gcm_client()->Register(kAppId, senders); | |
569 CompleteRegistration("reg_id"); | |
570 EXPECT_TRUE(ExistsRegistration(kAppId)); | |
571 | |
572 gcm_client()->Unregister(kAppId); | |
573 CompleteUnregistration(kAppId); | |
574 | |
575 EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event()); | |
576 EXPECT_EQ(kAppId, last_app_id()); | |
577 EXPECT_EQ(GCMClient::SUCCESS, last_result()); | |
578 EXPECT_FALSE(ExistsRegistration(kAppId)); | |
579 } | |
580 | |
581 TEST_F(GCMClientImplTest, DispatchDownstreamMessage) { | |
582 // Register to receive messages from kSender and kSender2 only. | |
583 std::vector<std::string> senders; | |
584 senders.push_back(kSender); | |
585 senders.push_back(kSender2); | |
586 AddRegistration(kAppId, senders, "reg_id"); | |
587 | |
588 std::map<std::string, std::string> expected_data; | |
589 expected_data["message_type"] = "gcm"; | |
590 expected_data["key"] = "value"; | |
591 expected_data["key2"] = "value2"; | |
592 | |
593 // Message for kSender will be received. | |
594 MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data)); | |
595 EXPECT_TRUE(message.IsValid()); | |
596 ReceiveMessageFromMCS(message); | |
597 | |
598 expected_data.erase(expected_data.find("message_type")); | |
599 EXPECT_EQ(MESSAGE_RECEIVED, last_event()); | |
600 EXPECT_EQ(kAppId, last_app_id()); | |
601 EXPECT_EQ(expected_data.size(), last_message().data.size()); | |
602 EXPECT_EQ(expected_data, last_message().data); | |
603 EXPECT_EQ(kSender, last_message().sender_id); | |
604 | |
605 reset_last_event(); | |
606 | |
607 // Message for kSender2 will be received. | |
608 MCSMessage message2(BuildDownstreamMessage(kSender2, kAppId, expected_data)); | |
609 EXPECT_TRUE(message2.IsValid()); | |
610 ReceiveMessageFromMCS(message2); | |
611 | |
612 EXPECT_EQ(MESSAGE_RECEIVED, last_event()); | |
613 EXPECT_EQ(kAppId, last_app_id()); | |
614 EXPECT_EQ(expected_data.size(), last_message().data.size()); | |
615 EXPECT_EQ(expected_data, last_message().data); | |
616 EXPECT_EQ(kSender2, last_message().sender_id); | |
617 | |
618 reset_last_event(); | |
619 | |
620 // Message from kSender3 will be dropped. | |
621 MCSMessage message3(BuildDownstreamMessage(kSender3, kAppId, expected_data)); | |
622 EXPECT_TRUE(message3.IsValid()); | |
623 ReceiveMessageFromMCS(message3); | |
624 | |
625 EXPECT_NE(MESSAGE_RECEIVED, last_event()); | |
626 EXPECT_NE(kAppId, last_app_id()); | |
627 } | |
628 | |
629 TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) { | |
630 std::map<std::string, std::string> expected_data; | |
631 expected_data["message_type"] = "send_error"; | |
632 expected_data["google.message_id"] = "007"; | |
633 expected_data["error_details"] = "some details"; | |
634 MCSMessage message(BuildDownstreamMessage( | |
635 kSender, kAppId, expected_data)); | |
636 EXPECT_TRUE(message.IsValid()); | |
637 ReceiveMessageFromMCS(message); | |
638 | |
639 EXPECT_EQ(MESSAGE_SEND_ERROR, last_event()); | |
640 EXPECT_EQ(kAppId, last_app_id()); | |
641 EXPECT_EQ("007", last_error_details().message_id); | |
642 EXPECT_EQ(1UL, last_error_details().additional_data.size()); | |
643 GCMClient::MessageData::const_iterator iter = | |
644 last_error_details().additional_data.find("error_details"); | |
645 EXPECT_TRUE(iter != last_error_details().additional_data.end()); | |
646 EXPECT_EQ("some details", iter->second); | |
647 } | |
648 | |
649 TEST_F(GCMClientImplTest, DispatchDownstreamMessgaesDeleted) { | |
650 std::map<std::string, std::string> expected_data; | |
651 expected_data["message_type"] = "deleted_messages"; | |
652 MCSMessage message(BuildDownstreamMessage( | |
653 kSender, kAppId, expected_data)); | |
654 EXPECT_TRUE(message.IsValid()); | |
655 ReceiveMessageFromMCS(message); | |
656 | |
657 EXPECT_EQ(MESSAGES_DELETED, last_event()); | |
658 EXPECT_EQ(kAppId, last_app_id()); | |
659 } | |
660 | |
661 TEST_F(GCMClientImplTest, SendMessage) { | |
662 mcs_proto::DataMessageStanza stanza; | |
663 stanza.set_ttl(500); | |
664 | |
665 GCMClient::OutgoingMessage message; | |
666 message.id = "007"; | |
667 message.time_to_live = 500; | |
668 message.data["key"] = "value"; | |
669 gcm_client()->Send(kAppId, kSender, message); | |
670 | |
671 EXPECT_EQ(kDataMessageStanzaTag, mcs_client()->last_message_tag()); | |
672 EXPECT_EQ(kAppId, mcs_client()->last_data_message_stanza().category()); | |
673 EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to()); | |
674 EXPECT_EQ(500, mcs_client()->last_data_message_stanza().ttl()); | |
675 EXPECT_EQ(CurrentTime(), mcs_client()->last_data_message_stanza().sent()); | |
676 EXPECT_EQ("007", mcs_client()->last_data_message_stanza().id()); | |
677 EXPECT_EQ("gcm@chrome.com", mcs_client()->last_data_message_stanza().from()); | |
678 EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to()); | |
679 EXPECT_EQ("key", mcs_client()->last_data_message_stanza().app_data(0).key()); | |
680 EXPECT_EQ("value", | |
681 mcs_client()->last_data_message_stanza().app_data(0).value()); | |
682 } | |
683 | |
684 class GCMClientImplCheckinTest : public GCMClientImplTest { | |
685 public: | |
686 GCMClientImplCheckinTest(); | |
687 virtual ~GCMClientImplCheckinTest(); | |
688 | |
689 virtual void SetUp() OVERRIDE; | |
690 }; | |
691 | |
692 GCMClientImplCheckinTest::GCMClientImplCheckinTest() { | |
693 } | |
694 | |
695 GCMClientImplCheckinTest::~GCMClientImplCheckinTest() { | |
696 } | |
697 | |
698 void GCMClientImplCheckinTest::SetUp() { | |
699 testing::Test::SetUp(); | |
700 // Creating unique temp directory that will be used by GCMStore shared between | |
701 // GCM Client and G-services settings. | |
702 ASSERT_TRUE(CreateUniqueTempDir()); | |
703 InitializeLoop(); | |
704 // Time will be advancing one hour every time it is checked. | |
705 BuildGCMClient(base::TimeDelta::FromSeconds(kSettingsCheckinInterval)); | |
706 InitializeGCMClient(); | |
707 } | |
708 | |
709 TEST_F(GCMClientImplCheckinTest, GServicesSettingsAfterInitialCheckin) { | |
710 std::map<std::string, std::string> settings; | |
711 settings["checkin_interval"] = base::Int64ToString(kSettingsCheckinInterval); | |
712 settings["checkin_url"] = "http://alternative.url/checkin"; | |
713 settings["gcm_hostname"] = "alternative.gcm.host"; | |
714 settings["gcm_secure_port"] = "7777"; | |
715 settings["gcm_registration_url"] = "http://alternative.url/registration"; | |
716 CompleteCheckin(kDeviceAndroidId, | |
717 kDeviceSecurityToken, | |
718 GServicesSettings::CalculateDigest(settings), | |
719 settings); | |
720 EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval), | |
721 gservices_settings().GetCheckinInterval()); | |
722 EXPECT_EQ(GURL("http://alternative.url/checkin"), | |
723 gservices_settings().GetCheckinURL()); | |
724 EXPECT_EQ(GURL("http://alternative.url/registration"), | |
725 gservices_settings().GetRegistrationURL()); | |
726 EXPECT_EQ(GURL("https://alternative.gcm.host:7777"), | |
727 gservices_settings().GetMCSMainEndpoint()); | |
728 EXPECT_EQ(GURL("https://alternative.gcm.host:443"), | |
729 gservices_settings().GetMCSFallbackEndpoint()); | |
730 } | |
731 | |
732 // This test only checks that periodic checkin happens. | |
733 TEST_F(GCMClientImplCheckinTest, PeriodicCheckin) { | |
734 std::map<std::string, std::string> settings; | |
735 settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval); | |
736 settings["checkin_url"] = "http://alternative.url/checkin"; | |
737 settings["gcm_hostname"] = "alternative.gcm.host"; | |
738 settings["gcm_secure_port"] = "7777"; | |
739 settings["gcm_registration_url"] = "http://alternative.url/registration"; | |
740 CompleteCheckin(kDeviceAndroidId, | |
741 kDeviceSecurityToken, | |
742 GServicesSettings::CalculateDigest(settings), | |
743 settings); | |
744 EXPECT_EQ(2, clock()->call_count()); | |
745 | |
746 PumpLoopUntilIdle(); | |
747 CompleteCheckin(kDeviceAndroidId, | |
748 kDeviceSecurityToken, | |
749 GServicesSettings::CalculateDigest(settings), | |
750 settings); | |
751 } | |
752 | |
753 TEST_F(GCMClientImplCheckinTest, LoadGSettingsFromStore) { | |
754 std::map<std::string, std::string> settings; | |
755 settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval); | |
756 settings["checkin_url"] = "http://alternative.url/checkin"; | |
757 settings["gcm_hostname"] = "alternative.gcm.host"; | |
758 settings["gcm_secure_port"] = "7777"; | |
759 settings["gcm_registration_url"] = "http://alternative.url/registration"; | |
760 CompleteCheckin(kDeviceAndroidId, | |
761 kDeviceSecurityToken, | |
762 GServicesSettings::CalculateDigest(settings), | |
763 settings); | |
764 | |
765 BuildGCMClient(base::TimeDelta()); | |
766 InitializeGCMClient(); | |
767 | |
768 EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval), | |
769 gservices_settings().GetCheckinInterval()); | |
770 EXPECT_EQ(GURL("http://alternative.url/checkin"), | |
771 gservices_settings().GetCheckinURL()); | |
772 EXPECT_EQ(GURL("http://alternative.url/registration"), | |
773 gservices_settings().GetRegistrationURL()); | |
774 EXPECT_EQ(GURL("https://alternative.gcm.host:7777"), | |
775 gservices_settings().GetMCSMainEndpoint()); | |
776 EXPECT_EQ(GURL("https://alternative.gcm.host:443"), | |
777 gservices_settings().GetMCSFallbackEndpoint()); | |
778 } | |
779 | |
780 } // namespace gcm | |
OLD | NEW |