1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/offline_pages/core/prefetch/prefetch_request_fetcher.h"
6 
7 #include "base/bind.h"
8 #include "base/test/mock_callback.h"
9 #include "components/offline_pages/core/prefetch/prefetch_request_test_base.h"
10 #include "components/offline_pages/core/prefetch/prefetch_types.h"
11 #include "net/http/http_status_code.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "url/gurl.h"
14 
15 using testing::_;
16 using testing::DoAll;
17 using testing::Eq;
18 using testing::SaveArg;
19 
20 namespace offline_pages {
21 
22 namespace {
23 const char kTestMessage[] = "Testing";
24 
25 // TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
26 // function.
TestURL()27 GURL TestURL() {
28   return GURL("http://example.org");
29 }
30 }  // namespace
31 
32 class PrefetchRequestFetcherTest : public PrefetchRequestTestBase {
33  public:
34   PrefetchRequestStatus RunFetcherWithNetError(net::Error net_error);
35   PrefetchRequestStatus RunFetcherWithHttpError(net::HttpStatusCode http_error);
36   PrefetchRequestStatus RunFetcherWithData(const std::string& response_data,
37                                            std::string* data_received);
38   PrefetchRequestStatus RunFetcherWithHttpErrorAndData(
39       net::HttpStatusCode http_error,
40       const std::string& response_data);
SetEmptyRequest(bool empty_request)41   void SetEmptyRequest(bool empty_request) { empty_request_ = empty_request; }
42 
43  private:
44   PrefetchRequestStatus RunFetcher(
45       base::OnceCallback<void(void)> respond_callback,
46       std::string* data_received);
47   bool empty_request_;
48 };
49 
RunFetcherWithNetError(net::Error net_error)50 PrefetchRequestStatus PrefetchRequestFetcherTest::RunFetcherWithNetError(
51     net::Error net_error) {
52   std::string data_received;
53   PrefetchRequestStatus status =
54       RunFetcher(base::BindOnce(&PrefetchRequestTestBase::RespondWithNetError,
55                                 base::Unretained(this), net_error),
56                  &data_received);
57   EXPECT_TRUE(data_received.empty());
58   return status;
59 }
60 
RunFetcherWithHttpError(net::HttpStatusCode http_error)61 PrefetchRequestStatus PrefetchRequestFetcherTest::RunFetcherWithHttpError(
62     net::HttpStatusCode http_error) {
63   std::string data_received;
64   PrefetchRequestStatus status =
65       RunFetcher(base::BindOnce(&PrefetchRequestTestBase::RespondWithHttpError,
66                                 base::Unretained(this), http_error),
67                  &data_received);
68   EXPECT_TRUE(data_received.empty());
69   return status;
70 }
71 
RunFetcherWithData(const std::string & response_data,std::string * data_received)72 PrefetchRequestStatus PrefetchRequestFetcherTest::RunFetcherWithData(
73     const std::string& response_data,
74     std::string* data_received) {
75   return RunFetcher(base::BindOnce(&PrefetchRequestTestBase::RespondWithData,
76                                    base::Unretained(this), response_data),
77                     data_received);
78 }
79 
80 PrefetchRequestStatus
RunFetcherWithHttpErrorAndData(net::HttpStatusCode http_error,const std::string & response_data)81 PrefetchRequestFetcherTest::RunFetcherWithHttpErrorAndData(
82     net::HttpStatusCode http_error,
83     const std::string& response_data) {
84   std::string data_received;
85   return RunFetcher(
86       base::BindOnce(&PrefetchRequestTestBase::RespondWithHttpErrorAndData,
87                      base::Unretained(this), http_error, response_data),
88       &data_received);
89 }
90 
RunFetcher(base::OnceCallback<void (void)> respond_callback,std::string * data_received)91 PrefetchRequestStatus PrefetchRequestFetcherTest::RunFetcher(
92     base::OnceCallback<void(void)> respond_callback,
93     std::string* data_received) {
94   base::MockCallback<PrefetchRequestFetcher::FinishedCallback> callback;
95   std::unique_ptr<PrefetchRequestFetcher> fetcher =
96       PrefetchRequestFetcher::CreateForPost(
97           TestURL(), kTestMessage, /*testing_header_value=*/"", empty_request_,
98           shared_url_loader_factory(), callback.Get());
99 
100   PrefetchRequestStatus status;
101   std::string data;
102   EXPECT_CALL(callback, Run(_, _))
103       .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&data)));
104   std::move(respond_callback).Run();
105   RunUntilIdle();
106 
107   *data_received = data;
108   return status;
109 }
110 
TEST_F(PrefetchRequestFetcherTest,NetErrors)111 TEST_F(PrefetchRequestFetcherTest, NetErrors) {
112   EXPECT_EQ(PrefetchRequestStatus::kShouldSuspendBlockedByAdministrator,
113             RunFetcherWithNetError(net::ERR_BLOCKED_BY_ADMINISTRATOR));
114 
115   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithoutBackoff,
116             RunFetcherWithNetError(net::ERR_INTERNET_DISCONNECTED));
117   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithoutBackoff,
118             RunFetcherWithNetError(net::ERR_NETWORK_CHANGED));
119   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithoutBackoff,
120             RunFetcherWithNetError(net::ERR_CONNECTION_RESET));
121   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithoutBackoff,
122             RunFetcherWithNetError(net::ERR_CONNECTION_CLOSED));
123   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithoutBackoff,
124             RunFetcherWithNetError(net::ERR_CONNECTION_REFUSED));
125 }
126 
TEST_F(PrefetchRequestFetcherTest,HttpErrors)127 TEST_F(PrefetchRequestFetcherTest, HttpErrors) {
128   EXPECT_EQ(PrefetchRequestStatus::kShouldSuspendNotImplemented,
129             RunFetcherWithHttpError(net::HTTP_NOT_IMPLEMENTED));
130   EXPECT_EQ(PrefetchRequestStatus::kShouldSuspendForbidden,
131             RunFetcherWithHttpError(net::HTTP_FORBIDDEN));
132 
133   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithBackoff,
134             RunFetcherWithHttpError(net::HTTP_BAD_REQUEST));
135   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithBackoff,
136             RunFetcherWithHttpError(net::HTTP_UNAUTHORIZED));
137   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithBackoff,
138             RunFetcherWithHttpError(net::HTTP_NOT_FOUND));
139   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithBackoff,
140             RunFetcherWithHttpError(net::HTTP_CONFLICT));
141   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithBackoff,
142             RunFetcherWithHttpError(net::HTTP_INTERNAL_SERVER_ERROR));
143   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithBackoff,
144             RunFetcherWithHttpError(net::HTTP_BAD_GATEWAY));
145   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithBackoff,
146             RunFetcherWithHttpError(net::HTTP_SERVICE_UNAVAILABLE));
147   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithBackoff,
148             RunFetcherWithHttpError(net::HTTP_GATEWAY_TIMEOUT));
149 
150   SetEmptyRequest(false);
151   EXPECT_EQ(PrefetchRequestStatus::kShouldSuspendNewlyForbiddenByOPS,
152             RunFetcherWithHttpErrorAndData(net::HTTP_FORBIDDEN,
153                                            "request forbidden by OPS"));
154   SetEmptyRequest(true);
155   EXPECT_EQ(PrefetchRequestStatus::kShouldSuspendForbiddenByOPS,
156             RunFetcherWithHttpErrorAndData(net::HTTP_FORBIDDEN,
157                                            "request forbidden by OPS"));
158 }
159 
TEST_F(PrefetchRequestFetcherTest,EmptyResponse)160 TEST_F(PrefetchRequestFetcherTest, EmptyResponse) {
161   std::string data;
162   EXPECT_EQ(PrefetchRequestStatus::kShouldRetryWithBackoff,
163             RunFetcherWithData("", &data));
164   EXPECT_TRUE(data.empty());
165 }
166 
TEST_F(PrefetchRequestFetcherTest,EmptyRequestSuccess)167 TEST_F(PrefetchRequestFetcherTest, EmptyRequestSuccess) {
168   std::string data;
169   SetEmptyRequest(true);
170   EXPECT_EQ(PrefetchRequestStatus::kEmptyRequestSuccess,
171             RunFetcherWithData("Any data.", &data));
172   EXPECT_FALSE(data.empty());
173 }
174 
TEST_F(PrefetchRequestFetcherTest,NonEmptyRequestSuccess)175 TEST_F(PrefetchRequestFetcherTest, NonEmptyRequestSuccess) {
176   std::string data;
177   SetEmptyRequest(false);
178   EXPECT_EQ(PrefetchRequestStatus::kSuccess,
179             RunFetcherWithData("Any data.", &data));
180   EXPECT_FALSE(data.empty());
181 }
182 
183 }  // namespace offline_pages
184