Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(380)

Side by Side Diff: http_fetcher_unittest.cc

Issue 3591018: AU: MultiHttpFetcher, an HttpFetcher for specific byte ranges (Closed) Base URL: ssh://git@chromiumos-git/update_engine.git
Patch Set: fixes for rewview Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « http_fetcher.h ('k') | libcurl_http_fetcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <unistd.h> 5 #include <unistd.h>
6 6
7 #include <string> 7 #include <string>
8 #include <utility>
8 #include <vector> 9 #include <vector>
9 10
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/scoped_ptr.h" 12 #include "base/scoped_ptr.h"
12 #include "base/string_util.h" 13 #include "base/string_util.h"
13 #include "glib.h" 14 #include "glib.h"
14 #include "gtest/gtest.h" 15 #include "gtest/gtest.h"
15 #include "update_engine/libcurl_http_fetcher.h" 16 #include "update_engine/libcurl_http_fetcher.h"
16 #include "update_engine/mock_http_fetcher.h" 17 #include "update_engine/mock_http_fetcher.h"
18 #include "update_engine/multi_http_fetcher.h"
17 19
20 using std::make_pair;
18 using std::string; 21 using std::string;
19 using std::vector; 22 using std::vector;
20 23
21 namespace chromeos_update_engine { 24 namespace chromeos_update_engine {
22 25
23 namespace { 26 namespace {
24 // WARNING, if you update this, you must also update test_http_server.py 27 // WARNING, if you update these, you must also update test_http_server.py
25 const char* const kServerPort = "8080"; 28 const char* const kServerPort = "8080";
29 const int kBigSize = 100000;
26 string LocalServerUrlForPath(const string& path) { 30 string LocalServerUrlForPath(const string& path) {
27 return string("http://127.0.0.1:") + kServerPort + path; 31 return string("http://127.0.0.1:") + kServerPort + path;
28 } 32 }
29 } 33 }
30 34
31 template <typename T> 35 template <typename T>
32 class HttpFetcherTest : public ::testing::Test { 36 class HttpFetcherTest : public ::testing::Test {
33 public: 37 public:
34 HttpFetcher* NewLargeFetcher() = 0; 38 HttpFetcher* NewLargeFetcher() = 0;
35 HttpFetcher* NewSmallFetcher() = 0; 39 HttpFetcher* NewSmallFetcher() = 0;
36 string BigUrl() const = 0; 40 string BigUrl() const = 0;
37 string SmallUrl() const = 0; 41 string SmallUrl() const = 0;
38 bool IsMock() const = 0; 42 bool IsMock() const = 0;
43 bool IsMulti() const = 0;
39 }; 44 };
40 45
41 class NullHttpServer { 46 class NullHttpServer {
42 public: 47 public:
43 NullHttpServer() : started_(true) {} 48 NullHttpServer() : started_(true) {}
44 ~NullHttpServer() {} 49 ~NullHttpServer() {}
45 bool started_; 50 bool started_;
46 }; 51 };
47 52
48 53
49 template <> 54 template <>
50 class HttpFetcherTest<MockHttpFetcher> : public ::testing::Test { 55 class HttpFetcherTest<MockHttpFetcher> : public ::testing::Test {
51 public: 56 public:
52 HttpFetcher* NewLargeFetcher() { 57 HttpFetcher* NewLargeFetcher() {
53 vector<char> big_data(1000000); 58 vector<char> big_data(1000000);
54 return new MockHttpFetcher(big_data.data(), big_data.size()); 59 return new MockHttpFetcher(big_data.data(), big_data.size());
55 } 60 }
56 HttpFetcher* NewSmallFetcher() { 61 HttpFetcher* NewSmallFetcher() {
57 return new MockHttpFetcher("x", 1); 62 return new MockHttpFetcher("x", 1);
58 } 63 }
59 string BigUrl() const { 64 string BigUrl() const {
60 return "unused://unused"; 65 return "unused://unused";
61 } 66 }
62 string SmallUrl() const { 67 string SmallUrl() const {
63 return "unused://unused"; 68 return "unused://unused";
64 } 69 }
65 bool IsMock() const { return true; } 70 bool IsMock() const { return true; }
71 bool IsMulti() const { return false; }
66 typedef NullHttpServer HttpServer; 72 typedef NullHttpServer HttpServer;
67 void IgnoreServerAborting(HttpServer* server) const {} 73 void IgnoreServerAborting(HttpServer* server) const {}
68 }; 74 };
69 75
70 class PythonHttpServer { 76 class PythonHttpServer {
71 public: 77 public:
72 PythonHttpServer() { 78 PythonHttpServer() {
73 char *argv[2] = {strdup("./test_http_server"), NULL}; 79 char *argv[2] = {strdup("./test_http_server"), NULL};
74 GError *err; 80 GError *err;
75 started_ = false; 81 started_ = false;
(...skipping 18 matching lines...) Expand all
94 LOG(INFO) << "done running wget to start"; 100 LOG(INFO) << "done running wget to start";
95 usleep(10 * 1000); // 10 ms 101 usleep(10 * 1000); // 10 ms
96 tries--; 102 tries--;
97 if (tries == 0) { 103 if (tries == 0) {
98 LOG(ERROR) << "Unable to start server."; 104 LOG(ERROR) << "Unable to start server.";
99 started_ = false; 105 started_ = false;
100 break; 106 break;
101 } 107 }
102 } 108 }
103 free(argv[0]); 109 free(argv[0]);
110 LOG(INFO) << "gdb attach now!";
104 return; 111 return;
105 } 112 }
106 ~PythonHttpServer() { 113 ~PythonHttpServer() {
107 if (!started_) 114 if (!started_)
108 return; 115 return;
109 // request that the server exit itself 116 // request that the server exit itself
110 LOG(INFO) << "running wget to exit"; 117 LOG(INFO) << "running wget to exit";
111 int rc = system((string("wget -t 1 --output-document=/dev/null ") + 118 int rc = system((string("wget -t 1 --output-document=/dev/null ") +
112 LocalServerUrlForPath("/quitquitquit")).c_str()); 119 LocalServerUrlForPath("/quitquitquit")).c_str());
113 LOG(INFO) << "done running wget to exit"; 120 LOG(INFO) << "done running wget to exit";
114 if (validate_quit_) 121 if (validate_quit_)
115 EXPECT_EQ(0, rc); 122 EXPECT_EQ(0, rc);
116 waitpid(pid_, NULL, 0); 123 waitpid(pid_, NULL, 0);
117 } 124 }
118 GPid pid_; 125 GPid pid_;
119 bool started_; 126 bool started_;
120 bool validate_quit_; 127 bool validate_quit_;
121 }; 128 };
122 129
123 template <> 130 template <>
124 class HttpFetcherTest<LibcurlHttpFetcher> : public ::testing::Test { 131 class HttpFetcherTest<LibcurlHttpFetcher> : public ::testing::Test {
125 public: 132 public:
126 HttpFetcher* NewLargeFetcher() { 133 virtual HttpFetcher* NewLargeFetcher() {
127 LibcurlHttpFetcher *ret = new LibcurlHttpFetcher; 134 LibcurlHttpFetcher *ret = new LibcurlHttpFetcher;
128 // Speed up test execution. 135 // Speed up test execution.
129 ret->set_idle_seconds(1); 136 ret->set_idle_seconds(1);
130 ret->set_retry_seconds(1); 137 ret->set_retry_seconds(1);
131 return ret; 138 return ret;
132 } 139 }
133 HttpFetcher* NewSmallFetcher() { 140 HttpFetcher* NewSmallFetcher() {
134 return NewLargeFetcher(); 141 return NewLargeFetcher();
135 } 142 }
136 string BigUrl() const { 143 string BigUrl() const {
137 return LocalServerUrlForPath("/big"); 144 return LocalServerUrlForPath("/big");
138 } 145 }
139 string SmallUrl() const { 146 string SmallUrl() const {
140 return LocalServerUrlForPath("/foo"); 147 return LocalServerUrlForPath("/foo");
141 } 148 }
142 bool IsMock() const { return false; } 149 bool IsMock() const { return false; }
150 bool IsMulti() const { return false; }
143 typedef PythonHttpServer HttpServer; 151 typedef PythonHttpServer HttpServer;
144 void IgnoreServerAborting(HttpServer* server) const { 152 void IgnoreServerAborting(HttpServer* server) const {
145 PythonHttpServer *pyserver = reinterpret_cast<PythonHttpServer*>(server); 153 PythonHttpServer *pyserver = reinterpret_cast<PythonHttpServer*>(server);
146 pyserver->validate_quit_ = false; 154 pyserver->validate_quit_ = false;
147 } 155 }
148 }; 156 };
149 157
150 typedef ::testing::Types<LibcurlHttpFetcher, MockHttpFetcher> 158 template <>
151 HttpFetcherTestTypes; 159 class HttpFetcherTest<MultiHttpFetcher<LibcurlHttpFetcher> >
160 : public HttpFetcherTest<LibcurlHttpFetcher> {
161 public:
162 HttpFetcher* NewLargeFetcher() {
163 MultiHttpFetcher<LibcurlHttpFetcher> *ret =
164 new MultiHttpFetcher<LibcurlHttpFetcher>;
165 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect
166 ranges(1, make_pair(0, -1));
167 ret->set_ranges(ranges);
168 // Speed up test execution.
169 ret->set_idle_seconds(1);
170 ret->set_retry_seconds(1);
171 return ret;
172 }
173 bool IsMulti() const { return true; }
174 };
175
176 typedef ::testing::Types<LibcurlHttpFetcher,
177 MockHttpFetcher,
178 MultiHttpFetcher<LibcurlHttpFetcher> >
179 HttpFetcherTestTypes;
152 TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes); 180 TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes);
153 181
154 namespace { 182 namespace {
155 class HttpFetcherTestDelegate : public HttpFetcherDelegate { 183 class HttpFetcherTestDelegate : public HttpFetcherDelegate {
156 public: 184 public:
157 virtual void ReceivedBytes(HttpFetcher* fetcher, 185 virtual void ReceivedBytes(HttpFetcher* fetcher,
158 const char* bytes, int length) { 186 const char* bytes, int length) {
159 char str[length + 1]; 187 char str[length + 1];
160 memset(str, 0, length + 1); 188 memset(str, 0, length + 1);
161 memcpy(str, bytes, length); 189 memcpy(str, bytes, length);
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 ASSERT_TRUE(server.started_); 354 ASSERT_TRUE(server.started_);
327 GSource* timeout_source_; 355 GSource* timeout_source_;
328 timeout_source_ = g_timeout_source_new(0); // ms 356 timeout_source_ = g_timeout_source_new(0); // ms
329 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate, 357 g_source_set_callback(timeout_source_, AbortingTimeoutCallback, &delegate,
330 NULL); 358 NULL);
331 g_source_attach(timeout_source_, NULL); 359 g_source_attach(timeout_source_, NULL);
332 fetcher->BeginTransfer(this->BigUrl()); 360 fetcher->BeginTransfer(this->BigUrl());
333 361
334 g_main_loop_run(loop); 362 g_main_loop_run(loop);
335 g_source_destroy(timeout_source_); 363 g_source_destroy(timeout_source_);
336 EXPECT_EQ(0, fetcher->http_response_code());
337 } 364 }
338 g_main_loop_unref(loop); 365 g_main_loop_unref(loop);
339 } 366 }
340 367
341 namespace { 368 namespace {
342 class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate { 369 class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate {
343 public: 370 public:
344 virtual void ReceivedBytes(HttpFetcher* fetcher, 371 virtual void ReceivedBytes(HttpFetcher* fetcher,
345 const char* bytes, int length) { 372 const char* bytes, int length) {
346 data.append(bytes, length); 373 data.append(bytes, length);
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 ASSERT_TRUE(server.started_); 570 ASSERT_TRUE(server.started_);
544 string url; 571 string url;
545 for (int r = 0; r < LibcurlHttpFetcher::kMaxRedirects + 1; r++) { 572 for (int r = 0; r < LibcurlHttpFetcher::kMaxRedirects + 1; r++) {
546 url += base::StringPrintf("/redirect/%d", 573 url += base::StringPrintf("/redirect/%d",
547 kRedirectCodes[r % arraysize(kRedirectCodes)]); 574 kRedirectCodes[r % arraysize(kRedirectCodes)]);
548 } 575 }
549 url += "/medium"; 576 url += "/medium";
550 RedirectTest(false, url, this->NewLargeFetcher()); 577 RedirectTest(false, url, this->NewLargeFetcher());
551 } 578 }
552 579
580 namespace {
581 class MultiHttpFetcherTestDelegate : public HttpFetcherDelegate {
582 public:
583 MultiHttpFetcherTestDelegate(int expected_response_code)
584 : expected_response_code_(expected_response_code) {}
585 virtual void ReceivedBytes(HttpFetcher* fetcher,
586 const char* bytes, int length) {
587 data.append(bytes, length);
588 }
589 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) {
590 EXPECT_EQ(expected_response_code_ != 0, successful);
591 if (expected_response_code_ != 0)
592 EXPECT_EQ(expected_response_code_, fetcher->http_response_code());
593 g_main_loop_quit(loop_);
594 }
595 int expected_response_code_;
596 string data;
597 GMainLoop* loop_;
598 };
599
600 void MultiTest(HttpFetcher* fetcher_in,
601 const string& url,
602 const MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect& ranges,
603 const string& expected_prefix,
604 off_t expected_size,
605 int expected_response_code) {
606 GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
607 {
608 MultiHttpFetcherTestDelegate delegate(expected_response_code);
609 delegate.loop_ = loop;
610 scoped_ptr<HttpFetcher> fetcher(fetcher_in);
611 MultiHttpFetcher<LibcurlHttpFetcher>* multi_fetcher =
612 dynamic_cast<MultiHttpFetcher<LibcurlHttpFetcher>*>(fetcher.get());
613 ASSERT_TRUE(multi_fetcher);
614 multi_fetcher->set_ranges(ranges);
615 fetcher->set_delegate(&delegate);
616
617 StartTransferArgs start_xfer_args = {fetcher.get(), url};
618
619 g_timeout_add(0, StartTransfer, &start_xfer_args);
620 g_main_loop_run(loop);
621
622 EXPECT_EQ(expected_size, delegate.data.size());
623 EXPECT_EQ(expected_prefix,
624 string(delegate.data.data(), expected_prefix.size()));
625 }
626 g_main_loop_unref(loop);
627 }
628 } // namespace {}
629
630 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherSimplTest) {
631 if (!this->IsMulti())
632 return;
633 typename TestFixture::HttpServer server;
634 ASSERT_TRUE(server.started_);
635
636 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
637 ranges.push_back(make_pair(0, 25));
638 ranges.push_back(make_pair(99, -1));
639 MultiTest(this->NewLargeFetcher(),
640 this->BigUrl(),
641 ranges,
642 "abcdefghijabcdefghijabcdejabcdefghijabcdef",
643 kBigSize - (99 - 25),
644 206);
645 }
646
647 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherLengthLimitTest) {
648 if (!this->IsMulti())
649 return;
650 typename TestFixture::HttpServer server;
651 ASSERT_TRUE(server.started_);
652
653 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
654 ranges.push_back(make_pair(0, 24));
655 MultiTest(this->NewLargeFetcher(),
656 this->BigUrl(),
657 ranges,
658 "abcdefghijabcdefghijabcd",
659 24,
660 200);
661 }
662
663 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherMultiEndTest) {
664 if (!this->IsMulti())
665 return;
666 typename TestFixture::HttpServer server;
667 ASSERT_TRUE(server.started_);
668
669 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
670 ranges.push_back(make_pair(kBigSize - 2, -1));
671 ranges.push_back(make_pair(kBigSize - 3, -1));
672 MultiTest(this->NewLargeFetcher(),
673 this->BigUrl(),
674 ranges,
675 "ijhij",
676 5,
677 206);
678 }
679
680 TYPED_TEST(HttpFetcherTest, MultiHttpFetcherInsufficientTest) {
681 if (!this->IsMulti())
682 return;
683 typename TestFixture::HttpServer server;
684 ASSERT_TRUE(server.started_);
685
686 MultiHttpFetcher<LibcurlHttpFetcher>::RangesVect ranges;
687 ranges.push_back(make_pair(kBigSize - 2, 4));
688 for (int i = 0; i < 2; ++i) {
689 MultiTest(this->NewLargeFetcher(),
690 this->BigUrl(),
691 ranges,
692 "ij",
693 2,
694 0);
695 ranges.push_back(make_pair(0, 5));
696 }
697 }
698
553 } // namespace chromeos_update_engine 699 } // namespace chromeos_update_engine
OLDNEW
« no previous file with comments | « http_fetcher.h ('k') | libcurl_http_fetcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698