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
55using brillo::MessageLoop;
56using std::make_pair;
57using std::pair;
58using std::string;
59using std::unique_ptr;
60using std::vector;
61using testing::DoAll;
62using testing::Return;
63using testing::SaveArg;
64using testing::_;
65
66namespace {
67
68const int kBigLength           = 100000;
69const int kMediumLength        = 1000;
70const int kFlakyTruncateLength = 29000;
71const int kFlakySleepEvery     = 3;
72const int kFlakySleepSecs      = 10;
73
74}  // namespace
75
76namespace chromeos_update_engine {
77
78static const char *kUnusedUrl = "unused://unused";
79
80static 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
91class HttpServer {
92 public:
93  // This makes it an abstract class (dirty but works).
94  virtual ~HttpServer() = 0;
95
96  virtual in_port_t GetPort() const {
97    return 0;
98  }
99
100  bool started_;
101};
102
103HttpServer::~HttpServer() {}
104
105
106class NullHttpServer : public HttpServer {
107 public:
108  NullHttpServer() {
109    started_ = true;
110  }
111};
112
113
114class PythonHttpServer : public HttpServer {
115 public:
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
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
178  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
189const char* PythonHttpServer::kServerListeningMsgPrefix = "listening on port ";
190
191//
192// Class hierarchy for HTTP fetcher test wrappers.
193//
194
195class AnyHttpFetcherTest {
196 public:
197  AnyHttpFetcherTest() {}
198  virtual ~AnyHttpFetcherTest() {}
199
200  virtual HttpFetcher* NewLargeFetcher(ProxyResolver* proxy_resolver) = 0;
201  HttpFetcher* NewLargeFetcher(size_t num_proxies) {
202    proxy_resolver_.set_num_proxies(num_proxies);
203    return NewLargeFetcher(&proxy_resolver_);
204  }
205  HttpFetcher* NewLargeFetcher() {
206    return NewLargeFetcher(1);
207  }
208
209  virtual HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) = 0;
210  HttpFetcher* NewSmallFetcher() {
211    proxy_resolver_.set_num_proxies(1);
212    return NewSmallFetcher(&proxy_resolver_);
213  }
214
215  virtual string BigUrl(in_port_t port) const { return kUnusedUrl; }
216  virtual string SmallUrl(in_port_t port) const { return kUnusedUrl; }
217  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
223  virtual void IgnoreServerAborting(HttpServer* server) const {}
224
225  virtual HttpServer* CreateServer() = 0;
226
227  FakeHardware* fake_hardware() {
228    return &fake_hardware_;
229  }
230
231 protected:
232  DirectProxyResolver proxy_resolver_;
233  FakeHardware fake_hardware_;
234};
235
236class MockHttpFetcherTest : public AnyHttpFetcherTest {
237 public:
238  // Necessary to unhide the definition in the base class.
239  using AnyHttpFetcherTest::NewLargeFetcher;
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;
248  HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
249    return new MockHttpFetcher("x", 1, proxy_resolver);
250  }
251
252  bool IsMock() const override { return true; }
253  bool IsMulti() const override { return false; }
254  bool IsHttpSupported() const override { return true; }
255
256  HttpServer* CreateServer() override {
257    return new NullHttpServer;
258  }
259};
260
261class LibcurlHttpFetcherTest : public AnyHttpFetcherTest {
262 public:
263  // Necessary to unhide the definition in the base class.
264  using AnyHttpFetcherTest::NewLargeFetcher;
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;
277  HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
278    return NewLargeFetcher(proxy_resolver);
279  }
280
281  string BigUrl(in_port_t port) const override {
282    return LocalServerUrlForPath(port,
283                                 base::StringPrintf("/download/%d",
284                                                    kBigLength));
285  }
286  string SmallUrl(in_port_t port) const override {
287    return LocalServerUrlForPath(port, "/foo");
288  }
289  string ErrorUrl(in_port_t port) const override {
290    return LocalServerUrlForPath(port, "/error");
291  }
292
293  bool IsMock() const override { return false; }
294  bool IsMulti() const override { return false; }
295  bool IsHttpSupported() const override { return true; }
296
297  void IgnoreServerAborting(HttpServer* server) const override {
298    // Nothing to do.
299  }
300
301  HttpServer* CreateServer() override {
302    return new PythonHttpServer;
303  }
304};
305
306class MultiRangeHttpFetcherTest : public LibcurlHttpFetcherTest {
307 public:
308  // Necessary to unhide the definition in the base class.
309  using AnyHttpFetcherTest::NewLargeFetcher;
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;
324  HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
325    return NewLargeFetcher(proxy_resolver);
326  }
327
328  bool IsMulti() const override { return true; }
329};
330
331class FileFetcherTest : public AnyHttpFetcherTest {
332 public:
333  // Necessary to unhide the definition in the base class.
334  using AnyHttpFetcherTest::NewLargeFetcher;
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;
341  HttpFetcher* NewSmallFetcher(ProxyResolver* proxy_resolver) override {
342    return NewLargeFetcher(proxy_resolver);
343  }
344
345  string BigUrl(in_port_t port) const override {
346    return "file://" + temp_file_.path();
347  }
348  string SmallUrl(in_port_t port) const override {
349    test_utils::WriteFileString(temp_file_.path(), "small contents");
350    return "file://" + temp_file_.path();
351  }
352  string ErrorUrl(in_port_t port) const override {
353    return "file:///path/to/non-existing-file";
354  }
355
356  bool IsMock() const override { return false; }
357  bool IsMulti() const override { return false; }
358  bool IsHttpSupported() const override { return false; }
359
360  void IgnoreServerAborting(HttpServer* server) const override {}
361
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
376template <typename T>
377class HttpFetcherTest : public ::testing::Test {
378 public:
379  base::MessageLoopForIO base_loop_;
380  brillo::BaseMessageLoop loop_{&base_loop_};
381
382  T test_;
383
384 protected:
385  HttpFetcherTest() {
386    loop_.SetAsCurrent();
387  }
388
389  void TearDown() override {
390    EXPECT_EQ(0, brillo::MessageLoopRunMaxIterations(&loop_, 1));
391  }
392
393 private:
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.
402typedef ::testing::Types<LibcurlHttpFetcherTest,
403                         MockHttpFetcherTest,
404                         MultiRangeHttpFetcherTest,
405                         FileFetcherTest>
406    HttpFetcherTestTypes;
407TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
408
409
410namespace {
411class HttpFetcherTestDelegate : public HttpFetcherDelegate {
412 public:
413  HttpFetcherTestDelegate() = default;
414
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
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
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
452void StartTransfer(HttpFetcher* http_fetcher, const string& url) {
453  http_fetcher->BeginTransfer(url);
454}
455}  // namespace
456
457TYPED_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
473TYPED_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.
491TYPED_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
521TYPED_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
560namespace {
561class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate {
562 public:
563  void ReceivedBytes(HttpFetcher* fetcher,
564                     const void* /* bytes */, size_t /* length */) override {
565    CHECK(!paused_);
566    paused_ = true;
567    fetcher->Pause();
568  }
569  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
570    MessageLoop::current()->BreakLoop();
571  }
572  void TransferTerminated(HttpFetcher* fetcher) override {
573    ADD_FAILURE();
574  }
575  void Unpause() {
576    CHECK(paused_);
577    paused_ = false;
578    fetcher_->Unpause();
579  }
580  bool paused_;
581  HttpFetcher* fetcher_;
582};
583
584void 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
596TYPED_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.
619TYPED_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
641namespace {
642class AbortingHttpFetcherTestDelegate : public HttpFetcherDelegate {
643 public:
644  void ReceivedBytes(HttpFetcher* fetcher,
645                     const void* bytes, size_t length) override {}
646  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
647    ADD_FAILURE();  // We should never get here
648    MessageLoop::current()->BreakLoop();
649  }
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  }
659  void TerminateTransfer() {
660    CHECK(once_);
661    once_ = false;
662    fetcher_->TerminateTransfer();
663  }
664  void EndLoop() {
665    MessageLoop::current()->BreakLoop();
666  }
667  bool once_;
668  bool callback_once_;
669  unique_ptr<HttpFetcher> fetcher_;
670};
671
672void 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
686TYPED_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
710TYPED_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
736namespace {
737class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
738 public:
739  void ReceivedBytes(HttpFetcher* fetcher,
740                     const void* bytes, size_t length) override {
741    data.append(reinterpret_cast<const char*>(bytes), length);
742  }
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  }
748  void TransferTerminated(HttpFetcher* fetcher) override {
749    ADD_FAILURE();
750  }
751  string data;
752};
753}  // namespace
754
755TYPED_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
786namespace {
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.
790class FailureHttpFetcherTestDelegate : public HttpFetcherDelegate {
791 public:
792  explicit FailureHttpFetcherTestDelegate(PythonHttpServer* server)
793      : server_(server) {}
794
795  ~FailureHttpFetcherTestDelegate() override {
796    if (server_) {
797      LOG(INFO) << "Stopping server in destructor";
798      server_.reset();
799      LOG(INFO) << "server stopped";
800    }
801  }
802
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  }
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  }
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
828TYPED_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
848TYPED_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
887TYPED_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.
921TYPED_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
967namespace {
968const HttpResponseCode kRedirectCodes[] = {
969  kHttpResponseMovedPermanently, kHttpResponseFound, kHttpResponseSeeOther,
970  kHttpResponseTempRedirect
971};
972
973class RedirectHttpFetcherTestDelegate : public HttpFetcherDelegate {
974 public:
975  explicit RedirectHttpFetcherTestDelegate(bool expected_successful)
976      : expected_successful_(expected_successful) {}
977  void ReceivedBytes(HttpFetcher* fetcher,
978                     const void* bytes, size_t length) override {
979    data.append(reinterpret_cast<const char*>(bytes), length);
980  }
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  }
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|.
999void 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
1023TYPED_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
1038TYPED_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
1054TYPED_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
1070namespace {
1071class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
1072 public:
1073  explicit MultiHttpFetcherTestDelegate(int expected_response_code)
1074      : expected_response_code_(expected_response_code) {}
1075
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
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
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
1101void 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
1141TYPED_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
1160TYPED_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
1178TYPED_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
1197TYPED_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.
1224TYPED_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.
1247TYPED_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
1268namespace {
1269// This HttpFetcherDelegate calls TerminateTransfer at a configurable point.
1270class MultiHttpFetcherTerminateTestDelegate : public HttpFetcherDelegate {
1271 public:
1272  explicit MultiHttpFetcherTerminateTestDelegate(size_t terminate_trigger_bytes)
1273      : terminate_trigger_bytes_(terminate_trigger_bytes) {}
1274
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
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
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
1309TYPED_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
1338namespace {
1339class BlockedTransferTestDelegate : public HttpFetcherDelegate {
1340 public:
1341  void ReceivedBytes(HttpFetcher* fetcher,
1342                     const void* bytes, size_t length) override {
1343    ADD_FAILURE();
1344  }
1345  void TransferComplete(HttpFetcher* fetcher, bool successful) override {
1346    EXPECT_FALSE(successful);
1347    MessageLoop::current()->BreakLoop();
1348  }
1349  void TransferTerminated(HttpFetcher* fetcher) override {
1350    ADD_FAILURE();
1351  }
1352};
1353
1354void 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
1378TYPED_TEST(HttpFetcherTest, BlockedTransferTest) {
1379  BlockedTransferTestHelper(&this->test_, false);
1380}
1381
1382TYPED_TEST(HttpFetcherTest, BlockedTransferOfficialBuildTest) {
1383  BlockedTransferTestHelper(&this->test_, true);
1384}
1385
1386}  // namespace chromeos_update_engine
1387