blob: b2fe913cc35c070850559b9fac81fe4ad6c0e495 [file] [log] [blame]
// Copyright 2018 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/invalidation/impl/per_user_topic_registration_request.h"
#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/gtest_util.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "components/invalidation/impl/json_unsafe_parser.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
namespace {
using testing::_;
using testing::SaveArg;
MATCHER_P(EqualsJSON, json, "equals JSON") {
std::unique_ptr<base::Value> expected = base::JSONReader::Read(json);
if (!expected) {
*result_listener << "INTERNAL ERROR: couldn't parse expected JSON";
return false;
}
std::string err_msg;
int err_line, err_col;
std::unique_ptr<base::Value> actual = base::JSONReader::ReadAndReturnError(
arg, base::JSON_PARSE_RFC, nullptr, &err_msg, &err_line, &err_col);
if (!actual) {
*result_listener << "input:" << err_line << ":" << err_col << ": "
<< "parse error: " << err_msg;
return false;
}
return *expected == *actual;
}
network::ResourceResponseHead CreateHeadersForTest(int responce_code) {
network::ResourceResponseHead head;
head.headers = new net::HttpResponseHeaders(base::StringPrintf(
"HTTP/1.1 %d OK\nContent-type: text/html\n\n", responce_code));
head.mime_type = "text/html";
return head;
}
} // namespace
class PerUserTopicRegistrationRequestTest : public testing::Test {
public:
PerUserTopicRegistrationRequestTest() {}
GURL url(PerUserTopicRegistrationRequest* request) {
return request->getUrl();
}
network::TestURLLoaderFactory* url_loader_factory() {
return &url_loader_factory_;
}
private:
base::test::ScopedTaskEnvironment task_environment_;
network::TestURLLoaderFactory url_loader_factory_;
DISALLOW_COPY_AND_ASSIGN(PerUserTopicRegistrationRequestTest);
};
TEST_F(PerUserTopicRegistrationRequestTest,
ShouldNotInvokeCallbackWhenCancelled) {
std::string token = "1234567890";
std::string url = "http://valid-url.test";
std::string topic = "test";
std::string project_id = "smarty-pants-12345";
PerUserTopicRegistrationRequest::RequestType type =
PerUserTopicRegistrationRequest::SUBSCRIBE;
base::MockCallback<PerUserTopicRegistrationRequest::CompletedCallback>
callback;
EXPECT_CALL(callback, Run(_, _)).Times(0);
PerUserTopicRegistrationRequest::Builder builder;
std::unique_ptr<PerUserTopicRegistrationRequest> request =
builder.SetToken(token)
.SetScope(url)
.SetPublicTopicName(topic)
.SetProjectId(project_id)
.SetType(type)
.Build();
request->Start(callback.Get(),
base::BindRepeating(&syncer::JsonUnsafeParser::Parse),
url_loader_factory());
base::RunLoop().RunUntilIdle();
// Destroy the request before getting any response.
request.reset();
}
TEST_F(PerUserTopicRegistrationRequestTest, ShouldSubscribeWithoutErrors) {
std::string token = "1234567890";
std::string base_url = "http://valid-url.test";
std::string topic = "test";
std::string project_id = "smarty-pants-12345";
PerUserTopicRegistrationRequest::RequestType type =
PerUserTopicRegistrationRequest::SUBSCRIBE;
base::MockCallback<PerUserTopicRegistrationRequest::CompletedCallback>
callback;
Status status(StatusCode::FAILED, "initial");
std::string private_topic;
EXPECT_CALL(callback, Run(_, _))
.WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&private_topic)));
PerUserTopicRegistrationRequest::Builder builder;
std::unique_ptr<PerUserTopicRegistrationRequest> request =
builder.SetToken(token)
.SetScope(base_url)
.SetPublicTopicName(topic)
.SetProjectId(project_id)
.SetType(type)
.Build();
std::string response_body = R"(
{
"privateTopicName": "test-pr"
}
)";
network::URLLoaderCompletionStatus response_status(net::OK);
response_status.decoded_body_length = response_body.size();
url_loader_factory()->AddResponse(url(request.get()),
CreateHeadersForTest(net::HTTP_OK),
response_body, response_status);
request->Start(callback.Get(),
base::BindRepeating(&syncer::JsonUnsafeParser::Parse),
url_loader_factory());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(status.code, StatusCode::SUCCESS);
EXPECT_EQ(private_topic, "test-pr");
}
TEST_F(PerUserTopicRegistrationRequestTest,
ShouleNotSubscribeWhenNetworkProblem) {
std::string token = "1234567890";
std::string base_url = "http://valid-url.test";
std::string topic = "test";
std::string project_id = "smarty-pants-12345";
PerUserTopicRegistrationRequest::RequestType type =
PerUserTopicRegistrationRequest::SUBSCRIBE;
base::MockCallback<PerUserTopicRegistrationRequest::CompletedCallback>
callback;
Status status(StatusCode::FAILED, "initial");
std::string private_topic;
EXPECT_CALL(callback, Run(_, _))
.WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&private_topic)));
PerUserTopicRegistrationRequest::Builder builder;
std::unique_ptr<PerUserTopicRegistrationRequest> request =
builder.SetToken(token)
.SetScope(base_url)
.SetPublicTopicName(topic)
.SetProjectId(project_id)
.SetType(type)
.Build();
std::string response_body = R"(
{
"privateTopicName": "test-pr"
}
)";
network::URLLoaderCompletionStatus response_status(net::ERR_TIMED_OUT);
response_status.decoded_body_length = response_body.size();
url_loader_factory()->AddResponse(url(request.get()),
CreateHeadersForTest(net::HTTP_OK),
response_body, response_status);
request->Start(callback.Get(),
base::BindRepeating(&syncer::JsonUnsafeParser::Parse),
url_loader_factory());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(status.code, StatusCode::FAILED);
}
TEST_F(PerUserTopicRegistrationRequestTest,
ShouldNotSubscribeWhenWrongResponse) {
std::string token = "1234567890";
std::string base_url = "http://valid-url.test";
std::string topic = "test";
std::string project_id = "smarty-pants-12345";
PerUserTopicRegistrationRequest::RequestType type =
PerUserTopicRegistrationRequest::SUBSCRIBE;
base::MockCallback<PerUserTopicRegistrationRequest::CompletedCallback>
callback;
Status status(StatusCode::SUCCESS, "initial");
std::string private_topic;
EXPECT_CALL(callback, Run(_, _))
.WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&private_topic)));
PerUserTopicRegistrationRequest::Builder builder;
std::unique_ptr<PerUserTopicRegistrationRequest> request =
builder.SetToken(token)
.SetScope(base_url)
.SetPublicTopicName(topic)
.SetProjectId(project_id)
.SetType(type)
.Build();
std::string response_body = R"(
{}
)";
network::URLLoaderCompletionStatus response_status(net::OK);
response_status.decoded_body_length = response_body.size();
url_loader_factory()->AddResponse(url(request.get()),
CreateHeadersForTest(net::HTTP_OK),
response_body, response_status);
request->Start(callback.Get(),
base::BindRepeating(&syncer::JsonUnsafeParser::Parse),
url_loader_factory());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(status.code, StatusCode::FAILED);
EXPECT_EQ(status.message, "Body parse error");
}
TEST_F(PerUserTopicRegistrationRequestTest, ShouldUnsubscribe) {
std::string token = "1234567890";
std::string base_url = "http://valid-url.test";
std::string topic = "test";
std::string project_id = "smarty-pants-12345";
PerUserTopicRegistrationRequest::RequestType type =
PerUserTopicRegistrationRequest::UNSUBSCRIBE;
base::MockCallback<PerUserTopicRegistrationRequest::CompletedCallback>
callback;
Status status(StatusCode::FAILED, "initial");
std::string private_topic;
EXPECT_CALL(callback, Run(_, _))
.WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&private_topic)));
PerUserTopicRegistrationRequest::Builder builder;
std::unique_ptr<PerUserTopicRegistrationRequest> request =
builder.SetToken(token)
.SetScope(base_url)
.SetPublicTopicName(topic)
.SetProjectId(project_id)
.SetType(type)
.Build();
std::string response_body = R"(
{}
)";
network::URLLoaderCompletionStatus response_status(net::OK);
response_status.decoded_body_length = response_body.size();
url_loader_factory()->AddResponse(url(request.get()),
CreateHeadersForTest(net::HTTP_OK),
response_body, response_status);
request->Start(callback.Get(),
base::BindRepeating(&syncer::JsonUnsafeParser::Parse),
url_loader_factory());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(status.code, StatusCode::SUCCESS);
EXPECT_EQ(status.message, std::string());
}
} // namespace syncer