xref: /aosp_15_r20/system/update_engine/common/http_fetcher_unittest.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2012 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker 
17*5a923131SAndroid Build Coastguard Worker #include <netinet/in.h>
18*5a923131SAndroid Build Coastguard Worker #include <netinet/ip.h>
19*5a923131SAndroid Build Coastguard Worker #include <sys/socket.h>
20*5a923131SAndroid Build Coastguard Worker #include <unistd.h>
21*5a923131SAndroid Build Coastguard Worker 
22*5a923131SAndroid Build Coastguard Worker #include <algorithm>
23*5a923131SAndroid Build Coastguard Worker #include <deque>
24*5a923131SAndroid Build Coastguard Worker #include <memory>
25*5a923131SAndroid Build Coastguard Worker #include <string>
26*5a923131SAndroid Build Coastguard Worker #include <utility>
27*5a923131SAndroid Build Coastguard Worker #include <vector>
28*5a923131SAndroid Build Coastguard Worker 
29*5a923131SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
30*5a923131SAndroid Build Coastguard Worker #include <base/bind.h>
31*5a923131SAndroid Build Coastguard Worker #include <base/location.h>
32*5a923131SAndroid Build Coastguard Worker #include <base/logging.h>
33*5a923131SAndroid Build Coastguard Worker #if BASE_VER < 780000  // Android
34*5a923131SAndroid Build Coastguard Worker #include <base/message_loop/message_loop.h>
35*5a923131SAndroid Build Coastguard Worker #endif  // BASE_VER < 780000
36*5a923131SAndroid Build Coastguard Worker #include <base/stl_util.h>
37*5a923131SAndroid Build Coastguard Worker #include <base/strings/string_number_conversions.h>
38*5a923131SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
39*5a923131SAndroid Build Coastguard Worker #if BASE_VER >= 780000  // CrOS
40*5a923131SAndroid Build Coastguard Worker #include <base/task/single_thread_task_executor.h>
41*5a923131SAndroid Build Coastguard Worker #endif  // BASE_VER >= 780000
42*5a923131SAndroid Build Coastguard Worker #include <base/time/time.h>
43*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/base_message_loop.h>
44*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/message_loop.h>
45*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/message_loop_utils.h>
46*5a923131SAndroid Build Coastguard Worker #ifdef __CHROMEOS__
47*5a923131SAndroid Build Coastguard Worker #include <brillo/process/process.h>
48*5a923131SAndroid Build Coastguard Worker #else
49*5a923131SAndroid Build Coastguard Worker #include <brillo/process.h>
50*5a923131SAndroid Build Coastguard Worker #endif  // __CHROMEOS__
51*5a923131SAndroid Build Coastguard Worker #include <brillo/streams/file_stream.h>
52*5a923131SAndroid Build Coastguard Worker #include <brillo/streams/stream.h>
53*5a923131SAndroid Build Coastguard Worker #include <gmock/gmock.h>
54*5a923131SAndroid Build Coastguard Worker #include <gtest/gtest.h>
55*5a923131SAndroid Build Coastguard Worker 
56*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/fake_hardware.h"
57*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/file_fetcher.h"
58*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/http_common.h"
59*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/mock_http_fetcher.h"
60*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/multi_range_http_fetcher.h"
61*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/test_utils.h"
62*5a923131SAndroid Build Coastguard Worker #include "update_engine/common/utils.h"
63*5a923131SAndroid Build Coastguard Worker #include "update_engine/libcurl_http_fetcher.h"
64*5a923131SAndroid Build Coastguard Worker 
65*5a923131SAndroid Build Coastguard Worker using brillo::MessageLoop;
66*5a923131SAndroid Build Coastguard Worker using std::make_pair;
67*5a923131SAndroid Build Coastguard Worker using std::pair;
68*5a923131SAndroid Build Coastguard Worker using std::string;
69*5a923131SAndroid Build Coastguard Worker using std::unique_ptr;
70*5a923131SAndroid Build Coastguard Worker using std::vector;
71*5a923131SAndroid Build Coastguard Worker using testing::_;
72*5a923131SAndroid Build Coastguard Worker using testing::DoAll;
73*5a923131SAndroid Build Coastguard Worker using testing::Return;
74*5a923131SAndroid Build Coastguard Worker using testing::SaveArg;
75*5a923131SAndroid Build Coastguard Worker 
76*5a923131SAndroid Build Coastguard Worker namespace {
77*5a923131SAndroid Build Coastguard Worker 
78*5a923131SAndroid Build Coastguard Worker const int kBigLength = 100000;
79*5a923131SAndroid Build Coastguard Worker const int kMediumLength = 1000;
80*5a923131SAndroid Build Coastguard Worker const int kFlakyTruncateLength = 29000;
81*5a923131SAndroid Build Coastguard Worker const int kFlakySleepEvery = 3;
82*5a923131SAndroid Build Coastguard Worker const int kFlakySleepSecs = 10;
83*5a923131SAndroid Build Coastguard Worker 
84*5a923131SAndroid Build Coastguard Worker }  // namespace
85*5a923131SAndroid Build Coastguard Worker 
86*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
87*5a923131SAndroid Build Coastguard Worker 
88*5a923131SAndroid Build Coastguard Worker static const char* kUnusedUrl = "unused://unused";
89*5a923131SAndroid Build Coastguard Worker 
LocalServerUrlForPath(in_port_t port,const string & path)90*5a923131SAndroid Build Coastguard Worker static inline string LocalServerUrlForPath(in_port_t port, const string& path) {
91*5a923131SAndroid Build Coastguard Worker   string port_str = (port ? android::base::StringPrintf(":%hu", port) : "");
92*5a923131SAndroid Build Coastguard Worker   return android::base::StringPrintf(
93*5a923131SAndroid Build Coastguard Worker       "http://127.0.0.1%s%s", port_str.c_str(), path.c_str());
94*5a923131SAndroid Build Coastguard Worker }
95*5a923131SAndroid Build Coastguard Worker 
96*5a923131SAndroid Build Coastguard Worker //
97*5a923131SAndroid Build Coastguard Worker // Class hierarchy for HTTP server implementations.
98*5a923131SAndroid Build Coastguard Worker //
99*5a923131SAndroid Build Coastguard Worker 
100*5a923131SAndroid Build Coastguard Worker namespace {
101*5a923131SAndroid Build Coastguard Worker 
102*5a923131SAndroid Build Coastguard Worker class HttpServer {
103*5a923131SAndroid Build Coastguard Worker  public:
104*5a923131SAndroid Build Coastguard Worker   // This makes it an abstract class (dirty but works).
105*5a923131SAndroid Build Coastguard Worker   virtual ~HttpServer() = 0;
106*5a923131SAndroid Build Coastguard Worker 
GetPort() const107*5a923131SAndroid Build Coastguard Worker   virtual in_port_t GetPort() const { return 0; }
108*5a923131SAndroid Build Coastguard Worker 
109*5a923131SAndroid Build Coastguard Worker   bool started_;
110*5a923131SAndroid Build Coastguard Worker };
111*5a923131SAndroid Build Coastguard Worker 
~HttpServer()112*5a923131SAndroid Build Coastguard Worker HttpServer::~HttpServer() {}
113*5a923131SAndroid Build Coastguard Worker 
114*5a923131SAndroid Build Coastguard Worker class NullHttpServer : public HttpServer {
115*5a923131SAndroid Build Coastguard Worker  public:
NullHttpServer()116*5a923131SAndroid Build Coastguard Worker   NullHttpServer() { started_ = true; }
117*5a923131SAndroid Build Coastguard Worker };
118*5a923131SAndroid Build Coastguard Worker 
119*5a923131SAndroid Build Coastguard Worker class PythonHttpServer : public HttpServer {
120*5a923131SAndroid Build Coastguard Worker  public:
PythonHttpServer()121*5a923131SAndroid Build Coastguard Worker   PythonHttpServer() : port_(0) {
122*5a923131SAndroid Build Coastguard Worker     started_ = false;
123*5a923131SAndroid Build Coastguard Worker 
124*5a923131SAndroid Build Coastguard Worker     // Spawn the server process.
125*5a923131SAndroid Build Coastguard Worker     unique_ptr<brillo::Process> http_server(new brillo::ProcessImpl());
126*5a923131SAndroid Build Coastguard Worker     http_server->AddArg(test_utils::GetBuildArtifactsPath("test_http_server"));
127*5a923131SAndroid Build Coastguard Worker     http_server->RedirectUsingPipe(STDOUT_FILENO, false);
128*5a923131SAndroid Build Coastguard Worker 
129*5a923131SAndroid Build Coastguard Worker     if (!http_server->Start()) {
130*5a923131SAndroid Build Coastguard Worker       ADD_FAILURE() << "failed to spawn http server process";
131*5a923131SAndroid Build Coastguard Worker       return;
132*5a923131SAndroid Build Coastguard Worker     }
133*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "started http server with pid " << http_server->pid();
134*5a923131SAndroid Build Coastguard Worker 
135*5a923131SAndroid Build Coastguard Worker     // Wait for server to begin accepting connections, obtain its port.
136*5a923131SAndroid Build Coastguard Worker     brillo::StreamPtr stdout = brillo::FileStream::FromFileDescriptor(
137*5a923131SAndroid Build Coastguard Worker         http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
138*5a923131SAndroid Build Coastguard Worker     if (!stdout)
139*5a923131SAndroid Build Coastguard Worker       return;
140*5a923131SAndroid Build Coastguard Worker 
141*5a923131SAndroid Build Coastguard Worker     vector<char> buf(128);
142*5a923131SAndroid Build Coastguard Worker     string line;
143*5a923131SAndroid Build Coastguard Worker     while (line.find('\n') == string::npos) {
144*5a923131SAndroid Build Coastguard Worker       size_t read{};
145*5a923131SAndroid Build Coastguard Worker       if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
146*5a923131SAndroid Build Coastguard Worker         ADD_FAILURE() << "error reading http server stdout";
147*5a923131SAndroid Build Coastguard Worker         return;
148*5a923131SAndroid Build Coastguard Worker       }
149*5a923131SAndroid Build Coastguard Worker       line.append(buf.data(), read);
150*5a923131SAndroid Build Coastguard Worker       if (read == 0)
151*5a923131SAndroid Build Coastguard Worker         break;
152*5a923131SAndroid Build Coastguard Worker     }
153*5a923131SAndroid Build Coastguard Worker     // Parse the port from the output line.
154*5a923131SAndroid Build Coastguard Worker     const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
155*5a923131SAndroid Build Coastguard Worker     if (line.size() < listening_msg_prefix_len) {
156*5a923131SAndroid Build Coastguard Worker       ADD_FAILURE() << "server output too short";
157*5a923131SAndroid Build Coastguard Worker       return;
158*5a923131SAndroid Build Coastguard Worker     }
159*5a923131SAndroid Build Coastguard Worker 
160*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(kServerListeningMsgPrefix,
161*5a923131SAndroid Build Coastguard Worker               line.substr(0, listening_msg_prefix_len));
162*5a923131SAndroid Build Coastguard Worker     string port_str = line.substr(listening_msg_prefix_len);
163*5a923131SAndroid Build Coastguard Worker     port_str.resize(port_str.find('\n'));
164*5a923131SAndroid Build Coastguard Worker     EXPECT_TRUE(base::StringToUint(port_str, &port_));
165*5a923131SAndroid Build Coastguard Worker 
166*5a923131SAndroid Build Coastguard Worker     started_ = true;
167*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "server running, listening on port " << port_;
168*5a923131SAndroid Build Coastguard Worker 
169*5a923131SAndroid Build Coastguard Worker     // Any failure before this point will SIGKILL the test server if started
170*5a923131SAndroid Build Coastguard Worker     // when the |http_server| goes out of scope.
171*5a923131SAndroid Build Coastguard Worker     http_server_ = std::move(http_server);
172*5a923131SAndroid Build Coastguard Worker   }
173*5a923131SAndroid Build Coastguard Worker 
~PythonHttpServer()174*5a923131SAndroid Build Coastguard Worker   ~PythonHttpServer() {
175*5a923131SAndroid Build Coastguard Worker     // If there's no process, do nothing.
176*5a923131SAndroid Build Coastguard Worker     if (!http_server_)
177*5a923131SAndroid Build Coastguard Worker       return;
178*5a923131SAndroid Build Coastguard Worker     // Wait up to 10 seconds for the process to finish. Destroying the process
179*5a923131SAndroid Build Coastguard Worker     // will kill it with a SIGKILL otherwise.
180*5a923131SAndroid Build Coastguard Worker     http_server_->Kill(SIGTERM, 10);
181*5a923131SAndroid Build Coastguard Worker   }
182*5a923131SAndroid Build Coastguard Worker 
GetPort() const183*5a923131SAndroid Build Coastguard Worker   in_port_t GetPort() const override { return port_; }
184*5a923131SAndroid Build Coastguard Worker 
185*5a923131SAndroid Build Coastguard Worker  private:
186*5a923131SAndroid Build Coastguard Worker   static const char* kServerListeningMsgPrefix;
187*5a923131SAndroid Build Coastguard Worker 
188*5a923131SAndroid Build Coastguard Worker   unique_ptr<brillo::Process> http_server_;
189*5a923131SAndroid Build Coastguard Worker   unsigned int port_;
190*5a923131SAndroid Build Coastguard Worker };
191*5a923131SAndroid Build Coastguard Worker 
192*5a923131SAndroid Build Coastguard Worker const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
193*5a923131SAndroid Build Coastguard Worker 
194*5a923131SAndroid Build Coastguard Worker //
195*5a923131SAndroid Build Coastguard Worker // Class hierarchy for HTTP fetcher test wrappers.
196*5a923131SAndroid Build Coastguard Worker //
197*5a923131SAndroid Build Coastguard Worker 
198*5a923131SAndroid Build Coastguard Worker class AnyHttpFetcherFactory {
199*5a923131SAndroid Build Coastguard Worker  public:
AnyHttpFetcherFactory()200*5a923131SAndroid Build Coastguard Worker   AnyHttpFetcherFactory() {}
~AnyHttpFetcherFactory()201*5a923131SAndroid Build Coastguard Worker   virtual ~AnyHttpFetcherFactory() {}
202*5a923131SAndroid Build Coastguard Worker 
203*5a923131SAndroid Build Coastguard Worker   virtual HttpFetcher* NewLargeFetcher() = 0;
NewLargeFetcher(size_t num_proxies)204*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewLargeFetcher(size_t num_proxies) {
205*5a923131SAndroid Build Coastguard Worker     auto res = NewLargeFetcher();
206*5a923131SAndroid Build Coastguard Worker 
207*5a923131SAndroid Build Coastguard Worker     res->SetProxies(std::deque<std::string>(num_proxies, kNoProxy));
208*5a923131SAndroid Build Coastguard Worker     return res;
209*5a923131SAndroid Build Coastguard Worker   }
210*5a923131SAndroid Build Coastguard Worker 
211*5a923131SAndroid Build Coastguard Worker   virtual HttpFetcher* NewSmallFetcher() = 0;
212*5a923131SAndroid Build Coastguard Worker 
BigUrl(in_port_t port) const213*5a923131SAndroid Build Coastguard Worker   virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
SmallUrl(in_port_t port) const214*5a923131SAndroid Build Coastguard Worker   virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
ErrorUrl(in_port_t port) const215*5a923131SAndroid Build Coastguard Worker   virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
216*5a923131SAndroid Build Coastguard Worker 
217*5a923131SAndroid Build Coastguard Worker   virtual bool IsMock() const = 0;
218*5a923131SAndroid Build Coastguard Worker   virtual bool IsMulti() const = 0;
219*5a923131SAndroid Build Coastguard Worker   virtual bool IsHttpSupported() const = 0;
220*5a923131SAndroid Build Coastguard Worker   virtual bool IsFileFetcher() const = 0;
221*5a923131SAndroid Build Coastguard Worker 
IgnoreServerAborting(HttpServer * server) const222*5a923131SAndroid Build Coastguard Worker   virtual void IgnoreServerAborting(HttpServer* server) const {}
223*5a923131SAndroid Build Coastguard Worker 
224*5a923131SAndroid Build Coastguard Worker   virtual HttpServer* CreateServer() = 0;
225*5a923131SAndroid Build Coastguard Worker 
fake_hardware()226*5a923131SAndroid Build Coastguard Worker   FakeHardware* fake_hardware() { return &fake_hardware_; }
227*5a923131SAndroid Build Coastguard Worker 
228*5a923131SAndroid Build Coastguard Worker  protected:
229*5a923131SAndroid Build Coastguard Worker   FakeHardware fake_hardware_;
230*5a923131SAndroid Build Coastguard Worker };
231*5a923131SAndroid Build Coastguard Worker 
232*5a923131SAndroid Build Coastguard Worker class MockHttpFetcherFactory : public AnyHttpFetcherFactory {
233*5a923131SAndroid Build Coastguard Worker  public:
234*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
235*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewLargeFetcher;
NewLargeFetcher()236*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewLargeFetcher() override {
237*5a923131SAndroid Build Coastguard Worker     brillo::Blob big_data(1000000);
238*5a923131SAndroid Build Coastguard Worker     return new MockHttpFetcher(big_data.data(), big_data.size());
239*5a923131SAndroid Build Coastguard Worker   }
240*5a923131SAndroid Build Coastguard Worker 
241*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
242*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewSmallFetcher;
NewSmallFetcher()243*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewSmallFetcher() override {
244*5a923131SAndroid Build Coastguard Worker     return new MockHttpFetcher("x", 1);
245*5a923131SAndroid Build Coastguard Worker   }
246*5a923131SAndroid Build Coastguard Worker 
IsMock() const247*5a923131SAndroid Build Coastguard Worker   bool IsMock() const override { return true; }
IsMulti() const248*5a923131SAndroid Build Coastguard Worker   bool IsMulti() const override { return false; }
IsHttpSupported() const249*5a923131SAndroid Build Coastguard Worker   bool IsHttpSupported() const override { return true; }
IsFileFetcher() const250*5a923131SAndroid Build Coastguard Worker   bool IsFileFetcher() const override { return false; }
251*5a923131SAndroid Build Coastguard Worker 
CreateServer()252*5a923131SAndroid Build Coastguard Worker   HttpServer* CreateServer() override { return new NullHttpServer; }
253*5a923131SAndroid Build Coastguard Worker };
254*5a923131SAndroid Build Coastguard Worker 
255*5a923131SAndroid Build Coastguard Worker class LibcurlHttpFetcherFactory : public AnyHttpFetcherFactory {
256*5a923131SAndroid Build Coastguard Worker  public:
257*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
258*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewLargeFetcher;
NewLargeFetcher()259*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewLargeFetcher() override {
260*5a923131SAndroid Build Coastguard Worker     LibcurlHttpFetcher* ret = new LibcurlHttpFetcher(&fake_hardware_);
261*5a923131SAndroid Build Coastguard Worker     // Speed up test execution.
262*5a923131SAndroid Build Coastguard Worker     ret->set_idle_seconds(1);
263*5a923131SAndroid Build Coastguard Worker     ret->set_retry_seconds(1);
264*5a923131SAndroid Build Coastguard Worker     fake_hardware_.SetIsOfficialBuild(false);
265*5a923131SAndroid Build Coastguard Worker     return ret;
266*5a923131SAndroid Build Coastguard Worker   }
267*5a923131SAndroid Build Coastguard Worker 
268*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
269*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewSmallFetcher;
270*5a923131SAndroid Build Coastguard Worker 
NewSmallFetcher()271*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }
272*5a923131SAndroid Build Coastguard Worker 
BigUrl(in_port_t port) const273*5a923131SAndroid Build Coastguard Worker   string BigUrl(in_port_t port) const override {
274*5a923131SAndroid Build Coastguard Worker     return LocalServerUrlForPath(
275*5a923131SAndroid Build Coastguard Worker         port, android::base::StringPrintf("/download/%d", kBigLength));
276*5a923131SAndroid Build Coastguard Worker   }
SmallUrl(in_port_t port) const277*5a923131SAndroid Build Coastguard Worker   string SmallUrl(in_port_t port) const override {
278*5a923131SAndroid Build Coastguard Worker     return LocalServerUrlForPath(port, "/foo");
279*5a923131SAndroid Build Coastguard Worker   }
ErrorUrl(in_port_t port) const280*5a923131SAndroid Build Coastguard Worker   string ErrorUrl(in_port_t port) const override {
281*5a923131SAndroid Build Coastguard Worker     return LocalServerUrlForPath(port, "/error");
282*5a923131SAndroid Build Coastguard Worker   }
283*5a923131SAndroid Build Coastguard Worker 
IsMock() const284*5a923131SAndroid Build Coastguard Worker   bool IsMock() const override { return false; }
IsMulti() const285*5a923131SAndroid Build Coastguard Worker   bool IsMulti() const override { return false; }
IsHttpSupported() const286*5a923131SAndroid Build Coastguard Worker   bool IsHttpSupported() const override { return true; }
IsFileFetcher() const287*5a923131SAndroid Build Coastguard Worker   bool IsFileFetcher() const override { return false; }
288*5a923131SAndroid Build Coastguard Worker 
IgnoreServerAborting(HttpServer * server) const289*5a923131SAndroid Build Coastguard Worker   void IgnoreServerAborting(HttpServer* server) const override {
290*5a923131SAndroid Build Coastguard Worker     // Nothing to do.
291*5a923131SAndroid Build Coastguard Worker   }
292*5a923131SAndroid Build Coastguard Worker 
CreateServer()293*5a923131SAndroid Build Coastguard Worker   HttpServer* CreateServer() override { return new PythonHttpServer; }
294*5a923131SAndroid Build Coastguard Worker };
295*5a923131SAndroid Build Coastguard Worker 
296*5a923131SAndroid Build Coastguard Worker class MultiRangeHttpFetcherFactory : public LibcurlHttpFetcherFactory {
297*5a923131SAndroid Build Coastguard Worker  public:
298*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
299*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewLargeFetcher;
NewLargeFetcher()300*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewLargeFetcher() override {
301*5a923131SAndroid Build Coastguard Worker     MultiRangeHttpFetcher* ret =
302*5a923131SAndroid Build Coastguard Worker         new MultiRangeHttpFetcher(new LibcurlHttpFetcher(&fake_hardware_));
303*5a923131SAndroid Build Coastguard Worker     ret->ClearRanges();
304*5a923131SAndroid Build Coastguard Worker     ret->AddRange(0);
305*5a923131SAndroid Build Coastguard Worker     // Speed up test execution.
306*5a923131SAndroid Build Coastguard Worker     ret->set_idle_seconds(1);
307*5a923131SAndroid Build Coastguard Worker     ret->set_retry_seconds(1);
308*5a923131SAndroid Build Coastguard Worker     fake_hardware_.SetIsOfficialBuild(false);
309*5a923131SAndroid Build Coastguard Worker     return ret;
310*5a923131SAndroid Build Coastguard Worker   }
311*5a923131SAndroid Build Coastguard Worker 
312*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
313*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewSmallFetcher;
NewSmallFetcher()314*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }
315*5a923131SAndroid Build Coastguard Worker 
IsMulti() const316*5a923131SAndroid Build Coastguard Worker   bool IsMulti() const override { return true; }
317*5a923131SAndroid Build Coastguard Worker };
318*5a923131SAndroid Build Coastguard Worker 
319*5a923131SAndroid Build Coastguard Worker class FileFetcherFactory : public AnyHttpFetcherFactory {
320*5a923131SAndroid Build Coastguard Worker  public:
321*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
322*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewLargeFetcher;
NewLargeFetcher()323*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewLargeFetcher() override { return new FileFetcher(); }
324*5a923131SAndroid Build Coastguard Worker 
325*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
326*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewSmallFetcher;
NewSmallFetcher()327*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }
328*5a923131SAndroid Build Coastguard Worker 
BigUrl(in_port_t port) const329*5a923131SAndroid Build Coastguard Worker   string BigUrl(in_port_t port) const override {
330*5a923131SAndroid Build Coastguard Worker     static string big_contents = []() {
331*5a923131SAndroid Build Coastguard Worker       string buf;
332*5a923131SAndroid Build Coastguard Worker       buf.reserve(kBigLength);
333*5a923131SAndroid Build Coastguard Worker       constexpr const char* kBigUrlContent = "abcdefghij";
334*5a923131SAndroid Build Coastguard Worker       for (size_t i = 0; i < kBigLength; i += strlen(kBigUrlContent)) {
335*5a923131SAndroid Build Coastguard Worker         buf.append(kBigUrlContent,
336*5a923131SAndroid Build Coastguard Worker                    std::min(kBigLength - i, strlen(kBigUrlContent)));
337*5a923131SAndroid Build Coastguard Worker       }
338*5a923131SAndroid Build Coastguard Worker       return buf;
339*5a923131SAndroid Build Coastguard Worker     }();
340*5a923131SAndroid Build Coastguard Worker     test_utils::WriteFileString(temp_file_.path(), big_contents);
341*5a923131SAndroid Build Coastguard Worker     return "file://" + temp_file_.path();
342*5a923131SAndroid Build Coastguard Worker   }
SmallUrl(in_port_t port) const343*5a923131SAndroid Build Coastguard Worker   string SmallUrl(in_port_t port) const override {
344*5a923131SAndroid Build Coastguard Worker     test_utils::WriteFileString(temp_file_.path(), "small contents");
345*5a923131SAndroid Build Coastguard Worker     return "file://" + temp_file_.path();
346*5a923131SAndroid Build Coastguard Worker   }
ErrorUrl(in_port_t port) const347*5a923131SAndroid Build Coastguard Worker   string ErrorUrl(in_port_t port) const override {
348*5a923131SAndroid Build Coastguard Worker     return "file:///path/to/non-existing-file";
349*5a923131SAndroid Build Coastguard Worker   }
350*5a923131SAndroid Build Coastguard Worker 
IsMock() const351*5a923131SAndroid Build Coastguard Worker   bool IsMock() const override { return false; }
IsMulti() const352*5a923131SAndroid Build Coastguard Worker   bool IsMulti() const override { return false; }
IsHttpSupported() const353*5a923131SAndroid Build Coastguard Worker   bool IsHttpSupported() const override { return false; }
IsFileFetcher() const354*5a923131SAndroid Build Coastguard Worker   bool IsFileFetcher() const override { return true; }
355*5a923131SAndroid Build Coastguard Worker 
IgnoreServerAborting(HttpServer * server) const356*5a923131SAndroid Build Coastguard Worker   void IgnoreServerAborting(HttpServer* server) const override {}
357*5a923131SAndroid Build Coastguard Worker 
CreateServer()358*5a923131SAndroid Build Coastguard Worker   HttpServer* CreateServer() override { return new NullHttpServer; }
359*5a923131SAndroid Build Coastguard Worker 
360*5a923131SAndroid Build Coastguard Worker  private:
361*5a923131SAndroid Build Coastguard Worker   ScopedTempFile temp_file_{"ue_file_fetcher.XXXXXX"};
362*5a923131SAndroid Build Coastguard Worker };
363*5a923131SAndroid Build Coastguard Worker 
364*5a923131SAndroid Build Coastguard Worker class MultiRangeHttpFetcherOverFileFetcherFactory : public FileFetcherFactory {
365*5a923131SAndroid Build Coastguard Worker  public:
366*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
367*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewLargeFetcher;
NewLargeFetcher()368*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewLargeFetcher() override {
369*5a923131SAndroid Build Coastguard Worker     MultiRangeHttpFetcher* ret = new MultiRangeHttpFetcher(new FileFetcher());
370*5a923131SAndroid Build Coastguard Worker     ret->ClearRanges();
371*5a923131SAndroid Build Coastguard Worker     // FileFetcher doesn't support range with unspecified length.
372*5a923131SAndroid Build Coastguard Worker     ret->AddRange(0, 1);
373*5a923131SAndroid Build Coastguard Worker     // Speed up test execution.
374*5a923131SAndroid Build Coastguard Worker     ret->set_idle_seconds(1);
375*5a923131SAndroid Build Coastguard Worker     ret->set_retry_seconds(1);
376*5a923131SAndroid Build Coastguard Worker     fake_hardware_.SetIsOfficialBuild(false);
377*5a923131SAndroid Build Coastguard Worker     return ret;
378*5a923131SAndroid Build Coastguard Worker   }
379*5a923131SAndroid Build Coastguard Worker 
380*5a923131SAndroid Build Coastguard Worker   // Necessary to unhide the definition in the base class.
381*5a923131SAndroid Build Coastguard Worker   using AnyHttpFetcherFactory::NewSmallFetcher;
NewSmallFetcher()382*5a923131SAndroid Build Coastguard Worker   HttpFetcher* NewSmallFetcher() override { return NewLargeFetcher(); }
383*5a923131SAndroid Build Coastguard Worker 
IsMulti() const384*5a923131SAndroid Build Coastguard Worker   bool IsMulti() const override { return true; }
385*5a923131SAndroid Build Coastguard Worker };
386*5a923131SAndroid Build Coastguard Worker 
387*5a923131SAndroid Build Coastguard Worker //
388*5a923131SAndroid Build Coastguard Worker // Infrastructure for type tests of HTTP fetcher.
389*5a923131SAndroid Build Coastguard Worker // See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
390*5a923131SAndroid Build Coastguard Worker //
391*5a923131SAndroid Build Coastguard Worker 
392*5a923131SAndroid Build Coastguard Worker // Fixture class template. We use an explicit constraint to guarantee that it
393*5a923131SAndroid Build Coastguard Worker // can only be instantiated with an AnyHttpFetcherTest type, see:
394*5a923131SAndroid Build Coastguard Worker // http://www2.research.att.com/~bs/bs_faq2.html#constraints
395*5a923131SAndroid Build Coastguard Worker template <typename T>
396*5a923131SAndroid Build Coastguard Worker class HttpFetcherTest : public ::testing::Test {
397*5a923131SAndroid Build Coastguard Worker  public:
398*5a923131SAndroid Build Coastguard Worker #if BASE_VER < 780000  // Android
399*5a923131SAndroid Build Coastguard Worker   base::MessageLoopForIO base_loop_;
400*5a923131SAndroid Build Coastguard Worker   brillo::BaseMessageLoop loop_{&base_loop_};
401*5a923131SAndroid Build Coastguard Worker #else   // Chrome OS
402*5a923131SAndroid Build Coastguard Worker   base::SingleThreadTaskExecutor base_loop_{base::MessagePumpType::IO};
403*5a923131SAndroid Build Coastguard Worker   brillo::BaseMessageLoop loop_{base_loop_.task_runner()};
404*5a923131SAndroid Build Coastguard Worker #endif  // BASE_VER < 780000
405*5a923131SAndroid Build Coastguard Worker 
406*5a923131SAndroid Build Coastguard Worker   T test_;
407*5a923131SAndroid Build Coastguard Worker 
408*5a923131SAndroid Build Coastguard Worker  protected:
HttpFetcherTest()409*5a923131SAndroid Build Coastguard Worker   HttpFetcherTest() { loop_.SetAsCurrent(); }
410*5a923131SAndroid Build Coastguard Worker 
TearDown()411*5a923131SAndroid Build Coastguard Worker   void TearDown() override {
412*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
413*5a923131SAndroid Build Coastguard Worker   }
414*5a923131SAndroid Build Coastguard Worker 
415*5a923131SAndroid Build Coastguard Worker  private:
TypeConstraint(T * a)416*5a923131SAndroid Build Coastguard Worker   static void TypeConstraint(T* a) {
417*5a923131SAndroid Build Coastguard Worker     AnyHttpFetcherFactory* b = a;
418*5a923131SAndroid Build Coastguard Worker     if (b == 0)  // Silence compiler warning of unused variable.
419*5a923131SAndroid Build Coastguard Worker       *b = a;
420*5a923131SAndroid Build Coastguard Worker   }
421*5a923131SAndroid Build Coastguard Worker };
422*5a923131SAndroid Build Coastguard Worker 
423*5a923131SAndroid Build Coastguard Worker // Test case types list.
424*5a923131SAndroid Build Coastguard Worker typedef ::testing::Types<LibcurlHttpFetcherFactory,
425*5a923131SAndroid Build Coastguard Worker                          MockHttpFetcherFactory,
426*5a923131SAndroid Build Coastguard Worker                          MultiRangeHttpFetcherFactory,
427*5a923131SAndroid Build Coastguard Worker                          FileFetcherFactory,
428*5a923131SAndroid Build Coastguard Worker                          MultiRangeHttpFetcherOverFileFetcherFactory>
429*5a923131SAndroid Build Coastguard Worker     HttpFetcherTestTypes;
430*5a923131SAndroid Build Coastguard Worker TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
431*5a923131SAndroid Build Coastguard Worker 
432*5a923131SAndroid Build Coastguard Worker class HttpFetcherTestDelegate : public HttpFetcherDelegate {
433*5a923131SAndroid Build Coastguard Worker  public:
434*5a923131SAndroid Build Coastguard Worker   HttpFetcherTestDelegate() = default;
435*5a923131SAndroid Build Coastguard Worker 
ReceivedBytes(HttpFetcher *,const void * bytes,size_t length)436*5a923131SAndroid Build Coastguard Worker   bool ReceivedBytes(HttpFetcher* /* fetcher */,
437*5a923131SAndroid Build Coastguard Worker                      const void* bytes,
438*5a923131SAndroid Build Coastguard Worker                      size_t length) override {
439*5a923131SAndroid Build Coastguard Worker     data.append(reinterpret_cast<const char*>(bytes), length);
440*5a923131SAndroid Build Coastguard Worker     // Update counters
441*5a923131SAndroid Build Coastguard Worker     times_received_bytes_called_++;
442*5a923131SAndroid Build Coastguard Worker     return true;
443*5a923131SAndroid Build Coastguard Worker   }
444*5a923131SAndroid Build Coastguard Worker 
TransferComplete(HttpFetcher * fetcher,bool successful)445*5a923131SAndroid Build Coastguard Worker   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
446*5a923131SAndroid Build Coastguard Worker     if (is_expect_error_)
447*5a923131SAndroid Build Coastguard Worker       EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
448*5a923131SAndroid Build Coastguard Worker     else
449*5a923131SAndroid Build Coastguard Worker       EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
450*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
451*5a923131SAndroid Build Coastguard Worker 
452*5a923131SAndroid Build Coastguard Worker     // Update counter
453*5a923131SAndroid Build Coastguard Worker     times_transfer_complete_called_++;
454*5a923131SAndroid Build Coastguard Worker   }
455*5a923131SAndroid Build Coastguard Worker 
TransferTerminated(HttpFetcher * fetcher)456*5a923131SAndroid Build Coastguard Worker   void TransferTerminated(HttpFetcher* fetcher) override {
457*5a923131SAndroid Build Coastguard Worker     times_transfer_terminated_called_++;
458*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
459*5a923131SAndroid Build Coastguard Worker   }
460*5a923131SAndroid Build Coastguard Worker 
461*5a923131SAndroid Build Coastguard Worker   // Are we expecting an error response? (default: no)
462*5a923131SAndroid Build Coastguard Worker   bool is_expect_error_{false};
463*5a923131SAndroid Build Coastguard Worker 
464*5a923131SAndroid Build Coastguard Worker   // Counters for callback invocations.
465*5a923131SAndroid Build Coastguard Worker   int times_transfer_complete_called_{0};
466*5a923131SAndroid Build Coastguard Worker   int times_transfer_terminated_called_{0};
467*5a923131SAndroid Build Coastguard Worker   int times_received_bytes_called_{0};
468*5a923131SAndroid Build Coastguard Worker 
469*5a923131SAndroid Build Coastguard Worker   // The received data bytes.
470*5a923131SAndroid Build Coastguard Worker   string data;
471*5a923131SAndroid Build Coastguard Worker };
472*5a923131SAndroid Build Coastguard Worker 
StartTransfer(HttpFetcher * http_fetcher,const string & url)473*5a923131SAndroid Build Coastguard Worker void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
474*5a923131SAndroid Build Coastguard Worker   http_fetcher->BeginTransfer(url);
475*5a923131SAndroid Build Coastguard Worker }
476*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,SimpleTest)477*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, SimpleTest) {
478*5a923131SAndroid Build Coastguard Worker   HttpFetcherTestDelegate delegate;
479*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
480*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
481*5a923131SAndroid Build Coastguard Worker 
482*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
483*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
484*5a923131SAndroid Build Coastguard Worker 
485*5a923131SAndroid Build Coastguard Worker   this->loop_.PostTask(FROM_HERE,
486*5a923131SAndroid Build Coastguard Worker                        base::Bind(StartTransfer,
487*5a923131SAndroid Build Coastguard Worker                                   fetcher.get(),
488*5a923131SAndroid Build Coastguard Worker                                   this->test_.SmallUrl(server->GetPort())));
489*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
490*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
491*5a923131SAndroid Build Coastguard Worker }
492*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,SimpleBigTest)493*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
494*5a923131SAndroid Build Coastguard Worker   HttpFetcherTestDelegate delegate;
495*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
496*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
497*5a923131SAndroid Build Coastguard Worker 
498*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
499*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
500*5a923131SAndroid Build Coastguard Worker 
501*5a923131SAndroid Build Coastguard Worker   this->loop_.PostTask(
502*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
503*5a923131SAndroid Build Coastguard Worker       base::Bind(
504*5a923131SAndroid Build Coastguard Worker           StartTransfer, fetcher.get(), this->test_.BigUrl(server->GetPort())));
505*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
506*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
507*5a923131SAndroid Build Coastguard Worker }
508*5a923131SAndroid Build Coastguard Worker 
509*5a923131SAndroid Build Coastguard Worker // Issue #9648: when server returns an error HTTP response, the fetcher needs to
510*5a923131SAndroid Build Coastguard Worker // terminate transfer prematurely, rather than try to process the error payload.
TYPED_TEST(HttpFetcherTest,ErrorTest)511*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, ErrorTest) {
512*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock() || this->test_.IsMulti())
513*5a923131SAndroid Build Coastguard Worker     return;
514*5a923131SAndroid Build Coastguard Worker   HttpFetcherTestDelegate delegate;
515*5a923131SAndroid Build Coastguard Worker 
516*5a923131SAndroid Build Coastguard Worker   // Delegate should expect an error response.
517*5a923131SAndroid Build Coastguard Worker   delegate.is_expect_error_ = true;
518*5a923131SAndroid Build Coastguard Worker 
519*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
520*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
521*5a923131SAndroid Build Coastguard Worker 
522*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
523*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
524*5a923131SAndroid Build Coastguard Worker 
525*5a923131SAndroid Build Coastguard Worker   this->loop_.PostTask(FROM_HERE,
526*5a923131SAndroid Build Coastguard Worker                        base::Bind(StartTransfer,
527*5a923131SAndroid Build Coastguard Worker                                   fetcher.get(),
528*5a923131SAndroid Build Coastguard Worker                                   this->test_.ErrorUrl(server->GetPort())));
529*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
530*5a923131SAndroid Build Coastguard Worker 
531*5a923131SAndroid Build Coastguard Worker   // Make sure that no bytes were received.
532*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_received_bytes_called_);
533*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0U, fetcher->GetBytesDownloaded());
534*5a923131SAndroid Build Coastguard Worker 
535*5a923131SAndroid Build Coastguard Worker   // Make sure that transfer completion was signaled once, and no termination
536*5a923131SAndroid Build Coastguard Worker   // was signaled.
537*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(1, delegate.times_transfer_complete_called_);
538*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
539*5a923131SAndroid Build Coastguard Worker }
540*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,ExtraHeadersInRequestTest)541*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, ExtraHeadersInRequestTest) {
542*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock() || !this->test_.IsHttpSupported())
543*5a923131SAndroid Build Coastguard Worker     return;
544*5a923131SAndroid Build Coastguard Worker 
545*5a923131SAndroid Build Coastguard Worker   HttpFetcherTestDelegate delegate;
546*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
547*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
548*5a923131SAndroid Build Coastguard Worker   fetcher->SetHeader("User-Agent", "MyTest");
549*5a923131SAndroid Build Coastguard Worker   fetcher->SetHeader("user-agent", "Override that header");
550*5a923131SAndroid Build Coastguard Worker   fetcher->SetHeader("Authorization", "Basic user:passwd");
551*5a923131SAndroid Build Coastguard Worker   fetcher->SetHeader("Cache-Control", "testControl");
552*5a923131SAndroid Build Coastguard Worker   fetcher->SetHeader("Connection", "testConnection");
553*5a923131SAndroid Build Coastguard Worker 
554*5a923131SAndroid Build Coastguard Worker   // Invalid headers.
555*5a923131SAndroid Build Coastguard Worker   fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
556*5a923131SAndroid Build Coastguard Worker   fetcher->SetHeader("X-Bar: ", "I do not know how to parse");
557*5a923131SAndroid Build Coastguard Worker 
558*5a923131SAndroid Build Coastguard Worker   // Hide Accept header normally added by default.
559*5a923131SAndroid Build Coastguard Worker   fetcher->SetHeader("Accept", "");
560*5a923131SAndroid Build Coastguard Worker 
561*5a923131SAndroid Build Coastguard Worker   PythonHttpServer server;
562*5a923131SAndroid Build Coastguard Worker   int port = server.GetPort();
563*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server.started_);
564*5a923131SAndroid Build Coastguard Worker 
565*5a923131SAndroid Build Coastguard Worker   this->loop_.PostTask(
566*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
567*5a923131SAndroid Build Coastguard Worker       base::Bind(StartTransfer,
568*5a923131SAndroid Build Coastguard Worker                  fetcher.get(),
569*5a923131SAndroid Build Coastguard Worker                  LocalServerUrlForPath(port, "/echo-headers")));
570*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
571*5a923131SAndroid Build Coastguard Worker 
572*5a923131SAndroid Build Coastguard Worker   EXPECT_NE(string::npos,
573*5a923131SAndroid Build Coastguard Worker             delegate.data.find("user-agent: Override that header\r\n"));
574*5a923131SAndroid Build Coastguard Worker   EXPECT_NE(string::npos,
575*5a923131SAndroid Build Coastguard Worker             delegate.data.find("Authorization: Basic user:passwd\r\n"));
576*5a923131SAndroid Build Coastguard Worker   EXPECT_NE(string::npos, delegate.data.find("Cache-Control: testControl\r\n"));
577*5a923131SAndroid Build Coastguard Worker   EXPECT_NE(string::npos, delegate.data.find("Connection: testConnection\r\n"));
578*5a923131SAndroid Build Coastguard Worker 
579*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
580*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
581*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(string::npos, delegate.data.find("X-Bar: I do not"));
582*5a923131SAndroid Build Coastguard Worker }
583*5a923131SAndroid Build Coastguard Worker 
584*5a923131SAndroid Build Coastguard Worker class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
585*5a923131SAndroid Build Coastguard Worker  public:
ReceivedBytes(HttpFetcher * fetcher,const void *,size_t)586*5a923131SAndroid Build Coastguard Worker   bool ReceivedBytes(HttpFetcher* fetcher,
587*5a923131SAndroid Build Coastguard Worker                      const void* /* bytes */,
588*5a923131SAndroid Build Coastguard Worker                      size_t /* length */) override {
589*5a923131SAndroid Build Coastguard Worker     CHECK(!paused_);
590*5a923131SAndroid Build Coastguard Worker     paused_ = true;
591*5a923131SAndroid Build Coastguard Worker     fetcher->Pause();
592*5a923131SAndroid Build Coastguard Worker     return true;
593*5a923131SAndroid Build Coastguard Worker   }
TransferComplete(HttpFetcher * fetcher,bool successful)594*5a923131SAndroid Build Coastguard Worker   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
595*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
596*5a923131SAndroid Build Coastguard Worker   }
TransferTerminated(HttpFetcher * fetcher)597*5a923131SAndroid Build Coastguard Worker   void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
Unpause()598*5a923131SAndroid Build Coastguard Worker   void Unpause() {
599*5a923131SAndroid Build Coastguard Worker     CHECK(paused_);
600*5a923131SAndroid Build Coastguard Worker     paused_ = false;
601*5a923131SAndroid Build Coastguard Worker     fetcher_->Unpause();
602*5a923131SAndroid Build Coastguard Worker   }
603*5a923131SAndroid Build Coastguard Worker   bool paused_;
604*5a923131SAndroid Build Coastguard Worker   HttpFetcher* fetcher_;
605*5a923131SAndroid Build Coastguard Worker };
606*5a923131SAndroid Build Coastguard Worker 
UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate * delegate,MessageLoop::TaskId * my_id)607*5a923131SAndroid Build Coastguard Worker void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
608*5a923131SAndroid Build Coastguard Worker                               MessageLoop::TaskId* my_id) {
609*5a923131SAndroid Build Coastguard Worker   if (delegate->paused_)
610*5a923131SAndroid Build Coastguard Worker     delegate->Unpause();
611*5a923131SAndroid Build Coastguard Worker   // Update the task id with the new scheduled callback.
612*5a923131SAndroid Build Coastguard Worker   *my_id = MessageLoop::current()->PostDelayedTask(
613*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
614*5a923131SAndroid Build Coastguard Worker       base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
615*5a923131SAndroid Build Coastguard Worker       base::TimeDelta::FromMilliseconds(200));
616*5a923131SAndroid Build Coastguard Worker }
617*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,PauseTest)618*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, PauseTest) {
619*5a923131SAndroid Build Coastguard Worker   PausingHttpFetcherTestDelegate delegate;
620*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
621*5a923131SAndroid Build Coastguard Worker   delegate.paused_ = false;
622*5a923131SAndroid Build Coastguard Worker   delegate.fetcher_ = fetcher.get();
623*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
624*5a923131SAndroid Build Coastguard Worker 
625*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
626*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
627*5a923131SAndroid Build Coastguard Worker 
628*5a923131SAndroid Build Coastguard Worker   MessageLoop::TaskId callback_id{};
629*5a923131SAndroid Build Coastguard Worker   callback_id = this->loop_.PostDelayedTask(
630*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
631*5a923131SAndroid Build Coastguard Worker       base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
632*5a923131SAndroid Build Coastguard Worker       base::TimeDelta::FromMilliseconds(200));
633*5a923131SAndroid Build Coastguard Worker   fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
634*5a923131SAndroid Build Coastguard Worker 
635*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
636*5a923131SAndroid Build Coastguard Worker   EXPECT_TRUE(this->loop_.CancelTask(callback_id));
637*5a923131SAndroid Build Coastguard Worker }
638*5a923131SAndroid Build Coastguard Worker 
639*5a923131SAndroid Build Coastguard Worker // This test will pause the fetcher while the download is not yet started
640*5a923131SAndroid Build Coastguard Worker // because it is waiting for the proxy to be resolved.
TYPED_TEST(HttpFetcherTest,PauseWhileResolvingProxyTest)641*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, PauseWhileResolvingProxyTest) {
642*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock() || !this->test_.IsHttpSupported())
643*5a923131SAndroid Build Coastguard Worker     return;
644*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
645*5a923131SAndroid Build Coastguard Worker 
646*5a923131SAndroid Build Coastguard Worker   // Saved arguments from the proxy call.
647*5a923131SAndroid Build Coastguard Worker   fetcher->BeginTransfer("http://fake_url");
648*5a923131SAndroid Build Coastguard Worker 
649*5a923131SAndroid Build Coastguard Worker   // Pausing and unpausing while resolving the proxy should not affect anything.
650*5a923131SAndroid Build Coastguard Worker   fetcher->Pause();
651*5a923131SAndroid Build Coastguard Worker   fetcher->Unpause();
652*5a923131SAndroid Build Coastguard Worker   fetcher->Pause();
653*5a923131SAndroid Build Coastguard Worker   // Proxy resolver comes back after we paused the fetcher.
654*5a923131SAndroid Build Coastguard Worker }
655*5a923131SAndroid Build Coastguard Worker 
656*5a923131SAndroid Build Coastguard Worker class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
657*5a923131SAndroid Build Coastguard Worker  public:
ReceivedBytes(HttpFetcher * fetcher,const void * bytes,size_t length)658*5a923131SAndroid Build Coastguard Worker   bool ReceivedBytes(HttpFetcher* fetcher,
659*5a923131SAndroid Build Coastguard Worker                      const void* bytes,
660*5a923131SAndroid Build Coastguard Worker                      size_t length) override {
661*5a923131SAndroid Build Coastguard Worker     return true;
662*5a923131SAndroid Build Coastguard Worker   }
TransferComplete(HttpFetcher * fetcher,bool successful)663*5a923131SAndroid Build Coastguard Worker   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
664*5a923131SAndroid Build Coastguard Worker     ADD_FAILURE();  // We should never get here
665*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
666*5a923131SAndroid Build Coastguard Worker   }
TransferTerminated(HttpFetcher * fetcher)667*5a923131SAndroid Build Coastguard Worker   void TransferTerminated(HttpFetcher* fetcher) override {
668*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(fetcher, fetcher_.get());
669*5a923131SAndroid Build Coastguard Worker     EXPECT_FALSE(once_);
670*5a923131SAndroid Build Coastguard Worker     EXPECT_TRUE(callback_once_);
671*5a923131SAndroid Build Coastguard Worker     callback_once_ = false;
672*5a923131SAndroid Build Coastguard Worker     // The fetcher could have a callback scheduled on the ProxyResolver that
673*5a923131SAndroid Build Coastguard Worker     // can fire after this callback. We wait until the end of the test to
674*5a923131SAndroid Build Coastguard Worker     // delete the fetcher.
675*5a923131SAndroid Build Coastguard Worker   }
TerminateTransfer()676*5a923131SAndroid Build Coastguard Worker   void TerminateTransfer() {
677*5a923131SAndroid Build Coastguard Worker     CHECK(once_);
678*5a923131SAndroid Build Coastguard Worker     once_ = false;
679*5a923131SAndroid Build Coastguard Worker     fetcher_->TerminateTransfer();
680*5a923131SAndroid Build Coastguard Worker   }
EndLoop()681*5a923131SAndroid Build Coastguard Worker   void EndLoop() { MessageLoop::current()->BreakLoop(); }
682*5a923131SAndroid Build Coastguard Worker   bool once_;
683*5a923131SAndroid Build Coastguard Worker   bool callback_once_;
684*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher_;
685*5a923131SAndroid Build Coastguard Worker };
686*5a923131SAndroid Build Coastguard Worker 
AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate * delegate,MessageLoop::TaskId * my_id)687*5a923131SAndroid Build Coastguard Worker void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
688*5a923131SAndroid Build Coastguard Worker                              MessageLoop::TaskId* my_id) {
689*5a923131SAndroid Build Coastguard Worker   if (delegate->once_) {
690*5a923131SAndroid Build Coastguard Worker     delegate->TerminateTransfer();
691*5a923131SAndroid Build Coastguard Worker     *my_id = MessageLoop::current()->PostTask(
692*5a923131SAndroid Build Coastguard Worker         FROM_HERE, base::Bind(AbortingTimeoutCallback, delegate, my_id));
693*5a923131SAndroid Build Coastguard Worker   } else {
694*5a923131SAndroid Build Coastguard Worker     delegate->EndLoop();
695*5a923131SAndroid Build Coastguard Worker     *my_id = MessageLoop::kTaskIdNull;
696*5a923131SAndroid Build Coastguard Worker   }
697*5a923131SAndroid Build Coastguard Worker }
698*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,AbortTest)699*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, AbortTest) {
700*5a923131SAndroid Build Coastguard Worker   AbortingHttpFetcherTestDelegate delegate;
701*5a923131SAndroid Build Coastguard Worker   delegate.fetcher_.reset(this->test_.NewLargeFetcher());
702*5a923131SAndroid Build Coastguard Worker   delegate.once_ = true;
703*5a923131SAndroid Build Coastguard Worker   delegate.callback_once_ = true;
704*5a923131SAndroid Build Coastguard Worker   delegate.fetcher_->set_delegate(&delegate);
705*5a923131SAndroid Build Coastguard Worker 
706*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
707*5a923131SAndroid Build Coastguard Worker   this->test_.IgnoreServerAborting(server.get());
708*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
709*5a923131SAndroid Build Coastguard Worker 
710*5a923131SAndroid Build Coastguard Worker   MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
711*5a923131SAndroid Build Coastguard Worker 
712*5a923131SAndroid Build Coastguard Worker   task_id = this->loop_.PostTask(
713*5a923131SAndroid Build Coastguard Worker       FROM_HERE, base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
714*5a923131SAndroid Build Coastguard Worker   delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
715*5a923131SAndroid Build Coastguard Worker 
716*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
717*5a923131SAndroid Build Coastguard Worker   CHECK(!delegate.once_);
718*5a923131SAndroid Build Coastguard Worker   CHECK(!delegate.callback_once_);
719*5a923131SAndroid Build Coastguard Worker   this->loop_.CancelTask(task_id);
720*5a923131SAndroid Build Coastguard Worker }
721*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,TerminateTransferWhileResolvingProxyTest)722*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, TerminateTransferWhileResolvingProxyTest) {
723*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock() || !this->test_.IsHttpSupported())
724*5a923131SAndroid Build Coastguard Worker     return;
725*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
726*5a923131SAndroid Build Coastguard Worker 
727*5a923131SAndroid Build Coastguard Worker   HttpFetcherTestDelegate delegate;
728*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
729*5a923131SAndroid Build Coastguard Worker 
730*5a923131SAndroid Build Coastguard Worker   fetcher->BeginTransfer("http://fake_url");
731*5a923131SAndroid Build Coastguard Worker   // Run the message loop until idle. This must call the MockProxyResolver with
732*5a923131SAndroid Build Coastguard Worker   // the request.
733*5a923131SAndroid Build Coastguard Worker   while (this->loop_.RunOnce(false)) {
734*5a923131SAndroid Build Coastguard Worker   }
735*5a923131SAndroid Build Coastguard Worker 
736*5a923131SAndroid Build Coastguard Worker   // Terminate the transfer right before the proxy resolution response.
737*5a923131SAndroid Build Coastguard Worker   fetcher->TerminateTransfer();
738*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_received_bytes_called_);
739*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_transfer_complete_called_);
740*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
741*5a923131SAndroid Build Coastguard Worker }
742*5a923131SAndroid Build Coastguard Worker 
743*5a923131SAndroid Build Coastguard Worker class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
744*5a923131SAndroid Build Coastguard Worker  public:
ReceivedBytes(HttpFetcher * fetcher,const void * bytes,size_t length)745*5a923131SAndroid Build Coastguard Worker   bool ReceivedBytes(HttpFetcher* fetcher,
746*5a923131SAndroid Build Coastguard Worker                      const void* bytes,
747*5a923131SAndroid Build Coastguard Worker                      size_t length) override {
748*5a923131SAndroid Build Coastguard Worker     data.append(reinterpret_cast<const char*>(bytes), length);
749*5a923131SAndroid Build Coastguard Worker     return true;
750*5a923131SAndroid Build Coastguard Worker   }
TransferComplete(HttpFetcher * fetcher,bool successful)751*5a923131SAndroid Build Coastguard Worker   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
752*5a923131SAndroid Build Coastguard Worker     EXPECT_TRUE(successful);
753*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
754*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
755*5a923131SAndroid Build Coastguard Worker   }
TransferTerminated(HttpFetcher * fetcher)756*5a923131SAndroid Build Coastguard Worker   void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
757*5a923131SAndroid Build Coastguard Worker   string data;
758*5a923131SAndroid Build Coastguard Worker };
759*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,FlakyTest)760*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, FlakyTest) {
761*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock() || !this->test_.IsHttpSupported())
762*5a923131SAndroid Build Coastguard Worker     return;
763*5a923131SAndroid Build Coastguard Worker   {
764*5a923131SAndroid Build Coastguard Worker     FlakyHttpFetcherTestDelegate delegate;
765*5a923131SAndroid Build Coastguard Worker     unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
766*5a923131SAndroid Build Coastguard Worker     fetcher->set_delegate(&delegate);
767*5a923131SAndroid Build Coastguard Worker 
768*5a923131SAndroid Build Coastguard Worker     unique_ptr<HttpServer> server(this->test_.CreateServer());
769*5a923131SAndroid Build Coastguard Worker     ASSERT_TRUE(server->started_);
770*5a923131SAndroid Build Coastguard Worker 
771*5a923131SAndroid Build Coastguard Worker     this->loop_.PostTask(
772*5a923131SAndroid Build Coastguard Worker         FROM_HERE,
773*5a923131SAndroid Build Coastguard Worker         base::Bind(&StartTransfer,
774*5a923131SAndroid Build Coastguard Worker                    fetcher.get(),
775*5a923131SAndroid Build Coastguard Worker                    LocalServerUrlForPath(
776*5a923131SAndroid Build Coastguard Worker                        server->GetPort(),
777*5a923131SAndroid Build Coastguard Worker                        android::base::StringPrintf("/flaky/%d/%d/%d/%d",
778*5a923131SAndroid Build Coastguard Worker                                                    kBigLength,
779*5a923131SAndroid Build Coastguard Worker                                                    kFlakyTruncateLength,
780*5a923131SAndroid Build Coastguard Worker                                                    kFlakySleepEvery,
781*5a923131SAndroid Build Coastguard Worker                                                    kFlakySleepSecs))));
782*5a923131SAndroid Build Coastguard Worker     this->loop_.Run();
783*5a923131SAndroid Build Coastguard Worker 
784*5a923131SAndroid Build Coastguard Worker     // verify the data we get back
785*5a923131SAndroid Build Coastguard Worker     ASSERT_EQ(kBigLength, static_cast<int>(delegate.data.size()));
786*5a923131SAndroid Build Coastguard Worker     for (int i = 0; i < kBigLength; i += 10) {
787*5a923131SAndroid Build Coastguard Worker       // Assert so that we don't flood the screen w/ EXPECT errors on failure.
788*5a923131SAndroid Build Coastguard Worker       ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
789*5a923131SAndroid Build Coastguard Worker     }
790*5a923131SAndroid Build Coastguard Worker   }
791*5a923131SAndroid Build Coastguard Worker }
792*5a923131SAndroid Build Coastguard Worker 
793*5a923131SAndroid Build Coastguard Worker // This delegate kills the server attached to it after receiving any bytes.
794*5a923131SAndroid Build Coastguard Worker // This can be used for testing what happens when you try to fetch data and
795*5a923131SAndroid Build Coastguard Worker // the server dies.
796*5a923131SAndroid Build Coastguard Worker class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
797*5a923131SAndroid Build Coastguard Worker  public:
FailureHttpFetcherTestDelegate(PythonHttpServer * server)798*5a923131SAndroid Build Coastguard Worker   explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
799*5a923131SAndroid Build Coastguard Worker       : server_(server) {}
800*5a923131SAndroid Build Coastguard Worker 
~FailureHttpFetcherTestDelegate()801*5a923131SAndroid Build Coastguard Worker   ~FailureHttpFetcherTestDelegate() override {
802*5a923131SAndroid Build Coastguard Worker     if (server_) {
803*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "Stopping server in destructor";
804*5a923131SAndroid Build Coastguard Worker       server_.reset();
805*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "server stopped";
806*5a923131SAndroid Build Coastguard Worker     }
807*5a923131SAndroid Build Coastguard Worker   }
808*5a923131SAndroid Build Coastguard Worker 
ReceivedBytes(HttpFetcher * fetcher,const void * bytes,size_t length)809*5a923131SAndroid Build Coastguard Worker   bool ReceivedBytes(HttpFetcher* fetcher,
810*5a923131SAndroid Build Coastguard Worker                      const void* bytes,
811*5a923131SAndroid Build Coastguard Worker                      size_t length) override {
812*5a923131SAndroid Build Coastguard Worker     if (server_) {
813*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "Stopping server in ReceivedBytes";
814*5a923131SAndroid Build Coastguard Worker       server_.reset();
815*5a923131SAndroid Build Coastguard Worker       LOG(INFO) << "server stopped";
816*5a923131SAndroid Build Coastguard Worker     }
817*5a923131SAndroid Build Coastguard Worker     return true;
818*5a923131SAndroid Build Coastguard Worker   }
TransferComplete(HttpFetcher * fetcher,bool successful)819*5a923131SAndroid Build Coastguard Worker   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
820*5a923131SAndroid Build Coastguard Worker     EXPECT_FALSE(successful);
821*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(0, fetcher->http_response_code());
822*5a923131SAndroid Build Coastguard Worker     times_transfer_complete_called_++;
823*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
824*5a923131SAndroid Build Coastguard Worker   }
TransferTerminated(HttpFetcher * fetcher)825*5a923131SAndroid Build Coastguard Worker   void TransferTerminated(HttpFetcher* fetcher) override {
826*5a923131SAndroid Build Coastguard Worker     times_transfer_terminated_called_++;
827*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
828*5a923131SAndroid Build Coastguard Worker   }
829*5a923131SAndroid Build Coastguard Worker   unique_ptr<PythonHttpServer> server_;
830*5a923131SAndroid Build Coastguard Worker   int times_transfer_terminated_called_{0};
831*5a923131SAndroid Build Coastguard Worker   int times_transfer_complete_called_{0};
832*5a923131SAndroid Build Coastguard Worker };
833*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,FailureTest)834*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, FailureTest) {
835*5a923131SAndroid Build Coastguard Worker   // This test ensures that a fetcher responds correctly when a server isn't
836*5a923131SAndroid Build Coastguard Worker   // available at all.
837*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock())
838*5a923131SAndroid Build Coastguard Worker     return;
839*5a923131SAndroid Build Coastguard Worker   FailureHttpFetcherTestDelegate delegate(nullptr);
840*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
841*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
842*5a923131SAndroid Build Coastguard Worker 
843*5a923131SAndroid Build Coastguard Worker   this->loop_.PostTask(
844*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
845*5a923131SAndroid Build Coastguard Worker       base::Bind(
846*5a923131SAndroid Build Coastguard Worker           StartTransfer, fetcher.get(), "http://host_doesnt_exist99999999"));
847*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
848*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(1, delegate.times_transfer_complete_called_);
849*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
850*5a923131SAndroid Build Coastguard Worker 
851*5a923131SAndroid Build Coastguard Worker   // Exiting and testing happens in the delegate
852*5a923131SAndroid Build Coastguard Worker }
853*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,NoResponseTest)854*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, NoResponseTest) {
855*5a923131SAndroid Build Coastguard Worker   // This test starts a new http server but the server doesn't respond and just
856*5a923131SAndroid Build Coastguard Worker   // closes the connection.
857*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock())
858*5a923131SAndroid Build Coastguard Worker     return;
859*5a923131SAndroid Build Coastguard Worker 
860*5a923131SAndroid Build Coastguard Worker   PythonHttpServer* server = new PythonHttpServer();
861*5a923131SAndroid Build Coastguard Worker   int port = server->GetPort();
862*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
863*5a923131SAndroid Build Coastguard Worker 
864*5a923131SAndroid Build Coastguard Worker   // Handles destruction and claims ownership.
865*5a923131SAndroid Build Coastguard Worker   FailureHttpFetcherTestDelegate delegate(server);
866*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
867*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
868*5a923131SAndroid Build Coastguard Worker   // The server will not reply at all, so we can limit the execution time of the
869*5a923131SAndroid Build Coastguard Worker   // test by reducing the low-speed timeout to something small. The test will
870*5a923131SAndroid Build Coastguard Worker   // finish once the TimeoutCallback() triggers (every second) and the timeout
871*5a923131SAndroid Build Coastguard Worker   // expired.
872*5a923131SAndroid Build Coastguard Worker   fetcher->set_low_speed_limit(kDownloadLowSpeedLimitBps, 1);
873*5a923131SAndroid Build Coastguard Worker 
874*5a923131SAndroid Build Coastguard Worker   this->loop_.PostTask(
875*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
876*5a923131SAndroid Build Coastguard Worker       base::Bind(
877*5a923131SAndroid Build Coastguard Worker           StartTransfer, fetcher.get(), LocalServerUrlForPath(port, "/hang")));
878*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
879*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(1, delegate.times_transfer_complete_called_);
880*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
881*5a923131SAndroid Build Coastguard Worker 
882*5a923131SAndroid Build Coastguard Worker   // Check that no other callback runs in the next two seconds. That would
883*5a923131SAndroid Build Coastguard Worker   // indicate a leaked callback.
884*5a923131SAndroid Build Coastguard Worker   bool timeout = false;
885*5a923131SAndroid Build Coastguard Worker   auto callback = base::Bind([](bool* timeout) { *timeout = true; },
886*5a923131SAndroid Build Coastguard Worker                              base::Unretained(&timeout));
887*5a923131SAndroid Build Coastguard Worker   this->loop_.PostDelayedTask(
888*5a923131SAndroid Build Coastguard Worker       FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
889*5a923131SAndroid Build Coastguard Worker   EXPECT_TRUE(this->loop_.RunOnce(true));
890*5a923131SAndroid Build Coastguard Worker   EXPECT_TRUE(timeout);
891*5a923131SAndroid Build Coastguard Worker }
892*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,ServerDiesTest)893*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
894*5a923131SAndroid Build Coastguard Worker   // This test starts a new http server and kills it after receiving its first
895*5a923131SAndroid Build Coastguard Worker   // set of bytes. It test whether or not our fetcher eventually gives up on
896*5a923131SAndroid Build Coastguard Worker   // retries and aborts correctly.
897*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock())
898*5a923131SAndroid Build Coastguard Worker     return;
899*5a923131SAndroid Build Coastguard Worker   PythonHttpServer* server = new PythonHttpServer();
900*5a923131SAndroid Build Coastguard Worker   int port = server->GetPort();
901*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
902*5a923131SAndroid Build Coastguard Worker 
903*5a923131SAndroid Build Coastguard Worker   // Handles destruction and claims ownership.
904*5a923131SAndroid Build Coastguard Worker   FailureHttpFetcherTestDelegate delegate(server);
905*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
906*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
907*5a923131SAndroid Build Coastguard Worker 
908*5a923131SAndroid Build Coastguard Worker   this->loop_.PostTask(
909*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
910*5a923131SAndroid Build Coastguard Worker       base::Bind(StartTransfer,
911*5a923131SAndroid Build Coastguard Worker                  fetcher.get(),
912*5a923131SAndroid Build Coastguard Worker                  LocalServerUrlForPath(
913*5a923131SAndroid Build Coastguard Worker                      port,
914*5a923131SAndroid Build Coastguard Worker                      android::base::StringPrintf("/flaky/%d/%d/%d/%d",
915*5a923131SAndroid Build Coastguard Worker                                                  kBigLength,
916*5a923131SAndroid Build Coastguard Worker                                                  kFlakyTruncateLength,
917*5a923131SAndroid Build Coastguard Worker                                                  kFlakySleepEvery,
918*5a923131SAndroid Build Coastguard Worker                                                  kFlakySleepSecs))));
919*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
920*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(1, delegate.times_transfer_complete_called_);
921*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_transfer_terminated_called_);
922*5a923131SAndroid Build Coastguard Worker 
923*5a923131SAndroid Build Coastguard Worker   // Exiting and testing happens in the delegate
924*5a923131SAndroid Build Coastguard Worker }
925*5a923131SAndroid Build Coastguard Worker 
926*5a923131SAndroid Build Coastguard Worker // Test that we can cancel a transfer while it is still trying to connect to the
927*5a923131SAndroid Build Coastguard Worker // server. This test kills the server after a few bytes are received.
TYPED_TEST(HttpFetcherTest,TerminateTransferWhenServerDiedTest)928*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, TerminateTransferWhenServerDiedTest) {
929*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock() || !this->test_.IsHttpSupported())
930*5a923131SAndroid Build Coastguard Worker     return;
931*5a923131SAndroid Build Coastguard Worker 
932*5a923131SAndroid Build Coastguard Worker   PythonHttpServer* server = new PythonHttpServer();
933*5a923131SAndroid Build Coastguard Worker   int port = server->GetPort();
934*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
935*5a923131SAndroid Build Coastguard Worker 
936*5a923131SAndroid Build Coastguard Worker   // Handles destruction and claims ownership.
937*5a923131SAndroid Build Coastguard Worker   FailureHttpFetcherTestDelegate delegate(server);
938*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
939*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
940*5a923131SAndroid Build Coastguard Worker 
941*5a923131SAndroid Build Coastguard Worker   this->loop_.PostTask(
942*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
943*5a923131SAndroid Build Coastguard Worker       base::Bind(StartTransfer,
944*5a923131SAndroid Build Coastguard Worker                  fetcher.get(),
945*5a923131SAndroid Build Coastguard Worker                  LocalServerUrlForPath(
946*5a923131SAndroid Build Coastguard Worker                      port,
947*5a923131SAndroid Build Coastguard Worker                      android::base::StringPrintf("/flaky/%d/%d/%d/%d",
948*5a923131SAndroid Build Coastguard Worker                                                  kBigLength,
949*5a923131SAndroid Build Coastguard Worker                                                  kFlakyTruncateLength,
950*5a923131SAndroid Build Coastguard Worker                                                  kFlakySleepEvery,
951*5a923131SAndroid Build Coastguard Worker                                                  kFlakySleepSecs))));
952*5a923131SAndroid Build Coastguard Worker   // Terminating the transfer after 3 seconds gives it a chance to contact the
953*5a923131SAndroid Build Coastguard Worker   // server and enter the retry loop.
954*5a923131SAndroid Build Coastguard Worker   this->loop_.PostDelayedTask(FROM_HERE,
955*5a923131SAndroid Build Coastguard Worker                               base::Bind(&HttpFetcher::TerminateTransfer,
956*5a923131SAndroid Build Coastguard Worker                                          base::Unretained(fetcher.get())),
957*5a923131SAndroid Build Coastguard Worker                               base::TimeDelta::FromSeconds(3));
958*5a923131SAndroid Build Coastguard Worker 
959*5a923131SAndroid Build Coastguard Worker   // Exiting and testing happens in the delegate.
960*5a923131SAndroid Build Coastguard Worker   this->loop_.Run();
961*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(0, delegate.times_transfer_complete_called_);
962*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(1, delegate.times_transfer_terminated_called_);
963*5a923131SAndroid Build Coastguard Worker 
964*5a923131SAndroid Build Coastguard Worker   // Check that no other callback runs in the next two seconds. That would
965*5a923131SAndroid Build Coastguard Worker   // indicate a leaked callback.
966*5a923131SAndroid Build Coastguard Worker   bool timeout = false;
967*5a923131SAndroid Build Coastguard Worker   auto callback = base::Bind([](bool* timeout) { *timeout = true; },
968*5a923131SAndroid Build Coastguard Worker                              base::Unretained(&timeout));
969*5a923131SAndroid Build Coastguard Worker   this->loop_.PostDelayedTask(
970*5a923131SAndroid Build Coastguard Worker       FROM_HERE, callback, base::TimeDelta::FromSeconds(2));
971*5a923131SAndroid Build Coastguard Worker   EXPECT_TRUE(this->loop_.RunOnce(true));
972*5a923131SAndroid Build Coastguard Worker   EXPECT_TRUE(timeout);
973*5a923131SAndroid Build Coastguard Worker }
974*5a923131SAndroid Build Coastguard Worker 
975*5a923131SAndroid Build Coastguard Worker const HttpResponseCode kRedirectCodes[] = {kHttpResponseMovedPermanently,
976*5a923131SAndroid Build Coastguard Worker                                            kHttpResponseFound,
977*5a923131SAndroid Build Coastguard Worker                                            kHttpResponseSeeOther,
978*5a923131SAndroid Build Coastguard Worker                                            kHttpResponseTempRedirect};
979*5a923131SAndroid Build Coastguard Worker 
980*5a923131SAndroid Build Coastguard Worker class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
981*5a923131SAndroid Build Coastguard Worker  public:
RedirectHttpFetcherTestDelegate(bool expected_successful)982*5a923131SAndroid Build Coastguard Worker   explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
983*5a923131SAndroid Build Coastguard Worker       : expected_successful_(expected_successful) {}
ReceivedBytes(HttpFetcher * fetcher,const void * bytes,size_t length)984*5a923131SAndroid Build Coastguard Worker   bool ReceivedBytes(HttpFetcher* fetcher,
985*5a923131SAndroid Build Coastguard Worker                      const void* bytes,
986*5a923131SAndroid Build Coastguard Worker                      size_t length) override {
987*5a923131SAndroid Build Coastguard Worker     data.append(reinterpret_cast<const char*>(bytes), length);
988*5a923131SAndroid Build Coastguard Worker     return true;
989*5a923131SAndroid Build Coastguard Worker   }
TransferComplete(HttpFetcher * fetcher,bool successful)990*5a923131SAndroid Build Coastguard Worker   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
991*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(expected_successful_, successful);
992*5a923131SAndroid Build Coastguard Worker     if (expected_successful_) {
993*5a923131SAndroid Build Coastguard Worker       EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
994*5a923131SAndroid Build Coastguard Worker     } else {
995*5a923131SAndroid Build Coastguard Worker       EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
996*5a923131SAndroid Build Coastguard Worker       EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
997*5a923131SAndroid Build Coastguard Worker     }
998*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
999*5a923131SAndroid Build Coastguard Worker   }
TransferTerminated(HttpFetcher * fetcher)1000*5a923131SAndroid Build Coastguard Worker   void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
1001*5a923131SAndroid Build Coastguard Worker   bool expected_successful_;
1002*5a923131SAndroid Build Coastguard Worker   string data;
1003*5a923131SAndroid Build Coastguard Worker };
1004*5a923131SAndroid Build Coastguard Worker 
1005*5a923131SAndroid Build Coastguard Worker // RedirectTest takes ownership of |http_fetcher|.
RedirectTest(const HttpServer * server,bool expected_successful,const string & url,HttpFetcher * http_fetcher)1006*5a923131SAndroid Build Coastguard Worker void RedirectTest(const HttpServer* server,
1007*5a923131SAndroid Build Coastguard Worker                   bool expected_successful,
1008*5a923131SAndroid Build Coastguard Worker                   const string& url,
1009*5a923131SAndroid Build Coastguard Worker                   HttpFetcher* http_fetcher) {
1010*5a923131SAndroid Build Coastguard Worker   RedirectHttpFetcherTestDelegate delegate(expected_successful);
1011*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(http_fetcher);
1012*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
1013*5a923131SAndroid Build Coastguard Worker 
1014*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->PostTask(
1015*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
1016*5a923131SAndroid Build Coastguard Worker       base::Bind(StartTransfer,
1017*5a923131SAndroid Build Coastguard Worker                  fetcher.get(),
1018*5a923131SAndroid Build Coastguard Worker                  LocalServerUrlForPath(server->GetPort(), url)));
1019*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->Run();
1020*5a923131SAndroid Build Coastguard Worker   if (expected_successful) {
1021*5a923131SAndroid Build Coastguard Worker     // verify the data we get back
1022*5a923131SAndroid Build Coastguard Worker     ASSERT_EQ(static_cast<size_t>(kMediumLength), delegate.data.size());
1023*5a923131SAndroid Build Coastguard Worker     for (int i = 0; i < kMediumLength; i += 10) {
1024*5a923131SAndroid Build Coastguard Worker       // Assert so that we don't flood the screen w/ EXPECT errors on failure.
1025*5a923131SAndroid Build Coastguard Worker       ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
1026*5a923131SAndroid Build Coastguard Worker     }
1027*5a923131SAndroid Build Coastguard Worker   }
1028*5a923131SAndroid Build Coastguard Worker }
1029*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,SimpleRedirectTest)1030*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
1031*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock() || !this->test_.IsHttpSupported())
1032*5a923131SAndroid Build Coastguard Worker     return;
1033*5a923131SAndroid Build Coastguard Worker 
1034*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1035*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1036*5a923131SAndroid Build Coastguard Worker 
1037*5a923131SAndroid Build Coastguard Worker   for (size_t c = 0; c < base::size(kRedirectCodes); ++c) {
1038*5a923131SAndroid Build Coastguard Worker     const string url = android::base::StringPrintf(
1039*5a923131SAndroid Build Coastguard Worker         "/redirect/%d/download/%d", kRedirectCodes[c], kMediumLength);
1040*5a923131SAndroid Build Coastguard Worker     RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
1041*5a923131SAndroid Build Coastguard Worker   }
1042*5a923131SAndroid Build Coastguard Worker }
1043*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,MaxRedirectTest)1044*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
1045*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock() || !this->test_.IsHttpSupported())
1046*5a923131SAndroid Build Coastguard Worker     return;
1047*5a923131SAndroid Build Coastguard Worker 
1048*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1049*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1050*5a923131SAndroid Build Coastguard Worker 
1051*5a923131SAndroid Build Coastguard Worker   string url;
1052*5a923131SAndroid Build Coastguard Worker   for (int r = 0; r < kDownloadMaxRedirects; r++) {
1053*5a923131SAndroid Build Coastguard Worker     url += android::base::StringPrintf(
1054*5a923131SAndroid Build Coastguard Worker         "/redirect/%d", kRedirectCodes[r % base::size(kRedirectCodes)]);
1055*5a923131SAndroid Build Coastguard Worker   }
1056*5a923131SAndroid Build Coastguard Worker   url += android::base::StringPrintf("/download/%d", kMediumLength);
1057*5a923131SAndroid Build Coastguard Worker   RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
1058*5a923131SAndroid Build Coastguard Worker }
1059*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,BeyondMaxRedirectTest)1060*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
1061*5a923131SAndroid Build Coastguard Worker   if (this->test_.IsMock() || !this->test_.IsHttpSupported())
1062*5a923131SAndroid Build Coastguard Worker     return;
1063*5a923131SAndroid Build Coastguard Worker 
1064*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1065*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1066*5a923131SAndroid Build Coastguard Worker 
1067*5a923131SAndroid Build Coastguard Worker   string url;
1068*5a923131SAndroid Build Coastguard Worker   for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
1069*5a923131SAndroid Build Coastguard Worker     url += android::base::StringPrintf(
1070*5a923131SAndroid Build Coastguard Worker         "/redirect/%d", kRedirectCodes[r % base::size(kRedirectCodes)]);
1071*5a923131SAndroid Build Coastguard Worker   }
1072*5a923131SAndroid Build Coastguard Worker   url += android::base::StringPrintf("/download/%d", kMediumLength);
1073*5a923131SAndroid Build Coastguard Worker   RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
1074*5a923131SAndroid Build Coastguard Worker }
1075*5a923131SAndroid Build Coastguard Worker 
1076*5a923131SAndroid Build Coastguard Worker class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1077*5a923131SAndroid Build Coastguard Worker  public:
MultiHttpFetcherTestDelegate(int expected_response_code)1078*5a923131SAndroid Build Coastguard Worker   explicit MultiHttpFetcherTestDelegate(int expected_response_code)
1079*5a923131SAndroid Build Coastguard Worker       : expected_response_code_(expected_response_code) {}
1080*5a923131SAndroid Build Coastguard Worker 
ReceivedBytes(HttpFetcher * fetcher,const void * bytes,size_t length)1081*5a923131SAndroid Build Coastguard Worker   bool ReceivedBytes(HttpFetcher* fetcher,
1082*5a923131SAndroid Build Coastguard Worker                      const void* bytes,
1083*5a923131SAndroid Build Coastguard Worker                      size_t length) override {
1084*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(fetcher, fetcher_.get());
1085*5a923131SAndroid Build Coastguard Worker     data.append(reinterpret_cast<const char*>(bytes), length);
1086*5a923131SAndroid Build Coastguard Worker     return true;
1087*5a923131SAndroid Build Coastguard Worker   }
1088*5a923131SAndroid Build Coastguard Worker 
TransferComplete(HttpFetcher * fetcher,bool successful)1089*5a923131SAndroid Build Coastguard Worker   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1090*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(fetcher, fetcher_.get());
1091*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
1092*5a923131SAndroid Build Coastguard Worker     if (expected_response_code_ != 0)
1093*5a923131SAndroid Build Coastguard Worker       EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
1094*5a923131SAndroid Build Coastguard Worker     // Destroy the fetcher (because we're allowed to).
1095*5a923131SAndroid Build Coastguard Worker     fetcher_.reset(nullptr);
1096*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
1097*5a923131SAndroid Build Coastguard Worker   }
1098*5a923131SAndroid Build Coastguard Worker 
TransferTerminated(HttpFetcher * fetcher)1099*5a923131SAndroid Build Coastguard Worker   void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
1100*5a923131SAndroid Build Coastguard Worker 
1101*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher_;
1102*5a923131SAndroid Build Coastguard Worker   int expected_response_code_;
1103*5a923131SAndroid Build Coastguard Worker   string data;
1104*5a923131SAndroid Build Coastguard Worker };
1105*5a923131SAndroid Build Coastguard Worker 
MultiTest(HttpFetcher * fetcher_in,FakeHardware * fake_hardware,const string & url,const vector<pair<off_t,off_t>> & ranges,const string & expected_prefix,size_t expected_size,HttpResponseCode expected_response_code)1106*5a923131SAndroid Build Coastguard Worker void MultiTest(HttpFetcher* fetcher_in,
1107*5a923131SAndroid Build Coastguard Worker                FakeHardware* fake_hardware,
1108*5a923131SAndroid Build Coastguard Worker                const string& url,
1109*5a923131SAndroid Build Coastguard Worker                const vector<pair<off_t, off_t>>& ranges,
1110*5a923131SAndroid Build Coastguard Worker                const string& expected_prefix,
1111*5a923131SAndroid Build Coastguard Worker                size_t expected_size,
1112*5a923131SAndroid Build Coastguard Worker                HttpResponseCode expected_response_code) {
1113*5a923131SAndroid Build Coastguard Worker   MultiHttpFetcherTestDelegate delegate(expected_response_code);
1114*5a923131SAndroid Build Coastguard Worker   delegate.fetcher_.reset(fetcher_in);
1115*5a923131SAndroid Build Coastguard Worker 
1116*5a923131SAndroid Build Coastguard Worker   MultiRangeHttpFetcher* multi_fetcher =
1117*5a923131SAndroid Build Coastguard Worker       static_cast<MultiRangeHttpFetcher*>(fetcher_in);
1118*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(multi_fetcher);
1119*5a923131SAndroid Build Coastguard Worker   multi_fetcher->ClearRanges();
1120*5a923131SAndroid Build Coastguard Worker   for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
1121*5a923131SAndroid Build Coastguard Worker                                                   e = ranges.end();
1122*5a923131SAndroid Build Coastguard Worker        it != e;
1123*5a923131SAndroid Build Coastguard Worker        ++it) {
1124*5a923131SAndroid Build Coastguard Worker     string tmp_str = android::base::StringPrintf("%jd+", it->first);
1125*5a923131SAndroid Build Coastguard Worker     if (it->second > 0) {
1126*5a923131SAndroid Build Coastguard Worker       android::base::StringAppendF(&tmp_str, "%jd", it->second);
1127*5a923131SAndroid Build Coastguard Worker       multi_fetcher->AddRange(it->first, it->second);
1128*5a923131SAndroid Build Coastguard Worker     } else {
1129*5a923131SAndroid Build Coastguard Worker       android::base::StringAppendF(&tmp_str, "?");
1130*5a923131SAndroid Build Coastguard Worker       multi_fetcher->AddRange(it->first);
1131*5a923131SAndroid Build Coastguard Worker     }
1132*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "added range: " << tmp_str;
1133*5a923131SAndroid Build Coastguard Worker   }
1134*5a923131SAndroid Build Coastguard Worker   fake_hardware->SetIsOfficialBuild(false);
1135*5a923131SAndroid Build Coastguard Worker   multi_fetcher->set_delegate(&delegate);
1136*5a923131SAndroid Build Coastguard Worker 
1137*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->PostTask(
1138*5a923131SAndroid Build Coastguard Worker       FROM_HERE, base::Bind(StartTransfer, multi_fetcher, url));
1139*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->Run();
1140*5a923131SAndroid Build Coastguard Worker 
1141*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(expected_size, delegate.data.size());
1142*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(expected_prefix,
1143*5a923131SAndroid Build Coastguard Worker             string(delegate.data.data(), expected_prefix.size()));
1144*5a923131SAndroid Build Coastguard Worker }
1145*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,MultiHttpFetcherSimpleTest)1146*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
1147*5a923131SAndroid Build Coastguard Worker   if (!this->test_.IsMulti())
1148*5a923131SAndroid Build Coastguard Worker     return;
1149*5a923131SAndroid Build Coastguard Worker 
1150*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1151*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1152*5a923131SAndroid Build Coastguard Worker 
1153*5a923131SAndroid Build Coastguard Worker   vector<pair<off_t, off_t>> ranges;
1154*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(0, 25));
1155*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(99, 17));
1156*5a923131SAndroid Build Coastguard Worker   MultiTest(this->test_.NewLargeFetcher(),
1157*5a923131SAndroid Build Coastguard Worker             this->test_.fake_hardware(),
1158*5a923131SAndroid Build Coastguard Worker             this->test_.BigUrl(server->GetPort()),
1159*5a923131SAndroid Build Coastguard Worker             ranges,
1160*5a923131SAndroid Build Coastguard Worker             "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1161*5a923131SAndroid Build Coastguard Worker             25 + 17,
1162*5a923131SAndroid Build Coastguard Worker             this->test_.IsFileFetcher() ? kHttpResponseOk
1163*5a923131SAndroid Build Coastguard Worker                                         : kHttpResponsePartialContent);
1164*5a923131SAndroid Build Coastguard Worker }
1165*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,MultiHttpFetcherUnspecifiedEndTest)1166*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, MultiHttpFetcherUnspecifiedEndTest) {
1167*5a923131SAndroid Build Coastguard Worker   if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1168*5a923131SAndroid Build Coastguard Worker     return;
1169*5a923131SAndroid Build Coastguard Worker 
1170*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1171*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1172*5a923131SAndroid Build Coastguard Worker 
1173*5a923131SAndroid Build Coastguard Worker   vector<pair<off_t, off_t>> ranges;
1174*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(0, 25));
1175*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(99, 0));
1176*5a923131SAndroid Build Coastguard Worker   MultiTest(this->test_.NewLargeFetcher(),
1177*5a923131SAndroid Build Coastguard Worker             this->test_.fake_hardware(),
1178*5a923131SAndroid Build Coastguard Worker             this->test_.BigUrl(server->GetPort()),
1179*5a923131SAndroid Build Coastguard Worker             ranges,
1180*5a923131SAndroid Build Coastguard Worker             "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1181*5a923131SAndroid Build Coastguard Worker             kBigLength - (99 - 25),
1182*5a923131SAndroid Build Coastguard Worker             kHttpResponsePartialContent);
1183*5a923131SAndroid Build Coastguard Worker }
1184*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,MultiHttpFetcherLengthLimitTest)1185*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
1186*5a923131SAndroid Build Coastguard Worker   if (!this->test_.IsMulti())
1187*5a923131SAndroid Build Coastguard Worker     return;
1188*5a923131SAndroid Build Coastguard Worker 
1189*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1190*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1191*5a923131SAndroid Build Coastguard Worker 
1192*5a923131SAndroid Build Coastguard Worker   vector<pair<off_t, off_t>> ranges;
1193*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(0, 24));
1194*5a923131SAndroid Build Coastguard Worker   MultiTest(this->test_.NewLargeFetcher(),
1195*5a923131SAndroid Build Coastguard Worker             this->test_.fake_hardware(),
1196*5a923131SAndroid Build Coastguard Worker             this->test_.BigUrl(server->GetPort()),
1197*5a923131SAndroid Build Coastguard Worker             ranges,
1198*5a923131SAndroid Build Coastguard Worker             "abcdefghijabcdefghijabcd",
1199*5a923131SAndroid Build Coastguard Worker             24,
1200*5a923131SAndroid Build Coastguard Worker             this->test_.IsFileFetcher() ? kHttpResponseOk
1201*5a923131SAndroid Build Coastguard Worker                                         : kHttpResponsePartialContent);
1202*5a923131SAndroid Build Coastguard Worker }
1203*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,MultiHttpFetcherMultiEndTest)1204*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
1205*5a923131SAndroid Build Coastguard Worker   if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1206*5a923131SAndroid Build Coastguard Worker     return;
1207*5a923131SAndroid Build Coastguard Worker 
1208*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1209*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1210*5a923131SAndroid Build Coastguard Worker 
1211*5a923131SAndroid Build Coastguard Worker   vector<pair<off_t, off_t>> ranges;
1212*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(kBigLength - 2, 0));
1213*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(kBigLength - 3, 0));
1214*5a923131SAndroid Build Coastguard Worker   MultiTest(this->test_.NewLargeFetcher(),
1215*5a923131SAndroid Build Coastguard Worker             this->test_.fake_hardware(),
1216*5a923131SAndroid Build Coastguard Worker             this->test_.BigUrl(server->GetPort()),
1217*5a923131SAndroid Build Coastguard Worker             ranges,
1218*5a923131SAndroid Build Coastguard Worker             "ijhij",
1219*5a923131SAndroid Build Coastguard Worker             5,
1220*5a923131SAndroid Build Coastguard Worker             kHttpResponsePartialContent);
1221*5a923131SAndroid Build Coastguard Worker }
1222*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,MultiHttpFetcherInsufficientTest)1223*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
1224*5a923131SAndroid Build Coastguard Worker   if (!this->test_.IsMulti())
1225*5a923131SAndroid Build Coastguard Worker     return;
1226*5a923131SAndroid Build Coastguard Worker 
1227*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1228*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1229*5a923131SAndroid Build Coastguard Worker 
1230*5a923131SAndroid Build Coastguard Worker   vector<pair<off_t, off_t>> ranges;
1231*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(kBigLength - 2, 4));
1232*5a923131SAndroid Build Coastguard Worker   for (int i = 0; i < 2; ++i) {
1233*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "i = " << i;
1234*5a923131SAndroid Build Coastguard Worker     MultiTest(this->test_.NewLargeFetcher(),
1235*5a923131SAndroid Build Coastguard Worker               this->test_.fake_hardware(),
1236*5a923131SAndroid Build Coastguard Worker               this->test_.BigUrl(server->GetPort()),
1237*5a923131SAndroid Build Coastguard Worker               ranges,
1238*5a923131SAndroid Build Coastguard Worker               "ij",
1239*5a923131SAndroid Build Coastguard Worker               2,
1240*5a923131SAndroid Build Coastguard Worker               kHttpResponseUndefined);
1241*5a923131SAndroid Build Coastguard Worker     ranges.push_back(make_pair(0, 5));
1242*5a923131SAndroid Build Coastguard Worker   }
1243*5a923131SAndroid Build Coastguard Worker }
1244*5a923131SAndroid Build Coastguard Worker 
1245*5a923131SAndroid Build Coastguard Worker // Issue #18143: when a fetch of a secondary chunk out of a chain, then it
1246*5a923131SAndroid Build Coastguard Worker // should retry with other proxies listed before giving up.
1247*5a923131SAndroid Build Coastguard Worker //
1248*5a923131SAndroid Build Coastguard Worker // (1) successful recovery: The offset fetch will fail twice but succeed with
1249*5a923131SAndroid Build Coastguard Worker // the third proxy.
TYPED_TEST(HttpFetcherTest,MultiHttpFetcherErrorIfOffsetRecoverableTest)1250*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
1251*5a923131SAndroid Build Coastguard Worker   if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1252*5a923131SAndroid Build Coastguard Worker     return;
1253*5a923131SAndroid Build Coastguard Worker 
1254*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1255*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1256*5a923131SAndroid Build Coastguard Worker 
1257*5a923131SAndroid Build Coastguard Worker   vector<pair<off_t, off_t>> ranges;
1258*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(0, 25));
1259*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(99, 0));
1260*5a923131SAndroid Build Coastguard Worker   MultiTest(this->test_.NewLargeFetcher(3),
1261*5a923131SAndroid Build Coastguard Worker             this->test_.fake_hardware(),
1262*5a923131SAndroid Build Coastguard Worker             LocalServerUrlForPath(server->GetPort(),
1263*5a923131SAndroid Build Coastguard Worker                                   android::base::StringPrintf(
1264*5a923131SAndroid Build Coastguard Worker                                       "/error-if-offset/%d/2", kBigLength)),
1265*5a923131SAndroid Build Coastguard Worker             ranges,
1266*5a923131SAndroid Build Coastguard Worker             "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1267*5a923131SAndroid Build Coastguard Worker             kBigLength - (99 - 25),
1268*5a923131SAndroid Build Coastguard Worker             kHttpResponsePartialContent);
1269*5a923131SAndroid Build Coastguard Worker }
1270*5a923131SAndroid Build Coastguard Worker 
1271*5a923131SAndroid Build Coastguard Worker // (2) unsuccessful recovery: The offset fetch will fail repeatedly.  The
1272*5a923131SAndroid Build Coastguard Worker // fetcher will signal a (failed) completed transfer to the delegate.
TYPED_TEST(HttpFetcherTest,MultiHttpFetcherErrorIfOffsetUnrecoverableTest)1273*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1274*5a923131SAndroid Build Coastguard Worker   if (!this->test_.IsMulti() || this->test_.IsFileFetcher())
1275*5a923131SAndroid Build Coastguard Worker     return;
1276*5a923131SAndroid Build Coastguard Worker 
1277*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1278*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1279*5a923131SAndroid Build Coastguard Worker 
1280*5a923131SAndroid Build Coastguard Worker   vector<pair<off_t, off_t>> ranges;
1281*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(0, 25));
1282*5a923131SAndroid Build Coastguard Worker   ranges.push_back(make_pair(99, 0));
1283*5a923131SAndroid Build Coastguard Worker   MultiTest(this->test_.NewLargeFetcher(),
1284*5a923131SAndroid Build Coastguard Worker             this->test_.fake_hardware(),
1285*5a923131SAndroid Build Coastguard Worker             LocalServerUrlForPath(server->GetPort(),
1286*5a923131SAndroid Build Coastguard Worker                                   android::base::StringPrintf(
1287*5a923131SAndroid Build Coastguard Worker                                       "/error-if-offset/%d/3", kBigLength)),
1288*5a923131SAndroid Build Coastguard Worker             ranges,
1289*5a923131SAndroid Build Coastguard Worker             "abcdefghijabcdefghijabcde",  // only received the first chunk
1290*5a923131SAndroid Build Coastguard Worker             25,
1291*5a923131SAndroid Build Coastguard Worker             kHttpResponseUndefined);
1292*5a923131SAndroid Build Coastguard Worker }
1293*5a923131SAndroid Build Coastguard Worker 
1294*5a923131SAndroid Build Coastguard Worker // This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1295*5a923131SAndroid Build Coastguard Worker class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1296*5a923131SAndroid Build Coastguard Worker  public:
MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)1297*5a923131SAndroid Build Coastguard Worker   explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1298*5a923131SAndroid Build Coastguard Worker       : terminate_trigger_bytes_(terminate_trigger_bytes) {}
1299*5a923131SAndroid Build Coastguard Worker 
ReceivedBytes(HttpFetcher * fetcher,const void * bytes,size_t length)1300*5a923131SAndroid Build Coastguard Worker   bool ReceivedBytes(HttpFetcher* fetcher,
1301*5a923131SAndroid Build Coastguard Worker                      const void* bytes,
1302*5a923131SAndroid Build Coastguard Worker                      size_t length) override {
1303*5a923131SAndroid Build Coastguard Worker     LOG(INFO) << "ReceivedBytes, " << length << " bytes.";
1304*5a923131SAndroid Build Coastguard Worker     EXPECT_EQ(fetcher, fetcher_.get());
1305*5a923131SAndroid Build Coastguard Worker     bool should_terminate = false;
1306*5a923131SAndroid Build Coastguard Worker     if (bytes_downloaded_ < terminate_trigger_bytes_ &&
1307*5a923131SAndroid Build Coastguard Worker         bytes_downloaded_ + length >= terminate_trigger_bytes_) {
1308*5a923131SAndroid Build Coastguard Worker       MessageLoop::current()->PostTask(
1309*5a923131SAndroid Build Coastguard Worker           FROM_HERE,
1310*5a923131SAndroid Build Coastguard Worker           base::Bind(&HttpFetcher::TerminateTransfer,
1311*5a923131SAndroid Build Coastguard Worker                      base::Unretained(fetcher_.get())));
1312*5a923131SAndroid Build Coastguard Worker       should_terminate = true;
1313*5a923131SAndroid Build Coastguard Worker     }
1314*5a923131SAndroid Build Coastguard Worker     bytes_downloaded_ += length;
1315*5a923131SAndroid Build Coastguard Worker     return !should_terminate;
1316*5a923131SAndroid Build Coastguard Worker   }
1317*5a923131SAndroid Build Coastguard Worker 
TransferComplete(HttpFetcher * fetcher,bool successful)1318*5a923131SAndroid Build Coastguard Worker   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1319*5a923131SAndroid Build Coastguard Worker     ADD_FAILURE() << "TransferComplete called but expected a failure";
1320*5a923131SAndroid Build Coastguard Worker     // Destroy the fetcher (because we're allowed to).
1321*5a923131SAndroid Build Coastguard Worker     fetcher_.reset(nullptr);
1322*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
1323*5a923131SAndroid Build Coastguard Worker   }
1324*5a923131SAndroid Build Coastguard Worker 
TransferTerminated(HttpFetcher * fetcher)1325*5a923131SAndroid Build Coastguard Worker   void TransferTerminated(HttpFetcher* fetcher) override {
1326*5a923131SAndroid Build Coastguard Worker     // Destroy the fetcher (because we're allowed to).
1327*5a923131SAndroid Build Coastguard Worker     fetcher_.reset(nullptr);
1328*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
1329*5a923131SAndroid Build Coastguard Worker   }
1330*5a923131SAndroid Build Coastguard Worker 
1331*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher_;
1332*5a923131SAndroid Build Coastguard Worker   size_t bytes_downloaded_{0};
1333*5a923131SAndroid Build Coastguard Worker   size_t terminate_trigger_bytes_;
1334*5a923131SAndroid Build Coastguard Worker };
1335*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,MultiHttpFetcherTerminateBetweenRangesTest)1336*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, MultiHttpFetcherTerminateBetweenRangesTest) {
1337*5a923131SAndroid Build Coastguard Worker   if (!this->test_.IsMulti())
1338*5a923131SAndroid Build Coastguard Worker     return;
1339*5a923131SAndroid Build Coastguard Worker   const size_t kRangeTrigger = 1000;
1340*5a923131SAndroid Build Coastguard Worker   MultiHttpFetcherTerminateTestDelegate delegate(kRangeTrigger);
1341*5a923131SAndroid Build Coastguard Worker 
1342*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(this->test_.CreateServer());
1343*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1344*5a923131SAndroid Build Coastguard Worker 
1345*5a923131SAndroid Build Coastguard Worker   MultiRangeHttpFetcher* multi_fetcher =
1346*5a923131SAndroid Build Coastguard Worker       static_cast<MultiRangeHttpFetcher*>(this->test_.NewLargeFetcher());
1347*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(multi_fetcher);
1348*5a923131SAndroid Build Coastguard Worker   // Transfer ownership of the fetcher to the delegate.
1349*5a923131SAndroid Build Coastguard Worker   delegate.fetcher_.reset(multi_fetcher);
1350*5a923131SAndroid Build Coastguard Worker   multi_fetcher->set_delegate(&delegate);
1351*5a923131SAndroid Build Coastguard Worker 
1352*5a923131SAndroid Build Coastguard Worker   multi_fetcher->ClearRanges();
1353*5a923131SAndroid Build Coastguard Worker   multi_fetcher->AddRange(45, kRangeTrigger);
1354*5a923131SAndroid Build Coastguard Worker   multi_fetcher->AddRange(2000, 100);
1355*5a923131SAndroid Build Coastguard Worker 
1356*5a923131SAndroid Build Coastguard Worker   this->test_.fake_hardware()->SetIsOfficialBuild(false);
1357*5a923131SAndroid Build Coastguard Worker 
1358*5a923131SAndroid Build Coastguard Worker   StartTransfer(multi_fetcher, this->test_.BigUrl(server->GetPort()));
1359*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->Run();
1360*5a923131SAndroid Build Coastguard Worker 
1361*5a923131SAndroid Build Coastguard Worker   // Check that the delegate made it to the trigger point.
1362*5a923131SAndroid Build Coastguard Worker   EXPECT_EQ(kRangeTrigger, delegate.bytes_downloaded_);
1363*5a923131SAndroid Build Coastguard Worker }
1364*5a923131SAndroid Build Coastguard Worker 
1365*5a923131SAndroid Build Coastguard Worker class BlockedTransferTestDelegate : public HttpFetcherDelegate {
1366*5a923131SAndroid Build Coastguard Worker  public:
ReceivedBytes(HttpFetcher * fetcher,const void * bytes,size_t length)1367*5a923131SAndroid Build Coastguard Worker   bool ReceivedBytes(HttpFetcher* fetcher,
1368*5a923131SAndroid Build Coastguard Worker                      const void* bytes,
1369*5a923131SAndroid Build Coastguard Worker                      size_t length) override {
1370*5a923131SAndroid Build Coastguard Worker     ADD_FAILURE();
1371*5a923131SAndroid Build Coastguard Worker     return true;
1372*5a923131SAndroid Build Coastguard Worker   }
TransferComplete(HttpFetcher * fetcher,bool successful)1373*5a923131SAndroid Build Coastguard Worker   void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1374*5a923131SAndroid Build Coastguard Worker     EXPECT_FALSE(successful);
1375*5a923131SAndroid Build Coastguard Worker     MessageLoop::current()->BreakLoop();
1376*5a923131SAndroid Build Coastguard Worker   }
TransferTerminated(HttpFetcher * fetcher)1377*5a923131SAndroid Build Coastguard Worker   void TransferTerminated(HttpFetcher* fetcher) override { ADD_FAILURE(); }
1378*5a923131SAndroid Build Coastguard Worker };
1379*5a923131SAndroid Build Coastguard Worker 
BlockedTransferTestHelper(AnyHttpFetcherFactory * fetcher_test,bool is_official_build)1380*5a923131SAndroid Build Coastguard Worker void BlockedTransferTestHelper(AnyHttpFetcherFactory* fetcher_test,
1381*5a923131SAndroid Build Coastguard Worker                                bool is_official_build) {
1382*5a923131SAndroid Build Coastguard Worker   if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1383*5a923131SAndroid Build Coastguard Worker     return;
1384*5a923131SAndroid Build Coastguard Worker 
1385*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1386*5a923131SAndroid Build Coastguard Worker   ASSERT_TRUE(server->started_);
1387*5a923131SAndroid Build Coastguard Worker 
1388*5a923131SAndroid Build Coastguard Worker   BlockedTransferTestDelegate delegate;
1389*5a923131SAndroid Build Coastguard Worker   unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1390*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "is_official_build: " << is_official_build;
1391*5a923131SAndroid Build Coastguard Worker   // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
1392*5a923131SAndroid Build Coastguard Worker   fetcher_test->fake_hardware()->SetIsOfficialBuild(is_official_build);
1393*5a923131SAndroid Build Coastguard Worker   fetcher->set_delegate(&delegate);
1394*5a923131SAndroid Build Coastguard Worker 
1395*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->PostTask(
1396*5a923131SAndroid Build Coastguard Worker       FROM_HERE,
1397*5a923131SAndroid Build Coastguard Worker       base::Bind(
1398*5a923131SAndroid Build Coastguard Worker           StartTransfer,
1399*5a923131SAndroid Build Coastguard Worker           fetcher.get(),
1400*5a923131SAndroid Build Coastguard Worker           LocalServerUrlForPath(server->GetPort(),
1401*5a923131SAndroid Build Coastguard Worker                                 fetcher_test->SmallUrl(server->GetPort()))));
1402*5a923131SAndroid Build Coastguard Worker   MessageLoop::current()->Run();
1403*5a923131SAndroid Build Coastguard Worker }
1404*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,BlockedTransferTest)1405*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
1406*5a923131SAndroid Build Coastguard Worker   BlockedTransferTestHelper(&this->test_, false);
1407*5a923131SAndroid Build Coastguard Worker }
1408*5a923131SAndroid Build Coastguard Worker 
TYPED_TEST(HttpFetcherTest,BlockedTransferOfficialBuildTest)1409*5a923131SAndroid Build Coastguard Worker TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1410*5a923131SAndroid Build Coastguard Worker   BlockedTransferTestHelper(&this->test_, true);
1411*5a923131SAndroid Build Coastguard Worker }
1412*5a923131SAndroid Build Coastguard Worker 
1413*5a923131SAndroid Build Coastguard Worker }  // namespace
1414*5a923131SAndroid Build Coastguard Worker 
1415*5a923131SAndroid Build Coastguard Worker }  // namespace chromeos_update_engine
1416