diff options
Diffstat (limited to 'components/gcm_driver/gcm_driver_unittest.cc')
-rw-r--r-- | components/gcm_driver/gcm_driver_unittest.cc | 900 |
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 |