Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / google_apis / gcm / 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 "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 "components/os_crypt/os_crypt_switches.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 kSettingsDefaultDigest[] = "default_digest";
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       scoped_refptr<net::HttpNetworkSession> network_session,
173       net::NetLog* net_log,
174       GCMStatsRecorder* recorder) OVERRIDE;
175
176  private:
177   base::TimeDelta clock_step_;
178 };
179
180 FakeGCMInternalsBuilder::FakeGCMInternalsBuilder(base::TimeDelta clock_step)
181     : clock_step_(clock_step) {
182 }
183
184 FakeGCMInternalsBuilder::~FakeGCMInternalsBuilder() {}
185
186 scoped_ptr<base::Clock> FakeGCMInternalsBuilder::BuildClock() {
187   return make_scoped_ptr<base::Clock>(new AutoAdvancingTestClock(clock_step_));
188 }
189
190 scoped_ptr<MCSClient> FakeGCMInternalsBuilder::BuildMCSClient(
191     const std::string& version,
192     base::Clock* clock,
193     ConnectionFactory* connection_factory,
194     GCMStore* gcm_store,
195     GCMStatsRecorder* recorder) {
196   return make_scoped_ptr<MCSClient>(new FakeMCSClient(clock,
197                                                       connection_factory,
198                                                       gcm_store,
199                                                       recorder));
200 }
201
202 scoped_ptr<ConnectionFactory> FakeGCMInternalsBuilder::BuildConnectionFactory(
203     const std::vector<GURL>& endpoints,
204     const net::BackoffEntry::Policy& backoff_policy,
205     scoped_refptr<net::HttpNetworkSession> network_session,
206     net::NetLog* net_log,
207     GCMStatsRecorder* recorder) {
208   return make_scoped_ptr<ConnectionFactory>(new FakeConnectionFactory());
209 }
210
211 }  // namespace
212
213 class GCMClientImplTest : public testing::Test,
214                           public GCMClient::Delegate {
215  public:
216   GCMClientImplTest();
217   virtual ~GCMClientImplTest();
218
219   virtual void SetUp() OVERRIDE;
220
221   void BuildGCMClient(base::TimeDelta clock_step);
222   void InitializeGCMClient();
223   void ReceiveMessageFromMCS(const MCSMessage& message);
224   void CompleteCheckin(uint64 android_id,
225                        uint64 security_token,
226                        const std::string& digest,
227                        const std::map<std::string, std::string>& settings);
228   void CompleteRegistration(const std::string& registration_id);
229   void CompleteUnregistration(const std::string& app_id);
230
231   bool ExistsRegistration(const std::string& app_id) const;
232   void AddRegistration(const std::string& app_id,
233                        const std::vector<std::string>& sender_ids,
234                        const std::string& registration_id);
235
236   // GCMClient::Delegate overrides (for verification).
237   virtual void OnRegisterFinished(const std::string& app_id,
238                                   const std::string& registration_id,
239                                   GCMClient::Result result) OVERRIDE;
240   virtual void OnUnregisterFinished(const std::string& app_id,
241                                     GCMClient::Result result) OVERRIDE;
242   virtual void OnSendFinished(const std::string& app_id,
243                               const std::string& message_id,
244                               GCMClient::Result result) OVERRIDE {}
245   virtual void OnMessageReceived(const std::string& registration_id,
246                                  const GCMClient::IncomingMessage& message)
247       OVERRIDE;
248   virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
249   virtual void OnMessageSendError(
250       const std::string& app_id,
251       const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
252   virtual void OnGCMReady() 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 #if defined(OS_MACOSX)
333   base::CommandLine::ForCurrentProcess()->AppendSwitch(
334       os_crypt::switches::kUseMockKeychain);
335 #endif  // OS_MACOSX
336   ASSERT_TRUE(CreateUniqueTempDir());
337   InitializeLoop();
338   BuildGCMClient(base::TimeDelta());
339   InitializeGCMClient();
340   CompleteCheckin(kDeviceAndroidId,
341                   kDeviceSecurityToken,
342                   std::string(),
343                   std::map<std::string, std::string>());
344 }
345
346 void GCMClientImplTest::PumpLoop() {
347   run_loop_->Run();
348   run_loop_.reset(new base::RunLoop());
349 }
350
351 void GCMClientImplTest::PumpLoopUntilIdle() {
352   run_loop_->RunUntilIdle();
353   run_loop_.reset(new base::RunLoop());
354 }
355
356 void GCMClientImplTest::QuitLoop() {
357   if (run_loop_ && run_loop_->running())
358     run_loop_->Quit();
359 }
360
361 void GCMClientImplTest::InitializeLoop() {
362   run_loop_.reset(new base::RunLoop);
363 }
364
365 bool GCMClientImplTest::CreateUniqueTempDir() {
366   return temp_directory_.CreateUniqueTempDir();
367 }
368
369 void GCMClientImplTest::BuildGCMClient(base::TimeDelta clock_step) {
370   gcm_client_.reset(new GCMClientImpl(make_scoped_ptr<GCMInternalsBuilder>(
371       new FakeGCMInternalsBuilder(clock_step))));
372 }
373
374 void GCMClientImplTest::CompleteCheckin(
375     uint64 android_id,
376     uint64 security_token,
377     const std::string& digest,
378     const std::map<std::string, std::string>& settings) {
379   checkin_proto::AndroidCheckinResponse response;
380   response.set_stats_ok(true);
381   response.set_android_id(android_id);
382   response.set_security_token(security_token);
383
384   // For testing G-services settings.
385   if (!digest.empty()) {
386     response.set_digest(digest);
387     for (std::map<std::string, std::string>::const_iterator it =
388              settings.begin();
389          it != settings.end();
390          ++it) {
391       checkin_proto::GservicesSetting* setting = response.add_setting();
392       setting->set_name(it->first);
393       setting->set_value(it->second);
394     }
395   }
396
397   std::string response_string;
398   response.SerializeToString(&response_string);
399
400   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
401   ASSERT_TRUE(fetcher);
402   fetcher->set_response_code(net::HTTP_OK);
403   fetcher->SetResponseString(response_string);
404   fetcher->delegate()->OnURLFetchComplete(fetcher);
405   url_fetcher_factory_.RemoveFetcherFromMap(0);
406 }
407
408 void GCMClientImplTest::CompleteRegistration(
409     const std::string& registration_id) {
410   std::string response(kRegistrationResponsePrefix);
411   response.append(registration_id);
412   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
413   ASSERT_TRUE(fetcher);
414   fetcher->set_response_code(net::HTTP_OK);
415   fetcher->SetResponseString(response);
416   fetcher->delegate()->OnURLFetchComplete(fetcher);
417   url_fetcher_factory_.RemoveFetcherFromMap(0);
418 }
419
420 void GCMClientImplTest::CompleteUnregistration(
421     const std::string& app_id) {
422   std::string response(kUnregistrationResponsePrefix);
423   response.append(app_id);
424   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
425   ASSERT_TRUE(fetcher);
426   fetcher->set_response_code(net::HTTP_OK);
427   fetcher->SetResponseString(response);
428   fetcher->delegate()->OnURLFetchComplete(fetcher);
429   url_fetcher_factory_.RemoveFetcherFromMap(0);
430 }
431
432 bool GCMClientImplTest::ExistsRegistration(const std::string& app_id) const {
433   return gcm_client_->registrations_.count(app_id) > 0;
434 }
435
436 void GCMClientImplTest::AddRegistration(
437     const std::string& app_id,
438     const std::vector<std::string>& sender_ids,
439     const std::string& registration_id) {
440   linked_ptr<RegistrationInfo> registration(new RegistrationInfo);
441   registration->sender_ids = sender_ids;
442   registration->registration_id = registration_id;
443   gcm_client_->registrations_[app_id] = registration;
444 }
445
446 void GCMClientImplTest::InitializeGCMClient() {
447   clock()->Advance(base::TimeDelta::FromMilliseconds(1));
448
449   // Actual initialization.
450   checkin_proto::ChromeBuildProto chrome_build_proto;
451   gcm_client_->Initialize(chrome_build_proto,
452                           temp_directory_.path(),
453                           std::vector<std::string>(),
454                           message_loop_.message_loop_proxy(),
455                           url_request_context_getter_,
456                           this);
457
458   // Start loading and check-in.
459   gcm_client_->Load();
460
461   PumpLoopUntilIdle();
462 }
463
464 void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) {
465   gcm_client_->OnMessageReceivedFromMCS(message);
466 }
467
468 void GCMClientImplTest::OnGCMReady() {
469   last_event_ = LOADING_COMPLETED;
470   QuitLoop();
471 }
472
473 void GCMClientImplTest::OnMessageReceived(
474     const std::string& registration_id,
475     const GCMClient::IncomingMessage& message) {
476   last_event_ = MESSAGE_RECEIVED;
477   last_app_id_ = registration_id;
478   last_message_ = message;
479   QuitLoop();
480 }
481
482 void GCMClientImplTest::OnRegisterFinished(const std::string& app_id,
483                                            const std::string& registration_id,
484                                            GCMClient::Result result) {
485   last_event_ = REGISTRATION_COMPLETED;
486   last_app_id_ = app_id;
487   last_registration_id_ = registration_id;
488   last_result_ = result;
489 }
490
491 void GCMClientImplTest::OnUnregisterFinished(const std::string& app_id,
492                                              GCMClient::Result result) {
493   last_event_ = UNREGISTRATION_COMPLETED;
494   last_app_id_ = app_id;
495   last_result_ = result;
496 }
497
498 void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) {
499   last_event_ = MESSAGES_DELETED;
500   last_app_id_ = app_id;
501 }
502
503 void GCMClientImplTest::OnMessageSendError(
504     const std::string& app_id,
505     const gcm::GCMClient::SendErrorDetails& send_error_details) {
506   last_event_ = MESSAGE_SEND_ERROR;
507   last_app_id_ = app_id;
508   last_error_details_ = send_error_details;
509 }
510
511 int64 GCMClientImplTest::CurrentTime() {
512   return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond;
513 }
514
515 TEST_F(GCMClientImplTest, LoadingCompleted) {
516   EXPECT_EQ(LOADING_COMPLETED, last_event());
517   EXPECT_EQ(kDeviceAndroidId, mcs_client()->last_android_id());
518   EXPECT_EQ(kDeviceSecurityToken, mcs_client()->last_security_token());
519 }
520
521 TEST_F(GCMClientImplTest, CheckOut) {
522   EXPECT_TRUE(mcs_client());
523   EXPECT_TRUE(connection_factory());
524   gcm_client()->CheckOut();
525   EXPECT_FALSE(mcs_client());
526   EXPECT_FALSE(connection_factory());
527 }
528
529 TEST_F(GCMClientImplTest, RegisterApp) {
530   EXPECT_FALSE(ExistsRegistration(kAppId));
531
532   std::vector<std::string> senders;
533   senders.push_back("sender");
534   gcm_client()->Register(kAppId, senders);
535   CompleteRegistration("reg_id");
536
537   EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
538   EXPECT_EQ(kAppId, last_app_id());
539   EXPECT_EQ("reg_id", last_registration_id());
540   EXPECT_EQ(GCMClient::SUCCESS, last_result());
541   EXPECT_TRUE(ExistsRegistration(kAppId));
542 }
543
544 TEST_F(GCMClientImplTest, DISABLED_RegisterAppFromCache) {
545   EXPECT_FALSE(ExistsRegistration(kAppId));
546
547   std::vector<std::string> senders;
548   senders.push_back("sender");
549   gcm_client()->Register(kAppId, senders);
550   CompleteRegistration("reg_id");
551   EXPECT_TRUE(ExistsRegistration(kAppId));
552
553   EXPECT_EQ(kAppId, last_app_id());
554   EXPECT_EQ("reg_id", last_registration_id());
555   EXPECT_EQ(GCMClient::SUCCESS, last_result());
556   EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
557
558   // Recreate GCMClient in order to load from the persistent store.
559   BuildGCMClient(base::TimeDelta());
560   InitializeGCMClient();
561
562   EXPECT_TRUE(ExistsRegistration(kAppId));
563 }
564
565 TEST_F(GCMClientImplTest, UnregisterApp) {
566   EXPECT_FALSE(ExistsRegistration(kAppId));
567
568   std::vector<std::string> senders;
569   senders.push_back("sender");
570   gcm_client()->Register(kAppId, senders);
571   CompleteRegistration("reg_id");
572   EXPECT_TRUE(ExistsRegistration(kAppId));
573
574   gcm_client()->Unregister(kAppId);
575   CompleteUnregistration(kAppId);
576
577   EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
578   EXPECT_EQ(kAppId, last_app_id());
579   EXPECT_EQ(GCMClient::SUCCESS, last_result());
580   EXPECT_FALSE(ExistsRegistration(kAppId));
581 }
582
583 TEST_F(GCMClientImplTest, DispatchDownstreamMessage) {
584   // Register to receive messages from kSender and kSender2 only.
585   std::vector<std::string> senders;
586   senders.push_back(kSender);
587   senders.push_back(kSender2);
588   AddRegistration(kAppId, senders, "reg_id");
589
590   std::map<std::string, std::string> expected_data;
591   expected_data["message_type"] = "gcm";
592   expected_data["key"] = "value";
593   expected_data["key2"] = "value2";
594
595   // Message for kSender will be received.
596   MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data));
597   EXPECT_TRUE(message.IsValid());
598   ReceiveMessageFromMCS(message);
599
600   expected_data.erase(expected_data.find("message_type"));
601   EXPECT_EQ(MESSAGE_RECEIVED, last_event());
602   EXPECT_EQ(kAppId, last_app_id());
603   EXPECT_EQ(expected_data.size(), last_message().data.size());
604   EXPECT_EQ(expected_data, last_message().data);
605   EXPECT_EQ(kSender, last_message().sender_id);
606
607   reset_last_event();
608
609   // Message for kSender2 will be received.
610   MCSMessage message2(BuildDownstreamMessage(kSender2, kAppId, expected_data));
611   EXPECT_TRUE(message2.IsValid());
612   ReceiveMessageFromMCS(message2);
613
614   EXPECT_EQ(MESSAGE_RECEIVED, last_event());
615   EXPECT_EQ(kAppId, last_app_id());
616   EXPECT_EQ(expected_data.size(), last_message().data.size());
617   EXPECT_EQ(expected_data, last_message().data);
618   EXPECT_EQ(kSender2, last_message().sender_id);
619
620   reset_last_event();
621
622   // Message from kSender3 will be dropped.
623   MCSMessage message3(BuildDownstreamMessage(kSender3, kAppId, expected_data));
624   EXPECT_TRUE(message3.IsValid());
625   ReceiveMessageFromMCS(message3);
626
627   EXPECT_NE(MESSAGE_RECEIVED, last_event());
628   EXPECT_NE(kAppId, last_app_id());
629 }
630
631 TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
632   std::map<std::string, std::string> expected_data;
633   expected_data["message_type"] = "send_error";
634   expected_data["google.message_id"] = "007";
635   expected_data["error_details"] = "some details";
636   MCSMessage message(BuildDownstreamMessage(
637       kSender, kAppId, expected_data));
638   EXPECT_TRUE(message.IsValid());
639   ReceiveMessageFromMCS(message);
640
641   EXPECT_EQ(MESSAGE_SEND_ERROR, last_event());
642   EXPECT_EQ(kAppId, last_app_id());
643   EXPECT_EQ("007", last_error_details().message_id);
644   EXPECT_EQ(1UL, last_error_details().additional_data.size());
645   GCMClient::MessageData::const_iterator iter =
646       last_error_details().additional_data.find("error_details");
647   EXPECT_TRUE(iter != last_error_details().additional_data.end());
648   EXPECT_EQ("some details", iter->second);
649 }
650
651 TEST_F(GCMClientImplTest, DispatchDownstreamMessgaesDeleted) {
652   std::map<std::string, std::string> expected_data;
653   expected_data["message_type"] = "deleted_messages";
654   MCSMessage message(BuildDownstreamMessage(
655       kSender, kAppId, expected_data));
656   EXPECT_TRUE(message.IsValid());
657   ReceiveMessageFromMCS(message);
658
659   EXPECT_EQ(MESSAGES_DELETED, last_event());
660   EXPECT_EQ(kAppId, last_app_id());
661 }
662
663 TEST_F(GCMClientImplTest, SendMessage) {
664   mcs_proto::DataMessageStanza stanza;
665   stanza.set_ttl(500);
666
667   GCMClient::OutgoingMessage message;
668   message.id = "007";
669   message.time_to_live = 500;
670   message.data["key"] = "value";
671   gcm_client()->Send(kAppId, kSender, message);
672
673   EXPECT_EQ(kDataMessageStanzaTag, mcs_client()->last_message_tag());
674   EXPECT_EQ(kAppId, mcs_client()->last_data_message_stanza().category());
675   EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
676   EXPECT_EQ(500, mcs_client()->last_data_message_stanza().ttl());
677   EXPECT_EQ(CurrentTime(), mcs_client()->last_data_message_stanza().sent());
678   EXPECT_EQ("007", mcs_client()->last_data_message_stanza().id());
679   EXPECT_EQ("gcm@chrome.com", mcs_client()->last_data_message_stanza().from());
680   EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
681   EXPECT_EQ("key", mcs_client()->last_data_message_stanza().app_data(0).key());
682   EXPECT_EQ("value",
683             mcs_client()->last_data_message_stanza().app_data(0).value());
684 }
685
686 class GCMClientImplCheckinTest : public GCMClientImplTest {
687  public:
688   GCMClientImplCheckinTest();
689   virtual ~GCMClientImplCheckinTest();
690
691   virtual void SetUp() OVERRIDE;
692
693   std::map<std::string, std::string> GenerateSettings(int64 checkin_interval);
694 };
695
696 GCMClientImplCheckinTest::GCMClientImplCheckinTest() {
697 }
698
699 GCMClientImplCheckinTest::~GCMClientImplCheckinTest() {
700 }
701
702 void GCMClientImplCheckinTest::SetUp() {
703   testing::Test::SetUp();
704 #if defined(OS_MACOSX)
705   base::CommandLine::ForCurrentProcess()->AppendSwitch(
706       os_crypt::switches::kUseMockKeychain);
707 #endif  // OS_MACOSX
708   // Creating unique temp directory that will be used by GCMStore shared between
709   // GCM Client and G-services settings.
710   ASSERT_TRUE(CreateUniqueTempDir());
711   InitializeLoop();
712   // Time will be advancing one hour every time it is checked.
713   BuildGCMClient(base::TimeDelta::FromSeconds(kSettingsCheckinInterval));
714   InitializeGCMClient();
715 }
716
717 TEST_F(GCMClientImplCheckinTest, GServicesSettingsAfterInitialCheckin) {
718   std::map<std::string, std::string> settings;
719   settings["checkin_interval"] = base::Int64ToString(kSettingsCheckinInterval);
720   settings["checkin_url"] = "http://alternative.url/checkin";
721   settings["gcm_hostname"] = "http://alternative.gcm.host";
722   settings["gcm_secure_port"] = "443";
723   settings["gcm_registration_url"] = "http://alternative.url/registration";
724   CompleteCheckin(
725       kDeviceAndroidId, kDeviceSecurityToken, kSettingsDefaultDigest, settings);
726   EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval),
727             gservices_settings().checkin_interval());
728   EXPECT_EQ(GURL("http://alternative.url/checkin"),
729             gservices_settings().checkin_url());
730   EXPECT_EQ(GURL("http://alternative.url/registration"),
731             gservices_settings().registration_url());
732   EXPECT_EQ("http://alternative.gcm.host", gservices_settings().mcs_hostname());
733   EXPECT_EQ(443, gservices_settings().mcs_secure_port());
734 }
735
736 // This test only checks that periodic checkin happens.
737 TEST_F(GCMClientImplCheckinTest, PeriodicCheckin) {
738   std::map<std::string, std::string> settings;
739   settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
740   settings["checkin_url"] = "http://alternative.url/checkin";
741   settings["gcm_hostname"] = "http://alternative.gcm.host";
742   settings["gcm_secure_port"] = "443";
743   settings["gcm_registration_url"] = "http://alternative.url/registration";
744   CompleteCheckin(
745       kDeviceAndroidId, kDeviceSecurityToken, kSettingsDefaultDigest, settings);
746   EXPECT_EQ(2, clock()->call_count());
747
748   PumpLoopUntilIdle();
749   CompleteCheckin(
750       kDeviceAndroidId, kDeviceSecurityToken, kSettingsDefaultDigest, 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"] = "http://alternative.gcm.host";
758   settings["gcm_secure_port"] = "443";
759   settings["gcm_registration_url"] = "http://alternative.url/registration";
760   CompleteCheckin(
761       kDeviceAndroidId, kDeviceSecurityToken, kSettingsDefaultDigest, settings);
762
763   BuildGCMClient(base::TimeDelta());
764   InitializeGCMClient();
765
766   EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval),
767             gservices_settings().checkin_interval());
768   EXPECT_EQ(GURL("http://alternative.url/checkin"),
769             gservices_settings().checkin_url());
770   EXPECT_EQ(GURL("http://alternative.url/registration"),
771             gservices_settings().registration_url());
772   EXPECT_EQ("http://alternative.gcm.host", gservices_settings().mcs_hostname());
773   EXPECT_EQ(443, gservices_settings().mcs_secure_port());
774 }
775
776 }  // namespace gcm