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