blob: d822e5157a2baa94d31759754d46f1adeccdb74b [file] [log] [blame]
Mike Frysinger8155d082012-04-06 15:23:18 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
rspangler@google.com49fdf182009-10-10 00:57:34 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07005#include <netinet/in.h>
6#include <netinet/ip.h>
7#include <sys/socket.h>
rspangler@google.com49fdf182009-10-10 00:57:34 +00008#include <unistd.h>
Darin Petkov41c2fcf2010-08-25 13:14:48 -07009
Ben Chan02f7c1d2014-10-18 15:18:02 -070010#include <memory>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000011#include <string>
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070012#include <utility>
adlr@google.comc98a7ed2009-12-04 18:54:03 +000013#include <vector>
Darin Petkov41c2fcf2010-08-25 13:14:48 -070014
Alex Deymo60ca1a72015-06-18 18:19:15 -070015#include <base/location.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080016#include <base/logging.h>
Alex Deymo535f3b72015-08-07 10:51:32 -070017#include <base/message_loop/message_loop.h>
18#include <base/strings/string_number_conversions.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070019#include <base/strings/string_util.h>
20#include <base/strings/stringprintf.h>
21#include <base/time/time.h>
Alex Deymo535f3b72015-08-07 10:51:32 -070022#include <chromeos/message_loops/base_message_loop.h>
Alex Deymo60ca1a72015-06-18 18:19:15 -070023#include <chromeos/message_loops/message_loop.h>
24#include <chromeos/message_loops/message_loop_utils.h>
Alex Deymo535f3b72015-08-07 10:51:32 -070025#include <chromeos/process.h>
26#include <chromeos/streams/file_stream.h>
27#include <chromeos/streams/stream.h>
Andrew de los Reyes45168102010-11-22 11:13:50 -080028#include <gtest/gtest.h>
29
Gilad Arnold5bb4c902014-04-10 12:32:13 -070030#include "update_engine/fake_system_state.h"
Gilad Arnold9bedeb52011-11-17 16:19:57 -080031#include "update_engine/http_common.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000032#include "update_engine/libcurl_http_fetcher.h"
33#include "update_engine/mock_http_fetcher.h"
Andrew de los Reyes819fef22010-12-17 11:33:58 -080034#include "update_engine/multi_range_http_fetcher.h"
Andrew de los Reyes45168102010-11-22 11:13:50 -080035#include "update_engine/proxy_resolver.h"
Alex Deymo535f3b72015-08-07 10:51:32 -070036#include "update_engine/test_utils.h"
Jay Srinivasan08fce042012-06-07 16:31:01 -070037#include "update_engine/utils.h"
rspangler@google.com49fdf182009-10-10 00:57:34 +000038
Alex Deymo60ca1a72015-06-18 18:19:15 -070039using chromeos::MessageLoop;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -070040using std::make_pair;
Andrew de los Reyes819fef22010-12-17 11:33:58 -080041using std::pair;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000042using std::string;
Ben Chan02f7c1d2014-10-18 15:18:02 -070043using std::unique_ptr;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000044using std::vector;
45
Gilad Arnold9bedeb52011-11-17 16:19:57 -080046namespace {
47
48const int kBigLength = 100000;
49const int kMediumLength = 1000;
Gilad Arnold34bf1ee2012-02-09 16:16:02 -080050const int kFlakyTruncateLength = 29000;
51const int kFlakySleepEvery = 3;
Gilad Arnold9bedeb52011-11-17 16:19:57 -080052const int kFlakySleepSecs = 10;
53
54} // namespace
55
rspangler@google.com49fdf182009-10-10 00:57:34 +000056namespace chromeos_update_engine {
57
Gilad Arnold9bedeb52011-11-17 16:19:57 -080058static const char *kUnusedUrl = "unused://unused";
59
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070060static inline string LocalServerUrlForPath(in_port_t port,
61 const string& path) {
Alex Vakulenko75039d72014-03-25 12:36:28 -070062 string port_str = (port ? base::StringPrintf(":%hu", port) : "");
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070063 return base::StringPrintf("http://127.0.0.1%s%s", port_str.c_str(),
64 path.c_str());
rspangler@google.com49fdf182009-10-10 00:57:34 +000065}
66
Gilad Arnold9bedeb52011-11-17 16:19:57 -080067//
68// Class hierarchy for HTTP server implementations.
69//
70
71class HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000072 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080073 // This makes it an abstract class (dirty but works).
74 virtual ~HttpServer() = 0;
75
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070076 virtual in_port_t GetPort() const {
77 return 0;
78 }
79
rspangler@google.com49fdf182009-10-10 00:57:34 +000080 bool started_;
81};
82
Gilad Arnold9bedeb52011-11-17 16:19:57 -080083HttpServer::~HttpServer() {}
rspangler@google.com49fdf182009-10-10 00:57:34 +000084
Gilad Arnold9bedeb52011-11-17 16:19:57 -080085
86class NullHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000087 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -080088 NullHttpServer() {
89 started_ = true;
rspangler@google.com49fdf182009-10-10 00:57:34 +000090 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000091};
92
Gilad Arnold9bedeb52011-11-17 16:19:57 -080093
94class PythonHttpServer : public HttpServer {
rspangler@google.com49fdf182009-10-10 00:57:34 +000095 public:
Alex Deymo535f3b72015-08-07 10:51:32 -070096 PythonHttpServer() : port_(0) {
rspangler@google.com49fdf182009-10-10 00:57:34 +000097 started_ = false;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -070098
99 // Spawn the server process.
Alex Deymo535f3b72015-08-07 10:51:32 -0700100 unique_ptr<chromeos::Process> http_server(new chromeos::ProcessImpl());
101 base::FilePath test_server_path =
102 test_utils::GetBuildArtifactsPath().Append("test_http_server");
103 http_server->AddArg(test_server_path.value());
104 http_server->RedirectUsingPipe(STDOUT_FILENO, false);
105
106 if (!http_server->Start()) {
107 ADD_FAILURE() << "failed to spawn http server process";
rspangler@google.com49fdf182009-10-10 00:57:34 +0000108 return;
109 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700110 LOG(INFO) << "started http server with pid " << http_server->pid();
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700111
112 // Wait for server to begin accepting connections, obtain its port.
Alex Deymo535f3b72015-08-07 10:51:32 -0700113 chromeos::StreamPtr stdout = chromeos::FileStream::FromFileDescriptor(
114 http_server->GetPipe(STDOUT_FILENO), false /* own */, nullptr);
115 if (!stdout)
116 return;
117
118 vector<char> buf(128);
119 string line;
120 while (line.find('\n') == string::npos) {
121 size_t read;
122 if (!stdout->ReadBlocking(buf.data(), buf.size(), &read, nullptr)) {
123 ADD_FAILURE() << "error reading http server stdout";
124 return;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700125 }
Alex Deymo535f3b72015-08-07 10:51:32 -0700126 line.append(buf.data(), read);
127 if (read == 0)
128 break;
129 }
130 // Parse the port from the output line.
131 const size_t listening_msg_prefix_len = strlen(kServerListeningMsgPrefix);
132 if (line.size() < listening_msg_prefix_len) {
133 ADD_FAILURE() << "server output too short";
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700134 return;
135 }
136
Alex Deymo535f3b72015-08-07 10:51:32 -0700137 EXPECT_EQ(kServerListeningMsgPrefix,
138 line.substr(0, listening_msg_prefix_len));
139 string port_str = line.substr(listening_msg_prefix_len);
140 port_str.resize(port_str.find('\n'));
141 EXPECT_TRUE(base::StringToUint(port_str, &port_));
142
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700143 started_ = true;
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700144 LOG(INFO) << "server running, listening on port " << port_;
Alex Deymo535f3b72015-08-07 10:51:32 -0700145
146 // Any failure before this point will SIGKILL the test server if started
147 // when the |http_server| goes out of scope.
148 http_server_ = std::move(http_server);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000149 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800150
rspangler@google.com49fdf182009-10-10 00:57:34 +0000151 ~PythonHttpServer() {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700152 // If there's no process, do nothing.
Alex Deymo535f3b72015-08-07 10:51:32 -0700153 if (!http_server_)
rspangler@google.com49fdf182009-10-10 00:57:34 +0000154 return;
Alex Deymo535f3b72015-08-07 10:51:32 -0700155 // Wait up to 10 seconds for the process to finish. Destroying the process
156 // will kill it with a SIGKILL otherwise.
157 http_server_->Kill(SIGTERM, 10);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000158 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800159
Alex Deymo610277e2014-11-11 21:18:11 -0800160 in_port_t GetPort() const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700161 return port_;
162 }
163
164 private:
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700165 static const char* kServerListeningMsgPrefix;
166
Alex Deymo535f3b72015-08-07 10:51:32 -0700167 unique_ptr<chromeos::Process> http_server_;
168 unsigned int port_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000169};
170
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700171const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
172
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800173//
174// Class hierarchy for HTTP fetcher test wrappers.
175//
176
177class AnyHttpFetcherTest {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000178 public:
Chris Sosa77f79e82014-06-02 18:16:24 -0700179 AnyHttpFetcherTest() {}
Alex Deymoc4acdf42014-05-28 21:07:10 -0700180 virtual ~AnyHttpFetcherTest() {}
Jay Srinivasan43488792012-06-19 00:25:31 -0700181
Alex Deymo7984bf02014-04-02 20:41:57 -0700182 virtual HttpFetcher* NewLargeFetcher(size_t num_proxies) = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800183 HttpFetcher* NewLargeFetcher() {
184 return NewLargeFetcher(1);
185 }
186
187 virtual HttpFetcher* NewSmallFetcher(size_t num_proxies) = 0;
188 HttpFetcher* NewSmallFetcher() {
189 return NewSmallFetcher(1);
190 }
191
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700192 virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
193 virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
194 virtual string ErrorUrl(in_port_t port) const { return kUnusedUrl; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800195
196 virtual bool IsMock() const = 0;
197 virtual bool IsMulti() const = 0;
198
199 virtual void IgnoreServerAborting(HttpServer* server) const {}
200
Alex Deymo60ca1a72015-06-18 18:19:15 -0700201 virtual HttpServer* CreateServer() = 0;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800202
203 protected:
204 DirectProxyResolver proxy_resolver_;
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700205 FakeSystemState fake_system_state_;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800206};
207
208class MockHttpFetcherTest : public AnyHttpFetcherTest {
209 public:
210 // Necessary to unhide the definition in the base class.
211 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800212 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800213 chromeos::Blob big_data(1000000);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700214 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800215 proxy_resolver_.set_num_proxies(num_proxies);
216 return new MockHttpFetcher(
217 big_data.data(),
218 big_data.size(),
219 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
220 }
221
222 // Necessary to unhide the definition in the base class.
223 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800224 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700225 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800226 proxy_resolver_.set_num_proxies(num_proxies);
227 return new MockHttpFetcher(
228 "x",
229 1,
230 reinterpret_cast<ProxyResolver*>(&proxy_resolver_));
231 }
232
Alex Deymo610277e2014-11-11 21:18:11 -0800233 bool IsMock() const override { return true; }
234 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800235
Alex Deymo60ca1a72015-06-18 18:19:15 -0700236 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800237 return new NullHttpServer;
238 }
239};
240
241class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
242 public:
243 // Necessary to unhide the definition in the base class.
244 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800245 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700246 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800247 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes45168102010-11-22 11:13:50 -0800248 LibcurlHttpFetcher *ret = new
Jay Srinivasan08fce042012-06-07 16:31:01 -0700249 LibcurlHttpFetcher(reinterpret_cast<ProxyResolver*>(&proxy_resolver_),
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700250 &fake_system_state_);
Darin Petkovb83371f2010-08-17 09:34:49 -0700251 // Speed up test execution.
252 ret->set_idle_seconds(1);
253 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700254 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000255 return ret;
256 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800257
258 // Necessary to unhide the definition in the base class.
259 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800260 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800261 return NewLargeFetcher(num_proxies);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000262 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800263
Alex Deymo610277e2014-11-11 21:18:11 -0800264 string BigUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700265 return LocalServerUrlForPath(port,
266 base::StringPrintf("/download/%d",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800267 kBigLength));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000268 }
Alex Deymo610277e2014-11-11 21:18:11 -0800269 string SmallUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700270 return LocalServerUrlForPath(port, "/foo");
rspangler@google.com49fdf182009-10-10 00:57:34 +0000271 }
Alex Deymo610277e2014-11-11 21:18:11 -0800272 string ErrorUrl(in_port_t port) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700273 return LocalServerUrlForPath(port, "/error");
Gilad Arnold48085ba2011-11-16 09:36:08 -0800274 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800275
Alex Deymo610277e2014-11-11 21:18:11 -0800276 bool IsMock() const override { return false; }
277 bool IsMulti() const override { return false; }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800278
Alex Deymo610277e2014-11-11 21:18:11 -0800279 void IgnoreServerAborting(HttpServer* server) const override {
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700280 // Nothing to do.
Andrew de los Reyes08c4e272010-04-15 14:02:17 -0700281 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800282
Alex Deymo60ca1a72015-06-18 18:19:15 -0700283 HttpServer* CreateServer() override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800284 return new PythonHttpServer;
285 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000286};
287
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800288class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700289 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800290 // Necessary to unhide the definition in the base class.
291 using AnyHttpFetcherTest::NewLargeFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800292 HttpFetcher* NewLargeFetcher(size_t num_proxies) override {
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700293 CHECK_GT(num_proxies, 0u);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800294 proxy_resolver_.set_num_proxies(num_proxies);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800295 ProxyResolver* resolver =
296 reinterpret_cast<ProxyResolver*>(&proxy_resolver_);
Gilad Arnold7c04e762012-05-23 10:54:02 -0700297 MultiRangeHttpFetcher *ret =
298 new MultiRangeHttpFetcher(
Nam T. Nguyen7d623eb2014-05-13 16:06:28 -0700299 new LibcurlHttpFetcher(resolver, &fake_system_state_));
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800300 ret->ClearRanges();
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800301 ret->AddRange(0);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700302 // Speed up test execution.
303 ret->set_idle_seconds(1);
304 ret->set_retry_seconds(1);
Gilad Arnold5bb4c902014-04-10 12:32:13 -0700305 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700306 return ret;
307 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800308
309 // Necessary to unhide the definition in the base class.
310 using AnyHttpFetcherTest::NewSmallFetcher;
Alex Deymo610277e2014-11-11 21:18:11 -0800311 HttpFetcher* NewSmallFetcher(size_t num_proxies) override {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800312 return NewLargeFetcher(num_proxies);
313 }
314
Alex Deymo610277e2014-11-11 21:18:11 -0800315 bool IsMulti() const override { return true; }
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700316};
317
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800318
319//
320// Infrastructure for type tests of HTTP fetcher.
321// See: http://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests
322//
323
324// Fixture class template. We use an explicit constraint to guarantee that it
325// can only be instantiated with an AnyHttpFetcherTest type, see:
326// http://www2.research.att.com/~bs/bs_faq2.html#constraints
327template <typename T>
328class HttpFetcherTest : public ::testing::Test {
329 public:
Alex Deymo535f3b72015-08-07 10:51:32 -0700330 base::MessageLoopForIO base_loop_;
331 chromeos::BaseMessageLoop loop_{&base_loop_};
Alex Deymo60ca1a72015-06-18 18:19:15 -0700332
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800333 T test_;
334
Alex Deymo60ca1a72015-06-18 18:19:15 -0700335 protected:
336 HttpFetcherTest() {
337 loop_.SetAsCurrent();
338 }
339
340 void TearDown() override {
341 EXPECT_EQ(0, chromeos::MessageLoopRunMaxIterations(&loop_, 1));
342 }
343
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800344 private:
Alex Deymo60ca1a72015-06-18 18:19:15 -0700345 static void TypeConstraint(T* a) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800346 AnyHttpFetcherTest *b = a;
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700347 if (b == 0) // Silence compiler warning of unused variable.
Yunlian Jiang2dac5762013-04-12 09:53:09 -0700348 *b = a;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800349 }
350};
351
352// Test case types list.
353typedef ::testing::Types<LibcurlHttpFetcherTest,
354 MockHttpFetcherTest,
355 MultiRangeHttpFetcherTest> HttpFetcherTestTypes;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000356TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
357
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800358
rspangler@google.com49fdf182009-10-10 00:57:34 +0000359namespace {
360class HttpFetcherTestDelegate : public HttpFetcherDelegate {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000361 public:
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800362 HttpFetcherTestDelegate() :
Gilad Arnold48085ba2011-11-16 09:36:08 -0800363 is_expect_error_(false), times_transfer_complete_called_(0),
364 times_transfer_terminated_called_(0), times_received_bytes_called_(0) {}
365
Alex Deymo610277e2014-11-11 21:18:11 -0800366 void ReceivedBytes(HttpFetcher* /* fetcher */,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800367 const void* /* bytes */, size_t /* length */) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800368 // Update counters
369 times_received_bytes_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000370 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800371
Alex Deymo610277e2014-11-11 21:18:11 -0800372 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Gilad Arnold48085ba2011-11-16 09:36:08 -0800373 if (is_expect_error_)
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800374 EXPECT_EQ(kHttpResponseNotFound, fetcher->http_response_code());
Gilad Arnold48085ba2011-11-16 09:36:08 -0800375 else
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800376 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700377 MessageLoop::current()->BreakLoop();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800378
379 // Update counter
380 times_transfer_complete_called_++;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000381 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800382
Alex Deymo610277e2014-11-11 21:18:11 -0800383 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800384 ADD_FAILURE();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800385 times_transfer_terminated_called_++;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800386 }
Gilad Arnold48085ba2011-11-16 09:36:08 -0800387
Gilad Arnold48085ba2011-11-16 09:36:08 -0800388 // Are we expecting an error response? (default: no)
389 bool is_expect_error_;
390
391 // Counters for callback invocations.
392 int times_transfer_complete_called_;
393 int times_transfer_terminated_called_;
394 int times_received_bytes_called_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000395};
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000396
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000397
Alex Deymo60ca1a72015-06-18 18:19:15 -0700398void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
399 http_fetcher->BeginTransfer(url);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000400}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700401} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000402
403TYPED_TEST(HttpFetcherTest, SimpleTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700404 HttpFetcherTestDelegate delegate;
405 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
406 fetcher->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000407
Alex Deymo60ca1a72015-06-18 18:19:15 -0700408 unique_ptr<HttpServer> server(this->test_.CreateServer());
409 ASSERT_TRUE(server->started_);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000410
Alex Deymo60ca1a72015-06-18 18:19:15 -0700411 this->loop_.PostTask(FROM_HERE, base::Bind(
412 StartTransfer,
413 fetcher.get(),
414 this->test_.SmallUrl(server->GetPort())));
415 this->loop_.Run();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000416}
417
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700418TYPED_TEST(HttpFetcherTest, SimpleBigTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700419 HttpFetcherTestDelegate delegate;
420 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
421 fetcher->set_delegate(&delegate);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700422
Alex Deymo60ca1a72015-06-18 18:19:15 -0700423 unique_ptr<HttpServer> server(this->test_.CreateServer());
424 ASSERT_TRUE(server->started_);
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700425
Alex Deymo60ca1a72015-06-18 18:19:15 -0700426 this->loop_.PostTask(FROM_HERE, base::Bind(
427 StartTransfer,
428 fetcher.get(),
429 this->test_.BigUrl(server->GetPort())));
430 this->loop_.Run();
Andrew de los Reyes3270f742010-07-15 22:28:14 -0700431}
432
Gilad Arnold48085ba2011-11-16 09:36:08 -0800433// Issue #9648: when server returns an error HTTP response, the fetcher needs to
434// terminate transfer prematurely, rather than try to process the error payload.
435TYPED_TEST(HttpFetcherTest, ErrorTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800436 if (this->test_.IsMock() || this->test_.IsMulti())
Gilad Arnold48085ba2011-11-16 09:36:08 -0800437 return;
Alex Deymo60ca1a72015-06-18 18:19:15 -0700438 HttpFetcherTestDelegate delegate;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800439
Alex Deymo60ca1a72015-06-18 18:19:15 -0700440 // Delegate should expect an error response.
441 delegate.is_expect_error_ = true;
Gilad Arnold48085ba2011-11-16 09:36:08 -0800442
Alex Deymo60ca1a72015-06-18 18:19:15 -0700443 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
444 fetcher->set_delegate(&delegate);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800445
Alex Deymo60ca1a72015-06-18 18:19:15 -0700446 unique_ptr<HttpServer> server(this->test_.CreateServer());
447 ASSERT_TRUE(server->started_);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800448
Alex Deymo60ca1a72015-06-18 18:19:15 -0700449 this->loop_.PostTask(FROM_HERE, base::Bind(
450 StartTransfer,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800451 fetcher.get(),
Alex Deymo60ca1a72015-06-18 18:19:15 -0700452 this->test_.ErrorUrl(server->GetPort())));
453 this->loop_.Run();
Gilad Arnold48085ba2011-11-16 09:36:08 -0800454
Alex Deymo60ca1a72015-06-18 18:19:15 -0700455 // Make sure that no bytes were received.
456 CHECK_EQ(delegate.times_received_bytes_called_, 0);
457 CHECK_EQ(fetcher->GetBytesDownloaded(), static_cast<size_t>(0));
Gilad Arnold48085ba2011-11-16 09:36:08 -0800458
Alex Deymo60ca1a72015-06-18 18:19:15 -0700459 // Make sure that transfer completion was signaled once, and no termination
460 // was signaled.
461 CHECK_EQ(delegate.times_transfer_complete_called_, 1);
462 CHECK_EQ(delegate.times_transfer_terminated_called_, 0);
Gilad Arnold48085ba2011-11-16 09:36:08 -0800463}
464
rspangler@google.com49fdf182009-10-10 00:57:34 +0000465namespace {
466class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
467 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800468 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800469 const void* /* bytes */, size_t /* length */) override {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000470 CHECK(!paused_);
471 paused_ = true;
472 fetcher->Pause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000473 }
Alex Deymo610277e2014-11-11 21:18:11 -0800474 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700475 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000476 }
Alex Deymo610277e2014-11-11 21:18:11 -0800477 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800478 ADD_FAILURE();
479 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000480 void Unpause() {
481 CHECK(paused_);
482 paused_ = false;
483 fetcher_->Unpause();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000484 }
485 bool paused_;
486 HttpFetcher* fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000487};
488
Alex Deymo60ca1a72015-06-18 18:19:15 -0700489void UnpausingTimeoutCallback(PausingHttpFetcherTestDelegate* delegate,
490 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000491 if (delegate->paused_)
492 delegate->Unpause();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700493 // Update the task id with the new scheduled callback.
494 *my_id = MessageLoop::current()->PostDelayedTask(
495 FROM_HERE,
496 base::Bind(&UnpausingTimeoutCallback, delegate, my_id),
497 base::TimeDelta::FromMilliseconds(200));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000498}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700499} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000500
501TYPED_TEST(HttpFetcherTest, PauseTest) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000502 {
503 PausingHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700504 unique_ptr<HttpFetcher> fetcher(this->test_.NewLargeFetcher());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000505 delegate.paused_ = false;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000506 delegate.fetcher_ = fetcher.get();
507 fetcher->set_delegate(&delegate);
508
Ben Chan02f7c1d2014-10-18 15:18:02 -0700509 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800510 ASSERT_TRUE(server->started_);
Andrew de los Reyesf3ed8e72011-02-16 10:35:46 -0800511
Alex Deymo60ca1a72015-06-18 18:19:15 -0700512 MessageLoop::TaskId callback_id;
513 callback_id = this->loop_.PostDelayedTask(
514 FROM_HERE,
515 base::Bind(&UnpausingTimeoutCallback, &delegate, &callback_id),
516 base::TimeDelta::FromMilliseconds(200));
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700517 fetcher->BeginTransfer(this->test_.BigUrl(server->GetPort()));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000518
Alex Deymo60ca1a72015-06-18 18:19:15 -0700519 this->loop_.Run();
520 EXPECT_TRUE(this->loop_.CancelTask(callback_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000521 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000522}
523
524namespace {
525class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
526 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800527 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800528 const void* bytes, size_t length) override {}
Alex Deymo610277e2014-11-11 21:18:11 -0800529 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800530 ADD_FAILURE(); // We should never get here
Alex Deymo60ca1a72015-06-18 18:19:15 -0700531 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000532 }
Alex Deymo610277e2014-11-11 21:18:11 -0800533 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800534 EXPECT_EQ(fetcher, fetcher_.get());
535 EXPECT_FALSE(once_);
536 EXPECT_TRUE(callback_once_);
537 callback_once_ = false;
Alex Deymoc4acdf42014-05-28 21:07:10 -0700538 // The fetcher could have a callback scheduled on the ProxyResolver that
539 // can fire after this callback. We wait until the end of the test to
540 // delete the fetcher.
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800541 }
rspangler@google.com49fdf182009-10-10 00:57:34 +0000542 void TerminateTransfer() {
543 CHECK(once_);
544 once_ = false;
545 fetcher_->TerminateTransfer();
546 }
547 void EndLoop() {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700548 MessageLoop::current()->BreakLoop();
rspangler@google.com49fdf182009-10-10 00:57:34 +0000549 }
550 bool once_;
Darin Petkov9ce452b2010-11-17 14:33:28 -0800551 bool callback_once_;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700552 unique_ptr<HttpFetcher> fetcher_;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000553};
554
Alex Deymo60ca1a72015-06-18 18:19:15 -0700555void AbortingTimeoutCallback(AbortingHttpFetcherTestDelegate* delegate,
556 MessageLoop::TaskId* my_id) {
rspangler@google.com49fdf182009-10-10 00:57:34 +0000557 if (delegate->once_) {
558 delegate->TerminateTransfer();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700559 *my_id = MessageLoop::current()->PostTask(
560 FROM_HERE,
561 base::Bind(AbortingTimeoutCallback, delegate, my_id));
rspangler@google.com49fdf182009-10-10 00:57:34 +0000562 } else {
563 delegate->EndLoop();
Alex Deymo60ca1a72015-06-18 18:19:15 -0700564 *my_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000565 }
566}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700567} // namespace
rspangler@google.com49fdf182009-10-10 00:57:34 +0000568
569TYPED_TEST(HttpFetcherTest, AbortTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700570 AbortingHttpFetcherTestDelegate delegate;
571 delegate.fetcher_.reset(this->test_.NewLargeFetcher());
572 delegate.once_ = true;
573 delegate.callback_once_ = true;
574 delegate.fetcher_->set_delegate(&delegate);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000575
Alex Deymo60ca1a72015-06-18 18:19:15 -0700576 unique_ptr<HttpServer> server(this->test_.CreateServer());
577 this->test_.IgnoreServerAborting(server.get());
578 ASSERT_TRUE(server->started_);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800579
Alex Deymo60ca1a72015-06-18 18:19:15 -0700580 MessageLoop::TaskId task_id = MessageLoop::kTaskIdNull;
rspangler@google.com49fdf182009-10-10 00:57:34 +0000581
Alex Deymo60ca1a72015-06-18 18:19:15 -0700582 task_id = this->loop_.PostTask(
583 FROM_HERE,
584 base::Bind(AbortingTimeoutCallback, &delegate, &task_id));
585 delegate.fetcher_->BeginTransfer(this->test_.BigUrl(server->GetPort()));
586
587 this->loop_.Run();
588 CHECK(!delegate.once_);
589 CHECK(!delegate.callback_once_);
590 this->loop_.CancelTask(task_id);
rspangler@google.com49fdf182009-10-10 00:57:34 +0000591}
592
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000593namespace {
594class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
595 public:
Alex Deymo610277e2014-11-11 21:18:11 -0800596 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800597 const void* bytes, size_t length) override {
598 data.append(reinterpret_cast<const char*>(bytes), length);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000599 }
Alex Deymo610277e2014-11-11 21:18:11 -0800600 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesfb4ad7d2010-07-19 10:43:46 -0700601 EXPECT_TRUE(successful);
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800602 EXPECT_EQ(kHttpResponsePartialContent, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700603 MessageLoop::current()->BreakLoop();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000604 }
Alex Deymo610277e2014-11-11 21:18:11 -0800605 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800606 ADD_FAILURE();
607 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000608 string data;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000609};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700610} // namespace
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000611
612TYPED_TEST(HttpFetcherTest, FlakyTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800613 if (this->test_.IsMock())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000614 return;
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000615 {
616 FlakyHttpFetcherTestDelegate delegate;
Ben Chan02f7c1d2014-10-18 15:18:02 -0700617 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000618 fetcher->set_delegate(&delegate);
619
Ben Chan02f7c1d2014-10-18 15:18:02 -0700620 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800621 ASSERT_TRUE(server->started_);
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000622
Alex Deymo60ca1a72015-06-18 18:19:15 -0700623 this->loop_.PostTask(FROM_HERE, base::Bind(
624 &StartTransfer,
625 fetcher.get(),
626 LocalServerUrlForPath(server->GetPort(),
627 base::StringPrintf("/flaky/%d/%d/%d/%d",
628 kBigLength,
629 kFlakyTruncateLength,
630 kFlakySleepEvery,
631 kFlakySleepSecs))));
632 this->loop_.Run();
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000633
634 // verify the data we get back
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800635 ASSERT_EQ(kBigLength, delegate.data.size());
636 for (int i = 0; i < kBigLength; i += 10) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000637 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
638 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
639 }
640 }
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000641}
642
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700643namespace {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700644// This delegate kills the server attached to it after receiving any bytes.
645// This can be used for testing what happens when you try to fetch data and
646// the server dies.
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700647class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
648 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700649 explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
Alex Deymo60ca1a72015-06-18 18:19:15 -0700650 : server_(server) {}
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700651
Alex Deymo610277e2014-11-11 21:18:11 -0800652 ~FailureHttpFetcherTestDelegate() override {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700653 if (server_) {
654 LOG(INFO) << "Stopping server in destructor";
655 delete server_;
656 LOG(INFO) << "server stopped";
657 }
658 }
659
Alex Deymo610277e2014-11-11 21:18:11 -0800660 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800661 const void* bytes, size_t length) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700662 if (server_) {
Jay Srinivasan135a58b2012-07-13 12:46:49 -0700663 LOG(INFO) << "Stopping server in ReceivedBytes";
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700664 delete server_;
665 LOG(INFO) << "server stopped";
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700666 server_ = nullptr;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700667 }
668 }
Alex Deymo610277e2014-11-11 21:18:11 -0800669 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700670 EXPECT_FALSE(successful);
Chris Sosa0a364bb2014-06-10 18:18:24 -0700671 EXPECT_EQ(0, fetcher->http_response_code());
Alex Deymo60ca1a72015-06-18 18:19:15 -0700672 MessageLoop::current()->BreakLoop();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700673 }
Alex Deymo610277e2014-11-11 21:18:11 -0800674 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800675 ADD_FAILURE();
676 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700677 PythonHttpServer* server_;
678};
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700679} // namespace
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700680
681
682TYPED_TEST(HttpFetcherTest, FailureTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700683 // This test ensures that a fetcher responds correctly when a server isn't
684 // available at all.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800685 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700686 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700687 {
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700688 FailureHttpFetcherTestDelegate delegate(nullptr);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700689 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700690 fetcher->set_delegate(&delegate);
691
Alex Deymo60ca1a72015-06-18 18:19:15 -0700692 this->loop_.PostTask(FROM_HERE,
693 base::Bind(StartTransfer,
694 fetcher.get(),
695 "http://host_doesnt_exist99999999"));
696 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700697
698 // Exiting and testing happens in the delegate
699 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700700}
701
702TYPED_TEST(HttpFetcherTest, ServerDiesTest) {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700703 // This test starts a new http server and kills it after receiving its first
704 // set of bytes. It test whether or not our fetcher eventually gives up on
705 // retries and aborts correctly.
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800706 if (this->test_.IsMock())
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700707 return;
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700708 {
Chris Sosa0a364bb2014-06-10 18:18:24 -0700709 PythonHttpServer* server = new PythonHttpServer();
710 int port = server->GetPort();
711 ASSERT_TRUE(server->started_);
712
713 // Handles destruction and claims ownership.
714 FailureHttpFetcherTestDelegate delegate(server);
Ben Chan02f7c1d2014-10-18 15:18:02 -0700715 unique_ptr<HttpFetcher> fetcher(this->test_.NewSmallFetcher());
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700716 fetcher->set_delegate(&delegate);
717
Alex Deymo60ca1a72015-06-18 18:19:15 -0700718 this->loop_.PostTask(FROM_HERE, base::Bind(
719 StartTransfer,
720 fetcher.get(),
721 LocalServerUrlForPath(port,
722 base::StringPrintf("/flaky/%d/%d/%d/%d",
723 kBigLength,
724 kFlakyTruncateLength,
725 kFlakySleepEvery,
726 kFlakySleepSecs))));
727 this->loop_.Run();
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700728
729 // Exiting and testing happens in the delegate
730 }
Andrew de los Reyes9bbd1872010-07-16 14:52:29 -0700731}
732
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700733namespace {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800734const HttpResponseCode kRedirectCodes[] = {
735 kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
736 kHttpResponseTempRedirect
737};
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700738
739class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
740 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700741 explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700742 : expected_successful_(expected_successful) {}
Alex Deymo610277e2014-11-11 21:18:11 -0800743 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800744 const void* bytes, size_t length) override {
745 data.append(reinterpret_cast<const char*>(bytes), length);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700746 }
Alex Deymo610277e2014-11-11 21:18:11 -0800747 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700748 EXPECT_EQ(expected_successful_, successful);
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700749 if (expected_successful_) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800750 EXPECT_EQ(kHttpResponseOk, fetcher->http_response_code());
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700751 } else {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800752 EXPECT_GE(fetcher->http_response_code(), kHttpResponseMovedPermanently);
753 EXPECT_LE(fetcher->http_response_code(), kHttpResponseTempRedirect);
Darin Petkovcb466212010-08-26 09:40:11 -0700754 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700755 MessageLoop::current()->BreakLoop();
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700756 }
Alex Deymo610277e2014-11-11 21:18:11 -0800757 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800758 ADD_FAILURE();
759 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700760 bool expected_successful_;
761 string data;
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700762};
763
764// RedirectTest takes ownership of |http_fetcher|.
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700765void RedirectTest(const HttpServer* server,
766 bool expected_successful,
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700767 const string& url,
768 HttpFetcher* http_fetcher) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700769 RedirectHttpFetcherTestDelegate delegate(expected_successful);
770 unique_ptr<HttpFetcher> fetcher(http_fetcher);
771 fetcher->set_delegate(&delegate);
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700772
Alex Deymo60ca1a72015-06-18 18:19:15 -0700773 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
774 StartTransfer,
775 fetcher.get(),
776 LocalServerUrlForPath(server->GetPort(), url)));
777 MessageLoop::current()->Run();
778 if (expected_successful) {
779 // verify the data we get back
780 ASSERT_EQ(kMediumLength, delegate.data.size());
781 for (int i = 0; i < kMediumLength; i += 10) {
782 // Assert so that we don't flood the screen w/ EXPECT errors on failure.
783 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij");
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700784 }
785 }
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700786}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700787} // namespace
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700788
789TYPED_TEST(HttpFetcherTest, SimpleRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800790 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700791 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800792
Ben Chan02f7c1d2014-10-18 15:18:02 -0700793 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800794 ASSERT_TRUE(server->started_);
795
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700796 for (size_t c = 0; c < arraysize(kRedirectCodes); ++c) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800797 const string url = base::StringPrintf("/redirect/%d/download/%d",
798 kRedirectCodes[c],
799 kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700800 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700801 }
802}
803
804TYPED_TEST(HttpFetcherTest, MaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800805 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700806 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800807
Ben Chan02f7c1d2014-10-18 15:18:02 -0700808 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800809 ASSERT_TRUE(server->started_);
810
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700811 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700812 for (int r = 0; r < kDownloadMaxRedirects; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700813 url += base::StringPrintf("/redirect/%d",
814 kRedirectCodes[r % arraysize(kRedirectCodes)]);
815 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800816 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700817 RedirectTest(server.get(), true, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700818}
819
820TYPED_TEST(HttpFetcherTest, BeyondMaxRedirectTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800821 if (this->test_.IsMock())
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700822 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800823
Ben Chan02f7c1d2014-10-18 15:18:02 -0700824 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800825 ASSERT_TRUE(server->started_);
826
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700827 string url;
David Zeuthen34135a92013-08-06 11:16:16 -0700828 for (int r = 0; r < kDownloadMaxRedirects + 1; r++) {
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700829 url += base::StringPrintf("/redirect/%d",
830 kRedirectCodes[r % arraysize(kRedirectCodes)]);
831 }
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800832 url += base::StringPrintf("/download/%d", kMediumLength);
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700833 RedirectTest(server.get(), false, url, this->test_.NewLargeFetcher());
Darin Petkov41c2fcf2010-08-25 13:14:48 -0700834}
835
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700836namespace {
837class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
838 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700839 explicit MultiHttpFetcherTestDelegate(int expected_response_code)
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700840 : expected_response_code_(expected_response_code) {}
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800841
Alex Deymo610277e2014-11-11 21:18:11 -0800842 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800843 const void* bytes, size_t length) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800844 EXPECT_EQ(fetcher, fetcher_.get());
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800845 data.append(reinterpret_cast<const char*>(bytes), length);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700846 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800847
Alex Deymo610277e2014-11-11 21:18:11 -0800848 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800849 EXPECT_EQ(fetcher, fetcher_.get());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800850 EXPECT_EQ(expected_response_code_ != kHttpResponseUndefined, successful);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700851 if (expected_response_code_ != 0)
852 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
Darin Petkov9ce452b2010-11-17 14:33:28 -0800853 // Destroy the fetcher (because we're allowed to).
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700854 fetcher_.reset(nullptr);
Alex Deymo60ca1a72015-06-18 18:19:15 -0700855 MessageLoop::current()->BreakLoop();
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700856 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800857
Alex Deymo610277e2014-11-11 21:18:11 -0800858 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -0800859 ADD_FAILURE();
860 }
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800861
Ben Chan02f7c1d2014-10-18 15:18:02 -0700862 unique_ptr<HttpFetcher> fetcher_;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700863 int expected_response_code_;
864 string data;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700865};
866
867void MultiTest(HttpFetcher* fetcher_in,
868 const string& url,
Ben Chanf9cb98c2014-09-21 18:31:30 -0700869 const vector<pair<off_t, off_t>>& ranges,
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700870 const string& expected_prefix,
871 off_t expected_size,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800872 HttpResponseCode expected_response_code) {
Alex Deymo60ca1a72015-06-18 18:19:15 -0700873 MultiHttpFetcherTestDelegate delegate(expected_response_code);
874 delegate.fetcher_.reset(fetcher_in);
Jay Srinivasan43488792012-06-19 00:25:31 -0700875
Alex Deymo60ca1a72015-06-18 18:19:15 -0700876 MultiRangeHttpFetcher* multi_fetcher =
877 dynamic_cast<MultiRangeHttpFetcher*>(fetcher_in);
878 ASSERT_TRUE(multi_fetcher);
879 multi_fetcher->ClearRanges();
880 for (vector<pair<off_t, off_t>>::const_iterator it = ranges.begin(),
881 e = ranges.end(); it != e; ++it) {
882 string tmp_str = base::StringPrintf("%jd+", it->first);
883 if (it->second > 0) {
884 base::StringAppendF(&tmp_str, "%jd", it->second);
885 multi_fetcher->AddRange(it->first, it->second);
886 } else {
887 base::StringAppendF(&tmp_str, "?");
888 multi_fetcher->AddRange(it->first);
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800889 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700890 LOG(INFO) << "added range: " << tmp_str;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700891 }
Alex Deymo60ca1a72015-06-18 18:19:15 -0700892 dynamic_cast<FakeSystemState*>(fetcher_in->GetSystemState())
893 ->fake_hardware()->SetIsOfficialBuild(false);
894 multi_fetcher->set_delegate(&delegate);
895
896 MessageLoop::current()->PostTask(
897 FROM_HERE,
898 base::Bind(StartTransfer, multi_fetcher, url));
899 MessageLoop::current()->Run();
900
901 EXPECT_EQ(expected_size, delegate.data.size());
902 EXPECT_EQ(expected_prefix,
903 string(delegate.data.data(), expected_prefix.size()));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700904}
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700905} // namespace
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700906
Darin Petkov9ce452b2010-11-17 14:33:28 -0800907TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimpleTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800908 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700909 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800910
Ben Chan02f7c1d2014-10-18 15:18:02 -0700911 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800912 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700913
Ben Chanf9cb98c2014-09-21 18:31:30 -0700914 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700915 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800916 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800917 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700918 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700919 ranges,
920 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800921 kBigLength - (99 - 25),
922 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700923}
924
925TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800926 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700927 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800928
Ben Chan02f7c1d2014-10-18 15:18:02 -0700929 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800930 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700931
Ben Chanf9cb98c2014-09-21 18:31:30 -0700932 vector<pair<off_t, off_t>> ranges;
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700933 ranges.push_back(make_pair(0, 24));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800934 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700935 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700936 ranges,
937 "abcdefghijabcdefghijabcd",
938 24,
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800939 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700940}
941
942TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800943 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700944 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800945
Ben Chan02f7c1d2014-10-18 15:18:02 -0700946 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800947 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700948
Ben Chanf9cb98c2014-09-21 18:31:30 -0700949 vector<pair<off_t, off_t>> ranges;
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800950 ranges.push_back(make_pair(kBigLength - 2, 0));
951 ranges.push_back(make_pair(kBigLength - 3, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800952 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700953 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700954 ranges,
955 "ijhij",
956 5,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800957 kHttpResponsePartialContent);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700958}
959
960TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800961 if (!this->test_.IsMulti())
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700962 return;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800963
Ben Chan02f7c1d2014-10-18 15:18:02 -0700964 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800965 ASSERT_TRUE(server->started_);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700966
Ben Chanf9cb98c2014-09-21 18:31:30 -0700967 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800968 ranges.push_back(make_pair(kBigLength - 2, 4));
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700969 for (int i = 0; i < 2; ++i) {
Andrew de los Reyes819fef22010-12-17 11:33:58 -0800970 LOG(INFO) << "i = " << i;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800971 MultiTest(this->test_.NewLargeFetcher(),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700972 this->test_.BigUrl(server->GetPort()),
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700973 ranges,
974 "ij",
975 2,
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800976 kHttpResponseUndefined);
Andrew de los Reyes3fd5d302010-10-07 20:07:18 -0700977 ranges.push_back(make_pair(0, 5));
978 }
979}
980
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800981// Issue #18143: when a fetch of a secondary chunk out of a chain, then it
982// should retry with other proxies listed before giving up.
983//
984// (1) successful recovery: The offset fetch will fail twice but succeed with
985// the third proxy.
986TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetRecoverableTest) {
987 if (!this->test_.IsMulti())
988 return;
989
Ben Chan02f7c1d2014-10-18 15:18:02 -0700990 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800991 ASSERT_TRUE(server->started_);
992
Ben Chanf9cb98c2014-09-21 18:31:30 -0700993 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800994 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -0800995 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800996 MultiTest(this->test_.NewLargeFetcher(3),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -0700997 LocalServerUrlForPath(server->GetPort(),
998 base::StringPrintf("/error-if-offset/%d/2",
Gilad Arnold9bedeb52011-11-17 16:19:57 -0800999 kBigLength)),
1000 ranges,
1001 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
1002 kBigLength - (99 - 25),
1003 kHttpResponsePartialContent);
1004}
1005
1006// (2) unsuccessful recovery: The offset fetch will fail repeatedly. The
1007// fetcher will signal a (failed) completed transfer to the delegate.
1008TYPED_TEST(HttpFetcherTest, MultiHttpFetcherErrorIfOffsetUnrecoverableTest) {
1009 if (!this->test_.IsMulti())
1010 return;
1011
Ben Chan02f7c1d2014-10-18 15:18:02 -07001012 unique_ptr<HttpServer> server(this->test_.CreateServer());
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001013 ASSERT_TRUE(server->started_);
1014
Ben Chanf9cb98c2014-09-21 18:31:30 -07001015 vector<pair<off_t, off_t>> ranges;
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001016 ranges.push_back(make_pair(0, 25));
Gilad Arnolde4ad2502011-12-29 17:08:54 -08001017 ranges.push_back(make_pair(99, 0));
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001018 MultiTest(this->test_.NewLargeFetcher(2),
Gilad Arnoldb6c562a2013-07-01 02:19:26 -07001019 LocalServerUrlForPath(server->GetPort(),
1020 base::StringPrintf("/error-if-offset/%d/3",
Gilad Arnold9bedeb52011-11-17 16:19:57 -08001021 kBigLength)),
1022 ranges,
1023 "abcdefghijabcdefghijabcde", // only received the first chunk
1024 25,
1025 kHttpResponseUndefined);
1026}
1027
1028
1029
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001030namespace {
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001031class BlockedTransferTestDelegate : public HttpFetcherDelegate {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001032 public:
Alex Deymo610277e2014-11-11 21:18:11 -08001033 void ReceivedBytes(HttpFetcher* fetcher,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -08001034 const void* bytes, size_t length) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001035 ADD_FAILURE();
1036 }
Alex Deymo610277e2014-11-11 21:18:11 -08001037 void TransferComplete(HttpFetcher* fetcher, bool successful) override {
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001038 EXPECT_FALSE(successful);
Alex Deymo60ca1a72015-06-18 18:19:15 -07001039 MessageLoop::current()->BreakLoop();
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001040 }
Alex Deymo610277e2014-11-11 21:18:11 -08001041 void TransferTerminated(HttpFetcher* fetcher) override {
Darin Petkov9ce452b2010-11-17 14:33:28 -08001042 ADD_FAILURE();
1043 }
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001044};
1045
Alex Deymo60ca1a72015-06-18 18:19:15 -07001046void BlockedTransferTestHelper(AnyHttpFetcherTest* fetcher_test,
1047 bool is_official_build) {
1048 if (fetcher_test->IsMock() || fetcher_test->IsMulti())
1049 return;
1050
1051 unique_ptr<HttpServer> server(fetcher_test->CreateServer());
1052 ASSERT_TRUE(server->started_);
1053
1054 BlockedTransferTestDelegate delegate;
1055 unique_ptr<HttpFetcher> fetcher(fetcher_test->NewLargeFetcher());
1056 LOG(INFO) << "is_official_build: " << is_official_build;
1057 // NewLargeFetcher creates the HttpFetcher* with a FakeSystemState.
1058 dynamic_cast<FakeSystemState*>(fetcher->GetSystemState())
1059 ->fake_hardware()->SetIsOfficialBuild(is_official_build);
1060 fetcher->set_delegate(&delegate);
1061
1062 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
1063 StartTransfer,
1064 fetcher.get(),
1065 LocalServerUrlForPath(server->GetPort(),
1066 fetcher_test->SmallUrl(server->GetPort()))));
1067 MessageLoop::current()->Run();
1068}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001069} // namespace
1070
Darin Petkovfc7a0ce2010-10-25 10:38:37 -07001071TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
Alex Deymo60ca1a72015-06-18 18:19:15 -07001072 BlockedTransferTestHelper(&this->test_, false);
1073}
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001074
Alex Deymo60ca1a72015-06-18 18:19:15 -07001075TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1076 BlockedTransferTestHelper(&this->test_, true);
Andrew de los Reyesd57d1472010-10-21 13:34:08 -07001077}
1078
rspangler@google.com49fdf182009-10-10 00:57:34 +00001079} // namespace chromeos_update_engine