blob: 77ca103279eed67ea40fdc101ba926ea3ea5bd6c [file] [log] [blame]
// 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_desktop.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 "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_;
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()
: task_runner_(new base::TestSimpleTaskRunner()),
io_thread_("IOThread"),
registration_result_(GCMClient::UNKNOWN_ERROR),
send_result_(GCMClient::UNKNOWN_ERROR),
unregistration_result_(GCMClient::UNKNOWN_ERROR) {
}
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());
// TODO(johnme): Need equivalent test coverage of GCMDriverAndroid.
driver_.reset(new GCMDriverDesktop(
scoped_ptr<GCMClientFactory>(new FakeGCMClientFactory(
gcm_client_start_mode,
base::MessageLoopProxy::current(),
io_thread_.message_loop_proxy())).Pass(),
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) {
driver_->OnSignedIn();
PumpIOLoop();
PumpUILoop();
}
void GCMDriverTest::SignOut() {
driver_->Purge();
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, Create) {
// 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());
EXPECT_FALSE(driver()->IsConnected());
EXPECT_FALSE(gcm_app_handler()->connected());
// GCM will be started only after both sign-in and app handler being added.
AddAppHandlers();
EXPECT_TRUE(driver()->IsStarted());
PumpIOLoop();
EXPECT_TRUE(driver()->IsConnected());
EXPECT_TRUE(gcm_app_handler()->connected());
}
TEST_F(GCMDriverTest, Shutdown) {
CreateDriver(FakeGCMClient::NO_DELAY_START);
EXPECT_FALSE(HasAppHandlers());
AddAppHandlers();
EXPECT_TRUE(HasAppHandlers());
driver()->Shutdown();
EXPECT_FALSE(HasAppHandlers());
EXPECT_FALSE(driver()->IsConnected());
EXPECT_FALSE(gcm_app_handler()->connected());
}
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_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
// GCMClient should be checked out after sign-out.
SignOut();
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_EQ(FakeGCMClient::UNINITIALIZED, GetGCMClient()->status());
// Check-out should still be performed after sign-out.
SignOut();
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_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
// GCMClient should be checked out after sign-out.
SignOut();
EXPECT_EQ(FakeGCMClient::CHECKED_OUT, GetGCMClient()->status());
// Sign-in with a different account.
SignIn(kTestAccountID2);
// GCMClient should be started again.
EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
}
TEST_F(GCMDriverTest, DisableAndReenableGCM) {
CreateDriver(FakeGCMClient::NO_DELAY_START);
AddAppHandlers();
SignIn(kTestAccountID1);
// GCMClient should be started.
EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
// Disables the GCM.
driver()->Disable();
PumpIOLoop();
PumpUILoop();
// GCMClient should be stopped.
EXPECT_EQ(FakeGCMClient::STOPPED, GetGCMClient()->status());
// Enables the GCM.
driver()->Enable();
PumpIOLoop();
PumpUILoop();
// GCMClient should be started.
EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
// Disables the GCM.
driver()->Disable();
PumpIOLoop();
PumpUILoop();
// GCMClient should be stopped.
EXPECT_EQ(FakeGCMClient::STOPPED, GetGCMClient()->status());
// Sign out.
SignOut();
// GCMClient should be checked out.
EXPECT_EQ(FakeGCMClient::CHECKED_OUT, GetGCMClient()->status());
}
TEST_F(GCMDriverTest, StartOrStopGCMOnDemand) {
CreateDriver(FakeGCMClient::NO_DELAY_START);
SignIn(kTestAccountID1);
// GCMClient is not started.
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_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
// Add another app handler.
driver()->AddAppHandler(kTestAppID2, gcm_app_handler());
PumpIOLoop();
PumpUILoop();
EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
// GCMClient remains active after one app handler is gone.
driver()->RemoveAppHandler(kTestAppID1);
PumpIOLoop();
PumpUILoop();
EXPECT_EQ(FakeGCMClient::STARTED, GetGCMClient()->status());
// GCMClient should be stopped after the last app handler is gone.
driver()->RemoveAppHandler(kTestAppID2);
PumpIOLoop();
PumpUILoop();
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_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