Home | History | Annotate | Download | only in gcm
      1 // Copyright (c) 2013 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 <algorithm>
      6 
      7 #include "base/bind.h"
      8 #include "base/command_line.h"
      9 #include "base/prefs/pref_service.h"
     10 #include "base/run_loop.h"
     11 #include "chrome/browser/extensions/state_store.h"
     12 #include "chrome/browser/extensions/test_extension_service.h"
     13 #include "chrome/browser/extensions/test_extension_system.h"
     14 #include "chrome/browser/services/gcm/gcm_client_mock.h"
     15 #include "chrome/browser/services/gcm/gcm_event_router.h"
     16 #include "chrome/browser/services/gcm/gcm_profile_service.h"
     17 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
     18 #include "chrome/browser/signin/fake_signin_manager.h"
     19 #include "chrome/browser/signin/signin_manager_factory.h"
     20 #include "chrome/browser/ui/browser.h"
     21 #include "chrome/common/pref_names.h"
     22 #include "chrome/test/base/testing_profile.h"
     23 #include "components/webdata/encryptor/encryptor.h"
     24 #include "content/public/test/test_browser_thread_bundle.h"
     25 #include "extensions/common/extension.h"
     26 #include "extensions/common/manifest_constants.h"
     27 #include "testing/gtest/include/gtest/gtest.h"
     28 
     29 #if defined(OS_CHROMEOS)
     30 #include "chrome/browser/chromeos/login/user_manager.h"
     31 #include "chrome/browser/chromeos/settings/cros_settings.h"
     32 #include "chrome/browser/chromeos/settings/device_settings_service.h"
     33 #endif
     34 
     35 using namespace extensions;
     36 
     37 namespace gcm {
     38 
     39 const char kTestExtensionName[] = "FooBar";
     40 const char kTestingUsername[] = "user (at) example.com";
     41 const char kTestingAppId[] = "test1";
     42 const char kTestingSha1Cert[] = "testing_cert1";
     43 const char kUserId[] = "user2";
     44 
     45 class GCMProfileServiceTest;
     46 
     47 class GCMEventRouterMock : public GCMEventRouter {
     48  public:
     49   enum Event {
     50     NO_EVENT,
     51     MESSAGE_EVENT,
     52     MESSAGES_DELETED_EVENT,
     53     SEND_ERROR_EVENT
     54   };
     55 
     56   explicit GCMEventRouterMock(GCMProfileServiceTest* test);
     57   virtual ~GCMEventRouterMock();
     58 
     59   virtual void OnMessage(const std::string& app_id,
     60                          const GCMClient::IncomingMessage& message) OVERRIDE;
     61   virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
     62   virtual void OnSendError(const std::string& app_id,
     63                            const std::string& message_id,
     64                            GCMClient::Result result) OVERRIDE;
     65 
     66   Event received_event() const { return received_event_; }
     67   const std::string& app_id() const { return app_id_; }
     68   const GCMClient::IncomingMessage incoming_message() const {
     69     return incoming_message_;
     70   }
     71   const std::string& send_message_id() const { return send_error_message_id_; }
     72   GCMClient::Result send_result() const { return send_error_result_; }
     73 
     74  private:
     75   GCMProfileServiceTest* test_;
     76   Event received_event_;
     77   std::string app_id_;
     78   GCMClient::IncomingMessage incoming_message_;
     79   std::string send_error_message_id_;
     80   GCMClient::Result send_error_result_;
     81 };
     82 
     83 class GCMProfileServiceTest : public testing::Test,
     84                               public GCMProfileService::TestingDelegate {
     85  public:
     86   static BrowserContextKeyedService* BuildGCMProfileService(
     87       content::BrowserContext* profile) {
     88     return new GCMProfileService(
     89         static_cast<Profile*>(profile), gps_testing_delegate_);
     90   }
     91 
     92   GCMProfileServiceTest() : extension_service_(NULL) {
     93   }
     94 
     95   virtual ~GCMProfileServiceTest() {
     96   }
     97 
     98   // Overridden from test::Test:
     99   virtual void SetUp() OVERRIDE {
    100     profile_.reset(new TestingProfile);
    101 
    102     // Make BrowserThread work in unittest.
    103     thread_bundle_.reset(new content::TestBrowserThreadBundle(
    104         content::TestBrowserThreadBundle::REAL_IO_THREAD));
    105 
    106     // This is needed to create extension service under CrOS.
    107 #if defined(OS_CHROMEOS)
    108     test_user_manager_.reset(new chromeos::ScopedTestUserManager());
    109 #endif
    110 
    111     // Create extension service in order to uninstall the extension.
    112     extensions::TestExtensionSystem* extension_system(
    113         static_cast<extensions::TestExtensionSystem*>(
    114             extensions::ExtensionSystem::Get(profile())));
    115     extension_system->CreateExtensionService(
    116         CommandLine::ForCurrentProcess(), base::FilePath(), false);
    117     extension_service_ = extension_system->Get(profile())->extension_service();
    118 
    119     // Mock a signed-in user.
    120     SigninManagerBase* signin_manager =
    121         SigninManagerFactory::GetForProfile(profile());
    122     signin_manager->SetAuthenticatedUsername(kTestingUsername);
    123 
    124     // Encryptor ends up needing access to the keychain on OS X. So use the mock
    125     // keychain to prevent prompts.
    126 #if defined(OS_MACOSX)
    127     Encryptor::UseMockKeychain(true);
    128 #endif
    129 
    130     // Mock a GCMClient.
    131     gcm_client_mock_.reset(new GCMClientMock());
    132     GCMClient::SetForTesting(gcm_client_mock_.get());
    133 
    134     // Mock a GCMEventRouter.
    135     gcm_event_router_mock_.reset(new GCMEventRouterMock(this));
    136 
    137     // Set |gps_testing_delegate_| for it to be picked up by
    138     // BuildGCMProfileService and pass it to GCMProfileService.
    139     gps_testing_delegate_ = this;
    140 
    141     // This will create GCMProfileService that causes check-in to be initiated.
    142     GCMProfileService::enable_gcm_for_testing_ = true;
    143     GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse(
    144         profile(), &GCMProfileServiceTest::BuildGCMProfileService);
    145 
    146     // Wait till the asynchronous check-in is done.
    147     WaitForCompleted();
    148   }
    149 
    150   virtual void TearDown() OVERRIDE {
    151     GCMClient::SetForTesting(NULL);
    152 
    153 #if defined(OS_CHROMEOS)
    154     test_user_manager_.reset();
    155 #endif
    156 
    157     extension_service_ = NULL;
    158     profile_.reset();
    159     base::RunLoop().RunUntilIdle();
    160   }
    161 
    162   // Overridden from GCMProfileService::TestingDelegate:
    163   virtual GCMEventRouter* GetEventRouter() const OVERRIDE {
    164     return gcm_event_router_mock_.get();
    165   }
    166 
    167   virtual void CheckInFinished(const GCMClient::CheckInInfo& checkin_info,
    168                                GCMClient::Result result) OVERRIDE {
    169     checkin_info_ = checkin_info;
    170     SignalCompleted();
    171   }
    172 
    173   virtual void LoadingFromPersistentStoreFinished() OVERRIDE {
    174     SignalCompleted();
    175   }
    176 
    177   // Waits until the asynchrnous operation finishes.
    178   void WaitForCompleted() {
    179     run_loop_.reset(new base::RunLoop);
    180     run_loop_->Run();
    181   }
    182 
    183   // Signals that the asynchrnous operation finishes.
    184   void SignalCompleted() {
    185     if (run_loop_ && run_loop_->running())
    186       run_loop_->Quit();
    187   }
    188 
    189   // Returns a barebones test extension.
    190   scoped_refptr<Extension> CreateExtension() {
    191 #if defined(OS_WIN)
    192     base::FilePath path(FILE_PATH_LITERAL("c:\\foo"));
    193 #elif defined(OS_POSIX)
    194     base::FilePath path(FILE_PATH_LITERAL("/foo"));
    195 #endif
    196 
    197     DictionaryValue manifest;
    198     manifest.SetString(manifest_keys::kVersion, "1.0.0.0");
    199     manifest.SetString(manifest_keys::kName, kTestExtensionName);
    200     ListValue* permission_list = new ListValue;
    201     permission_list->Append(Value::CreateStringValue("gcm"));
    202     manifest.Set(manifest_keys::kPermissions, permission_list);
    203 
    204     std::string error;
    205     scoped_refptr<Extension> extension =
    206         Extension::Create(path.AppendASCII(kTestExtensionName),
    207                           Manifest::INVALID_LOCATION,
    208                           manifest,
    209                           Extension::NO_FLAGS,
    210                           &error);
    211     EXPECT_TRUE(extension.get()) << error;
    212 
    213     extension_service_->AddExtension(extension.get());
    214     return extension;
    215   }
    216 
    217   Profile* profile() const { return profile_.get(); }
    218 
    219   GCMProfileService* GetGCMProfileService() const {
    220     return GCMProfileServiceFactory::GetForProfile(profile());
    221   }
    222 
    223  protected:
    224   scoped_ptr<TestingProfile> profile_;
    225   scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_;
    226   ExtensionService* extension_service_;  // Not owned.
    227   scoped_ptr<GCMClientMock> gcm_client_mock_;
    228   scoped_ptr<base::RunLoop> run_loop_;
    229   scoped_ptr<GCMEventRouterMock> gcm_event_router_mock_;
    230   GCMClient::CheckInInfo checkin_info_;
    231 
    232 #if defined(OS_CHROMEOS)
    233   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
    234   chromeos::ScopedTestCrosSettings test_cros_settings_;
    235   scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
    236 #endif
    237 
    238  private:
    239   static GCMProfileService::TestingDelegate* gps_testing_delegate_;
    240 
    241   DISALLOW_COPY_AND_ASSIGN(GCMProfileServiceTest);
    242 };
    243 
    244 GCMProfileService::TestingDelegate*
    245 GCMProfileServiceTest::gps_testing_delegate_ = NULL;
    246 
    247 GCMEventRouterMock::GCMEventRouterMock(GCMProfileServiceTest* test)
    248     : test_(test),
    249       received_event_(NO_EVENT),
    250       send_error_result_(GCMClient::SUCCESS) {
    251 }
    252 
    253 GCMEventRouterMock::~GCMEventRouterMock() {
    254 }
    255 
    256 void GCMEventRouterMock::OnMessage(const std::string& app_id,
    257                                    const GCMClient::IncomingMessage& message) {
    258   received_event_ = MESSAGE_EVENT;
    259   app_id_ = app_id;
    260   incoming_message_ = message;
    261   test_->SignalCompleted();
    262 }
    263 
    264 void GCMEventRouterMock::OnMessagesDeleted(const std::string& app_id) {
    265   received_event_ = MESSAGES_DELETED_EVENT;
    266   app_id_ = app_id;
    267   test_->SignalCompleted();
    268 }
    269 
    270 void GCMEventRouterMock::OnSendError(const std::string& app_id,
    271                                      const std::string& message_id,
    272                                      GCMClient::Result result) {
    273   received_event_ = SEND_ERROR_EVENT;
    274   app_id_ = app_id;
    275   send_error_message_id_ = message_id;
    276   send_error_result_ = result;
    277   test_->SignalCompleted();
    278 }
    279 
    280 TEST_F(GCMProfileServiceTest, CheckIn) {
    281   EXPECT_TRUE(checkin_info_.IsValid());
    282 
    283   GCMClient::CheckInInfo expected_checkin_info =
    284       gcm_client_mock_->GetCheckInInfoFromUsername(kTestingUsername);
    285   EXPECT_EQ(expected_checkin_info.android_id, checkin_info_.android_id);
    286   EXPECT_EQ(expected_checkin_info.secret, checkin_info_.secret);
    287 }
    288 
    289 TEST_F(GCMProfileServiceTest, CheckInFromPrefsStore) {
    290   // The first check-in should be successful.
    291   EXPECT_TRUE(checkin_info_.IsValid());
    292   GCMClient::CheckInInfo saved_checkin_info = checkin_info_;
    293   checkin_info_.Reset();
    294 
    295   gcm_client_mock_->set_checkin_failure_enabled(true);
    296 
    297   // Recreate GCMProfileService to test reading the check-in info from the
    298   // prefs store.
    299   GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse(
    300       profile(), &GCMProfileServiceTest::BuildGCMProfileService);
    301 
    302   EXPECT_EQ(saved_checkin_info.android_id, checkin_info_.android_id);
    303   EXPECT_EQ(saved_checkin_info.secret, checkin_info_.secret);
    304 }
    305 
    306 TEST_F(GCMProfileServiceTest, CheckOut) {
    307   EXPECT_TRUE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMUserAccountID));
    308   EXPECT_TRUE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMUserToken));
    309 
    310   GetGCMProfileService()->RemoveUser();
    311 
    312   EXPECT_FALSE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMUserAccountID));
    313   EXPECT_FALSE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMUserToken));
    314 }
    315 
    316 class GCMProfileServiceRegisterTest : public GCMProfileServiceTest {
    317  public:
    318   GCMProfileServiceRegisterTest()
    319       : result_(GCMClient::SUCCESS),
    320         has_persisted_registration_info_(false) {
    321   }
    322 
    323   virtual ~GCMProfileServiceRegisterTest() {
    324   }
    325 
    326   void Register(const std::string& app_id,
    327                 const std::vector<std::string>& sender_ids) {
    328     GetGCMProfileService()->Register(
    329         app_id,
    330         sender_ids,
    331         kTestingSha1Cert,
    332         base::Bind(&GCMProfileServiceRegisterTest::RegisterCompleted,
    333                    base::Unretained(this)));
    334   }
    335 
    336   void RegisterCompleted(const std::string& registration_id,
    337                          GCMClient::Result result) {
    338     registration_id_ = registration_id;
    339     result_ = result;
    340     SignalCompleted();
    341   }
    342 
    343   bool HasPersistedRegistrationInfo(const std::string& app_id) {
    344     StateStore* storage = ExtensionSystem::Get(profile())->state_store();
    345     if (!storage)
    346       return false;
    347     has_persisted_registration_info_ = false;
    348     storage->GetExtensionValue(
    349         app_id,
    350         GCMProfileService::GetPersistentRegisterKeyForTesting(),
    351         base::Bind(
    352             &GCMProfileServiceRegisterTest::ReadRegistrationInfoFinished,
    353             base::Unretained(this)));
    354     WaitForCompleted();
    355     return has_persisted_registration_info_;
    356   }
    357 
    358   void ReadRegistrationInfoFinished(scoped_ptr<base::Value> value) {
    359     has_persisted_registration_info_ = value.get() != NULL;
    360     SignalCompleted();
    361   }
    362 
    363  protected:
    364   std::string registration_id_;
    365   GCMClient::Result result_;
    366   bool has_persisted_registration_info_;
    367 
    368  private:
    369   DISALLOW_COPY_AND_ASSIGN(GCMProfileServiceRegisterTest);
    370 };
    371 
    372 TEST_F(GCMProfileServiceRegisterTest, Register) {
    373   std::vector<std::string> sender_ids;
    374   sender_ids.push_back("sender1");
    375   Register(kTestingAppId, sender_ids);
    376   std::string expected_registration_id =
    377       gcm_client_mock_->GetRegistrationIdFromSenderIds(sender_ids);
    378 
    379   WaitForCompleted();
    380   EXPECT_FALSE(registration_id_.empty());
    381   EXPECT_EQ(expected_registration_id, registration_id_);
    382   EXPECT_EQ(GCMClient::SUCCESS, result_);
    383 }
    384 
    385 TEST_F(GCMProfileServiceRegisterTest, DoubleRegister) {
    386   std::vector<std::string> sender_ids;
    387   sender_ids.push_back("sender1");
    388   Register(kTestingAppId, sender_ids);
    389   std::string expected_registration_id =
    390       gcm_client_mock_->GetRegistrationIdFromSenderIds(sender_ids);
    391 
    392   // Calling regsiter 2nd time without waiting 1st one to finish will fail
    393   // immediately.
    394   sender_ids.push_back("sender2");
    395   Register(kTestingAppId, sender_ids);
    396   EXPECT_TRUE(registration_id_.empty());
    397   EXPECT_NE(GCMClient::SUCCESS, result_);
    398 
    399   // The 1st register is still doing fine.
    400   WaitForCompleted();
    401   EXPECT_FALSE(registration_id_.empty());
    402   EXPECT_EQ(expected_registration_id, registration_id_);
    403   EXPECT_EQ(GCMClient::SUCCESS, result_);
    404 }
    405 
    406 TEST_F(GCMProfileServiceRegisterTest, RegisterError) {
    407   std::vector<std::string> sender_ids;
    408   sender_ids.push_back("sender1@error");
    409   Register(kTestingAppId, sender_ids);
    410 
    411   WaitForCompleted();
    412   EXPECT_TRUE(registration_id_.empty());
    413   EXPECT_NE(GCMClient::SUCCESS, result_);
    414 }
    415 
    416 TEST_F(GCMProfileServiceRegisterTest, RegisterAgainWithSameSenderIDs) {
    417   std::vector<std::string> sender_ids;
    418   sender_ids.push_back("sender1");
    419   sender_ids.push_back("sender2");
    420   Register(kTestingAppId, sender_ids);
    421   std::string expected_registration_id =
    422       gcm_client_mock_->GetRegistrationIdFromSenderIds(sender_ids);
    423 
    424   WaitForCompleted();
    425   EXPECT_EQ(expected_registration_id, registration_id_);
    426   EXPECT_EQ(GCMClient::SUCCESS, result_);
    427 
    428   // Clears the results the would be set by the Register callback in preparation
    429   // to call register 2nd time.
    430   registration_id_.clear();
    431   result_ = GCMClient::UNKNOWN_ERROR;
    432 
    433   // Calling register 2nd time with the same set of sender IDs but different
    434   // ordering will get back the same registration ID. There is no need to wait
    435   // since register simply returns the cached registration ID.
    436   std::vector<std::string> another_sender_ids;
    437   another_sender_ids.push_back("sender2");
    438   another_sender_ids.push_back("sender1");
    439   Register(kTestingAppId, another_sender_ids);
    440   EXPECT_EQ(expected_registration_id, registration_id_);
    441   EXPECT_EQ(GCMClient::SUCCESS, result_);
    442 }
    443 
    444 TEST_F(GCMProfileServiceRegisterTest, RegisterAgainWithDifferentSenderIDs) {
    445   std::vector<std::string> sender_ids;
    446   sender_ids.push_back("sender1");
    447   Register(kTestingAppId, sender_ids);
    448   std::string expected_registration_id =
    449       gcm_client_mock_->GetRegistrationIdFromSenderIds(sender_ids);
    450 
    451   WaitForCompleted();
    452   EXPECT_EQ(expected_registration_id, registration_id_);
    453   EXPECT_EQ(GCMClient::SUCCESS, result_);
    454 
    455   // Make sender IDs different.
    456   sender_ids.push_back("sender2");
    457   std::string expected_registration_id2 =
    458       gcm_client_mock_->GetRegistrationIdFromSenderIds(sender_ids);
    459 
    460   // Calling register 2nd time with the different sender IDs will get back a new
    461   // registration ID.
    462   Register(kTestingAppId, sender_ids);
    463   WaitForCompleted();
    464   EXPECT_EQ(expected_registration_id2, registration_id_);
    465   EXPECT_EQ(GCMClient::SUCCESS, result_);
    466 }
    467 
    468 // http://crbug.com/326321
    469 #if defined(OS_WIN)
    470 #define MAYBE_RegisterFromStateStore DISABLED_RegisterFromStateStore
    471 #else
    472 #define MAYBE_RegisterFromStateStore RegisterFromStateStore
    473 #endif
    474 TEST_F(GCMProfileServiceRegisterTest, MAYBE_RegisterFromStateStore) {
    475   scoped_refptr<Extension> extension(CreateExtension());
    476 
    477   std::vector<std::string> sender_ids;
    478   sender_ids.push_back("sender1");
    479   Register(extension->id(), sender_ids);
    480 
    481   WaitForCompleted();
    482   EXPECT_FALSE(registration_id_.empty());
    483   EXPECT_EQ(GCMClient::SUCCESS, result_);
    484   std::string old_registration_id = registration_id_;
    485 
    486   // Clears the results the would be set by the Register callback in preparation
    487   // to call register 2nd time.
    488   registration_id_.clear();
    489   result_ = GCMClient::UNKNOWN_ERROR;
    490 
    491   // Simulate start-up by recreating GCMProfileService.
    492   GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse(
    493       profile(), &GCMProfileServiceTest::BuildGCMProfileService);
    494 
    495   // Simulate start-up by reloading extension.
    496   extension_service_->UnloadExtension(extension->id(),
    497                                       UnloadedExtensionInfo::REASON_TERMINATE);
    498   extension_service_->AddExtension(extension.get());
    499 
    500   // TODO(jianli): The waiting would be removed once we support delaying running
    501   // register operation until the persistent loading completes.
    502   WaitForCompleted();
    503 
    504   // This should read the registration info from the extension's state store.
    505   // There is no need to wait since register returns the registration ID being
    506   // read.
    507   Register(extension->id(), sender_ids);
    508   EXPECT_EQ(old_registration_id, registration_id_);
    509   EXPECT_EQ(GCMClient::SUCCESS, result_);
    510 }
    511 
    512 TEST_F(GCMProfileServiceRegisterTest, Unregister) {
    513   scoped_refptr<Extension> extension(CreateExtension());
    514 
    515   std::vector<std::string> sender_ids;
    516   sender_ids.push_back("sender1");
    517   Register(extension->id(), sender_ids);
    518 
    519   WaitForCompleted();
    520   EXPECT_FALSE(registration_id_.empty());
    521   EXPECT_EQ(GCMClient::SUCCESS, result_);
    522 
    523   // The registration info should be cached.
    524   EXPECT_FALSE(GetGCMProfileService()->registration_info_map_.empty());
    525 
    526   // The registration info should be persisted.
    527   EXPECT_TRUE(HasPersistedRegistrationInfo(extension->id()));
    528 
    529   // Uninstall the extension.
    530   extension_service_->UninstallExtension(extension->id(), false, NULL);
    531   base::MessageLoop::current()->RunUntilIdle();
    532 
    533   // The cached registration info should be removed.
    534   EXPECT_TRUE(GetGCMProfileService()->registration_info_map_.empty());
    535 
    536   // The persisted registration info should be removed.
    537   EXPECT_FALSE(HasPersistedRegistrationInfo(extension->id()));
    538 }
    539 
    540 class GCMProfileServiceSendTest : public GCMProfileServiceTest {
    541  public:
    542   GCMProfileServiceSendTest() : result_(GCMClient::SUCCESS) {
    543   }
    544 
    545   virtual ~GCMProfileServiceSendTest() {
    546   }
    547 
    548   void Send(const std::string& receiver_id,
    549             const GCMClient::OutgoingMessage& message) {
    550     GetGCMProfileService()->Send(
    551         kTestingAppId,
    552         receiver_id,
    553         message,
    554         base::Bind(&GCMProfileServiceSendTest::SendCompleted,
    555                    base::Unretained(this)));
    556   }
    557 
    558   void SendCompleted(const std::string& message_id, GCMClient::Result result) {
    559     message_id_ = message_id;
    560     result_ = result;
    561     SignalCompleted();
    562   }
    563 
    564  protected:
    565   std::string message_id_;
    566   GCMClient::Result result_;
    567 
    568  private:
    569   DISALLOW_COPY_AND_ASSIGN(GCMProfileServiceSendTest);
    570 };
    571 
    572 TEST_F(GCMProfileServiceSendTest, Send) {
    573   GCMClient::OutgoingMessage message;
    574   message.id = "1";
    575   message.data["key1"] = "value1";
    576   message.data["key2"] = "value2";
    577   Send(kUserId, message);
    578 
    579   // Wait for the send callback is called.
    580   WaitForCompleted();
    581   EXPECT_EQ(message_id_, message.id);
    582   EXPECT_EQ(GCMClient::SUCCESS, result_);
    583 }
    584 
    585 TEST_F(GCMProfileServiceSendTest, SendError) {
    586   GCMClient::OutgoingMessage message;
    587   // Embedding error in id will tell the mock to simulate the send error.
    588   message.id = "1@error";
    589   message.data["key1"] = "value1";
    590   message.data["key2"] = "value2";
    591   Send(kUserId, message);
    592 
    593   // Wait for the send callback is called.
    594   WaitForCompleted();
    595   EXPECT_EQ(message_id_, message.id);
    596   EXPECT_EQ(GCMClient::SUCCESS, result_);
    597 
    598   // Wait for the send error.
    599   WaitForCompleted();
    600   EXPECT_EQ(GCMEventRouterMock::SEND_ERROR_EVENT,
    601             gcm_event_router_mock_->received_event());
    602   EXPECT_EQ(kTestingAppId, gcm_event_router_mock_->app_id());
    603   EXPECT_EQ(message_id_, gcm_event_router_mock_->send_message_id());
    604   EXPECT_NE(GCMClient::SUCCESS, gcm_event_router_mock_->send_result());
    605 }
    606 
    607 TEST_F(GCMProfileServiceTest, MessageReceived) {
    608   GCMClient::IncomingMessage message;
    609   message.data["key1"] = "value1";
    610   message.data["key2"] = "value2";
    611   gcm_client_mock_->ReceiveMessage(kTestingUsername, kTestingAppId, message);
    612   WaitForCompleted();
    613   EXPECT_EQ(GCMEventRouterMock::MESSAGE_EVENT,
    614             gcm_event_router_mock_->received_event());
    615   EXPECT_EQ(kTestingAppId, gcm_event_router_mock_->app_id());
    616   ASSERT_EQ(message.data.size(),
    617             gcm_event_router_mock_->incoming_message().data.size());
    618   EXPECT_EQ(
    619       message.data.find("key1")->second,
    620       gcm_event_router_mock_->incoming_message().data.find("key1")->second);
    621   EXPECT_EQ(
    622       message.data.find("key2")->second,
    623       gcm_event_router_mock_->incoming_message().data.find("key2")->second);
    624 }
    625 
    626 TEST_F(GCMProfileServiceTest, MessagesDeleted) {
    627   gcm_client_mock_->DeleteMessages(kTestingUsername, kTestingAppId);
    628   WaitForCompleted();
    629   EXPECT_EQ(GCMEventRouterMock::MESSAGES_DELETED_EVENT,
    630             gcm_event_router_mock_->received_event());
    631   EXPECT_EQ(kTestingAppId, gcm_event_router_mock_->app_id());
    632 }
    633 
    634 }  // namespace gcm
    635