Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / components / gcm_driver / gcm_client_impl_unittest.cc
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 "components/gcm_driver/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_SEND_ACK,
39   MESSAGE_RECEIVED,
40   MESSAGES_DELETED,
41 };
42
43 const uint64 kDeviceAndroidId = 54321;
44 const uint64 kDeviceSecurityToken = 12345;
45 const int64 kSettingsCheckinInterval = 16 * 60 * 60;
46 const char kAppId[] = "app_id";
47 const char kSender[] = "project_id";
48 const char kSender2[] = "project_id2";
49 const char kSender3[] = "project_id3";
50 const char kRegistrationResponsePrefix[] = "token=";
51 const char kUnregistrationResponsePrefix[] = "deleted=";
52
53 // Helper for building arbitrary data messages.
54 MCSMessage BuildDownstreamMessage(
55     const std::string& project_id,
56     const std::string& app_id,
57     const std::map<std::string, std::string>& data) {
58   mcs_proto::DataMessageStanza data_message;
59   data_message.set_from(project_id);
60   data_message.set_category(app_id);
61   for (std::map<std::string, std::string>::const_iterator iter = data.begin();
62        iter != data.end();
63        ++iter) {
64     mcs_proto::AppData* app_data = data_message.add_app_data();
65     app_data->set_key(iter->first);
66     app_data->set_value(iter->second);
67   }
68   return MCSMessage(kDataMessageStanzaTag, data_message);
69 }
70
71 class FakeMCSClient : public MCSClient {
72  public:
73   FakeMCSClient(base::Clock* clock,
74                 ConnectionFactory* connection_factory,
75                 GCMStore* gcm_store,
76                 GCMStatsRecorder* recorder);
77   virtual ~FakeMCSClient();
78   virtual void Login(uint64 android_id, uint64 security_token) OVERRIDE;
79   virtual void SendMessage(const MCSMessage& message) OVERRIDE;
80
81   uint64 last_android_id() const { return last_android_id_; }
82   uint64 last_security_token() const { return last_security_token_; }
83   uint8 last_message_tag() const { return last_message_tag_; }
84   const mcs_proto::DataMessageStanza& last_data_message_stanza() const {
85     return last_data_message_stanza_;
86   }
87
88  private:
89   uint64 last_android_id_;
90   uint64 last_security_token_;
91   uint8 last_message_tag_;
92   mcs_proto::DataMessageStanza last_data_message_stanza_;
93 };
94
95 FakeMCSClient::FakeMCSClient(base::Clock* clock,
96                              ConnectionFactory* connection_factory,
97                              GCMStore* gcm_store,
98                              GCMStatsRecorder* recorder)
99     : MCSClient("", clock, connection_factory, gcm_store, recorder),
100       last_android_id_(0u),
101       last_security_token_(0u),
102       last_message_tag_(kNumProtoTypes) {
103 }
104
105 FakeMCSClient::~FakeMCSClient() {
106 }
107
108 void FakeMCSClient::Login(uint64 android_id, uint64 security_token) {
109   last_android_id_ = android_id;
110   last_security_token_ = security_token;
111 }
112
113 void FakeMCSClient::SendMessage(const MCSMessage& message) {
114   last_message_tag_ = message.tag();
115   if (last_message_tag_ == kDataMessageStanzaTag) {
116     last_data_message_stanza_.CopyFrom(
117         reinterpret_cast<const mcs_proto::DataMessageStanza&>(
118             message.GetProtobuf()));
119   }
120 }
121
122 class AutoAdvancingTestClock : public base::Clock {
123  public:
124   explicit AutoAdvancingTestClock(base::TimeDelta auto_increment_time_delta);
125   virtual ~AutoAdvancingTestClock();
126
127   virtual base::Time Now() OVERRIDE;
128   void Advance(TimeDelta delta);
129   int call_count() const { return call_count_; }
130
131  private:
132   int call_count_;
133   base::TimeDelta auto_increment_time_delta_;
134   base::Time now_;
135
136   DISALLOW_COPY_AND_ASSIGN(AutoAdvancingTestClock);
137 };
138
139 AutoAdvancingTestClock::AutoAdvancingTestClock(
140     base::TimeDelta auto_increment_time_delta)
141     : call_count_(0), auto_increment_time_delta_(auto_increment_time_delta) {
142 }
143
144 AutoAdvancingTestClock::~AutoAdvancingTestClock() {
145 }
146
147 base::Time AutoAdvancingTestClock::Now() {
148   call_count_++;
149   now_ += auto_increment_time_delta_;
150   return now_;
151 }
152
153 void AutoAdvancingTestClock::Advance(base::TimeDelta delta) {
154   now_ += delta;
155 }
156
157 class FakeGCMInternalsBuilder : public GCMInternalsBuilder {
158  public:
159   FakeGCMInternalsBuilder(base::TimeDelta clock_step);
160   virtual ~FakeGCMInternalsBuilder();
161
162   virtual scoped_ptr<base::Clock> BuildClock() OVERRIDE;
163   virtual scoped_ptr<MCSClient> BuildMCSClient(
164       const std::string& version,
165       base::Clock* clock,
166       ConnectionFactory* connection_factory,
167       GCMStore* gcm_store,
168       GCMStatsRecorder* recorder) OVERRIDE;
169   virtual scoped_ptr<ConnectionFactory> BuildConnectionFactory(
170       const std::vector<GURL>& endpoints,
171       const net::BackoffEntry::Policy& backoff_policy,
172       const scoped_refptr<net::HttpNetworkSession>& gcm_network_session,
173       const scoped_refptr<net::HttpNetworkSession>& http_network_session,
174       net::NetLog* net_log,
175       GCMStatsRecorder* recorder) OVERRIDE;
176
177  private:
178   base::TimeDelta clock_step_;
179 };
180
181 FakeGCMInternalsBuilder::FakeGCMInternalsBuilder(base::TimeDelta clock_step)
182     : clock_step_(clock_step) {
183 }
184
185 FakeGCMInternalsBuilder::~FakeGCMInternalsBuilder() {}
186
187 scoped_ptr<base::Clock> FakeGCMInternalsBuilder::BuildClock() {
188   return make_scoped_ptr<base::Clock>(new AutoAdvancingTestClock(clock_step_));
189 }
190
191 scoped_ptr<MCSClient> FakeGCMInternalsBuilder::BuildMCSClient(
192     const std::string& version,
193     base::Clock* clock,
194     ConnectionFactory* connection_factory,
195     GCMStore* gcm_store,
196     GCMStatsRecorder* recorder) {
197   return make_scoped_ptr<MCSClient>(new FakeMCSClient(clock,
198                                                       connection_factory,
199                                                       gcm_store,
200                                                       recorder));
201 }
202
203 scoped_ptr<ConnectionFactory> FakeGCMInternalsBuilder::BuildConnectionFactory(
204     const std::vector<GURL>& endpoints,
205     const net::BackoffEntry::Policy& backoff_policy,
206     const scoped_refptr<net::HttpNetworkSession>& gcm_network_session,
207     const scoped_refptr<net::HttpNetworkSession>& http_network_session,
208     net::NetLog* net_log,
209     GCMStatsRecorder* recorder) {
210   return make_scoped_ptr<ConnectionFactory>(new FakeConnectionFactory());
211 }
212
213 }  // namespace
214
215 class GCMClientImplTest : public testing::Test,
216                           public GCMClient::Delegate {
217  public:
218   GCMClientImplTest();
219   virtual ~GCMClientImplTest();
220
221   virtual void SetUp() OVERRIDE;
222
223   void BuildGCMClient(base::TimeDelta clock_step);
224   void InitializeGCMClient();
225   void StartGCMClient();
226   void ReceiveMessageFromMCS(const MCSMessage& message);
227   void ReceiveOnMessageSentToMCS(
228       const std::string& app_id,
229       const std::string& message_id,
230       const MCSClient::MessageSendStatus status);
231   void CompleteCheckin(uint64 android_id,
232                        uint64 security_token,
233                        const std::string& digest,
234                        const std::map<std::string, std::string>& settings);
235   void CompleteRegistration(const std::string& registration_id);
236   void CompleteUnregistration(const std::string& app_id);
237
238   bool ExistsRegistration(const std::string& app_id) const;
239   void AddRegistration(const std::string& app_id,
240                        const std::vector<std::string>& sender_ids,
241                        const std::string& registration_id);
242
243   // GCMClient::Delegate overrides (for verification).
244   virtual void OnRegisterFinished(const std::string& app_id,
245                                   const std::string& registration_id,
246                                   GCMClient::Result result) OVERRIDE;
247   virtual void OnUnregisterFinished(const std::string& app_id,
248                                     GCMClient::Result result) OVERRIDE;
249   virtual void OnSendFinished(const std::string& app_id,
250                               const std::string& message_id,
251                               GCMClient::Result result) OVERRIDE {}
252   virtual void OnMessageReceived(const std::string& registration_id,
253                                  const GCMClient::IncomingMessage& message)
254       OVERRIDE;
255   virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
256   virtual void OnMessageSendError(
257       const std::string& app_id,
258       const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
259   virtual void OnSendAcknowledged(const std::string& app_id,
260                                   const std::string& message_id) OVERRIDE;
261   virtual void OnGCMReady(
262       const std::vector<AccountMapping>& account_mappings) OVERRIDE;
263   virtual void OnActivityRecorded() OVERRIDE {}
264   virtual void OnConnected(const net::IPEndPoint& ip_endpoint) OVERRIDE {}
265   virtual void OnDisconnected() OVERRIDE {}
266
267   GCMClientImpl* gcm_client() const { return gcm_client_.get(); }
268   FakeMCSClient* mcs_client() const {
269     return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get());
270   }
271   ConnectionFactory* connection_factory() const {
272     return gcm_client_->connection_factory_.get();
273   }
274
275   const GCMClientImpl::CheckinInfo& device_checkin_info() const {
276     return gcm_client_->device_checkin_info_;
277   }
278
279   void reset_last_event() {
280     last_event_ = NONE;
281     last_app_id_.clear();
282     last_registration_id_.clear();
283     last_message_id_.clear();
284     last_result_ = GCMClient::UNKNOWN_ERROR;
285   }
286
287   LastEvent last_event() const { return last_event_; }
288   const std::string& last_app_id() const { return last_app_id_; }
289   const std::string& last_registration_id() const {
290     return last_registration_id_;
291   }
292   const std::string& last_message_id() const { return last_message_id_; }
293   GCMClient::Result last_result() const { return last_result_; }
294   const GCMClient::IncomingMessage& last_message() const {
295     return last_message_;
296   }
297   const GCMClient::SendErrorDetails& last_error_details() const {
298     return last_error_details_;
299   }
300
301   const GServicesSettings& gservices_settings() const {
302     return gcm_client_->gservices_settings_;
303   }
304
305   int64 CurrentTime();
306
307   // Tooling.
308   void PumpLoop();
309   void PumpLoopUntilIdle();
310   void QuitLoop();
311   void InitializeLoop();
312   bool CreateUniqueTempDir();
313   AutoAdvancingTestClock* clock() const {
314     return reinterpret_cast<AutoAdvancingTestClock*>(gcm_client_->clock_.get());
315   }
316
317  private:
318   // Variables used for verification.
319   LastEvent last_event_;
320   std::string last_app_id_;
321   std::string last_registration_id_;
322   std::string last_message_id_;
323   GCMClient::Result last_result_;
324   GCMClient::IncomingMessage last_message_;
325   GCMClient::SendErrorDetails last_error_details_;
326
327   scoped_ptr<GCMClientImpl> gcm_client_;
328
329   base::MessageLoop message_loop_;
330   scoped_ptr<base::RunLoop> run_loop_;
331   net::TestURLFetcherFactory url_fetcher_factory_;
332
333   // Injected to GCM client:
334   base::ScopedTempDir temp_directory_;
335   scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
336 };
337
338 GCMClientImplTest::GCMClientImplTest()
339     : last_event_(NONE),
340       last_result_(GCMClient::UNKNOWN_ERROR),
341       url_request_context_getter_(new net::TestURLRequestContextGetter(
342           message_loop_.message_loop_proxy())) {
343 }
344
345 GCMClientImplTest::~GCMClientImplTest() {}
346
347 void GCMClientImplTest::SetUp() {
348   testing::Test::SetUp();
349   ASSERT_TRUE(CreateUniqueTempDir());
350   InitializeLoop();
351   BuildGCMClient(base::TimeDelta());
352   InitializeGCMClient();
353   StartGCMClient();
354   CompleteCheckin(kDeviceAndroidId,
355                   kDeviceSecurityToken,
356                   std::string(),
357                   std::map<std::string, std::string>());
358 }
359
360 void GCMClientImplTest::PumpLoop() {
361   run_loop_->Run();
362   run_loop_.reset(new base::RunLoop());
363 }
364
365 void GCMClientImplTest::PumpLoopUntilIdle() {
366   run_loop_->RunUntilIdle();
367   run_loop_.reset(new base::RunLoop());
368 }
369
370 void GCMClientImplTest::QuitLoop() {
371   if (run_loop_ && run_loop_->running())
372     run_loop_->Quit();
373 }
374
375 void GCMClientImplTest::InitializeLoop() {
376   run_loop_.reset(new base::RunLoop);
377 }
378
379 bool GCMClientImplTest::CreateUniqueTempDir() {
380   return temp_directory_.CreateUniqueTempDir();
381 }
382
383 void GCMClientImplTest::BuildGCMClient(base::TimeDelta clock_step) {
384   gcm_client_.reset(new GCMClientImpl(make_scoped_ptr<GCMInternalsBuilder>(
385       new FakeGCMInternalsBuilder(clock_step))));
386 }
387
388 void GCMClientImplTest::CompleteCheckin(
389     uint64 android_id,
390     uint64 security_token,
391     const std::string& digest,
392     const std::map<std::string, std::string>& settings) {
393   checkin_proto::AndroidCheckinResponse response;
394   response.set_stats_ok(true);
395   response.set_android_id(android_id);
396   response.set_security_token(security_token);
397
398   // For testing G-services settings.
399   if (!digest.empty()) {
400     response.set_digest(digest);
401     for (std::map<std::string, std::string>::const_iterator it =
402              settings.begin();
403          it != settings.end();
404          ++it) {
405       checkin_proto::GservicesSetting* setting = response.add_setting();
406       setting->set_name(it->first);
407       setting->set_value(it->second);
408     }
409     response.set_settings_diff(false);
410   }
411
412   std::string response_string;
413   response.SerializeToString(&response_string);
414
415   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
416   ASSERT_TRUE(fetcher);
417   fetcher->set_response_code(net::HTTP_OK);
418   fetcher->SetResponseString(response_string);
419   fetcher->delegate()->OnURLFetchComplete(fetcher);
420   url_fetcher_factory_.RemoveFetcherFromMap(0);
421 }
422
423 void GCMClientImplTest::CompleteRegistration(
424     const std::string& registration_id) {
425   std::string response(kRegistrationResponsePrefix);
426   response.append(registration_id);
427   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
428   ASSERT_TRUE(fetcher);
429   fetcher->set_response_code(net::HTTP_OK);
430   fetcher->SetResponseString(response);
431   fetcher->delegate()->OnURLFetchComplete(fetcher);
432   url_fetcher_factory_.RemoveFetcherFromMap(0);
433 }
434
435 void GCMClientImplTest::CompleteUnregistration(
436     const std::string& app_id) {
437   std::string response(kUnregistrationResponsePrefix);
438   response.append(app_id);
439   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
440   ASSERT_TRUE(fetcher);
441   fetcher->set_response_code(net::HTTP_OK);
442   fetcher->SetResponseString(response);
443   fetcher->delegate()->OnURLFetchComplete(fetcher);
444   url_fetcher_factory_.RemoveFetcherFromMap(0);
445 }
446
447 bool GCMClientImplTest::ExistsRegistration(const std::string& app_id) const {
448   return gcm_client_->registrations_.count(app_id) > 0;
449 }
450
451 void GCMClientImplTest::AddRegistration(
452     const std::string& app_id,
453     const std::vector<std::string>& sender_ids,
454     const std::string& registration_id) {
455   linked_ptr<RegistrationInfo> registration(new RegistrationInfo);
456   registration->sender_ids = sender_ids;
457   registration->registration_id = registration_id;
458   gcm_client_->registrations_[app_id] = registration;
459 }
460
461 void GCMClientImplTest::InitializeGCMClient() {
462   clock()->Advance(base::TimeDelta::FromMilliseconds(1));
463
464   // Actual initialization.
465   GCMClient::ChromeBuildInfo chrome_build_info;
466   gcm_client_->Initialize(chrome_build_info,
467                           temp_directory_.path(),
468                           message_loop_.message_loop_proxy(),
469                           url_request_context_getter_,
470                           make_scoped_ptr<Encryptor>(new FakeEncryptor),
471                           this);
472 }
473
474 void GCMClientImplTest::StartGCMClient() {
475   // Start loading and check-in.
476   gcm_client_->Start();
477
478   PumpLoopUntilIdle();
479 }
480
481 void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) {
482   gcm_client_->recorder_.RecordConnectionInitiated(std::string());
483   gcm_client_->recorder_.RecordConnectionSuccess();
484   gcm_client_->OnMessageReceivedFromMCS(message);
485 }
486
487 void GCMClientImplTest::ReceiveOnMessageSentToMCS(
488       const std::string& app_id,
489       const std::string& message_id,
490       const MCSClient::MessageSendStatus status) {
491   gcm_client_->OnMessageSentToMCS(0LL, app_id, message_id, status);
492 }
493
494 void GCMClientImplTest::OnGCMReady(
495     const std::vector<AccountMapping>& account_mappings) {
496   last_event_ = LOADING_COMPLETED;
497   QuitLoop();
498   // TODO(fgorski): Add scenario verifying contents of account_mappings, when
499   // the list is not empty.
500 }
501
502 void GCMClientImplTest::OnMessageReceived(
503     const std::string& registration_id,
504     const GCMClient::IncomingMessage& message) {
505   last_event_ = MESSAGE_RECEIVED;
506   last_app_id_ = registration_id;
507   last_message_ = message;
508   QuitLoop();
509 }
510
511 void GCMClientImplTest::OnRegisterFinished(const std::string& app_id,
512                                            const std::string& registration_id,
513                                            GCMClient::Result result) {
514   last_event_ = REGISTRATION_COMPLETED;
515   last_app_id_ = app_id;
516   last_registration_id_ = registration_id;
517   last_result_ = result;
518 }
519
520 void GCMClientImplTest::OnUnregisterFinished(const std::string& app_id,
521                                              GCMClient::Result result) {
522   last_event_ = UNREGISTRATION_COMPLETED;
523   last_app_id_ = app_id;
524   last_result_ = result;
525 }
526
527 void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) {
528   last_event_ = MESSAGES_DELETED;
529   last_app_id_ = app_id;
530 }
531
532 void GCMClientImplTest::OnMessageSendError(
533     const std::string& app_id,
534     const gcm::GCMClient::SendErrorDetails& send_error_details) {
535   last_event_ = MESSAGE_SEND_ERROR;
536   last_app_id_ = app_id;
537   last_error_details_ = send_error_details;
538 }
539
540 void GCMClientImplTest::OnSendAcknowledged(const std::string& app_id,
541                                            const std::string& message_id) {
542   last_event_ = MESSAGE_SEND_ACK;
543   last_app_id_ = app_id;
544   last_message_id_ = message_id;
545 }
546
547 int64 GCMClientImplTest::CurrentTime() {
548   return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond;
549 }
550
551 TEST_F(GCMClientImplTest, LoadingCompleted) {
552   EXPECT_EQ(LOADING_COMPLETED, last_event());
553   EXPECT_EQ(kDeviceAndroidId, mcs_client()->last_android_id());
554   EXPECT_EQ(kDeviceSecurityToken, mcs_client()->last_security_token());
555
556   // Checking freshly loaded CheckinInfo.
557   EXPECT_EQ(kDeviceAndroidId, device_checkin_info().android_id);
558   EXPECT_EQ(kDeviceSecurityToken, device_checkin_info().secret);
559   EXPECT_TRUE(device_checkin_info().last_checkin_accounts.empty());
560   EXPECT_TRUE(device_checkin_info().accounts_set);
561   EXPECT_TRUE(device_checkin_info().account_tokens.empty());
562 }
563
564 TEST_F(GCMClientImplTest, CheckOut) {
565   EXPECT_TRUE(mcs_client());
566   EXPECT_TRUE(connection_factory());
567   gcm_client()->CheckOut();
568   EXPECT_FALSE(mcs_client());
569   EXPECT_FALSE(connection_factory());
570 }
571
572 TEST_F(GCMClientImplTest, RegisterApp) {
573   EXPECT_FALSE(ExistsRegistration(kAppId));
574
575   std::vector<std::string> senders;
576   senders.push_back("sender");
577   gcm_client()->Register(kAppId, senders);
578   CompleteRegistration("reg_id");
579
580   EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
581   EXPECT_EQ(kAppId, last_app_id());
582   EXPECT_EQ("reg_id", last_registration_id());
583   EXPECT_EQ(GCMClient::SUCCESS, last_result());
584   EXPECT_TRUE(ExistsRegistration(kAppId));
585 }
586
587 TEST_F(GCMClientImplTest, DISABLED_RegisterAppFromCache) {
588   EXPECT_FALSE(ExistsRegistration(kAppId));
589
590   std::vector<std::string> senders;
591   senders.push_back("sender");
592   gcm_client()->Register(kAppId, senders);
593   CompleteRegistration("reg_id");
594   EXPECT_TRUE(ExistsRegistration(kAppId));
595
596   EXPECT_EQ(kAppId, last_app_id());
597   EXPECT_EQ("reg_id", last_registration_id());
598   EXPECT_EQ(GCMClient::SUCCESS, last_result());
599   EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
600
601   // Recreate GCMClient in order to load from the persistent store.
602   BuildGCMClient(base::TimeDelta());
603   InitializeGCMClient();
604   StartGCMClient();
605
606   EXPECT_TRUE(ExistsRegistration(kAppId));
607 }
608
609 TEST_F(GCMClientImplTest, UnregisterApp) {
610   EXPECT_FALSE(ExistsRegistration(kAppId));
611
612   std::vector<std::string> senders;
613   senders.push_back("sender");
614   gcm_client()->Register(kAppId, senders);
615   CompleteRegistration("reg_id");
616   EXPECT_TRUE(ExistsRegistration(kAppId));
617
618   gcm_client()->Unregister(kAppId);
619   CompleteUnregistration(kAppId);
620
621   EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
622   EXPECT_EQ(kAppId, last_app_id());
623   EXPECT_EQ(GCMClient::SUCCESS, last_result());
624   EXPECT_FALSE(ExistsRegistration(kAppId));
625 }
626
627 TEST_F(GCMClientImplTest, DispatchDownstreamMessage) {
628   // Register to receive messages from kSender and kSender2 only.
629   std::vector<std::string> senders;
630   senders.push_back(kSender);
631   senders.push_back(kSender2);
632   AddRegistration(kAppId, senders, "reg_id");
633
634   std::map<std::string, std::string> expected_data;
635   expected_data["message_type"] = "gcm";
636   expected_data["key"] = "value";
637   expected_data["key2"] = "value2";
638
639   // Message for kSender will be received.
640   MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data));
641   EXPECT_TRUE(message.IsValid());
642   ReceiveMessageFromMCS(message);
643
644   expected_data.erase(expected_data.find("message_type"));
645   EXPECT_EQ(MESSAGE_RECEIVED, last_event());
646   EXPECT_EQ(kAppId, last_app_id());
647   EXPECT_EQ(expected_data.size(), last_message().data.size());
648   EXPECT_EQ(expected_data, last_message().data);
649   EXPECT_EQ(kSender, last_message().sender_id);
650
651   reset_last_event();
652
653   // Message for kSender2 will be received.
654   MCSMessage message2(BuildDownstreamMessage(kSender2, kAppId, expected_data));
655   EXPECT_TRUE(message2.IsValid());
656   ReceiveMessageFromMCS(message2);
657
658   EXPECT_EQ(MESSAGE_RECEIVED, last_event());
659   EXPECT_EQ(kAppId, last_app_id());
660   EXPECT_EQ(expected_data.size(), last_message().data.size());
661   EXPECT_EQ(expected_data, last_message().data);
662   EXPECT_EQ(kSender2, last_message().sender_id);
663
664   reset_last_event();
665
666   // Message from kSender3 will be dropped.
667   MCSMessage message3(BuildDownstreamMessage(kSender3, kAppId, expected_data));
668   EXPECT_TRUE(message3.IsValid());
669   ReceiveMessageFromMCS(message3);
670
671   EXPECT_NE(MESSAGE_RECEIVED, last_event());
672   EXPECT_NE(kAppId, last_app_id());
673 }
674
675 TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
676   std::map<std::string, std::string> expected_data;
677   expected_data["message_type"] = "send_error";
678   expected_data["google.message_id"] = "007";
679   expected_data["error_details"] = "some details";
680   MCSMessage message(BuildDownstreamMessage(
681       kSender, kAppId, expected_data));
682   EXPECT_TRUE(message.IsValid());
683   ReceiveMessageFromMCS(message);
684
685   EXPECT_EQ(MESSAGE_SEND_ERROR, last_event());
686   EXPECT_EQ(kAppId, last_app_id());
687   EXPECT_EQ("007", last_error_details().message_id);
688   EXPECT_EQ(1UL, last_error_details().additional_data.size());
689   GCMClient::MessageData::const_iterator iter =
690       last_error_details().additional_data.find("error_details");
691   EXPECT_TRUE(iter != last_error_details().additional_data.end());
692   EXPECT_EQ("some details", iter->second);
693 }
694
695 TEST_F(GCMClientImplTest, DispatchDownstreamMessgaesDeleted) {
696   std::map<std::string, std::string> expected_data;
697   expected_data["message_type"] = "deleted_messages";
698   MCSMessage message(BuildDownstreamMessage(
699       kSender, kAppId, expected_data));
700   EXPECT_TRUE(message.IsValid());
701   ReceiveMessageFromMCS(message);
702
703   EXPECT_EQ(MESSAGES_DELETED, last_event());
704   EXPECT_EQ(kAppId, last_app_id());
705 }
706
707 TEST_F(GCMClientImplTest, SendMessage) {
708   GCMClient::OutgoingMessage message;
709   message.id = "007";
710   message.time_to_live = 500;
711   message.data["key"] = "value";
712   gcm_client()->Send(kAppId, kSender, message);
713
714   EXPECT_EQ(kDataMessageStanzaTag, mcs_client()->last_message_tag());
715   EXPECT_EQ(kAppId, mcs_client()->last_data_message_stanza().category());
716   EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
717   EXPECT_EQ(500, mcs_client()->last_data_message_stanza().ttl());
718   EXPECT_EQ(CurrentTime(), mcs_client()->last_data_message_stanza().sent());
719   EXPECT_EQ("007", mcs_client()->last_data_message_stanza().id());
720   EXPECT_EQ("gcm@chrome.com", mcs_client()->last_data_message_stanza().from());
721   EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
722   EXPECT_EQ("key", mcs_client()->last_data_message_stanza().app_data(0).key());
723   EXPECT_EQ("value",
724             mcs_client()->last_data_message_stanza().app_data(0).value());
725 }
726
727 TEST_F(GCMClientImplTest, SendMessageAcknowledged) {
728   ReceiveOnMessageSentToMCS(kAppId, "007", MCSClient::SENT);
729   EXPECT_EQ(MESSAGE_SEND_ACK, last_event());
730   EXPECT_EQ(kAppId, last_app_id());
731   EXPECT_EQ("007", last_message_id());
732 }
733
734 class GCMClientImplCheckinTest : public GCMClientImplTest {
735  public:
736   GCMClientImplCheckinTest();
737   virtual ~GCMClientImplCheckinTest();
738
739   virtual void SetUp() OVERRIDE;
740 };
741
742 GCMClientImplCheckinTest::GCMClientImplCheckinTest() {
743 }
744
745 GCMClientImplCheckinTest::~GCMClientImplCheckinTest() {
746 }
747
748 void GCMClientImplCheckinTest::SetUp() {
749   testing::Test::SetUp();
750   // Creating unique temp directory that will be used by GCMStore shared between
751   // GCM Client and G-services settings.
752   ASSERT_TRUE(CreateUniqueTempDir());
753   InitializeLoop();
754   // Time will be advancing one hour every time it is checked.
755   BuildGCMClient(base::TimeDelta::FromSeconds(kSettingsCheckinInterval));
756   InitializeGCMClient();
757   StartGCMClient();
758 }
759
760 TEST_F(GCMClientImplCheckinTest, GServicesSettingsAfterInitialCheckin) {
761   std::map<std::string, std::string> settings;
762   settings["checkin_interval"] = base::Int64ToString(kSettingsCheckinInterval);
763   settings["checkin_url"] = "http://alternative.url/checkin";
764   settings["gcm_hostname"] = "alternative.gcm.host";
765   settings["gcm_secure_port"] = "7777";
766   settings["gcm_registration_url"] = "http://alternative.url/registration";
767   CompleteCheckin(kDeviceAndroidId,
768                   kDeviceSecurityToken,
769                   GServicesSettings::CalculateDigest(settings),
770                   settings);
771   EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval),
772             gservices_settings().GetCheckinInterval());
773   EXPECT_EQ(GURL("http://alternative.url/checkin"),
774             gservices_settings().GetCheckinURL());
775   EXPECT_EQ(GURL("http://alternative.url/registration"),
776             gservices_settings().GetRegistrationURL());
777   EXPECT_EQ(GURL("https://alternative.gcm.host:7777"),
778             gservices_settings().GetMCSMainEndpoint());
779   EXPECT_EQ(GURL("https://alternative.gcm.host:443"),
780             gservices_settings().GetMCSFallbackEndpoint());
781 }
782
783 // This test only checks that periodic checkin happens.
784 TEST_F(GCMClientImplCheckinTest, PeriodicCheckin) {
785   std::map<std::string, std::string> settings;
786   settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
787   settings["checkin_url"] = "http://alternative.url/checkin";
788   settings["gcm_hostname"] = "alternative.gcm.host";
789   settings["gcm_secure_port"] = "7777";
790   settings["gcm_registration_url"] = "http://alternative.url/registration";
791   CompleteCheckin(kDeviceAndroidId,
792                   kDeviceSecurityToken,
793                   GServicesSettings::CalculateDigest(settings),
794                   settings);
795
796   EXPECT_EQ(2, clock()->call_count());
797
798   PumpLoopUntilIdle();
799   CompleteCheckin(kDeviceAndroidId,
800                   kDeviceSecurityToken,
801                   GServicesSettings::CalculateDigest(settings),
802                   settings);
803 }
804
805 TEST_F(GCMClientImplCheckinTest, LoadGSettingsFromStore) {
806   std::map<std::string, std::string> settings;
807   settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
808   settings["checkin_url"] = "http://alternative.url/checkin";
809   settings["gcm_hostname"] = "alternative.gcm.host";
810   settings["gcm_secure_port"] = "7777";
811   settings["gcm_registration_url"] = "http://alternative.url/registration";
812   CompleteCheckin(kDeviceAndroidId,
813                   kDeviceSecurityToken,
814                   GServicesSettings::CalculateDigest(settings),
815                   settings);
816
817   BuildGCMClient(base::TimeDelta());
818   InitializeGCMClient();
819   StartGCMClient();
820
821   EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval),
822             gservices_settings().GetCheckinInterval());
823   EXPECT_EQ(GURL("http://alternative.url/checkin"),
824             gservices_settings().GetCheckinURL());
825   EXPECT_EQ(GURL("http://alternative.url/registration"),
826             gservices_settings().GetRegistrationURL());
827   EXPECT_EQ(GURL("https://alternative.gcm.host:7777"),
828             gservices_settings().GetMCSMainEndpoint());
829   EXPECT_EQ(GURL("https://alternative.gcm.host:443"),
830             gservices_settings().GetMCSFallbackEndpoint());
831 }
832
833 // This test only checks that periodic checkin happens.
834 TEST_F(GCMClientImplCheckinTest, CheckinWithAccounts) {
835   std::map<std::string, std::string> settings;
836   settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
837   settings["checkin_url"] = "http://alternative.url/checkin";
838   settings["gcm_hostname"] = "alternative.gcm.host";
839   settings["gcm_secure_port"] = "7777";
840   settings["gcm_registration_url"] = "http://alternative.url/registration";
841   CompleteCheckin(kDeviceAndroidId,
842                   kDeviceSecurityToken,
843                   GServicesSettings::CalculateDigest(settings),
844                   settings);
845
846   std::map<std::string, std::string> account_tokens;
847   account_tokens["test_user1@gmail.com"] = "token1";
848   account_tokens["test_user2@gmail.com"] = "token2";
849   gcm_client()->SetAccountsForCheckin(account_tokens);
850
851   EXPECT_TRUE(device_checkin_info().last_checkin_accounts.empty());
852   EXPECT_TRUE(device_checkin_info().accounts_set);
853   EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
854
855   PumpLoopUntilIdle();
856   CompleteCheckin(kDeviceAndroidId,
857                   kDeviceSecurityToken,
858                   GServicesSettings::CalculateDigest(settings),
859                   settings);
860
861   std::set<std::string> accounts;
862   accounts.insert("test_user1@gmail.com");
863   accounts.insert("test_user2@gmail.com");
864   EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts);
865   EXPECT_TRUE(device_checkin_info().accounts_set);
866   EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
867 }
868
869 // This test only checks that periodic checkin happens.
870 TEST_F(GCMClientImplCheckinTest, CheckinWhenAccountRemoved) {
871   std::map<std::string, std::string> settings;
872   settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
873   settings["checkin_url"] = "http://alternative.url/checkin";
874   settings["gcm_hostname"] = "alternative.gcm.host";
875   settings["gcm_secure_port"] = "7777";
876   settings["gcm_registration_url"] = "http://alternative.url/registration";
877   CompleteCheckin(kDeviceAndroidId,
878                   kDeviceSecurityToken,
879                   GServicesSettings::CalculateDigest(settings),
880                   settings);
881
882   std::map<std::string, std::string> account_tokens;
883   account_tokens["test_user1@gmail.com"] = "token1";
884   account_tokens["test_user2@gmail.com"] = "token2";
885   gcm_client()->SetAccountsForCheckin(account_tokens);
886   PumpLoopUntilIdle();
887   CompleteCheckin(kDeviceAndroidId,
888                   kDeviceSecurityToken,
889                   GServicesSettings::CalculateDigest(settings),
890                   settings);
891
892   EXPECT_EQ(2UL, device_checkin_info().last_checkin_accounts.size());
893   EXPECT_TRUE(device_checkin_info().accounts_set);
894   EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
895
896   account_tokens.erase(account_tokens.find("test_user2@gmail.com"));
897   gcm_client()->SetAccountsForCheckin(account_tokens);
898
899   PumpLoopUntilIdle();
900   CompleteCheckin(kDeviceAndroidId,
901                   kDeviceSecurityToken,
902                   GServicesSettings::CalculateDigest(settings),
903                   settings);
904
905   std::set<std::string> accounts;
906   accounts.insert("test_user1@gmail.com");
907   EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts);
908   EXPECT_TRUE(device_checkin_info().accounts_set);
909   EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
910 }
911
912 // This test only checks that periodic checkin happens.
913 TEST_F(GCMClientImplCheckinTest, CheckinWhenAccountReplaced) {
914   std::map<std::string, std::string> settings;
915   settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
916   settings["checkin_url"] = "http://alternative.url/checkin";
917   settings["gcm_hostname"] = "alternative.gcm.host";
918   settings["gcm_secure_port"] = "7777";
919   settings["gcm_registration_url"] = "http://alternative.url/registration";
920   CompleteCheckin(kDeviceAndroidId,
921                   kDeviceSecurityToken,
922                   GServicesSettings::CalculateDigest(settings),
923                   settings);
924
925   std::map<std::string, std::string> account_tokens;
926   account_tokens["test_user1@gmail.com"] = "token1";
927   gcm_client()->SetAccountsForCheckin(account_tokens);
928
929   PumpLoopUntilIdle();
930   CompleteCheckin(kDeviceAndroidId,
931                   kDeviceSecurityToken,
932                   GServicesSettings::CalculateDigest(settings),
933                   settings);
934
935   std::set<std::string> accounts;
936   accounts.insert("test_user1@gmail.com");
937   EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts);
938
939   // This should trigger another checkin, because the list of accounts is
940   // different.
941   account_tokens.erase(account_tokens.find("test_user1@gmail.com"));
942   account_tokens["test_user2@gmail.com"] = "token2";
943   gcm_client()->SetAccountsForCheckin(account_tokens);
944
945   PumpLoopUntilIdle();
946   CompleteCheckin(kDeviceAndroidId,
947                   kDeviceSecurityToken,
948                   GServicesSettings::CalculateDigest(settings),
949                   settings);
950
951   accounts.clear();
952   accounts.insert("test_user2@gmail.com");
953   EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts);
954   EXPECT_TRUE(device_checkin_info().accounts_set);
955   EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
956 }
957
958 class GCMClientImplStartAndStopTest : public GCMClientImplTest {
959 public:
960   GCMClientImplStartAndStopTest();
961   virtual ~GCMClientImplStartAndStopTest();
962
963   virtual void SetUp() OVERRIDE;
964 };
965
966 GCMClientImplStartAndStopTest::GCMClientImplStartAndStopTest() {
967 }
968
969 GCMClientImplStartAndStopTest::~GCMClientImplStartAndStopTest() {
970 }
971
972 void GCMClientImplStartAndStopTest::SetUp() {
973   testing::Test::SetUp();
974   ASSERT_TRUE(CreateUniqueTempDir());
975   InitializeLoop();
976   BuildGCMClient(base::TimeDelta());
977   InitializeGCMClient();
978 }
979
980 TEST_F(GCMClientImplStartAndStopTest, StartStopAndRestart) {
981   // Start the GCM and wait until it is ready.
982   gcm_client()->Start();
983   PumpLoopUntilIdle();
984
985   // Stop the GCM.
986   gcm_client()->Stop();
987   PumpLoopUntilIdle();
988
989   // Restart the GCM.
990   gcm_client()->Start();
991   PumpLoopUntilIdle();
992 }
993
994 TEST_F(GCMClientImplStartAndStopTest, StartAndStopImmediately) {
995   // Start the GCM and then stop it immediately.
996   gcm_client()->Start();
997   gcm_client()->Stop();
998
999   PumpLoopUntilIdle();
1000 }
1001
1002 TEST_F(GCMClientImplStartAndStopTest, StartStopAndRestartImmediately) {
1003   // Start the GCM and then stop and restart it immediately.
1004   gcm_client()->Start();
1005   gcm_client()->Stop();
1006   gcm_client()->Start();
1007
1008   PumpLoopUntilIdle();
1009 }
1010
1011 }  // namespace gcm