summaryrefslogtreecommitdiffstats
path: root/components/gcm_driver/gcm_driver_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'components/gcm_driver/gcm_driver_unittest.cc')
-rw-r--r--components/gcm_driver/gcm_driver_unittest.cc900
1 files changed, 900 insertions, 0 deletions
diff --git a/components/gcm_driver/gcm_driver_unittest.cc b/components/gcm_driver/gcm_driver_unittest.cc
new file mode 100644
index 0000000..52f6abb
--- /dev/null
+++ b/components/gcm_driver/gcm_driver_unittest.cc
@@ -0,0 +1,900 @@
+// 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 "components/gcm_driver/gcm_driver.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread.h"
+#include "components/gcm_driver/fake_gcm_app_handler.h"
+#include "components/gcm_driver/fake_gcm_client.h"
+#include "components/gcm_driver/fake_gcm_client_factory.h"
+#include "components/gcm_driver/gcm_app_handler.h"
+#include "components/gcm_driver/gcm_client_factory.h"
+#include "google_apis/gaia/fake_identity_provider.h"
+#include "google_apis/gaia/fake_oauth2_token_service.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 kTestAppID1[] = "TestApp1";
+const char kTestAppID2[] = "TestApp2";
+const char kUserID1[] = "user1";
+
+void PumpCurrentLoop() {
+ base::MessageLoop::ScopedNestableTaskAllower
+ nestable_task_allower(base::MessageLoop::current());
+ base::RunLoop().RunUntilIdle();
+}
+
+void PumpUILoop() {
+ PumpCurrentLoop();
+}
+
+std::vector<std::string> ToSenderList(const std::string& sender_ids) {
+ std::vector<std::string> senders;
+ Tokenize(sender_ids, ",", &senders);
+ return senders;
+}
+
+} // namespace
+
+class GCMDriverTest : public testing::Test {
+ public:
+ enum WaitToFinish {
+ DO_NOT_WAIT,
+ WAIT
+ };
+
+ GCMDriverTest();
+ virtual ~GCMDriverTest();
+
+ // testing::Test:
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ GCMDriver* driver() { return driver_.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 PumpIOLoop();
+
+ void ClearResults();
+
+ bool HasAppHandlers() const;
+ FakeGCMClient* GetGCMClient();
+
+ void CreateDriver(FakeGCMClient::StartMode gcm_client_start_mode);
+ void AddAppHandlers();
+ void RemoveAppHandlers();
+
+ void SignIn(const std::string& account_id);
+ void SignOut();
+
+ void Register(const std::string& app_id,
+ const std::vector<std::string>& sender_ids,
+ WaitToFinish wait_to_finish);
+ void Send(const std::string& app_id,
+ const std::string& receiver_id,
+ const GCMClient::OutgoingMessage& message,
+ WaitToFinish wait_to_finish);
+ void Unregister(const std::string& app_id, WaitToFinish wait_to_finish);
+
+ void WaitForAsyncOperation();
+
+ private:
+ void RegisterCompleted(const std::string& registration_id,
+ GCMClient::Result result);
+ void SendCompleted(const std::string& message_id, GCMClient::Result result);
+ void UnregisterCompleted(GCMClient::Result result);
+
+ base::ScopedTempDir temp_dir_;
+ FakeOAuth2TokenService token_service_;
+ scoped_ptr<FakeIdentityProvider> identity_provider_owner_;
+ FakeIdentityProvider* identity_provider_;
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+ base::MessageLoopForUI message_loop_;
+ base::Thread io_thread_;
+ scoped_ptr<GCMDriver> driver_;
+ scoped_ptr<FakeGCMAppHandler> gcm_app_handler_;
+
+ base::Closure async_operation_completed_callback_;
+
+ std::string registration_id_;
+ GCMClient::Result registration_result_;
+ std::string send_message_id_;
+ GCMClient::Result send_result_;
+ GCMClient::Result unregistration_result_;
+
+ DISALLOW_COPY_AND_ASSIGN(GCMDriverTest);
+};
+
+GCMDriverTest::GCMDriverTest()
+ : identity_provider_(NULL),
+ task_runner_(new base::TestSimpleTaskRunner()),
+ io_thread_("IOThread"),
+ registration_result_(GCMClient::UNKNOWN_ERROR),
+ send_result_(GCMClient::UNKNOWN_ERROR),
+ unregistration_result_(GCMClient::UNKNOWN_ERROR) {
+ identity_provider_owner_.reset(new FakeIdentityProvider(&token_service_));
+ identity_provider_ = identity_provider_owner_.get();
+}
+
+GCMDriverTest::~GCMDriverTest() {
+}
+
+void GCMDriverTest::SetUp() {
+ io_thread_.Start();
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+}
+
+void GCMDriverTest::TearDown() {
+ if (!driver_)
+ return;
+
+ driver_->Shutdown();
+ driver_.reset();
+ PumpIOLoop();
+
+ io_thread_.Stop();
+}
+
+void GCMDriverTest::PumpIOLoop() {
+ base::RunLoop run_loop;
+ io_thread_.message_loop_proxy()->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&PumpCurrentLoop),
+ run_loop.QuitClosure());
+ run_loop.Run();
+}
+
+void GCMDriverTest::ClearResults() {
+ registration_id_.clear();
+ registration_result_ = GCMClient::UNKNOWN_ERROR;
+
+ send_message_id_.clear();
+ send_result_ = GCMClient::UNKNOWN_ERROR;
+
+ unregistration_result_ = GCMClient::UNKNOWN_ERROR;
+}
+
+bool GCMDriverTest::HasAppHandlers() const {
+ return !driver_->app_handlers().empty();
+}
+
+FakeGCMClient* GCMDriverTest::GetGCMClient() {
+ return static_cast<FakeGCMClient*>(driver_->GetGCMClientForTesting());
+}
+
+void GCMDriverTest::CreateDriver(
+ FakeGCMClient::StartMode gcm_client_start_mode) {
+ scoped_refptr<net::URLRequestContextGetter> request_context =
+ new net::TestURLRequestContextGetter(io_thread_.message_loop_proxy());
+ driver_.reset(new GCMDriver(
+ scoped_ptr<GCMClientFactory>(new FakeGCMClientFactory(
+ gcm_client_start_mode,
+ base::MessageLoopProxy::current(),
+ io_thread_.message_loop_proxy())).Pass(),
+ identity_provider_owner_.PassAs<IdentityProvider>(),
+ GCMClient::ChromeBuildInfo(),
+ temp_dir_.path(),
+ request_context,
+ base::MessageLoopProxy::current(),
+ io_thread_.message_loop_proxy(),
+ task_runner_));
+
+ gcm_app_handler_.reset(new FakeGCMAppHandler);
+}
+
+void GCMDriverTest::AddAppHandlers() {
+ driver_->AddAppHandler(kTestAppID1, gcm_app_handler_.get());
+ driver_->AddAppHandler(kTestAppID2, gcm_app_handler_.get());
+}
+
+void GCMDriverTest::RemoveAppHandlers() {
+ driver_->RemoveAppHandler(kTestAppID1);
+ driver_->RemoveAppHandler(kTestAppID2);
+}
+
+void GCMDriverTest::SignIn(const std::string& account_id) {
+ token_service_.AddAccount(account_id);
+ identity_provider_->LogIn(account_id);
+ PumpIOLoop();
+ PumpUILoop();
+}
+
+void GCMDriverTest::SignOut() {
+ identity_provider_->LogOut();
+ PumpIOLoop();
+ PumpUILoop();
+}
+
+void GCMDriverTest::Register(const std::string& app_id,
+ const std::vector<std::string>& sender_ids,
+ WaitToFinish wait_to_finish) {
+ base::RunLoop run_loop;
+ async_operation_completed_callback_ = run_loop.QuitClosure();
+ driver_->Register(app_id,
+ sender_ids,
+ base::Bind(&GCMDriverTest::RegisterCompleted,
+ base::Unretained(this)));
+ if (wait_to_finish == WAIT)
+ run_loop.Run();
+}
+
+void GCMDriverTest::Send(const std::string& app_id,
+ const std::string& receiver_id,
+ const GCMClient::OutgoingMessage& message,
+ WaitToFinish wait_to_finish) {
+ base::RunLoop run_loop;
+ async_operation_completed_callback_ = run_loop.QuitClosure();
+ driver_->Send(app_id,
+ receiver_id,
+ message,
+ base::Bind(&GCMDriverTest::SendCompleted,
+ base::Unretained(this)));
+ if (wait_to_finish == WAIT)
+ run_loop.Run();
+}
+
+void GCMDriverTest::Unregister(const std::string& app_id,
+ WaitToFinish wait_to_finish) {
+ base::RunLoop run_loop;
+ async_operation_completed_callback_ = run_loop.QuitClosure();
+ driver_->Unregister(app_id,
+ base::Bind(&GCMDriverTest::UnregisterCompleted,
+ base::Unretained(this)));
+ if (wait_to_finish == WAIT)
+ run_loop.Run();
+}
+
+void GCMDriverTest::WaitForAsyncOperation() {
+ base::RunLoop run_loop;
+ async_operation_completed_callback_ = run_loop.QuitClosure();
+ run_loop.Run();
+}
+
+void GCMDriverTest::RegisterCompleted(const std::string& registration_id,
+ GCMClient::Result result) {
+ registration_id_ = registration_id;
+ registration_result_ = result;
+ if (!async_operation_completed_callback_.is_null())
+ async_operation_completed_callback_.Run();
+}
+
+void GCMDriverTest::SendCompleted(const std::string& message_id,
+ GCMClient::Result result) {
+ send_message_id_ = message_id;
+ send_result_ = result;
+ if (!async_operation_completed_callback_.is_null())
+ async_operation_completed_callback_.Run();
+}
+
+void GCMDriverTest::UnregisterCompleted(GCMClient::Result result) {
+ unregistration_result_ = result;
+ if (!async_operation_completed_callback_.is_null())
+ async_operation_completed_callback_.Run();
+}
+
+TEST_F(GCMDriverTest, CreateGCMDriverBeforeSignIn) {
+ // Create GCMDriver first. GCM is not started.
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+ EXPECT_FALSE(driver()->IsStarted());
+
+ // Sign in. GCM is still not started.
+ SignIn(kTestAccountID1);
+ EXPECT_FALSE(driver()->IsStarted());
+
+ // GCM will be started only after both sign-in and app handler being
+ AddAppHandlers();
+ EXPECT_TRUE(driver()->IsStarted());
+}
+
+TEST_F(GCMDriverTest, CreateGCMDriverAfterSignIn) {
+ // Sign in. Nothings happens since GCMDriver is not created.
+ SignIn(kTestAccountID1);
+
+ // Create GCMDriver after sign-in. GCM is not started.
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+ EXPECT_FALSE(driver()->IsStarted());
+
+ // GCM will be started only after both sign-in and app handler being
+ AddAppHandlers();
+ EXPECT_TRUE(driver()->IsStarted());
+}
+
+TEST_F(GCMDriverTest, Shutdown) {
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+ EXPECT_FALSE(HasAppHandlers());
+
+ AddAppHandlers();
+ EXPECT_TRUE(HasAppHandlers());
+
+ driver()->Shutdown();
+ EXPECT_FALSE(HasAppHandlers());
+}
+
+TEST_F(GCMDriverTest, SignInAndSignOutOnGCMEnabled) {
+ // By default, GCM is enabled.
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+ AddAppHandlers();
+
+ // GCMClient should be started after sign-in.
+ SignIn(kTestAccountID1);
+ EXPECT_TRUE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
+
+ // GCMClient should be checked out after sign-out.
+ SignOut();
+ EXPECT_FALSE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::CHECKED_OUT, GetGCMClient()->status());
+}
+
+TEST_F(GCMDriverTest, SignInAndSignOutOnGCMDisabled) {
+ // By default, GCM is enabled.
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+ AddAppHandlers();
+
+ // Disable GCM.
+ driver()->Disable();
+
+ // GCMClient should not be started after sign-in.
+ SignIn(kTestAccountID1);
+ EXPECT_FALSE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::UNINITIALIZED, GetGCMClient()->status());
+
+ // Check-out should still be performed after sign-out.
+ SignOut();
+ EXPECT_FALSE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::CHECKED_OUT, GetGCMClient()->status());
+}
+
+TEST_F(GCMDriverTest, SignOutAndThenSignIn) {
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+ AddAppHandlers();
+
+ // GCMClient should be started after sign-in.
+ SignIn(kTestAccountID1);
+ EXPECT_TRUE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
+
+ // GCMClient should be checked out after sign-out.
+ SignOut();
+ EXPECT_FALSE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::CHECKED_OUT, GetGCMClient()->status());
+
+ // Sign-in with a different account.
+ SignIn(kTestAccountID2);
+
+ // GCMClient should be started again.
+ EXPECT_TRUE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
+}
+
+TEST_F(GCMDriverTest, DisableAndReenableGCM) {
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+ AddAppHandlers();
+ SignIn(kTestAccountID1);
+
+ // GCMClient should be started.
+ EXPECT_TRUE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
+
+ // Disables the GCM.
+ driver()->Disable();
+ PumpIOLoop();
+ PumpUILoop();
+
+ // GCMClient should be stopped.
+ EXPECT_FALSE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STOPPED, GetGCMClient()->status());
+
+ // Enables the GCM.
+ driver()->Enable();
+ PumpIOLoop();
+ PumpUILoop();
+
+ // GCMClient should be started.
+ EXPECT_TRUE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
+
+ // Disables the GCM.
+ driver()->Disable();
+ PumpIOLoop();
+ PumpUILoop();
+
+ // GCMClient should be stopped.
+ EXPECT_FALSE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STOPPED, GetGCMClient()->status());
+
+ // Sign out.
+ SignOut();
+
+ // GCMClient should be checked out.
+ EXPECT_FALSE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::CHECKED_OUT, GetGCMClient()->status());
+}
+
+TEST_F(GCMDriverTest, StartOrStopGCMOnDemand) {
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+ SignIn(kTestAccountID1);
+
+ // GCMClient is not started.
+ EXPECT_FALSE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::UNINITIALIZED, GetGCMClient()->status());
+
+ // GCMClient is started after an app handler has been added.
+ driver()->AddAppHandler(kTestAppID1, gcm_app_handler());
+ PumpIOLoop();
+ PumpUILoop();
+ EXPECT_TRUE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
+
+ // Add another app handler.
+ driver()->AddAppHandler(kTestAppID2, gcm_app_handler());
+ PumpIOLoop();
+ PumpUILoop();
+ EXPECT_TRUE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
+
+ // GCMClient remains active after one app handler is gone.
+ driver()->RemoveAppHandler(kTestAppID1);
+ PumpIOLoop();
+ PumpUILoop();
+ EXPECT_TRUE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
+
+ // GCMClient should be stopped after the last app handler is gone.
+ driver()->RemoveAppHandler(kTestAppID2);
+ PumpIOLoop();
+ PumpUILoop();
+ EXPECT_FALSE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STOPPED, GetGCMClient()->status());
+
+ // GCMClient is restarted after an app handler has been added.
+ driver()->AddAppHandler(kTestAppID2, gcm_app_handler());
+ PumpIOLoop();
+ PumpUILoop();
+ EXPECT_TRUE(driver()->IsGCMClientReady());
+ EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
+}
+
+TEST_F(GCMDriverTest, RegisterFailed) {
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1");
+
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+
+ // Registration fails when GCM is disabled.
+ driver()->Disable();
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ EXPECT_TRUE(registration_id().empty());
+ EXPECT_EQ(GCMClient::GCM_DISABLED, registration_result());
+
+ ClearResults();
+
+ // Registration fails when the sign-in does not occur.
+ driver()->Enable();
+ AddAppHandlers();
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ EXPECT_TRUE(registration_id().empty());
+ EXPECT_EQ(GCMClient::NOT_SIGNED_IN, registration_result());
+
+ ClearResults();
+
+ // Registration fails when the no app handler is added.
+ RemoveAppHandlers();
+ SignIn(kTestAccountID1);
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ EXPECT_TRUE(registration_id().empty());
+ EXPECT_EQ(GCMClient::UNKNOWN_ERROR, registration_result());
+}
+
+TEST_F(GCMDriverTest, UnregisterFailed) {
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+
+ // Unregistration fails when GCM is disabled.
+ driver()->Disable();
+ Unregister(kTestAppID1, GCMDriverTest::WAIT);
+ EXPECT_EQ(GCMClient::GCM_DISABLED, unregistration_result());
+
+ ClearResults();
+
+ // Unregistration fails when the sign-in does not occur.
+ driver()->Enable();
+ AddAppHandlers();
+ Unregister(kTestAppID1, GCMDriverTest::WAIT);
+ EXPECT_EQ(GCMClient::NOT_SIGNED_IN, unregistration_result());
+
+ ClearResults();
+
+ // Unregistration fails when the no app handler is added.
+ RemoveAppHandlers();
+ SignIn(kTestAccountID1);
+ Unregister(kTestAppID1, GCMDriverTest::WAIT);
+ EXPECT_EQ(GCMClient::UNKNOWN_ERROR, unregistration_result());
+}
+
+TEST_F(GCMDriverTest, SendFailed) {
+ GCMClient::OutgoingMessage message;
+ message.id = "1";
+ message.data["key1"] = "value1";
+
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+
+ // Sending fails when GCM is disabled.
+ driver()->Disable();
+ Send(kTestAppID1, kUserID1, message, GCMDriverTest::WAIT);
+ EXPECT_TRUE(send_message_id().empty());
+ EXPECT_EQ(GCMClient::GCM_DISABLED, send_result());
+
+ ClearResults();
+
+ // Sending fails when the sign-in does not occur.
+ driver()->Enable();
+ AddAppHandlers();
+ Send(kTestAppID1, kUserID1, message, GCMDriverTest::WAIT);
+ EXPECT_TRUE(send_message_id().empty());
+ EXPECT_EQ(GCMClient::NOT_SIGNED_IN, send_result());
+
+ ClearResults();
+
+ // Sending fails when the no app handler is added.
+ RemoveAppHandlers();
+ SignIn(kTestAccountID1);
+ Send(kTestAppID1, kUserID1, message, GCMDriverTest::WAIT);
+ EXPECT_TRUE(send_message_id().empty());
+ EXPECT_EQ(GCMClient::UNKNOWN_ERROR, send_result());
+}
+
+TEST_F(GCMDriverTest, GCMClientNotReadyBeforeRegistration) {
+ // Make GCMClient not ready initially.
+ CreateDriver(FakeGCMClient::DELAY_START);
+ SignIn(kTestAccountID1);
+ AddAppHandlers();
+
+ // The registration is on hold until GCMClient is ready.
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1");
+ Register(kTestAppID1,
+ sender_ids,
+ GCMDriverTest::DO_NOT_WAIT);
+ PumpIOLoop();
+ PumpUILoop();
+ EXPECT_TRUE(registration_id().empty());
+ EXPECT_EQ(GCMClient::UNKNOWN_ERROR, registration_result());
+
+ // Register operation will be invoked after GCMClient becomes ready.
+ GetGCMClient()->PerformDelayedLoading();
+ WaitForAsyncOperation();
+ EXPECT_FALSE(registration_id().empty());
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+}
+
+TEST_F(GCMDriverTest, GCMClientNotReadyBeforeSending) {
+ // Make GCMClient not ready initially.
+ CreateDriver(FakeGCMClient::DELAY_START);
+ SignIn(kTestAccountID1);
+ AddAppHandlers();
+
+ // The sending is on hold until GCMClient is ready.
+ GCMClient::OutgoingMessage message;
+ message.id = "1";
+ message.data["key1"] = "value1";
+ message.data["key2"] = "value2";
+ Send(kTestAppID1, kUserID1, message, GCMDriverTest::DO_NOT_WAIT);
+ PumpIOLoop();
+ PumpUILoop();
+
+ EXPECT_TRUE(send_message_id().empty());
+ EXPECT_EQ(GCMClient::UNKNOWN_ERROR, send_result());
+
+ // Send operation will be invoked after GCMClient becomes ready.
+ GetGCMClient()->PerformDelayedLoading();
+ WaitForAsyncOperation();
+ EXPECT_EQ(message.id, send_message_id());
+ EXPECT_EQ(GCMClient::SUCCESS, send_result());
+}
+
+// Tests a single instance of GCMDriver.
+class GCMDriverFunctionalTest : public GCMDriverTest {
+ public:
+ GCMDriverFunctionalTest();
+ virtual ~GCMDriverFunctionalTest();
+
+ // GCMDriverTest:
+ virtual void SetUp() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GCMDriverFunctionalTest);
+};
+
+GCMDriverFunctionalTest::GCMDriverFunctionalTest() {
+}
+
+GCMDriverFunctionalTest::~GCMDriverFunctionalTest() {
+}
+
+void GCMDriverFunctionalTest::SetUp() {
+ GCMDriverTest::SetUp();
+
+ CreateDriver(FakeGCMClient::NO_DELAY_START);
+ AddAppHandlers();
+ SignIn(kTestAccountID1);
+}
+
+TEST_F(GCMDriverFunctionalTest, Register) {
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1");
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ const std::string expected_registration_id =
+ FakeGCMClient::GetRegistrationIdFromSenderIds(sender_ids);
+
+ EXPECT_EQ(expected_registration_id, registration_id());
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, RegisterError) {
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1@error");
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+
+ EXPECT_TRUE(registration_id().empty());
+ EXPECT_NE(GCMClient::SUCCESS, registration_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, RegisterAgainWithSameSenderIDs) {
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1");
+ sender_ids.push_back("sender2");
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ const std::string expected_registration_id =
+ FakeGCMClient::GetRegistrationIdFromSenderIds(sender_ids);
+
+ EXPECT_EQ(expected_registration_id, registration_id());
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+
+ // Clears the results the would be set by the Register callback in preparation
+ // to call register 2nd time.
+ ClearResults();
+
+ // 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");
+ Register(kTestAppID1, another_sender_ids, GCMDriverTest::WAIT);
+
+ EXPECT_EQ(expected_registration_id, registration_id());
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, RegisterAgainWithDifferentSenderIDs) {
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1");
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ const std::string expected_registration_id =
+ FakeGCMClient::GetRegistrationIdFromSenderIds(sender_ids);
+
+ EXPECT_EQ(expected_registration_id, registration_id());
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+
+ // Make sender IDs different.
+ sender_ids.push_back("sender2");
+ const std::string expected_registration_id2 =
+ FakeGCMClient::GetRegistrationIdFromSenderIds(sender_ids);
+
+ // Calling register 2nd time with the different sender IDs will get back a new
+ // registration ID.
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ EXPECT_EQ(expected_registration_id2, registration_id());
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, RegisterAfterSignOut) {
+ // This will trigger check-out.
+ SignOut();
+
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1");
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+
+ EXPECT_TRUE(registration_id().empty());
+ EXPECT_EQ(GCMClient::NOT_SIGNED_IN, registration_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, UnregisterExplicitly) {
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1");
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+
+ EXPECT_FALSE(registration_id().empty());
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+
+ Unregister(kTestAppID1, GCMDriverTest::WAIT);
+
+ EXPECT_EQ(GCMClient::SUCCESS, unregistration_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, UnregisterWhenAsyncOperationPending) {
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1");
+ // First start registration without waiting for it to complete.
+ Register(kTestAppID1,
+ sender_ids,
+ GCMDriverTest::DO_NOT_WAIT);
+
+ // Test that unregistration fails with async operation pending when there is a
+ // registration already in progress.
+ Unregister(kTestAppID1, GCMDriverTest::WAIT);
+ EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
+ unregistration_result());
+
+ // Complete the unregistration.
+ WaitForAsyncOperation();
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+
+ // Start unregistration without waiting for it to complete. This time no async
+ // operation is pending.
+ Unregister(kTestAppID1, GCMDriverTest::DO_NOT_WAIT);
+
+ // Test that unregistration fails with async operation pending when there is
+ // an unregistration already in progress.
+ Unregister(kTestAppID1, GCMDriverTest::WAIT);
+ EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
+ unregistration_result());
+ ClearResults();
+
+ // Complete unregistration.
+ WaitForAsyncOperation();
+ EXPECT_EQ(GCMClient::SUCCESS, unregistration_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, RegisterWhenAsyncOperationPending) {
+ std::vector<std::string> sender_ids;
+ sender_ids.push_back("sender1");
+ // First start registration without waiting for it to complete.
+ Register(kTestAppID1,
+ sender_ids,
+ GCMDriverTest::DO_NOT_WAIT);
+
+ // Test that registration fails with async operation pending when there is a
+ // registration already in progress.
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
+ registration_result());
+ ClearResults();
+
+ // Complete the registration.
+ WaitForAsyncOperation();
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+
+ // Start unregistration without waiting for it to complete. This time no async
+ // operation is pending.
+ Unregister(kTestAppID1, GCMDriverTest::DO_NOT_WAIT);
+
+ // Test that registration fails with async operation pending when there is an
+ // unregistration already in progress.
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
+ registration_result());
+
+ // Complete the first unregistration expecting success.
+ WaitForAsyncOperation();
+ EXPECT_EQ(GCMClient::SUCCESS, unregistration_result());
+
+ // Test that it is ok to register again after unregistration.
+ Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
+ EXPECT_EQ(GCMClient::SUCCESS, registration_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, Send) {
+ GCMClient::OutgoingMessage message;
+ message.id = "1";
+ message.data["key1"] = "value1";
+ message.data["key2"] = "value2";
+ Send(kTestAppID1, kUserID1, message, GCMDriverTest::WAIT);
+
+ EXPECT_EQ(message.id, send_message_id());
+ EXPECT_EQ(GCMClient::SUCCESS, send_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, SendAfterSignOut) {
+ // This will trigger check-out.
+ SignOut();
+
+ GCMClient::OutgoingMessage message;
+ message.id = "1";
+ message.data["key1"] = "value1";
+ message.data["key2"] = "value2";
+ Send(kTestAppID1, kUserID1, message, GCMDriverTest::WAIT);
+
+ EXPECT_TRUE(send_message_id().empty());
+ EXPECT_EQ(GCMClient::NOT_SIGNED_IN, send_result());
+}
+
+TEST_F(GCMDriverFunctionalTest, 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";
+ Send(kTestAppID1, kUserID1, message, GCMDriverTest::WAIT);
+
+ EXPECT_EQ(message.id, send_message_id());
+ EXPECT_EQ(GCMClient::SUCCESS, send_result());
+
+ // Wait for the send error.
+ gcm_app_handler()->WaitForNotification();
+ EXPECT_EQ(FakeGCMAppHandler::SEND_ERROR_EVENT,
+ gcm_app_handler()->received_event());
+ EXPECT_EQ(kTestAppID1, gcm_app_handler()->app_id());
+ EXPECT_EQ(message.id,
+ gcm_app_handler()->send_error_details().message_id);
+ EXPECT_NE(GCMClient::SUCCESS,
+ gcm_app_handler()->send_error_details().result);
+ EXPECT_EQ(message.data,
+ gcm_app_handler()->send_error_details().additional_data);
+}
+
+TEST_F(GCMDriverFunctionalTest, MessageReceived) {
+ Register(kTestAppID1, ToSenderList("sender"), GCMDriverTest::WAIT);
+ GCMClient::IncomingMessage message;
+ message.data["key1"] = "value1";
+ message.data["key2"] = "value2";
+ message.sender_id = "sender";
+ GetGCMClient()->ReceiveMessage(kTestAppID1, message);
+ gcm_app_handler()->WaitForNotification();
+ EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
+ gcm_app_handler()->received_event());
+ EXPECT_EQ(kTestAppID1, gcm_app_handler()->app_id());
+ EXPECT_EQ(message.data, gcm_app_handler()->message().data);
+ EXPECT_TRUE(gcm_app_handler()->message().collapse_key.empty());
+ EXPECT_EQ(message.sender_id, gcm_app_handler()->message().sender_id);
+}
+
+TEST_F(GCMDriverFunctionalTest, MessageWithCollapseKeyReceived) {
+ Register(kTestAppID1, ToSenderList("sender"), GCMDriverTest::WAIT);
+ GCMClient::IncomingMessage message;
+ message.data["key1"] = "value1";
+ message.collapse_key = "collapse_key_value";
+ message.sender_id = "sender";
+ GetGCMClient()->ReceiveMessage(kTestAppID1, message);
+ gcm_app_handler()->WaitForNotification();
+ EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
+ gcm_app_handler()->received_event());
+ EXPECT_EQ(kTestAppID1, gcm_app_handler()->app_id());
+ EXPECT_EQ(message.data, gcm_app_handler()->message().data);
+ EXPECT_EQ(message.collapse_key,
+ gcm_app_handler()->message().collapse_key);
+}
+
+TEST_F(GCMDriverFunctionalTest, MessagesDeleted) {
+ GetGCMClient()->DeleteMessages(kTestAppID1);
+ gcm_app_handler()->WaitForNotification();
+ EXPECT_EQ(FakeGCMAppHandler::MESSAGES_DELETED_EVENT,
+ gcm_app_handler()->received_event());
+ EXPECT_EQ(kTestAppID1, gcm_app_handler()->app_id());
+}
+
+} // namespace gcm