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