| Index: chrome/browser/services/gcm/gcm_service_unittest.cc
|
| diff --git a/chrome/browser/services/gcm/gcm_service_unittest.cc b/chrome/browser/services/gcm/gcm_service_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b32c74055789f0195ef1af2b8015e5c8d1cdc5ea
|
| --- /dev/null
|
| +++ b/chrome/browser/services/gcm/gcm_service_unittest.cc
|
| @@ -0,0 +1,1283 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/services/gcm/gcm_service.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/files/scoped_temp_dir.h"
|
| +#include "base/location.h"
|
| +#include "base/run_loop.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "chrome/browser/services/gcm/fake_gcm_client_factory.h"
|
| +#include "chrome/browser/services/gcm/gcm_app_handler.h"
|
| +#include "chrome/browser/services/gcm/gcm_client_factory.h"
|
| +#include "chrome/browser/services/gcm/gcm_client_mock.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "content/public/test/test_browser_thread_bundle.h"
|
| +#include "google_apis/gaia/fake_identity_provider.h"
|
| +#include "net/url_request/url_request_context_getter.h"
|
| +#include "net/url_request/url_request_test_util.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace gcm {
|
| +
|
| +namespace {
|
| +
|
| +const char kTestAccountID1[] = "user1@example.com";
|
| +const char kTestAccountID2[] = "user2@example.com";
|
| +const char kTestAccountID3[] = "user3@example.com";
|
| +const char kTestAppID1[] = "TestApp1";
|
| +const char kTestAppID2[] = "TestApp2";
|
| +const char kUserID1[] = "user1";
|
| +const char kUserID2[] = "user2";
|
| +
|
| +void PumpUILoop() {
|
| + base::RunLoop().RunUntilIdle();
|
| +}
|
| +
|
| +void PumpIOLoop() {
|
| + base::RunLoop run_loop;
|
| + content::BrowserThread::PostTaskAndReply(content::BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&base::DoNothing),
|
| + run_loop.QuitClosure());
|
| + run_loop.Run();
|
| +}
|
| +
|
| +std::vector<std::string> ToSenderList(const std::string& sender_ids) {
|
| + std::vector<std::string> senders;
|
| + Tokenize(sender_ids, ",", &senders);
|
| + return senders;
|
| +}
|
| +
|
| +class FakeGCMAppHandler : public GCMAppHandler {
|
| + public:
|
| + enum Event {
|
| + NO_EVENT,
|
| + MESSAGE_EVENT,
|
| + MESSAGES_DELETED_EVENT,
|
| + SEND_ERROR_EVENT
|
| + };
|
| +
|
| + FakeGCMAppHandler();
|
| + virtual ~FakeGCMAppHandler();
|
| +
|
| + const Event& received_event() const { return received_event_; }
|
| + const std::string& app_id() const { return app_id_; }
|
| + const GCMClient::IncomingMessage& message() const { return message_; }
|
| + const GCMClient::SendErrorDetails& send_error_details() const {
|
| + return send_error_details_;
|
| + }
|
| +
|
| + void WaitForNotification();
|
| +
|
| + // GCMAppHandler:
|
| + virtual void ShutdownHandler() OVERRIDE;
|
| + virtual void OnMessage(const std::string& app_id,
|
| + const GCMClient::IncomingMessage& message) OVERRIDE;
|
| + virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
|
| + virtual void OnSendError(
|
| + const std::string& app_id,
|
| + const GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
|
| +
|
| + private:
|
| + void ClearResults();
|
| +
|
| + scoped_ptr<base::RunLoop> run_loop_;
|
| +
|
| + Event received_event_;
|
| + std::string app_id_;
|
| + GCMClient::IncomingMessage message_;
|
| + GCMClient::SendErrorDetails send_error_details_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(FakeGCMAppHandler);
|
| +};
|
| +
|
| +class TestGCMService : public GCMService {
|
| + public:
|
| + TestGCMService(
|
| + bool start_automatically,
|
| + scoped_ptr<IdentityProvider> identity_provider,
|
| + const scoped_refptr<net::URLRequestContextGetter>& request_context);
|
| + virtual ~TestGCMService();
|
| +
|
| + // GCMService:
|
| + virtual void Initialize(
|
| + scoped_ptr<GCMClientFactory> gcm_client_factory) OVERRIDE;
|
| +
|
| + protected:
|
| + // GCMService:
|
| + virtual bool StartAutomatically() const OVERRIDE;
|
| + virtual base::FilePath GetStorePath() const OVERRIDE;
|
| + virtual scoped_refptr<net::URLRequestContextGetter>
|
| + GetURLRequestContextGetter() const OVERRIDE;
|
| +
|
| + private:
|
| + base::ScopedTempDir temp_dir_;
|
| + scoped_refptr<net::URLRequestContextGetter> request_context_;
|
| + const bool start_automatically_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TestGCMService);
|
| +};
|
| +
|
| +FakeGCMAppHandler::FakeGCMAppHandler() : received_event_(NO_EVENT) {
|
| +}
|
| +
|
| +FakeGCMAppHandler::~FakeGCMAppHandler() {
|
| +}
|
| +
|
| +void FakeGCMAppHandler::WaitForNotification() {
|
| + run_loop_.reset(new base::RunLoop);
|
| + run_loop_->Run();
|
| + run_loop_.reset();
|
| +}
|
| +
|
| +void FakeGCMAppHandler::ShutdownHandler() {
|
| +}
|
| +
|
| +void FakeGCMAppHandler::OnMessage(const std::string& app_id,
|
| + const GCMClient::IncomingMessage& message) {
|
| + ClearResults();
|
| + received_event_ = MESSAGE_EVENT;
|
| + app_id_ = app_id;
|
| + message_ = message;
|
| + if (run_loop_)
|
| + run_loop_->Quit();
|
| +}
|
| +
|
| +void FakeGCMAppHandler::OnMessagesDeleted(const std::string& app_id) {
|
| + ClearResults();
|
| + received_event_ = MESSAGES_DELETED_EVENT;
|
| + app_id_ = app_id;
|
| + if (run_loop_)
|
| + run_loop_->Quit();
|
| +}
|
| +
|
| +void FakeGCMAppHandler::OnSendError(
|
| + const std::string& app_id,
|
| + const GCMClient::SendErrorDetails& send_error_details) {
|
| + ClearResults();
|
| + received_event_ = SEND_ERROR_EVENT;
|
| + app_id_ = app_id;
|
| + send_error_details_ = send_error_details;
|
| + if (run_loop_)
|
| + run_loop_->Quit();
|
| +}
|
| +
|
| +void FakeGCMAppHandler::ClearResults() {
|
| + received_event_ = NO_EVENT;
|
| + app_id_.clear();
|
| + message_ = GCMClient::IncomingMessage();
|
| + send_error_details_ = GCMClient::SendErrorDetails();
|
| +}
|
| +
|
| +TestGCMService::TestGCMService(
|
| + bool start_automatically,
|
| + scoped_ptr<IdentityProvider> identity_provider,
|
| + const scoped_refptr<net::URLRequestContextGetter>& request_context)
|
| + : GCMService(identity_provider.Pass()),
|
| + request_context_(request_context),
|
| + start_automatically_(start_automatically) {
|
| +}
|
| +
|
| +TestGCMService::~TestGCMService() {
|
| +}
|
| +
|
| +void TestGCMService::Initialize(
|
| + scoped_ptr<GCMClientFactory> gcm_client_factory) {
|
| + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
|
| + GCMService::Initialize(gcm_client_factory.Pass());
|
| +}
|
| +
|
| +bool TestGCMService::StartAutomatically() const {
|
| + return start_automatically_;
|
| +}
|
| +
|
| +base::FilePath TestGCMService::GetStorePath() const {
|
| + return temp_dir_.path();
|
| +}
|
| +
|
| +scoped_refptr<net::URLRequestContextGetter>
|
| +TestGCMService::GetURLRequestContextGetter() const {
|
| + return request_context_;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +class TestGCMServiceWrapper {
|
| + public:
|
| + explicit TestGCMServiceWrapper(
|
| + const scoped_refptr<net::URLRequestContextGetter>& request_context);
|
| + ~TestGCMServiceWrapper();
|
| +
|
| + TestGCMService* service() { return service_.get(); }
|
| + FakeGCMAppHandler* gcm_app_handler() { return gcm_app_handler_.get(); }
|
| + const std::string& registration_id() const { return registration_id_; }
|
| + GCMClient::Result registration_result() const { return registration_result_; }
|
| + const std::string& send_message_id() const { return send_message_id_; }
|
| + GCMClient::Result send_result() const { return send_result_; }
|
| + GCMClient::Result unregistration_result() const {
|
| + return unregistration_result_;
|
| + }
|
| +
|
| + void ClearRegistrationResult();
|
| + void ClearUnregistrationResult();
|
| +
|
| + bool ServiceHasAppHandlers() const;
|
| + GCMClientMock* GetGCMClient();
|
| +
|
| + void CreateService(bool start_automatically,
|
| + GCMClientMock::LoadingDelay gcm_client_loading_delay);
|
| +
|
| + void SignIn(const std::string& account_id);
|
| + void SignOut();
|
| +
|
| + void Register(const std::string& app_id,
|
| + const std::vector<std::string>& sender_ids,
|
| + bool wait);
|
| + void Send(const std::string& app_id,
|
| + const std::string& receiver_id,
|
| + const GCMClient::OutgoingMessage& message,
|
| + bool wait);
|
| + void Unregister(const std::string& app_id, bool wait);
|
| +
|
| + private:
|
| + scoped_refptr<net::URLRequestContextGetter> request_context_;
|
| + scoped_ptr<FakeIdentityProvider> identity_provider_owner_;
|
| + FakeIdentityProvider* identity_provider_;
|
| + scoped_ptr<TestGCMService> service_;
|
| + scoped_ptr<FakeGCMAppHandler> gcm_app_handler_;
|
| +
|
| + std::string registration_id_;
|
| + GCMClient::Result registration_result_;
|
| + std::string send_message_id_;
|
| + GCMClient::Result send_result_;
|
| + GCMClient::Result unregistration_result_;
|
| +
|
| + void RegisterCompleted(const base::Closure& callback,
|
| + const std::string& registration_id,
|
| + GCMClient::Result result);
|
| + void SendCompleted(const base::Closure& callback,
|
| + const std::string& message_id,
|
| + GCMClient::Result result);
|
| + void UnregisterCompleted(const base::Closure& callback,
|
| + GCMClient::Result result);
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TestGCMServiceWrapper);
|
| +};
|
| +
|
| +TestGCMServiceWrapper::TestGCMServiceWrapper(
|
| + const scoped_refptr<net::URLRequestContextGetter>& request_context)
|
| + : request_context_(request_context),
|
| + identity_provider_(NULL),
|
| + registration_result_(GCMClient::UNKNOWN_ERROR),
|
| + send_result_(GCMClient::UNKNOWN_ERROR),
|
| + unregistration_result_(GCMClient::UNKNOWN_ERROR) {
|
| + identity_provider_owner_.reset(new FakeIdentityProvider(NULL));
|
| + identity_provider_ = identity_provider_owner_.get();
|
| +}
|
| +
|
| +TestGCMServiceWrapper::~TestGCMServiceWrapper() {
|
| + if (!service_)
|
| + return;
|
| +
|
| + service_->Shutdown();
|
| + service_.reset();
|
| + PumpIOLoop();
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::ClearRegistrationResult() {
|
| + registration_id_.clear();
|
| + registration_result_ = GCMClient::UNKNOWN_ERROR;
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::ClearUnregistrationResult() {
|
| + unregistration_result_ = GCMClient::UNKNOWN_ERROR;
|
| +}
|
| +
|
| +bool TestGCMServiceWrapper::ServiceHasAppHandlers() const {
|
| + return !service_->app_handlers_.empty();
|
| +}
|
| +
|
| +GCMClientMock* TestGCMServiceWrapper::GetGCMClient() {
|
| + return static_cast<GCMClientMock*>(service_->GetGCMClientForTesting());
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::CreateService(
|
| + bool start_automatically,
|
| + GCMClientMock::LoadingDelay gcm_client_loading_delay) {
|
| + service_.reset(new TestGCMService(
|
| + start_automatically,
|
| + identity_provider_owner_.PassAs<IdentityProvider>(),
|
| + request_context_));
|
| + service_->Initialize(scoped_ptr<GCMClientFactory>(
|
| + new FakeGCMClientFactory(gcm_client_loading_delay)));
|
| +
|
| + gcm_app_handler_.reset(new FakeGCMAppHandler);
|
| + service_->AddAppHandler(kTestAppID1, gcm_app_handler_.get());
|
| + service_->AddAppHandler(kTestAppID2, gcm_app_handler_.get());
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::SignIn(const std::string& account_id) {
|
| + identity_provider_->LogIn(account_id);
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::SignOut() {
|
| + identity_provider_->LogOut();
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::Register(const std::string& app_id,
|
| + const std::vector<std::string>& sender_ids,
|
| + bool wait) {
|
| + base::RunLoop run_loop;
|
| + service_->Register(
|
| + app_id,
|
| + sender_ids,
|
| + base::Bind(&TestGCMServiceWrapper::RegisterCompleted,
|
| + base::Unretained(this),
|
| + wait ? run_loop.QuitClosure() : base::Bind(&base::DoNothing)));
|
| + if (wait)
|
| + run_loop.Run();
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::Send(const std::string& app_id,
|
| + const std::string& receiver_id,
|
| + const GCMClient::OutgoingMessage& message,
|
| + bool wait) {
|
| + base::RunLoop run_loop;
|
| + service_->Send(
|
| + app_id,
|
| + receiver_id,
|
| + message,
|
| + base::Bind(&TestGCMServiceWrapper::SendCompleted,
|
| + base::Unretained(this),
|
| + wait ? run_loop.QuitClosure() : base::Bind(&base::DoNothing)));
|
| + if (wait)
|
| + run_loop.Run();
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::Unregister(const std::string& app_id, bool wait) {
|
| + base::RunLoop run_loop;
|
| + service_->Unregister(
|
| + app_id,
|
| + base::Bind(&TestGCMServiceWrapper::UnregisterCompleted,
|
| + base::Unretained(this),
|
| + wait ? run_loop.QuitClosure() : base::Bind(&base::DoNothing)));
|
| + if (wait)
|
| + run_loop.Run();
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::RegisterCompleted(
|
| + const base::Closure& callback,
|
| + const std::string& registration_id,
|
| + GCMClient::Result result) {
|
| + registration_id_ = registration_id;
|
| + registration_result_ = result;
|
| + callback.Run();
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::SendCompleted(const base::Closure& callback,
|
| + const std::string& message_id,
|
| + GCMClient::Result result) {
|
| + send_message_id_ = message_id;
|
| + send_result_ = result;
|
| + callback.Run();
|
| +}
|
| +
|
| +void TestGCMServiceWrapper::UnregisterCompleted(const base::Closure& callback,
|
| + GCMClient::Result result) {
|
| + unregistration_result_ = result;
|
| + callback.Run();
|
| +}
|
| +
|
| +class GCMServiceTest : public testing::Test {
|
| + protected:
|
| + GCMServiceTest();
|
| + virtual ~GCMServiceTest();
|
| +
|
| + // testing::Test:
|
| + void SetUp() OVERRIDE;
|
| + void TearDown() OVERRIDE;
|
| +
|
| + scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_;
|
| + scoped_refptr<net::URLRequestContextGetter> request_context_;
|
| + scoped_ptr<TestGCMServiceWrapper> wrapper_;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(GCMServiceTest);
|
| +};
|
| +
|
| +GCMServiceTest::GCMServiceTest() {
|
| +}
|
| +
|
| +GCMServiceTest::~GCMServiceTest() {
|
| +}
|
| +
|
| +void GCMServiceTest::SetUp() {
|
| + thread_bundle_.reset(new content::TestBrowserThreadBundle(
|
| + content::TestBrowserThreadBundle::REAL_IO_THREAD));
|
| + request_context_ = new net::TestURLRequestContextGetter(
|
| + content::BrowserThread::GetMessageLoopProxyForThread(
|
| + content::BrowserThread::IO));
|
| + wrapper_.reset(new TestGCMServiceWrapper(request_context_));
|
| +}
|
| +
|
| +void GCMServiceTest::TearDown() {
|
| + wrapper_.reset();
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, CreateGCMServiceBeforeSignIn) {
|
| + // Create CreateGMCService first.
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| + EXPECT_FALSE(wrapper_->service()->IsStarted());
|
| +
|
| + // Sign in. This will kick off the check-in.
|
| + wrapper_->SignIn(kTestAccountID1);
|
| + EXPECT_TRUE(wrapper_->service()->IsStarted());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, CreateGCMServiceAfterSignIn) {
|
| + // Sign in. This will not initiate the check-in.
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +
|
| + // Create GCMeService after sign-in.
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| + EXPECT_TRUE(wrapper_->service()->IsStarted());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, Shutdown) {
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| + EXPECT_TRUE(wrapper_->ServiceHasAppHandlers());
|
| +
|
| + wrapper_->service()->Shutdown();
|
| + EXPECT_FALSE(wrapper_->ServiceHasAppHandlers());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, SignInAndSignOutUnderPositiveChannelSignal) {
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +
|
| + // GCMClient should be loaded.
|
| + EXPECT_TRUE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::LOADED, wrapper_->GetGCMClient()->status());
|
| +
|
| + wrapper_->SignOut();
|
| +
|
| + // GCMClient should be checked out.
|
| + EXPECT_FALSE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::CHECKED_OUT, wrapper_->GetGCMClient()->status());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, SignInAndSignOutUnderNonPositiveChannelSignal) {
|
| + // Non-positive channel signal will prevent GCMClient from checking in during
|
| + // sign-in.
|
| + wrapper_->CreateService(false, GCMClientMock::NO_DELAY_LOADING);
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +
|
| + // GCMClient should not be loaded.
|
| + EXPECT_FALSE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::UNINITIALIZED, wrapper_->GetGCMClient()->status());
|
| +
|
| + wrapper_->SignOut();
|
| +
|
| + // Check-out should still be performed.
|
| + EXPECT_FALSE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::CHECKED_OUT, wrapper_->GetGCMClient()->status());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, SignOutAndThenSignIn) {
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +
|
| + // GCMClient should be loaded.
|
| + EXPECT_TRUE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::LOADED, wrapper_->GetGCMClient()->status());
|
| +
|
| + wrapper_->SignOut();
|
| +
|
| + // GCMClient should be checked out.
|
| + EXPECT_FALSE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::CHECKED_OUT, wrapper_->GetGCMClient()->status());
|
| +
|
| + // Sign-in with a different account.
|
| + wrapper_->SignIn(kTestAccountID2);
|
| +
|
| + // GCMClient should be loaded again.
|
| + EXPECT_TRUE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::LOADED, wrapper_->GetGCMClient()->status());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, StopAndRestartGCM) {
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +
|
| + // GCMClient should be loaded.
|
| + EXPECT_TRUE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::LOADED, wrapper_->GetGCMClient()->status());
|
| +
|
| + // Stops the GCM.
|
| + wrapper_->service()->Stop();
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| +
|
| + // GCMClient should be stopped.
|
| + EXPECT_FALSE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::STOPPED, wrapper_->GetGCMClient()->status());
|
| +
|
| + // Restarts the GCM.
|
| + wrapper_->service()->Start();
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| +
|
| + // GCMClient should be loaded.
|
| + EXPECT_TRUE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::LOADED, wrapper_->GetGCMClient()->status());
|
| +
|
| + // Stops the GCM.
|
| + wrapper_->service()->Stop();
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| +
|
| + // GCMClient should be stopped.
|
| + EXPECT_FALSE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::STOPPED, wrapper_->GetGCMClient()->status());
|
| +
|
| + // Sign out.
|
| + wrapper_->SignOut();
|
| +
|
| + // GCMClient should be checked out.
|
| + EXPECT_FALSE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::CHECKED_OUT, wrapper_->GetGCMClient()->status());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, RegisterWhenNotSignedIn) {
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| +
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| +
|
| + EXPECT_TRUE(wrapper_->registration_id().empty());
|
| + EXPECT_EQ(GCMClient::NOT_SIGNED_IN, wrapper_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, RegisterUnderNonPositiveChannelSignal) {
|
| + // Non-positive channel signal will prevent GCMClient from checking in during
|
| + // sign-in.
|
| + wrapper_->CreateService(false, GCMClientMock::NO_DELAY_LOADING);
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +
|
| + // GCMClient should not be checked in.
|
| + EXPECT_FALSE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::UNINITIALIZED, wrapper_->GetGCMClient()->status());
|
| +
|
| + // Invoking register will make GCMClient checked in.
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| +
|
| + // GCMClient should be checked in.
|
| + EXPECT_TRUE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::LOADED, wrapper_->GetGCMClient()->status());
|
| +
|
| + // Registration should succeed.
|
| + const std::string expected_registration_id =
|
| + GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids);
|
| + EXPECT_EQ(expected_registration_id, wrapper_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, SendWhenNotSignedIn) {
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| +
|
| + GCMClient::OutgoingMessage message;
|
| + message.id = "1";
|
| + message.data["key1"] = "value1";
|
| + wrapper_->Send(kTestAppID1, kUserID1, message, true);
|
| +
|
| + EXPECT_TRUE(wrapper_->send_message_id().empty());
|
| + EXPECT_EQ(GCMClient::NOT_SIGNED_IN, wrapper_->send_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceTest, SendUnderNonPositiveChannelSignal) {
|
| + // Non-positive channel signal will prevent GCMClient from checking in during
|
| + // sign-in.
|
| + wrapper_->CreateService(false, GCMClientMock::NO_DELAY_LOADING);
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +
|
| + // GCMClient should not be checked in.
|
| + EXPECT_FALSE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::UNINITIALIZED, wrapper_->GetGCMClient()->status());
|
| +
|
| + // Invoking send will make GCMClient checked in.
|
| + GCMClient::OutgoingMessage message;
|
| + message.id = "1";
|
| + message.data["key1"] = "value1";
|
| + wrapper_->Send(kTestAppID1, kUserID1, message, true);
|
| +
|
| + // GCMClient should be checked in.
|
| + EXPECT_TRUE(wrapper_->service()->IsGCMClientReady());
|
| + EXPECT_EQ(GCMClientMock::LOADED, wrapper_->GetGCMClient()->status());
|
| +
|
| + // Sending should succeed.
|
| + EXPECT_EQ(message.id, wrapper_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->send_result());
|
| +}
|
| +
|
| +// Tests a single instance of GCMService.
|
| +class GCMServiceSingleInstanceTest : public GCMServiceTest {
|
| + public:
|
| + GCMServiceSingleInstanceTest();
|
| + virtual ~GCMServiceSingleInstanceTest();
|
| +
|
| + // GCMServiceTest:
|
| + virtual void SetUp() OVERRIDE;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(GCMServiceSingleInstanceTest);
|
| +};
|
| +
|
| +GCMServiceSingleInstanceTest::GCMServiceSingleInstanceTest() {
|
| +}
|
| +
|
| +GCMServiceSingleInstanceTest::~GCMServiceSingleInstanceTest() {
|
| +}
|
| +
|
| +void GCMServiceSingleInstanceTest::SetUp() {
|
| + GCMServiceTest::SetUp();
|
| +
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, Register) {
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| + const std::string expected_registration_id =
|
| + GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids);
|
| +
|
| + EXPECT_EQ(expected_registration_id, wrapper_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, RegisterError) {
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1@error");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| +
|
| + EXPECT_TRUE(wrapper_->registration_id().empty());
|
| + EXPECT_NE(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, RegisterAgainWithSameSenderIDs) {
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + sender_ids.push_back("sender2");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| + const std::string expected_registration_id =
|
| + GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids);
|
| +
|
| + EXPECT_EQ(expected_registration_id, wrapper_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +
|
| + // Clears the results the would be set by the Register callback in preparation
|
| + // to call register 2nd time.
|
| + wrapper_->ClearRegistrationResult();
|
| +
|
| + // Calling register 2nd time with the same set of sender IDs but different
|
| + // ordering will get back the same registration ID.
|
| + std::vector<std::string> another_sender_ids;
|
| + another_sender_ids.push_back("sender2");
|
| + another_sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, another_sender_ids, true);
|
| +
|
| + EXPECT_EQ(expected_registration_id, wrapper_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, RegisterAgainWithDifferentSenderIDs) {
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| + const std::string expected_registration_id =
|
| + GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids);
|
| +
|
| + EXPECT_EQ(expected_registration_id, wrapper_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +
|
| + // Make sender IDs different.
|
| + sender_ids.push_back("sender2");
|
| + const std::string expected_registration_id2 =
|
| + GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids);
|
| +
|
| + // Calling register 2nd time with the different sender IDs will get back a new
|
| + // registration ID.
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| + EXPECT_EQ(expected_registration_id2, wrapper_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, GCMClientNotReadyBeforeRegistration) {
|
| + // Make GCMClient not ready initially.
|
| + wrapper_.reset(new TestGCMServiceWrapper(request_context_));
|
| + wrapper_->CreateService(true, GCMClientMock::DELAY_LOADING);
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +
|
| + // The registration is on hold until GCMClient is ready.
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, sender_ids, false);
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| + EXPECT_TRUE(wrapper_->registration_id().empty());
|
| + EXPECT_EQ(GCMClient::UNKNOWN_ERROR, wrapper_->registration_result());
|
| +
|
| + // Register operation will be invoked after GCMClient becomes ready.
|
| + wrapper_->GetGCMClient()->PerformDelayedLoading();
|
| + PumpIOLoop();
|
| + PumpIOLoop();
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| + EXPECT_FALSE(wrapper_->registration_id().empty());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, RegisterAfterSignOut) {
|
| + // This will trigger check-out.
|
| + wrapper_->SignOut();
|
| +
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| +
|
| + EXPECT_TRUE(wrapper_->registration_id().empty());
|
| + EXPECT_EQ(GCMClient::NOT_SIGNED_IN, wrapper_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, UnregisterExplicitly) {
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| +
|
| + EXPECT_FALSE(wrapper_->registration_id().empty());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +
|
| + wrapper_->Unregister(kTestAppID1, true);
|
| +
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->unregistration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, UnregisterWhenAsyncOperationPending) {
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + // First start registration without waiting for it to complete.
|
| + wrapper_->Register(kTestAppID1, sender_ids, false);
|
| +
|
| + // Test that unregistration fails with async operation pending when there is a
|
| + // registration already in progress.
|
| + wrapper_->Unregister(kTestAppID1, true);
|
| + EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
|
| + wrapper_->unregistration_result());
|
| +
|
| + // Complete the unregistration.
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +
|
| + // Start unregistration without waiting for it to complete. This time no async
|
| + // operation is pending.
|
| + wrapper_->Unregister(kTestAppID1, false);
|
| +
|
| + // Test that unregistration fails with async operation pending when there is
|
| + // an unregistration already in progress.
|
| + wrapper_->Unregister(kTestAppID1, true);
|
| + EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
|
| + wrapper_->unregistration_result());
|
| + wrapper_->ClearUnregistrationResult();
|
| +
|
| + // Complete unregistration.
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->unregistration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, RegisterWhenAsyncOperationPending) {
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + // First start registration without waiting for it to complete.
|
| + wrapper_->Register(kTestAppID1, sender_ids, false);
|
| +
|
| + // Test that registration fails with async operation pending when there is a
|
| + // registration already in progress.
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| + EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
|
| + wrapper_->registration_result());
|
| + wrapper_->ClearRegistrationResult();
|
| +
|
| + // Complete the registration.
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +
|
| + // Start unregistration without waiting for it to complete. This time no async
|
| + // operation is pending.
|
| + wrapper_->Unregister(kTestAppID1, false);
|
| +
|
| + // Test that registration fails with async operation pending when there is an
|
| + // unregistration already in progress.
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| + EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
|
| + wrapper_->registration_result());
|
| +
|
| + // Complete the first unregistration expecting success.
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->unregistration_result());
|
| +
|
| + // Test that it is ok to register again after unregistration.
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, Send) {
|
| + GCMClient::OutgoingMessage message;
|
| + message.id = "1";
|
| + message.data["key1"] = "value1";
|
| + message.data["key2"] = "value2";
|
| + wrapper_->Send(kTestAppID1, kUserID1, message, true);
|
| +
|
| + EXPECT_EQ(message.id, wrapper_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->send_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, GCMClientNotReadyBeforeSending) {
|
| + // Make GCMClient not ready initially.
|
| + wrapper_.reset(new TestGCMServiceWrapper(request_context_));
|
| + wrapper_->CreateService(true, GCMClientMock::DELAY_LOADING);
|
| + wrapper_->SignIn(kTestAccountID1);
|
| +
|
| + // The sending is on hold until GCMClient is ready.
|
| + GCMClient::OutgoingMessage message;
|
| + message.id = "1";
|
| + message.data["key1"] = "value1";
|
| + message.data["key2"] = "value2";
|
| + wrapper_->Send(kTestAppID1, kUserID1, message, false);
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| +
|
| + EXPECT_TRUE(wrapper_->send_message_id().empty());
|
| + EXPECT_EQ(GCMClient::UNKNOWN_ERROR, wrapper_->send_result());
|
| +
|
| + // Send operation will be invoked after GCMClient becomes ready.
|
| + wrapper_->GetGCMClient()->PerformDelayedLoading();
|
| + PumpIOLoop();
|
| + PumpIOLoop();
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| + EXPECT_EQ(message.id, wrapper_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->send_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, SendAfterSignOut) {
|
| + // This will trigger check-out.
|
| + wrapper_->SignOut();
|
| +
|
| + GCMClient::OutgoingMessage message;
|
| + message.id = "1";
|
| + message.data["key1"] = "value1";
|
| + message.data["key2"] = "value2";
|
| + wrapper_->Send(kTestAppID1, kUserID1, message, true);
|
| +
|
| + EXPECT_TRUE(wrapper_->send_message_id().empty());
|
| + EXPECT_EQ(GCMClient::NOT_SIGNED_IN, wrapper_->send_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, SendError) {
|
| + GCMClient::OutgoingMessage message;
|
| + // Embedding error in id will tell the mock to simulate the send error.
|
| + message.id = "1@error";
|
| + message.data["key1"] = "value1";
|
| + message.data["key2"] = "value2";
|
| + wrapper_->Send(kTestAppID1, kUserID1, message, true);
|
| +
|
| + EXPECT_EQ(message.id, wrapper_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->send_result());
|
| +
|
| + // Wait for the send error.
|
| + wrapper_->gcm_app_handler()->WaitForNotification();
|
| + EXPECT_EQ(FakeGCMAppHandler::SEND_ERROR_EVENT,
|
| + wrapper_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID1, wrapper_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(message.id,
|
| + wrapper_->gcm_app_handler()->send_error_details().message_id);
|
| + EXPECT_NE(GCMClient::SUCCESS,
|
| + wrapper_->gcm_app_handler()->send_error_details().result);
|
| + EXPECT_EQ(message.data,
|
| + wrapper_->gcm_app_handler()->send_error_details().additional_data);
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, MessageReceived) {
|
| + wrapper_->Register(kTestAppID1, ToSenderList("sender"), true);
|
| + GCMClient::IncomingMessage message;
|
| + message.data["key1"] = "value1";
|
| + message.data["key2"] = "value2";
|
| + message.sender_id = "sender";
|
| + wrapper_->GetGCMClient()->ReceiveMessage(kTestAppID1, message);
|
| + wrapper_->gcm_app_handler()->WaitForNotification();
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
|
| + wrapper_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID1, wrapper_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(message.data, wrapper_->gcm_app_handler()->message().data);
|
| + EXPECT_TRUE(wrapper_->gcm_app_handler()->message().collapse_key.empty());
|
| + EXPECT_EQ(message.sender_id,
|
| + wrapper_->gcm_app_handler()->message().sender_id);
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, MessageWithCollapseKeyReceived) {
|
| + wrapper_->Register(kTestAppID1, ToSenderList("sender"), true);
|
| + GCMClient::IncomingMessage message;
|
| + message.data["key1"] = "value1";
|
| + message.collapse_key = "collapse_key_value";
|
| + message.sender_id = "sender";
|
| + wrapper_->GetGCMClient()->ReceiveMessage(kTestAppID1, message);
|
| + wrapper_->gcm_app_handler()->WaitForNotification();
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
|
| + wrapper_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID1, wrapper_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(message.data, wrapper_->gcm_app_handler()->message().data);
|
| + EXPECT_EQ(message.collapse_key,
|
| + wrapper_->gcm_app_handler()->message().collapse_key);
|
| +}
|
| +
|
| +TEST_F(GCMServiceSingleInstanceTest, MessagesDeleted) {
|
| + wrapper_->GetGCMClient()->DeleteMessages(kTestAppID1);
|
| + wrapper_->gcm_app_handler()->WaitForNotification();
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGES_DELETED_EVENT,
|
| + wrapper_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID1, wrapper_->gcm_app_handler()->app_id());
|
| +}
|
| +
|
| +// Tests to make sure that concurrent GCMService instances work correctly
|
| +// regardless how GCMClient is created.
|
| +class GCMServiceMultipleInstanceTest : public GCMServiceTest {
|
| + protected:
|
| + GCMServiceMultipleInstanceTest();
|
| + virtual ~GCMServiceMultipleInstanceTest();
|
| +
|
| + // GCMServiceTest:
|
| + virtual void SetUp() OVERRIDE;
|
| + virtual void TearDown() OVERRIDE;
|
| +
|
| + scoped_ptr<TestGCMServiceWrapper> wrapper2_;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(GCMServiceMultipleInstanceTest);
|
| +};
|
| +
|
| +GCMServiceMultipleInstanceTest::GCMServiceMultipleInstanceTest() {
|
| +}
|
| +
|
| +GCMServiceMultipleInstanceTest::~GCMServiceMultipleInstanceTest() {
|
| +}
|
| +
|
| +void GCMServiceMultipleInstanceTest::SetUp() {
|
| + GCMServiceTest::SetUp();
|
| +
|
| + wrapper2_.reset(new TestGCMServiceWrapper(request_context_));
|
| +
|
| + wrapper_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| + wrapper2_->CreateService(true, GCMClientMock::NO_DELAY_LOADING);
|
| +
|
| + // Initiate check-in for each instance.
|
| + wrapper_->SignIn(kTestAccountID1);
|
| + wrapper2_->SignIn(kTestAccountID2);
|
| +}
|
| +
|
| +void GCMServiceMultipleInstanceTest::TearDown() {
|
| + wrapper2_.reset();
|
| +}
|
| +
|
| +TEST_F(GCMServiceMultipleInstanceTest, Register) {
|
| + // Register an app.
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| +
|
| + // Register the same app in a different instance.
|
| + std::vector<std::string> sender_ids2;
|
| + sender_ids2.push_back("foo");
|
| + sender_ids2.push_back("bar");
|
| + wrapper2_->Register(kTestAppID1, sender_ids2, true);
|
| +
|
| + EXPECT_EQ(GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids),
|
| + wrapper_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +
|
| + EXPECT_EQ(GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids2),
|
| + wrapper2_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper2_->registration_result());
|
| +
|
| + // Register a different app in a different instance.
|
| + std::vector<std::string> sender_ids3;
|
| + sender_ids3.push_back("sender1");
|
| + sender_ids3.push_back("sender2");
|
| + sender_ids3.push_back("sender3");
|
| + wrapper2_->Register(kTestAppID2, sender_ids3, true);
|
| +
|
| + EXPECT_EQ(GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids3),
|
| + wrapper2_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper2_->registration_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceMultipleInstanceTest, Send) {
|
| + // Send a message from one app in one instance.
|
| + GCMClient::OutgoingMessage message;
|
| + message.id = "1";
|
| + message.data["key1"] = "value1";
|
| + message.data["key2"] = "value2";
|
| + wrapper_->Send(kTestAppID1, kUserID1, message, true);
|
| +
|
| + // Send a message from same app in another instance.
|
| + GCMClient::OutgoingMessage message2;
|
| + message2.id = "2";
|
| + message2.data["foo"] = "bar";
|
| + wrapper2_->Send(kTestAppID1, kUserID2, message2, true);
|
| +
|
| + EXPECT_EQ(message.id, wrapper_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->send_result());
|
| +
|
| + EXPECT_EQ(message2.id, wrapper2_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper2_->send_result());
|
| +
|
| + // Send another message from different app in another instance.
|
| + GCMClient::OutgoingMessage message3;
|
| + message3.id = "3";
|
| + message3.data["hello"] = "world";
|
| + wrapper2_->Send(kTestAppID2, kUserID1, message3, true);
|
| +
|
| + EXPECT_EQ(message3.id, wrapper2_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper2_->send_result());
|
| +}
|
| +
|
| +TEST_F(GCMServiceMultipleInstanceTest, MessageReceived) {
|
| + wrapper_->Register(kTestAppID1, ToSenderList("sender"), true);
|
| + wrapper2_->Register(kTestAppID1, ToSenderList("sender"), true);
|
| + wrapper2_->Register(kTestAppID2, ToSenderList("sender2"), true);
|
| +
|
| + // Trigger an incoming message for an app in one instance.
|
| + GCMClient::IncomingMessage message;
|
| + message.data["key1"] = "value1";
|
| + message.data["key2"] = "value2";
|
| + message.sender_id = "sender";
|
| + wrapper_->GetGCMClient()->ReceiveMessage(kTestAppID1, message);
|
| + wrapper_->gcm_app_handler()->WaitForNotification();
|
| +
|
| + // Trigger an incoming message for the same app in another instance.
|
| + GCMClient::IncomingMessage message2;
|
| + message2.data["foo"] = "bar";
|
| + message2.sender_id = "sender";
|
| + wrapper2_->GetGCMClient()->ReceiveMessage(kTestAppID1, message2);
|
| + wrapper2_->gcm_app_handler()->WaitForNotification();
|
| +
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
|
| + wrapper_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID1, wrapper_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(message.data, wrapper_->gcm_app_handler()->message().data);
|
| + EXPECT_EQ("sender", wrapper_->gcm_app_handler()->message().sender_id);
|
| +
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
|
| + wrapper2_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID1, wrapper2_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(message2.data, wrapper2_->gcm_app_handler()->message().data);
|
| + EXPECT_EQ("sender", wrapper2_->gcm_app_handler()->message().sender_id);
|
| +
|
| + // Trigger another incoming message for a different app in another instance.
|
| + GCMClient::IncomingMessage message3;
|
| + message3.data["bar1"] = "foo1";
|
| + message3.data["bar2"] = "foo2";
|
| + message3.sender_id = "sender2";
|
| + wrapper2_->GetGCMClient()->ReceiveMessage(kTestAppID2, message3);
|
| + wrapper2_->gcm_app_handler()->WaitForNotification();
|
| +
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
|
| + wrapper2_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID2, wrapper2_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(message3.data, wrapper2_->gcm_app_handler()->message().data);
|
| + EXPECT_EQ("sender2", wrapper2_->gcm_app_handler()->message().sender_id);
|
| +}
|
| +
|
| +// Test a set of GCM operations on multiple instances.
|
| +// 1) Register 1 app in instance 1 and register 2 apps in instance 2;
|
| +// 2) Send a message from instance 1;
|
| +// 3) Receive a message to an app in instance 1 and receive a message for each
|
| +// of the two apps in instance 2;
|
| +// 4) Send a message for each of the two apps in instance 2;
|
| +// 5) Sign out of instance 1.
|
| +// 6) Register/send stops working for instance 1;
|
| +// 7) The app in instance 2 can still receive these events;
|
| +// 8) Sign into instance 1 with a different account.
|
| +// 9) The message to the newly signed-in account will be routed.
|
| +TEST_F(GCMServiceMultipleInstanceTest, Combined) {
|
| + // Register an app.
|
| + std::vector<std::string> sender_ids;
|
| + sender_ids.push_back("sender1");
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| +
|
| + // Register the same app in a different instance.
|
| + std::vector<std::string> sender_ids2;
|
| + sender_ids2.push_back("foo");
|
| + sender_ids2.push_back("bar");
|
| + wrapper2_->Register(kTestAppID1, sender_ids2, true);
|
| +
|
| + // Register a different app in a different instance.
|
| + std::vector<std::string> sender_ids3;
|
| + sender_ids3.push_back("sender1");
|
| + sender_ids3.push_back("sender2");
|
| + sender_ids3.push_back("sender3");
|
| + wrapper2_->Register(kTestAppID2, sender_ids3, true);
|
| +
|
| + EXPECT_EQ(GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids),
|
| + wrapper_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->registration_result());
|
| +
|
| + EXPECT_EQ(GCMClientMock::GetRegistrationIdFromSenderIds(sender_ids3),
|
| + wrapper2_->registration_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper2_->registration_result());
|
| +
|
| + // Send a message from one instance.
|
| + GCMClient::OutgoingMessage out_message;
|
| + out_message.id = "1";
|
| + out_message.data["out1"] = "out_data1";
|
| + out_message.data["out1_2"] = "out_data1_2";
|
| + wrapper_->Send(kTestAppID1, kUserID1, out_message, true);
|
| +
|
| + EXPECT_EQ(out_message.id, wrapper_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper_->send_result());
|
| +
|
| + // Trigger an incoming message for an app in one instance.
|
| + GCMClient::IncomingMessage in_message;
|
| + in_message.data["in1"] = "in_data1";
|
| + in_message.data["in1_2"] = "in_data1_2";
|
| + in_message.sender_id = "sender1";
|
| + wrapper_->GetGCMClient()->ReceiveMessage(kTestAppID1, in_message);
|
| + wrapper_->gcm_app_handler()->WaitForNotification();
|
| +
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
|
| + wrapper_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID1, wrapper_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(in_message.data, wrapper_->gcm_app_handler()->message().data);
|
| +
|
| + // Trigger 2 incoming messages, one for each app respectively, in another
|
| + // instance.
|
| + GCMClient::IncomingMessage in_message2;
|
| + in_message2.data["in2"] = "in_data2";
|
| + in_message2.sender_id = "sender3";
|
| + wrapper2_->GetGCMClient()->ReceiveMessage(kTestAppID2, in_message2);
|
| +
|
| + GCMClient::IncomingMessage in_message3;
|
| + in_message3.data["in3"] = "in_data3";
|
| + in_message3.data["in3_2"] = "in_data3_2";
|
| + in_message3.sender_id = "foo";
|
| + wrapper2_->GetGCMClient()->ReceiveMessage(kTestAppID1, in_message3);
|
| +
|
| + wrapper2_->gcm_app_handler()->WaitForNotification();
|
| +
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
|
| + wrapper2_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID2, wrapper2_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(in_message2.data, wrapper2_->gcm_app_handler()->message().data);
|
| +
|
| + wrapper2_->gcm_app_handler()->WaitForNotification();
|
| +
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
|
| + wrapper2_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID1, wrapper2_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(in_message3.data, wrapper2_->gcm_app_handler()->message().data);
|
| +
|
| + // Send two messages, one for each app respectively, from another instance.
|
| + GCMClient::OutgoingMessage out_message2;
|
| + out_message2.id = "2";
|
| + out_message2.data["out2"] = "out_data2";
|
| + wrapper2_->Send(kTestAppID1, kUserID2, out_message2, true);
|
| +
|
| + GCMClient::OutgoingMessage out_message3;
|
| + out_message3.id = "3";
|
| + out_message3.data["out3"] = "out_data3";
|
| + wrapper2_->Send(kTestAppID2, kUserID2, out_message3, false);
|
| +
|
| + EXPECT_EQ(out_message2.id, wrapper2_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper2_->send_result());
|
| +
|
| + PumpIOLoop();
|
| + PumpUILoop();
|
| +
|
| + EXPECT_EQ(out_message3.id, wrapper2_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper2_->send_result());
|
| +
|
| + // Sign out of one instance.
|
| + wrapper_->SignOut();
|
| +
|
| + // Register/send stops working for signed-out instance.
|
| + wrapper_->Register(kTestAppID1, sender_ids, true);
|
| + EXPECT_TRUE(wrapper_->registration_id().empty());
|
| + EXPECT_EQ(GCMClient::NOT_SIGNED_IN, wrapper_->registration_result());
|
| +
|
| + wrapper_->Send(kTestAppID2, kUserID2, out_message3, true);
|
| + EXPECT_TRUE(wrapper_->send_message_id().empty());
|
| + EXPECT_EQ(GCMClient::NOT_SIGNED_IN, wrapper_->send_result());
|
| +
|
| + // Deleted messages event will go through for another signed-in instance.
|
| + wrapper2_->GetGCMClient()->DeleteMessages(kTestAppID2);
|
| + wrapper2_->gcm_app_handler()->WaitForNotification();
|
| +
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGES_DELETED_EVENT,
|
| + wrapper2_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID2, wrapper2_->gcm_app_handler()->app_id());
|
| +
|
| + // Send error event will go through for another signed-in instance.
|
| + GCMClient::OutgoingMessage out_message4;
|
| + out_message4.id = "1@error";
|
| + out_message4.data["out4"] = "out_data4";
|
| + wrapper2_->Send(kTestAppID1, kUserID1, out_message4, true);
|
| +
|
| + EXPECT_EQ(out_message4.id, wrapper2_->send_message_id());
|
| + EXPECT_EQ(GCMClient::SUCCESS, wrapper2_->send_result());
|
| +
|
| + wrapper2_->gcm_app_handler()->WaitForNotification();
|
| + EXPECT_EQ(FakeGCMAppHandler::SEND_ERROR_EVENT,
|
| + wrapper2_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(kTestAppID1, wrapper2_->gcm_app_handler()->app_id());
|
| + EXPECT_EQ(out_message4.id,
|
| + wrapper2_->gcm_app_handler()->send_error_details().message_id);
|
| + EXPECT_NE(GCMClient::SUCCESS,
|
| + wrapper2_->gcm_app_handler()->send_error_details().result);
|
| + EXPECT_EQ(out_message4.data,
|
| + wrapper2_->gcm_app_handler()->send_error_details().additional_data);
|
| +
|
| + // Sign in with a different account.
|
| + wrapper_->SignIn(kTestAccountID3);
|
| +
|
| + // Signing out cleared all registrations, so we need to register again.
|
| + wrapper_->Register(kTestAppID1, ToSenderList("sender1"), true);
|
| +
|
| + // Incoming message will go through for the new signed-in account.
|
| + GCMClient::IncomingMessage in_message5;
|
| + in_message5.data["in5"] = "in_data5";
|
| + in_message5.sender_id = "sender1";
|
| + wrapper_->GetGCMClient()->ReceiveMessage(kTestAppID1, in_message5);
|
| +
|
| + wrapper_->gcm_app_handler()->WaitForNotification();
|
| +
|
| + EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
|
| + wrapper_->gcm_app_handler()->received_event());
|
| + EXPECT_EQ(in_message5.data, wrapper_->gcm_app_handler()->message().data);
|
| +}
|
| +
|
| +} // namespace gcm
|
|
|