• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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.
BuildDownstreamMessage(const std::string & project_id,const std::string & app_id,const std::map<std::string,std::string> & data)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 
last_android_id() const80   uint64 last_android_id() const { return last_android_id_; }
last_security_token() const81   uint64 last_security_token() const { return last_security_token_; }
last_message_tag() const82   uint8 last_message_tag() const { return last_message_tag_; }
last_data_message_stanza() const83   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 
FakeMCSClient(base::Clock * clock,ConnectionFactory * connection_factory,GCMStore * gcm_store,GCMStatsRecorder * recorder)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 
~FakeMCSClient()104 FakeMCSClient::~FakeMCSClient() {
105 }
106 
Login(uint64 android_id,uint64 security_token)107 void FakeMCSClient::Login(uint64 android_id, uint64 security_token) {
108   last_android_id_ = android_id;
109   last_security_token_ = security_token;
110 }
111 
SendMessage(const MCSMessage & message)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);
call_count() const128   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 
AutoAdvancingTestClock(base::TimeDelta auto_increment_time_delta)138 AutoAdvancingTestClock::AutoAdvancingTestClock(
139     base::TimeDelta auto_increment_time_delta)
140     : call_count_(0), auto_increment_time_delta_(auto_increment_time_delta) {
141 }
142 
~AutoAdvancingTestClock()143 AutoAdvancingTestClock::~AutoAdvancingTestClock() {
144 }
145 
Now()146 base::Time AutoAdvancingTestClock::Now() {
147   call_count_++;
148   now_ += auto_increment_time_delta_;
149   return now_;
150 }
151 
Advance(base::TimeDelta delta)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 
FakeGCMInternalsBuilder(base::TimeDelta clock_step)179 FakeGCMInternalsBuilder::FakeGCMInternalsBuilder(base::TimeDelta clock_step)
180     : clock_step_(clock_step) {
181 }
182 
~FakeGCMInternalsBuilder()183 FakeGCMInternalsBuilder::~FakeGCMInternalsBuilder() {}
184 
BuildClock()185 scoped_ptr<base::Clock> FakeGCMInternalsBuilder::BuildClock() {
186   return make_scoped_ptr<base::Clock>(new AutoAdvancingTestClock(clock_step_));
187 }
188 
BuildMCSClient(const std::string & version,base::Clock * clock,ConnectionFactory * connection_factory,GCMStore * gcm_store,GCMStatsRecorder * recorder)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 
BuildConnectionFactory(const std::vector<GURL> & endpoints,const net::BackoffEntry::Policy & backoff_policy,scoped_refptr<net::HttpNetworkSession> network_session,net::NetLog * net_log,GCMStatsRecorder * recorder)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 StartGCMClient();
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;
OnSendFinished(const std::string & app_id,const std::string & message_id,GCMClient::Result result)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;
OnActivityRecorded()253   virtual void OnActivityRecorded() OVERRIDE {}
OnConnected(const net::IPEndPoint & ip_endpoint)254   virtual void OnConnected(const net::IPEndPoint& ip_endpoint) OVERRIDE {}
OnDisconnected()255   virtual void OnDisconnected() OVERRIDE {}
256 
gcm_client() const257   GCMClientImpl* gcm_client() const { return gcm_client_.get(); }
mcs_client() const258   FakeMCSClient* mcs_client() const {
259     return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get());
260   }
connection_factory() const261   ConnectionFactory* connection_factory() const {
262     return gcm_client_->connection_factory_.get();
263   }
264 
reset_last_event()265   void reset_last_event() {
266     last_event_ = NONE;
267     last_app_id_.clear();
268     last_registration_id_.clear();
269     last_message_id_.clear();
270     last_result_ = GCMClient::UNKNOWN_ERROR;
271   }
272 
last_event() const273   LastEvent last_event() const { return last_event_; }
last_app_id() const274   const std::string& last_app_id() const { return last_app_id_; }
last_registration_id() const275   const std::string& last_registration_id() const {
276     return last_registration_id_;
277   }
last_message_id() const278   const std::string& last_message_id() const { return last_message_id_; }
last_result() const279   GCMClient::Result last_result() const { return last_result_; }
last_message() const280   const GCMClient::IncomingMessage& last_message() const {
281     return last_message_;
282   }
last_error_details() const283   const GCMClient::SendErrorDetails& last_error_details() const {
284     return last_error_details_;
285   }
286 
gservices_settings() const287   const GServicesSettings& gservices_settings() const {
288     return gcm_client_->gservices_settings_;
289   }
290 
291   int64 CurrentTime();
292 
293   // Tooling.
294   void PumpLoop();
295   void PumpLoopUntilIdle();
296   void QuitLoop();
297   void InitializeLoop();
298   bool CreateUniqueTempDir();
clock() const299   AutoAdvancingTestClock* clock() const {
300     return reinterpret_cast<AutoAdvancingTestClock*>(gcm_client_->clock_.get());
301   }
302 
303  private:
304   // Variables used for verification.
305   LastEvent last_event_;
306   std::string last_app_id_;
307   std::string last_registration_id_;
308   std::string last_message_id_;
309   GCMClient::Result last_result_;
310   GCMClient::IncomingMessage last_message_;
311   GCMClient::SendErrorDetails last_error_details_;
312 
313   scoped_ptr<GCMClientImpl> gcm_client_;
314 
315   base::MessageLoop message_loop_;
316   scoped_ptr<base::RunLoop> run_loop_;
317   net::TestURLFetcherFactory url_fetcher_factory_;
318 
319   // Injected to GCM client:
320   base::ScopedTempDir temp_directory_;
321   scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
322 };
323 
GCMClientImplTest()324 GCMClientImplTest::GCMClientImplTest()
325     : last_event_(NONE),
326       last_result_(GCMClient::UNKNOWN_ERROR),
327       url_request_context_getter_(new net::TestURLRequestContextGetter(
328           message_loop_.message_loop_proxy())) {
329 }
330 
~GCMClientImplTest()331 GCMClientImplTest::~GCMClientImplTest() {}
332 
SetUp()333 void GCMClientImplTest::SetUp() {
334   testing::Test::SetUp();
335   ASSERT_TRUE(CreateUniqueTempDir());
336   InitializeLoop();
337   BuildGCMClient(base::TimeDelta());
338   InitializeGCMClient();
339   StartGCMClient();
340   CompleteCheckin(kDeviceAndroidId,
341                   kDeviceSecurityToken,
342                   std::string(),
343                   std::map<std::string, std::string>());
344 }
345 
PumpLoop()346 void GCMClientImplTest::PumpLoop() {
347   run_loop_->Run();
348   run_loop_.reset(new base::RunLoop());
349 }
350 
PumpLoopUntilIdle()351 void GCMClientImplTest::PumpLoopUntilIdle() {
352   run_loop_->RunUntilIdle();
353   run_loop_.reset(new base::RunLoop());
354 }
355 
QuitLoop()356 void GCMClientImplTest::QuitLoop() {
357   if (run_loop_ && run_loop_->running())
358     run_loop_->Quit();
359 }
360 
InitializeLoop()361 void GCMClientImplTest::InitializeLoop() {
362   run_loop_.reset(new base::RunLoop);
363 }
364 
CreateUniqueTempDir()365 bool GCMClientImplTest::CreateUniqueTempDir() {
366   return temp_directory_.CreateUniqueTempDir();
367 }
368 
BuildGCMClient(base::TimeDelta clock_step)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 
CompleteCheckin(uint64 android_id,uint64 security_token,const std::string & digest,const std::map<std::string,std::string> & settings)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     response.set_settings_diff(false);
396   }
397 
398   std::string response_string;
399   response.SerializeToString(&response_string);
400 
401   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
402   ASSERT_TRUE(fetcher);
403   fetcher->set_response_code(net::HTTP_OK);
404   fetcher->SetResponseString(response_string);
405   fetcher->delegate()->OnURLFetchComplete(fetcher);
406   url_fetcher_factory_.RemoveFetcherFromMap(0);
407 }
408 
CompleteRegistration(const std::string & registration_id)409 void GCMClientImplTest::CompleteRegistration(
410     const std::string& registration_id) {
411   std::string response(kRegistrationResponsePrefix);
412   response.append(registration_id);
413   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
414   ASSERT_TRUE(fetcher);
415   fetcher->set_response_code(net::HTTP_OK);
416   fetcher->SetResponseString(response);
417   fetcher->delegate()->OnURLFetchComplete(fetcher);
418   url_fetcher_factory_.RemoveFetcherFromMap(0);
419 }
420 
CompleteUnregistration(const std::string & app_id)421 void GCMClientImplTest::CompleteUnregistration(
422     const std::string& app_id) {
423   std::string response(kUnregistrationResponsePrefix);
424   response.append(app_id);
425   net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
426   ASSERT_TRUE(fetcher);
427   fetcher->set_response_code(net::HTTP_OK);
428   fetcher->SetResponseString(response);
429   fetcher->delegate()->OnURLFetchComplete(fetcher);
430   url_fetcher_factory_.RemoveFetcherFromMap(0);
431 }
432 
ExistsRegistration(const std::string & app_id) const433 bool GCMClientImplTest::ExistsRegistration(const std::string& app_id) const {
434   return gcm_client_->registrations_.count(app_id) > 0;
435 }
436 
AddRegistration(const std::string & app_id,const std::vector<std::string> & sender_ids,const std::string & registration_id)437 void GCMClientImplTest::AddRegistration(
438     const std::string& app_id,
439     const std::vector<std::string>& sender_ids,
440     const std::string& registration_id) {
441   linked_ptr<RegistrationInfo> registration(new RegistrationInfo);
442   registration->sender_ids = sender_ids;
443   registration->registration_id = registration_id;
444   gcm_client_->registrations_[app_id] = registration;
445 }
446 
InitializeGCMClient()447 void GCMClientImplTest::InitializeGCMClient() {
448   clock()->Advance(base::TimeDelta::FromMilliseconds(1));
449 
450   // Actual initialization.
451   GCMClient::ChromeBuildInfo chrome_build_info;
452   gcm_client_->Initialize(chrome_build_info,
453                           temp_directory_.path(),
454                           message_loop_.message_loop_proxy(),
455                           url_request_context_getter_,
456                           make_scoped_ptr<Encryptor>(new FakeEncryptor),
457                           this);
458 }
459 
StartGCMClient()460 void GCMClientImplTest::StartGCMClient() {
461   // Start loading and check-in.
462   gcm_client_->Start();
463 
464   PumpLoopUntilIdle();
465 }
466 
ReceiveMessageFromMCS(const MCSMessage & message)467 void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) {
468   gcm_client_->OnMessageReceivedFromMCS(message);
469 }
470 
OnGCMReady()471 void GCMClientImplTest::OnGCMReady() {
472   last_event_ = LOADING_COMPLETED;
473   QuitLoop();
474 }
475 
OnMessageReceived(const std::string & registration_id,const GCMClient::IncomingMessage & message)476 void GCMClientImplTest::OnMessageReceived(
477     const std::string& registration_id,
478     const GCMClient::IncomingMessage& message) {
479   last_event_ = MESSAGE_RECEIVED;
480   last_app_id_ = registration_id;
481   last_message_ = message;
482   QuitLoop();
483 }
484 
OnRegisterFinished(const std::string & app_id,const std::string & registration_id,GCMClient::Result result)485 void GCMClientImplTest::OnRegisterFinished(const std::string& app_id,
486                                            const std::string& registration_id,
487                                            GCMClient::Result result) {
488   last_event_ = REGISTRATION_COMPLETED;
489   last_app_id_ = app_id;
490   last_registration_id_ = registration_id;
491   last_result_ = result;
492 }
493 
OnUnregisterFinished(const std::string & app_id,GCMClient::Result result)494 void GCMClientImplTest::OnUnregisterFinished(const std::string& app_id,
495                                              GCMClient::Result result) {
496   last_event_ = UNREGISTRATION_COMPLETED;
497   last_app_id_ = app_id;
498   last_result_ = result;
499 }
500 
OnMessagesDeleted(const std::string & app_id)501 void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) {
502   last_event_ = MESSAGES_DELETED;
503   last_app_id_ = app_id;
504 }
505 
OnMessageSendError(const std::string & app_id,const gcm::GCMClient::SendErrorDetails & send_error_details)506 void GCMClientImplTest::OnMessageSendError(
507     const std::string& app_id,
508     const gcm::GCMClient::SendErrorDetails& send_error_details) {
509   last_event_ = MESSAGE_SEND_ERROR;
510   last_app_id_ = app_id;
511   last_error_details_ = send_error_details;
512 }
513 
CurrentTime()514 int64 GCMClientImplTest::CurrentTime() {
515   return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond;
516 }
517 
TEST_F(GCMClientImplTest,LoadingCompleted)518 TEST_F(GCMClientImplTest, LoadingCompleted) {
519   EXPECT_EQ(LOADING_COMPLETED, last_event());
520   EXPECT_EQ(kDeviceAndroidId, mcs_client()->last_android_id());
521   EXPECT_EQ(kDeviceSecurityToken, mcs_client()->last_security_token());
522 }
523 
TEST_F(GCMClientImplTest,CheckOut)524 TEST_F(GCMClientImplTest, CheckOut) {
525   EXPECT_TRUE(mcs_client());
526   EXPECT_TRUE(connection_factory());
527   gcm_client()->CheckOut();
528   EXPECT_FALSE(mcs_client());
529   EXPECT_FALSE(connection_factory());
530 }
531 
TEST_F(GCMClientImplTest,RegisterApp)532 TEST_F(GCMClientImplTest, RegisterApp) {
533   EXPECT_FALSE(ExistsRegistration(kAppId));
534 
535   std::vector<std::string> senders;
536   senders.push_back("sender");
537   gcm_client()->Register(kAppId, senders);
538   CompleteRegistration("reg_id");
539 
540   EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
541   EXPECT_EQ(kAppId, last_app_id());
542   EXPECT_EQ("reg_id", last_registration_id());
543   EXPECT_EQ(GCMClient::SUCCESS, last_result());
544   EXPECT_TRUE(ExistsRegistration(kAppId));
545 }
546 
TEST_F(GCMClientImplTest,DISABLED_RegisterAppFromCache)547 TEST_F(GCMClientImplTest, DISABLED_RegisterAppFromCache) {
548   EXPECT_FALSE(ExistsRegistration(kAppId));
549 
550   std::vector<std::string> senders;
551   senders.push_back("sender");
552   gcm_client()->Register(kAppId, senders);
553   CompleteRegistration("reg_id");
554   EXPECT_TRUE(ExistsRegistration(kAppId));
555 
556   EXPECT_EQ(kAppId, last_app_id());
557   EXPECT_EQ("reg_id", last_registration_id());
558   EXPECT_EQ(GCMClient::SUCCESS, last_result());
559   EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
560 
561   // Recreate GCMClient in order to load from the persistent store.
562   BuildGCMClient(base::TimeDelta());
563   InitializeGCMClient();
564   StartGCMClient();
565 
566   EXPECT_TRUE(ExistsRegistration(kAppId));
567 }
568 
TEST_F(GCMClientImplTest,UnregisterApp)569 TEST_F(GCMClientImplTest, UnregisterApp) {
570   EXPECT_FALSE(ExistsRegistration(kAppId));
571 
572   std::vector<std::string> senders;
573   senders.push_back("sender");
574   gcm_client()->Register(kAppId, senders);
575   CompleteRegistration("reg_id");
576   EXPECT_TRUE(ExistsRegistration(kAppId));
577 
578   gcm_client()->Unregister(kAppId);
579   CompleteUnregistration(kAppId);
580 
581   EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
582   EXPECT_EQ(kAppId, last_app_id());
583   EXPECT_EQ(GCMClient::SUCCESS, last_result());
584   EXPECT_FALSE(ExistsRegistration(kAppId));
585 }
586 
TEST_F(GCMClientImplTest,DispatchDownstreamMessage)587 TEST_F(GCMClientImplTest, DispatchDownstreamMessage) {
588   // Register to receive messages from kSender and kSender2 only.
589   std::vector<std::string> senders;
590   senders.push_back(kSender);
591   senders.push_back(kSender2);
592   AddRegistration(kAppId, senders, "reg_id");
593 
594   std::map<std::string, std::string> expected_data;
595   expected_data["message_type"] = "gcm";
596   expected_data["key"] = "value";
597   expected_data["key2"] = "value2";
598 
599   // Message for kSender will be received.
600   MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data));
601   EXPECT_TRUE(message.IsValid());
602   ReceiveMessageFromMCS(message);
603 
604   expected_data.erase(expected_data.find("message_type"));
605   EXPECT_EQ(MESSAGE_RECEIVED, last_event());
606   EXPECT_EQ(kAppId, last_app_id());
607   EXPECT_EQ(expected_data.size(), last_message().data.size());
608   EXPECT_EQ(expected_data, last_message().data);
609   EXPECT_EQ(kSender, last_message().sender_id);
610 
611   reset_last_event();
612 
613   // Message for kSender2 will be received.
614   MCSMessage message2(BuildDownstreamMessage(kSender2, kAppId, expected_data));
615   EXPECT_TRUE(message2.IsValid());
616   ReceiveMessageFromMCS(message2);
617 
618   EXPECT_EQ(MESSAGE_RECEIVED, last_event());
619   EXPECT_EQ(kAppId, last_app_id());
620   EXPECT_EQ(expected_data.size(), last_message().data.size());
621   EXPECT_EQ(expected_data, last_message().data);
622   EXPECT_EQ(kSender2, last_message().sender_id);
623 
624   reset_last_event();
625 
626   // Message from kSender3 will be dropped.
627   MCSMessage message3(BuildDownstreamMessage(kSender3, kAppId, expected_data));
628   EXPECT_TRUE(message3.IsValid());
629   ReceiveMessageFromMCS(message3);
630 
631   EXPECT_NE(MESSAGE_RECEIVED, last_event());
632   EXPECT_NE(kAppId, last_app_id());
633 }
634 
TEST_F(GCMClientImplTest,DispatchDownstreamMessageSendError)635 TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
636   std::map<std::string, std::string> expected_data;
637   expected_data["message_type"] = "send_error";
638   expected_data["google.message_id"] = "007";
639   expected_data["error_details"] = "some details";
640   MCSMessage message(BuildDownstreamMessage(
641       kSender, kAppId, expected_data));
642   EXPECT_TRUE(message.IsValid());
643   ReceiveMessageFromMCS(message);
644 
645   EXPECT_EQ(MESSAGE_SEND_ERROR, last_event());
646   EXPECT_EQ(kAppId, last_app_id());
647   EXPECT_EQ("007", last_error_details().message_id);
648   EXPECT_EQ(1UL, last_error_details().additional_data.size());
649   GCMClient::MessageData::const_iterator iter =
650       last_error_details().additional_data.find("error_details");
651   EXPECT_TRUE(iter != last_error_details().additional_data.end());
652   EXPECT_EQ("some details", iter->second);
653 }
654 
TEST_F(GCMClientImplTest,DispatchDownstreamMessgaesDeleted)655 TEST_F(GCMClientImplTest, DispatchDownstreamMessgaesDeleted) {
656   std::map<std::string, std::string> expected_data;
657   expected_data["message_type"] = "deleted_messages";
658   MCSMessage message(BuildDownstreamMessage(
659       kSender, kAppId, expected_data));
660   EXPECT_TRUE(message.IsValid());
661   ReceiveMessageFromMCS(message);
662 
663   EXPECT_EQ(MESSAGES_DELETED, last_event());
664   EXPECT_EQ(kAppId, last_app_id());
665 }
666 
TEST_F(GCMClientImplTest,SendMessage)667 TEST_F(GCMClientImplTest, SendMessage) {
668   mcs_proto::DataMessageStanza stanza;
669   stanza.set_ttl(500);
670 
671   GCMClient::OutgoingMessage message;
672   message.id = "007";
673   message.time_to_live = 500;
674   message.data["key"] = "value";
675   gcm_client()->Send(kAppId, kSender, message);
676 
677   EXPECT_EQ(kDataMessageStanzaTag, mcs_client()->last_message_tag());
678   EXPECT_EQ(kAppId, mcs_client()->last_data_message_stanza().category());
679   EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
680   EXPECT_EQ(500, mcs_client()->last_data_message_stanza().ttl());
681   EXPECT_EQ(CurrentTime(), mcs_client()->last_data_message_stanza().sent());
682   EXPECT_EQ("007", mcs_client()->last_data_message_stanza().id());
683   EXPECT_EQ("gcm@chrome.com", mcs_client()->last_data_message_stanza().from());
684   EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
685   EXPECT_EQ("key", mcs_client()->last_data_message_stanza().app_data(0).key());
686   EXPECT_EQ("value",
687             mcs_client()->last_data_message_stanza().app_data(0).value());
688 }
689 
690 class GCMClientImplCheckinTest : public GCMClientImplTest {
691  public:
692   GCMClientImplCheckinTest();
693   virtual ~GCMClientImplCheckinTest();
694 
695   virtual void SetUp() OVERRIDE;
696 };
697 
GCMClientImplCheckinTest()698 GCMClientImplCheckinTest::GCMClientImplCheckinTest() {
699 }
700 
~GCMClientImplCheckinTest()701 GCMClientImplCheckinTest::~GCMClientImplCheckinTest() {
702 }
703 
SetUp()704 void GCMClientImplCheckinTest::SetUp() {
705   testing::Test::SetUp();
706   // Creating unique temp directory that will be used by GCMStore shared between
707   // GCM Client and G-services settings.
708   ASSERT_TRUE(CreateUniqueTempDir());
709   InitializeLoop();
710   // Time will be advancing one hour every time it is checked.
711   BuildGCMClient(base::TimeDelta::FromSeconds(kSettingsCheckinInterval));
712   InitializeGCMClient();
713   StartGCMClient();
714 }
715 
TEST_F(GCMClientImplCheckinTest,GServicesSettingsAfterInitialCheckin)716 TEST_F(GCMClientImplCheckinTest, GServicesSettingsAfterInitialCheckin) {
717   std::map<std::string, std::string> settings;
718   settings["checkin_interval"] = base::Int64ToString(kSettingsCheckinInterval);
719   settings["checkin_url"] = "http://alternative.url/checkin";
720   settings["gcm_hostname"] = "alternative.gcm.host";
721   settings["gcm_secure_port"] = "7777";
722   settings["gcm_registration_url"] = "http://alternative.url/registration";
723   CompleteCheckin(kDeviceAndroidId,
724                   kDeviceSecurityToken,
725                   GServicesSettings::CalculateDigest(settings),
726                   settings);
727   EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval),
728             gservices_settings().GetCheckinInterval());
729   EXPECT_EQ(GURL("http://alternative.url/checkin"),
730             gservices_settings().GetCheckinURL());
731   EXPECT_EQ(GURL("http://alternative.url/registration"),
732             gservices_settings().GetRegistrationURL());
733   EXPECT_EQ(GURL("https://alternative.gcm.host:7777"),
734             gservices_settings().GetMCSMainEndpoint());
735   EXPECT_EQ(GURL("https://alternative.gcm.host:443"),
736             gservices_settings().GetMCSFallbackEndpoint());
737 }
738 
739 // This test only checks that periodic checkin happens.
TEST_F(GCMClientImplCheckinTest,PeriodicCheckin)740 TEST_F(GCMClientImplCheckinTest, PeriodicCheckin) {
741   std::map<std::string, std::string> settings;
742   settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
743   settings["checkin_url"] = "http://alternative.url/checkin";
744   settings["gcm_hostname"] = "alternative.gcm.host";
745   settings["gcm_secure_port"] = "7777";
746   settings["gcm_registration_url"] = "http://alternative.url/registration";
747   CompleteCheckin(kDeviceAndroidId,
748                   kDeviceSecurityToken,
749                   GServicesSettings::CalculateDigest(settings),
750                   settings);
751   EXPECT_EQ(2, clock()->call_count());
752 
753   PumpLoopUntilIdle();
754   CompleteCheckin(kDeviceAndroidId,
755                   kDeviceSecurityToken,
756                   GServicesSettings::CalculateDigest(settings),
757                   settings);
758 }
759 
TEST_F(GCMClientImplCheckinTest,LoadGSettingsFromStore)760 TEST_F(GCMClientImplCheckinTest, LoadGSettingsFromStore) {
761   std::map<std::string, std::string> settings;
762   settings["checkin_interval"] = base::IntToString(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 
772   BuildGCMClient(base::TimeDelta());
773   InitializeGCMClient();
774   StartGCMClient();
775 
776   EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval),
777             gservices_settings().GetCheckinInterval());
778   EXPECT_EQ(GURL("http://alternative.url/checkin"),
779             gservices_settings().GetCheckinURL());
780   EXPECT_EQ(GURL("http://alternative.url/registration"),
781             gservices_settings().GetRegistrationURL());
782   EXPECT_EQ(GURL("https://alternative.gcm.host:7777"),
783             gservices_settings().GetMCSMainEndpoint());
784   EXPECT_EQ(GURL("https://alternative.gcm.host:443"),
785             gservices_settings().GetMCSFallbackEndpoint());
786 }
787 
788 class GCMClientImplStartAndStopTest : public GCMClientImplTest {
789 public:
790   GCMClientImplStartAndStopTest();
791   virtual ~GCMClientImplStartAndStopTest();
792 
793   virtual void SetUp() OVERRIDE;
794 };
795 
GCMClientImplStartAndStopTest()796 GCMClientImplStartAndStopTest::GCMClientImplStartAndStopTest() {
797 }
798 
~GCMClientImplStartAndStopTest()799 GCMClientImplStartAndStopTest::~GCMClientImplStartAndStopTest() {
800 }
801 
SetUp()802 void GCMClientImplStartAndStopTest::SetUp() {
803   testing::Test::SetUp();
804   ASSERT_TRUE(CreateUniqueTempDir());
805   InitializeLoop();
806   BuildGCMClient(base::TimeDelta());
807   InitializeGCMClient();
808 }
809 
TEST_F(GCMClientImplStartAndStopTest,StartStopAndRestart)810 TEST_F(GCMClientImplStartAndStopTest, StartStopAndRestart) {
811   // Start the GCM and wait until it is ready.
812   gcm_client()->Start();
813   PumpLoopUntilIdle();
814 
815   // Stop the GCM.
816   gcm_client()->Stop();
817   PumpLoopUntilIdle();
818 
819   // Restart the GCM.
820   gcm_client()->Start();
821   PumpLoopUntilIdle();
822 }
823 
TEST_F(GCMClientImplStartAndStopTest,StartAndStopImmediately)824 TEST_F(GCMClientImplStartAndStopTest, StartAndStopImmediately) {
825   // Start the GCM and then stop it immediately.
826   gcm_client()->Start();
827   gcm_client()->Stop();
828 
829   PumpLoopUntilIdle();
830 }
831 
TEST_F(GCMClientImplStartAndStopTest,StartStopAndRestartImmediately)832 TEST_F(GCMClientImplStartAndStopTest, StartStopAndRestartImmediately) {
833   // Start the GCM and then stop and restart it immediately.
834   gcm_client()->Start();
835   gcm_client()->Stop();
836   gcm_client()->Start();
837 
838   PumpLoopUntilIdle();
839 }
840 
841 }  // namespace gcm
842