Home | History | Annotate | Download | only in gcm_driver
      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.
     53 MCSMessage BuildDownstreamMessage(
     54     const std::string& project_id,
     55     const std::string& app_id,
     56     const std::map<std::string, std::string>& data) {
     57   mcs_proto::DataMessageStanza data_message;
     58   data_message.set_from(project_id);
     59   data_message.set_category(app_id);
     60   for (std::map<std::string, std::string>::const_iterator iter = data.begin();
     61        iter != data.end();
     62        ++iter) {
     63     mcs_proto::AppData* app_data = data_message.add_app_data();
     64     app_data->set_key(iter->first);
     65     app_data->set_value(iter->second);
     66   }
     67   return MCSMessage(kDataMessageStanzaTag, data_message);
     68 }
     69 
     70 class FakeMCSClient : public MCSClient {
     71  public:
     72   FakeMCSClient(base::Clock* clock,
     73                 ConnectionFactory* connection_factory,
     74                 GCMStore* gcm_store,
     75                 GCMStatsRecorder* recorder);
     76   virtual ~FakeMCSClient();
     77   virtual void Login(uint64 android_id, uint64 security_token) OVERRIDE;
     78   virtual void SendMessage(const MCSMessage& message) OVERRIDE;
     79 
     80   uint64 last_android_id() const { return last_android_id_; }
     81   uint64 last_security_token() const { return last_security_token_; }
     82   uint8 last_message_tag() const { return last_message_tag_; }
     83   const mcs_proto::DataMessageStanza& last_data_message_stanza() const {
     84     return last_data_message_stanza_;
     85   }
     86 
     87  private:
     88   uint64 last_android_id_;
     89   uint64 last_security_token_;
     90   uint8 last_message_tag_;
     91   mcs_proto::DataMessageStanza last_data_message_stanza_;
     92 };
     93 
     94 FakeMCSClient::FakeMCSClient(base::Clock* clock,
     95                              ConnectionFactory* connection_factory,
     96                              GCMStore* gcm_store,
     97                              GCMStatsRecorder* recorder)
     98     : MCSClient("", clock, connection_factory, gcm_store, recorder),
     99       last_android_id_(0u),
    100       last_security_token_(0u),
    101       last_message_tag_(kNumProtoTypes) {
    102 }
    103 
    104 FakeMCSClient::~FakeMCSClient() {
    105 }
    106 
    107 void FakeMCSClient::Login(uint64 android_id, uint64 security_token) {
    108   last_android_id_ = android_id;
    109   last_security_token_ = security_token;
    110 }
    111 
    112 void FakeMCSClient::SendMessage(const MCSMessage& message) {
    113   last_message_tag_ = message.tag();
    114   if (last_message_tag_ == kDataMessageStanzaTag) {
    115     last_data_message_stanza_.CopyFrom(
    116         reinterpret_cast<const mcs_proto::DataMessageStanza&>(
    117             message.GetProtobuf()));
    118   }
    119 }
    120 
    121 class AutoAdvancingTestClock : public base::Clock {
    122  public:
    123   explicit AutoAdvancingTestClock(base::TimeDelta auto_increment_time_delta);
    124   virtual ~AutoAdvancingTestClock();
    125 
    126   virtual base::Time Now() OVERRIDE;
    127   void Advance(TimeDelta delta);
    128   int call_count() const { return call_count_; }
    129 
    130  private:
    131   int call_count_;
    132   base::TimeDelta auto_increment_time_delta_;
    133   base::Time now_;
    134 
    135   DISALLOW_COPY_AND_ASSIGN(AutoAdvancingTestClock);
    136 };
    137 
    138 AutoAdvancingTestClock::AutoAdvancingTestClock(
    139     base::TimeDelta auto_increment_time_delta)
    140     : call_count_(0), auto_increment_time_delta_(auto_increment_time_delta) {
    141 }
    142 
    143 AutoAdvancingTestClock::~AutoAdvancingTestClock() {
    144 }
    145 
    146 base::Time AutoAdvancingTestClock::Now() {
    147   call_count_++;
    148   now_ += auto_increment_time_delta_;
    149   return now_;
    150 }
    151 
    152 void AutoAdvancingTestClock::Advance(base::TimeDelta delta) {
    153   now_ += delta;
    154 }
    155 
    156 class FakeGCMInternalsBuilder : public GCMInternalsBuilder {
    157  public:
    158   FakeGCMInternalsBuilder(base::TimeDelta clock_step);
    159   virtual ~FakeGCMInternalsBuilder();
    160 
    161   virtual scoped_ptr<base::Clock> BuildClock() OVERRIDE;
    162   virtual scoped_ptr<MCSClient> BuildMCSClient(
    163       const std::string& version,
    164       base::Clock* clock,
    165       ConnectionFactory* connection_factory,
    166       GCMStore* gcm_store,
    167       GCMStatsRecorder* recorder) OVERRIDE;
    168   virtual scoped_ptr<ConnectionFactory> BuildConnectionFactory(
    169       const std::vector<GURL>& endpoints,
    170       const net::BackoffEntry::Policy& backoff_policy,
    171       scoped_refptr<net::HttpNetworkSession> network_session,
    172       net::NetLog* net_log,
    173       GCMStatsRecorder* recorder) OVERRIDE;
    174 
    175  private:
    176   base::TimeDelta clock_step_;
    177 };
    178 
    179 FakeGCMInternalsBuilder::FakeGCMInternalsBuilder(base::TimeDelta clock_step)
    180     : clock_step_(clock_step) {
    181 }
    182 
    183 FakeGCMInternalsBuilder::~FakeGCMInternalsBuilder() {}
    184 
    185 scoped_ptr<base::Clock> FakeGCMInternalsBuilder::BuildClock() {
    186   return make_scoped_ptr<base::Clock>(new AutoAdvancingTestClock(clock_step_));
    187 }
    188 
    189 scoped_ptr<MCSClient> FakeGCMInternalsBuilder::BuildMCSClient(
    190     const std::string& version,
    191     base::Clock* clock,
    192     ConnectionFactory* connection_factory,
    193     GCMStore* gcm_store,
    194     GCMStatsRecorder* recorder) {
    195   return make_scoped_ptr<MCSClient>(new FakeMCSClient(clock,
    196                                                       connection_factory,
    197                                                       gcm_store,
    198                                                       recorder));
    199 }
    200 
    201 scoped_ptr<ConnectionFactory> FakeGCMInternalsBuilder::BuildConnectionFactory(
    202     const std::vector<GURL>& endpoints,
    203     const net::BackoffEntry::Policy& backoff_policy,
    204     scoped_refptr<net::HttpNetworkSession> network_session,
    205     net::NetLog* net_log,
    206     GCMStatsRecorder* recorder) {
    207   return make_scoped_ptr<ConnectionFactory>(new FakeConnectionFactory());
    208 }
    209 
    210 }  // namespace
    211 
    212 class GCMClientImplTest : public testing::Test,
    213                           public GCMClient::Delegate {
    214  public:
    215   GCMClientImplTest();
    216   virtual ~GCMClientImplTest();
    217 
    218   virtual void SetUp() OVERRIDE;
    219 
    220   void BuildGCMClient(base::TimeDelta clock_step);
    221   void InitializeGCMClient();
    222   void 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;
    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   virtual void OnActivityRecorded() OVERRIDE {}
    254   virtual void OnConnected(const net::IPEndPoint& ip_endpoint) OVERRIDE {}
    255   virtual void OnDisconnected() OVERRIDE {}
    256 
    257   GCMClientImpl* gcm_client() const { return gcm_client_.get(); }
    258   FakeMCSClient* mcs_client() const {
    259     return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get());
    260   }
    261   ConnectionFactory* connection_factory() const {
    262     return gcm_client_->connection_factory_.get();
    263   }
    264 
    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 
    273   LastEvent last_event() const { return last_event_; }
    274   const std::string& last_app_id() const { return last_app_id_; }
    275   const std::string& last_registration_id() const {
    276     return last_registration_id_;
    277   }
    278   const std::string& last_message_id() const { return last_message_id_; }
    279   GCMClient::Result last_result() const { return last_result_; }
    280   const GCMClient::IncomingMessage& last_message() const {
    281     return last_message_;
    282   }
    283   const GCMClient::SendErrorDetails& last_error_details() const {
    284     return last_error_details_;
    285   }
    286 
    287   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();
    299   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 
    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 
    331 GCMClientImplTest::~GCMClientImplTest() {}
    332 
    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 
    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     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 
    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 
    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 
    433 bool GCMClientImplTest::ExistsRegistration(const std::string& app_id) const {
    434   return gcm_client_->registrations_.count(app_id) > 0;
    435 }
    436 
    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 
    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 
    460 void GCMClientImplTest::StartGCMClient() {
    461   // Start loading and check-in.
    462   gcm_client_->Start();
    463 
    464   PumpLoopUntilIdle();
    465 }
    466 
    467 void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) {
    468   gcm_client_->OnMessageReceivedFromMCS(message);
    469 }
    470 
    471 void GCMClientImplTest::OnGCMReady() {
    472   last_event_ = LOADING_COMPLETED;
    473   QuitLoop();
    474 }
    475 
    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 
    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 
    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 
    501 void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) {
    502   last_event_ = MESSAGES_DELETED;
    503   last_app_id_ = app_id;
    504 }
    505 
    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 
    514 int64 GCMClientImplTest::CurrentTime() {
    515   return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond;
    516 }
    517 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 (at) 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 
    698 GCMClientImplCheckinTest::GCMClientImplCheckinTest() {
    699 }
    700 
    701 GCMClientImplCheckinTest::~GCMClientImplCheckinTest() {
    702 }
    703 
    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 
    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.
    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 
    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 
    796 GCMClientImplStartAndStopTest::GCMClientImplStartAndStopTest() {
    797 }
    798 
    799 GCMClientImplStartAndStopTest::~GCMClientImplStartAndStopTest() {
    800 }
    801 
    802 void GCMClientImplStartAndStopTest::SetUp() {
    803   testing::Test::SetUp();
    804   ASSERT_TRUE(CreateUniqueTempDir());
    805   InitializeLoop();
    806   BuildGCMClient(base::TimeDelta());
    807   InitializeGCMClient();
    808 }
    809 
    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 
    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 
    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