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