OLD | NEW |
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 #include <string> |
| 7 #include <vector> |
6 #include <base/scoped_ptr.h> | 8 #include <base/scoped_ptr.h> |
7 #include <glib.h> | 9 #include <glib.h> |
8 #include <base/logging.h> | |
9 #include <gtest/gtest.h> | 10 #include <gtest/gtest.h> |
| 11 #include "chromeos/obsolete_logging.h" |
10 #include "update_engine/libcurl_http_fetcher.h" | 12 #include "update_engine/libcurl_http_fetcher.h" |
11 #include "update_engine/mock_http_fetcher.h" | 13 #include "update_engine/mock_http_fetcher.h" |
12 | 14 |
| 15 using std::string; |
| 16 using std::vector; |
| 17 |
13 namespace chromeos_update_engine { | 18 namespace chromeos_update_engine { |
14 | 19 |
15 namespace { | 20 namespace { |
16 // WARNING, if you update this, you must also update test_http_server.py | 21 // WARNING, if you update this, you must also update test_http_server.py |
17 const char* const kServerPort = "8080"; | 22 const char* const kServerPort = "8080"; |
18 string LocalServerUrlForPath(const string& path) { | 23 string LocalServerUrlForPath(const string& path) { |
19 return string("http://127.0.0.1:") + kServerPort + path; | 24 return string("http://127.0.0.1:") + kServerPort + path; |
20 } | 25 } |
21 } | 26 } |
22 | 27 |
23 template <typename T> | 28 template <typename T> |
24 class HttpFetcherTest : public ::testing::Test { | 29 class HttpFetcherTest : public ::testing::Test { |
25 public: | 30 public: |
26 HttpFetcher* NewLargeFetcher() = 0; | 31 HttpFetcher* NewLargeFetcher() = 0; |
27 HttpFetcher* NewSmallFetcher() = 0; | 32 HttpFetcher* NewSmallFetcher() = 0; |
28 string BigUrl() const = 0; | 33 string BigUrl() const = 0; |
29 string SmallUrl() const = 0; | 34 string SmallUrl() const = 0; |
| 35 bool IsMock() const = 0; |
30 }; | 36 }; |
31 | 37 |
32 class NullHttpServer { | 38 class NullHttpServer { |
33 public: | 39 public: |
34 NullHttpServer() : started_(true) {} | 40 NullHttpServer() : started_(true) {} |
35 ~NullHttpServer() {} | 41 ~NullHttpServer() {} |
36 bool started_; | 42 bool started_; |
37 }; | 43 }; |
38 | 44 |
39 | 45 |
40 template <> | 46 template <> |
41 class HttpFetcherTest<MockHttpFetcher> : public ::testing::Test { | 47 class HttpFetcherTest<MockHttpFetcher> : public ::testing::Test { |
42 public: | 48 public: |
43 HttpFetcher* NewLargeFetcher() { | 49 HttpFetcher* NewLargeFetcher() { |
44 vector<char> big_data(1000000); | 50 vector<char> big_data(1000000); |
45 return new MockHttpFetcher(big_data.data(), big_data.size()); | 51 return new MockHttpFetcher(big_data.data(), big_data.size()); |
46 } | 52 } |
47 HttpFetcher* NewSmallFetcher() { | 53 HttpFetcher* NewSmallFetcher() { |
48 return new MockHttpFetcher("x", 1); | 54 return new MockHttpFetcher("x", 1); |
49 } | 55 } |
50 string BigUrl() const { | 56 string BigUrl() const { |
51 return "unused://unused"; | 57 return "unused://unused"; |
52 } | 58 } |
53 string SmallUrl() const { | 59 string SmallUrl() const { |
54 return "unused://unused"; | 60 return "unused://unused"; |
55 } | 61 } |
| 62 bool IsMock() const { return true; } |
56 typedef NullHttpServer HttpServer; | 63 typedef NullHttpServer HttpServer; |
57 }; | 64 }; |
58 | 65 |
59 class PythonHttpServer { | 66 class PythonHttpServer { |
60 public: | 67 public: |
61 PythonHttpServer() { | 68 PythonHttpServer() { |
62 char *argv[2] = {strdup("./test_http_server.py"), NULL}; | 69 char *argv[2] = {strdup("./test_http_server"), NULL}; |
63 GError *err; | 70 GError *err; |
64 started_ = false; | 71 started_ = false; |
65 if (!g_spawn_async(NULL, | 72 if (!g_spawn_async(NULL, |
66 argv, | 73 argv, |
67 NULL, | 74 NULL, |
68 G_SPAWN_DO_NOT_REAP_CHILD, | 75 G_SPAWN_DO_NOT_REAP_CHILD, |
69 NULL, | 76 NULL, |
70 NULL, | 77 NULL, |
71 &pid_, | 78 &pid_, |
72 &err)) { | 79 &err)) { |
73 return; | 80 return; |
74 } | 81 } |
75 int rc = 1; | 82 int rc = 1; |
76 while (0 != rc) { | 83 while (0 != rc) { |
77 | |
78 rc = system((string("wget --output-document=/dev/null ") + | 84 rc = system((string("wget --output-document=/dev/null ") + |
79 LocalServerUrlForPath("/test")).c_str()); | 85 LocalServerUrlForPath("/test")).c_str()); |
80 usleep(10 * 1000); // 10 ms | 86 usleep(10 * 1000); // 10 ms |
81 } | 87 } |
82 started_ = true; | 88 started_ = true; |
83 free(argv[0]); | 89 free(argv[0]); |
84 return; | 90 return; |
85 } | 91 } |
86 ~PythonHttpServer() { | 92 ~PythonHttpServer() { |
87 if (!started_) | 93 if (!started_) |
(...skipping 17 matching lines...) Expand all Loading... |
105 } | 111 } |
106 HttpFetcher* NewSmallFetcher() { | 112 HttpFetcher* NewSmallFetcher() { |
107 return NewLargeFetcher(); | 113 return NewLargeFetcher(); |
108 } | 114 } |
109 string BigUrl() const { | 115 string BigUrl() const { |
110 return LocalServerUrlForPath("/big"); | 116 return LocalServerUrlForPath("/big"); |
111 } | 117 } |
112 string SmallUrl() const { | 118 string SmallUrl() const { |
113 return LocalServerUrlForPath("/foo"); | 119 return LocalServerUrlForPath("/foo"); |
114 } | 120 } |
| 121 bool IsMock() const { return false; } |
115 typedef PythonHttpServer HttpServer; | 122 typedef PythonHttpServer HttpServer; |
116 }; | 123 }; |
117 | 124 |
118 typedef ::testing::Types<LibcurlHttpFetcher, MockHttpFetcher> | 125 typedef ::testing::Types<LibcurlHttpFetcher, MockHttpFetcher> |
119 HttpFetcherTestTypes; | 126 HttpFetcherTestTypes; |
120 TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes); | 127 TYPED_TEST_CASE(HttpFetcherTest, HttpFetcherTestTypes); |
121 | 128 |
122 namespace { | 129 namespace { |
123 class HttpFetcherTestDelegate : public HttpFetcherDelegate { | 130 class HttpFetcherTestDelegate : public HttpFetcherDelegate { |
124 public: | 131 public: |
125 virtual void ReceivedBytes(HttpFetcher* fetcher, | 132 virtual void ReceivedBytes(HttpFetcher* fetcher, |
126 const char* bytes, int length) { | 133 const char* bytes, int length) { |
127 char str[length + 1]; | 134 char str[length + 1]; |
128 memset(str, 0, length + 1); | 135 memset(str, 0, length + 1); |
129 memcpy(str, bytes, length); | 136 memcpy(str, bytes, length); |
130 } | 137 } |
131 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { | 138 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { |
132 g_main_loop_quit(loop_); | 139 g_main_loop_quit(loop_); |
133 } | 140 } |
134 GMainLoop* loop_; | 141 GMainLoop* loop_; |
135 }; | 142 }; |
| 143 |
| 144 struct StartTransferArgs { |
| 145 HttpFetcher *http_fetcher; |
| 146 string url; |
| 147 }; |
| 148 |
| 149 gboolean StartTransfer(gpointer data) { |
| 150 StartTransferArgs *args = reinterpret_cast<StartTransferArgs*>(data); |
| 151 args->http_fetcher->BeginTransfer(args->url); |
| 152 return FALSE; |
| 153 } |
136 } // namespace {} | 154 } // namespace {} |
137 | 155 |
138 TYPED_TEST(HttpFetcherTest, SimpleTest) { | 156 TYPED_TEST(HttpFetcherTest, SimpleTest) { |
139 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); | 157 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
140 { | 158 { |
141 HttpFetcherTestDelegate delegate; | 159 HttpFetcherTestDelegate delegate; |
142 delegate.loop_ = loop; | 160 delegate.loop_ = loop; |
143 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher()); | 161 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher()); |
144 fetcher->set_delegate(&delegate); | 162 fetcher->set_delegate(&delegate); |
145 | 163 |
146 typename TestFixture::HttpServer server; | 164 typename TestFixture::HttpServer server; |
147 ASSERT_TRUE(server.started_); | 165 ASSERT_TRUE(server.started_); |
148 | 166 |
149 fetcher->BeginTransfer(this->SmallUrl()); | 167 StartTransferArgs start_xfer_args = {fetcher.get(), this->SmallUrl()}; |
| 168 |
| 169 g_timeout_add(0, StartTransfer, &start_xfer_args); |
150 g_main_loop_run(loop); | 170 g_main_loop_run(loop); |
151 } | 171 } |
152 g_main_loop_unref(loop); | 172 g_main_loop_unref(loop); |
153 } | 173 } |
154 | 174 |
155 namespace { | 175 namespace { |
156 class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate { | 176 class PausingHttpFetcherTestDelegate : public HttpFetcherDelegate { |
157 public: | 177 public: |
158 virtual void ReceivedBytes(HttpFetcher* fetcher, | 178 virtual void ReceivedBytes(HttpFetcher* fetcher, |
159 const char* bytes, int length) { | 179 const char* bytes, int length) { |
160 char str[length + 1]; | 180 char str[length + 1]; |
161 LOG(INFO) << "got " << length << " bytes"; | |
162 memset(str, 0, length + 1); | 181 memset(str, 0, length + 1); |
163 memcpy(str, bytes, length); | 182 memcpy(str, bytes, length); |
164 CHECK(!paused_); | 183 CHECK(!paused_); |
165 paused_ = true; | 184 paused_ = true; |
166 fetcher->Pause(); | 185 fetcher->Pause(); |
167 LOG(INFO) << "calling pause"; | |
168 } | 186 } |
169 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { | 187 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { |
170 g_main_loop_quit(loop_); | 188 g_main_loop_quit(loop_); |
171 } | 189 } |
172 void Unpause() { | 190 void Unpause() { |
173 CHECK(paused_); | 191 CHECK(paused_); |
174 paused_ = false; | 192 paused_ = false; |
175 fetcher_->Unpause(); | 193 fetcher_->Unpause(); |
176 LOG(INFO) << "calling unpause"; | |
177 } | 194 } |
178 bool paused_; | 195 bool paused_; |
179 HttpFetcher* fetcher_; | 196 HttpFetcher* fetcher_; |
180 GMainLoop* loop_; | 197 GMainLoop* loop_; |
181 }; | 198 }; |
182 | 199 |
183 gboolean UnpausingTimeoutCallback(gpointer data) { | 200 gboolean UnpausingTimeoutCallback(gpointer data) { |
184 PausingHttpFetcherTestDelegate *delegate = | 201 PausingHttpFetcherTestDelegate *delegate = |
185 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data); | 202 reinterpret_cast<PausingHttpFetcherTestDelegate*>(data); |
186 if (delegate->paused_) | 203 if (delegate->paused_) |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 NULL); | 284 NULL); |
268 g_source_attach(timeout_source_, NULL); | 285 g_source_attach(timeout_source_, NULL); |
269 fetcher->BeginTransfer(this->BigUrl()); | 286 fetcher->BeginTransfer(this->BigUrl()); |
270 | 287 |
271 g_main_loop_run(loop); | 288 g_main_loop_run(loop); |
272 g_source_destroy(timeout_source_); | 289 g_source_destroy(timeout_source_); |
273 } | 290 } |
274 g_main_loop_unref(loop); | 291 g_main_loop_unref(loop); |
275 } | 292 } |
276 | 293 |
| 294 namespace { |
| 295 class FlakyHttpFetcherTestDelegate : public HttpFetcherDelegate { |
| 296 public: |
| 297 virtual void ReceivedBytes(HttpFetcher* fetcher, |
| 298 const char* bytes, int length) { |
| 299 data.append(bytes, length); |
| 300 } |
| 301 virtual void TransferComplete(HttpFetcher* fetcher, bool successful) { |
| 302 g_main_loop_quit(loop_); |
| 303 } |
| 304 string data; |
| 305 GMainLoop* loop_; |
| 306 }; |
| 307 } // namespace {} |
| 308 |
| 309 TYPED_TEST(HttpFetcherTest, FlakyTest) { |
| 310 if (this->IsMock()) |
| 311 return; |
| 312 GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); |
| 313 { |
| 314 FlakyHttpFetcherTestDelegate delegate; |
| 315 delegate.loop_ = loop; |
| 316 scoped_ptr<HttpFetcher> fetcher(this->NewSmallFetcher()); |
| 317 fetcher->set_delegate(&delegate); |
| 318 |
| 319 typename TestFixture::HttpServer server; |
| 320 ASSERT_TRUE(server.started_); |
| 321 |
| 322 StartTransferArgs start_xfer_args = { |
| 323 fetcher.get(), |
| 324 LocalServerUrlForPath("/flaky") |
| 325 }; |
| 326 |
| 327 g_timeout_add(0, StartTransfer, &start_xfer_args); |
| 328 g_main_loop_run(loop); |
| 329 |
| 330 // verify the data we get back |
| 331 ASSERT_EQ(100000, delegate.data.size()); |
| 332 for (int i = 0; i < 100000; i += 10) { |
| 333 // Assert so that we don't flood the screen w/ EXPECT errors on failure. |
| 334 ASSERT_EQ(delegate.data.substr(i, 10), "abcdefghij"); |
| 335 } |
| 336 } |
| 337 g_main_loop_unref(loop); |
| 338 } |
| 339 |
277 } // namespace chromeos_update_engine | 340 } // namespace chromeos_update_engine |
OLD | NEW |