123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- // 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_subscription_request.h"
- #include "base/bind.h"
- #include "base/memory/ptr_util.h"
- #include "base/run_loop.h"
- #include "base/strings/stringprintf.h"
- #include "base/test/bind.h"
- #include "base/test/gtest_util.h"
- #include "base/test/mock_callback.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/test/task_environment.h"
- #include "base/test/test_simple_task_runner.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "base/values.h"
- #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
- #include "services/network/public/mojom/url_response_head.mojom.h"
- #include "services/network/test/test_url_loader_factory.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "url/gurl.h"
- namespace invalidation {
- namespace {
- using testing::_;
- using testing::DoAll;
- using testing::SaveArg;
- network::mojom::URLResponseHeadPtr CreateHeadersForTest(int responce_code) {
- auto head = network::mojom::URLResponseHead::New();
- 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 PerUserTopicSubscriptionRequestTest : public testing::Test {
- public:
- PerUserTopicSubscriptionRequestTest() = default;
- ~PerUserTopicSubscriptionRequestTest() override = default;
- GURL url(PerUserTopicSubscriptionRequest* request) {
- return request->GetUrlForTesting();
- }
- network::TestURLLoaderFactory* url_loader_factory() {
- return &url_loader_factory_;
- }
- private:
- base::test::SingleThreadTaskEnvironment task_environment_;
- data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
- network::TestURLLoaderFactory url_loader_factory_;
- };
- TEST_F(PerUserTopicSubscriptionRequestTest,
- ShouldNotInvokeCallbackWhenCancelled) {
- std::string token = "1234567890";
- std::string url = "http://valid-url.test";
- std::string topic = "test";
- std::string project_id = "smarty-pants-12345";
- PerUserTopicSubscriptionRequest::RequestType type =
- PerUserTopicSubscriptionRequest::SUBSCRIBE;
- base::MockCallback<PerUserTopicSubscriptionRequest::CompletedCallback>
- callback;
- EXPECT_CALL(callback, Run(_, _)).Times(0);
- PerUserTopicSubscriptionRequest::Builder builder;
- std::unique_ptr<PerUserTopicSubscriptionRequest> request =
- builder.SetInstanceIdToken(token)
- .SetScope(url)
- .SetPublicTopicName(topic)
- .SetProjectId(project_id)
- .SetType(type)
- .Build();
- request->Start(callback.Get(), url_loader_factory());
- base::RunLoop().RunUntilIdle();
- // Destroy the request before getting any response.
- request.reset();
- }
- TEST_F(PerUserTopicSubscriptionRequestTest, ShouldSubscribeWithoutErrors) {
- std::string token = "1234567890";
- std::string base_url = "http://valid-url.test";
- std::string topic = "test";
- std::string project_id = "smarty-pants-12345";
- PerUserTopicSubscriptionRequest::RequestType type =
- PerUserTopicSubscriptionRequest::SUBSCRIBE;
- base::MockCallback<PerUserTopicSubscriptionRequest::CompletedCallback>
- callback;
- Status status(StatusCode::FAILED, "initial");
- std::string private_topic;
- EXPECT_CALL(callback, Run(_, _))
- .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&private_topic)));
- PerUserTopicSubscriptionRequest::Builder builder;
- std::unique_ptr<PerUserTopicSubscriptionRequest> request =
- builder.SetInstanceIdToken(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(), url_loader_factory());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(status.code, StatusCode::SUCCESS);
- EXPECT_EQ(private_topic, "test-pr");
- }
- TEST_F(PerUserTopicSubscriptionRequestTest,
- ShouleNotSubscribeWhenNetworkProblem) {
- std::string token = "1234567890";
- std::string base_url = "http://valid-url.test";
- std::string topic = "test";
- std::string project_id = "smarty-pants-12345";
- PerUserTopicSubscriptionRequest::RequestType type =
- PerUserTopicSubscriptionRequest::SUBSCRIBE;
- base::MockCallback<PerUserTopicSubscriptionRequest::CompletedCallback>
- callback;
- Status status(StatusCode::FAILED, "initial");
- std::string private_topic;
- EXPECT_CALL(callback, Run(_, _))
- .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&private_topic)));
- PerUserTopicSubscriptionRequest::Builder builder;
- std::unique_ptr<PerUserTopicSubscriptionRequest> request =
- builder.SetInstanceIdToken(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(), url_loader_factory());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(status.code, StatusCode::FAILED);
- }
- TEST_F(PerUserTopicSubscriptionRequestTest,
- ShouldNotSubscribeWhenWrongResponse) {
- std::string token = "1234567890";
- std::string base_url = "http://valid-url.test";
- std::string topic = "test";
- std::string project_id = "smarty-pants-12345";
- PerUserTopicSubscriptionRequest::RequestType type =
- PerUserTopicSubscriptionRequest::SUBSCRIBE;
- base::MockCallback<PerUserTopicSubscriptionRequest::CompletedCallback>
- callback;
- Status status(StatusCode::SUCCESS, "initial");
- std::string private_topic;
- EXPECT_CALL(callback, Run(_, _))
- .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&private_topic)));
- PerUserTopicSubscriptionRequest::Builder builder;
- std::unique_ptr<PerUserTopicSubscriptionRequest> request =
- builder.SetInstanceIdToken(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(), url_loader_factory());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(status.code, StatusCode::FAILED);
- EXPECT_EQ(status.message, "Missing topic name");
- }
- TEST_F(PerUserTopicSubscriptionRequestTest, ShouldUnsubscribe) {
- std::string token = "1234567890";
- std::string base_url = "http://valid-url.test";
- std::string topic = "test";
- std::string project_id = "smarty-pants-12345";
- PerUserTopicSubscriptionRequest::RequestType type =
- PerUserTopicSubscriptionRequest::UNSUBSCRIBE;
- base::MockCallback<PerUserTopicSubscriptionRequest::CompletedCallback>
- callback;
- Status status(StatusCode::FAILED, "initial");
- std::string private_topic;
- EXPECT_CALL(callback, Run(_, _))
- .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&private_topic)));
- PerUserTopicSubscriptionRequest::Builder builder;
- std::unique_ptr<PerUserTopicSubscriptionRequest> request =
- builder.SetInstanceIdToken(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(), url_loader_factory());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(status.code, StatusCode::SUCCESS);
- EXPECT_EQ(status.message, std::string());
- }
- // Regression test for crbug.com/1054590, |completed_callback| destroys
- // |request|.
- TEST_F(PerUserTopicSubscriptionRequestTest, ShouldDestroyOnFailure) {
- std::string token = "1234567890";
- std::string base_url = "http://valid-url.test";
- std::string topic = "test";
- std::string project_id = "smarty-pants-12345";
- PerUserTopicSubscriptionRequest::RequestType type =
- PerUserTopicSubscriptionRequest::SUBSCRIBE;
- std::unique_ptr<PerUserTopicSubscriptionRequest> request;
- bool callback_called = false;
- auto completed_callback = base::BindLambdaForTesting(
- [&](const Status& status, const std::string& topic_name) {
- request.reset();
- callback_called = true;
- });
- PerUserTopicSubscriptionRequest::Builder builder;
- request = builder.SetInstanceIdToken(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(std::move(completed_callback), url_loader_factory());
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(callback_called);
- // The main expectation is that there is no crash.
- }
- class PerUserTopicSubscriptionRequestParamTest
- : public PerUserTopicSubscriptionRequestTest,
- public testing::WithParamInterface<net::HttpStatusCode> {
- public:
- PerUserTopicSubscriptionRequestParamTest() = default;
- PerUserTopicSubscriptionRequestParamTest(
- const PerUserTopicSubscriptionRequestParamTest&) = delete;
- PerUserTopicSubscriptionRequestParamTest& operator=(
- const PerUserTopicSubscriptionRequestParamTest&) = delete;
- ~PerUserTopicSubscriptionRequestParamTest() override = default;
- };
- TEST_P(PerUserTopicSubscriptionRequestParamTest,
- ShouldNotSubscribeWhenNonRepeatableError) {
- std::string token = "1234567890";
- std::string base_url = "http://valid-url.test";
- std::string topic = "test";
- std::string project_id = "smarty-pants-12345";
- PerUserTopicSubscriptionRequest::RequestType type =
- PerUserTopicSubscriptionRequest::SUBSCRIBE;
- base::MockCallback<PerUserTopicSubscriptionRequest::CompletedCallback>
- callback;
- Status status(StatusCode::FAILED, "initial");
- std::string private_topic;
- EXPECT_CALL(callback, Run(_, _))
- .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&private_topic)));
- PerUserTopicSubscriptionRequest::Builder builder;
- std::unique_ptr<PerUserTopicSubscriptionRequest> request =
- builder.SetInstanceIdToken(token)
- .SetScope(base_url)
- .SetPublicTopicName(topic)
- .SetProjectId(project_id)
- .SetType(type)
- .Build();
- network::URLLoaderCompletionStatus response_status(net::OK);
- url_loader_factory()->AddResponse(
- url(request.get()), CreateHeadersForTest(GetParam()),
- /* response_body */ std::string(), response_status);
- request->Start(callback.Get(), url_loader_factory());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(status.code, StatusCode::FAILED_NON_RETRIABLE);
- }
- INSTANTIATE_TEST_SUITE_P(All,
- PerUserTopicSubscriptionRequestParamTest,
- testing::Values(net::HTTP_BAD_REQUEST,
- net::HTTP_FORBIDDEN,
- net::HTTP_NOT_FOUND));
- } // namespace invalidation
|