OLD | NEW |
| (Empty) |
1 // Copyright 2007-2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include <windows.h> | |
17 #include <winhttp.h> | |
18 #include <vector> | |
19 #include "base/scoped_ptr.h" | |
20 #include "base/basictypes.h" | |
21 #include "omaha/base/app_util.h" | |
22 #include "omaha/base/browser_utils.h" | |
23 #include "omaha/base/constants.h" | |
24 #include "omaha/base/error.h" | |
25 #include "omaha/base/logging.h" | |
26 #include "omaha/base/queue_timer.h" | |
27 #include "omaha/base/scope_guard.h" | |
28 #include "omaha/base/scoped_any.h" | |
29 #include "omaha/base/scoped_ptr_address.h" | |
30 #include "omaha/base/time.h" | |
31 #include "omaha/base/utils.h" | |
32 #include "omaha/base/vista_utils.h" | |
33 #include "omaha/net/bits_request.h" | |
34 #include "omaha/net/cup_request.h" | |
35 #include "omaha/net/network_config.h" | |
36 #include "omaha/net/network_request.h" | |
37 #include "omaha/net/simple_request.h" | |
38 #include "omaha/net/urlmon_request.h" | |
39 #include "omaha/testing/unit_test.h" | |
40 | |
41 namespace omaha { | |
42 | |
43 class NetworkRequestTest | |
44 : public testing::Test, | |
45 public NetworkRequestCallback { | |
46 protected: | |
47 NetworkRequestTest() {} | |
48 | |
49 static void SetUpTestCase() { | |
50 // Initialize the detection chain: GoogleProxy, FireFox if it is the | |
51 // default browser, and IE. | |
52 NetworkConfig* network_config = NULL; | |
53 EXPECT_HRESULT_SUCCEEDED( | |
54 NetworkConfigManager::Instance().GetUserNetworkConfig(&network_config)); | |
55 | |
56 network_config->Clear(); | |
57 network_config->Add(new UpdateDevProxyDetector); | |
58 BrowserType browser_type(BROWSER_UNKNOWN); | |
59 GetDefaultBrowserType(&browser_type); | |
60 if (browser_type == BROWSER_FIREFOX) { | |
61 network_config->Add(new FirefoxProxyDetector); | |
62 } | |
63 network_config->Add(new IEProxyDetector); | |
64 network_config->Add(new DefaultProxyDetector); | |
65 | |
66 vista::GetLoggedOnUserToken(&token_); | |
67 } | |
68 | |
69 static void TearDownTestCase() { | |
70 if (token_) { | |
71 ::CloseHandle(token_); | |
72 } | |
73 | |
74 NetworkConfig* network_config = NULL; | |
75 EXPECT_HRESULT_SUCCEEDED( | |
76 NetworkConfigManager::Instance().GetUserNetworkConfig(&network_config)); | |
77 | |
78 network_config->Clear(); | |
79 } | |
80 | |
81 virtual void SetUp() { | |
82 NetworkConfig* network_config = NULL; | |
83 EXPECT_HRESULT_SUCCEEDED( | |
84 NetworkConfigManager::Instance().GetUserNetworkConfig(&network_config)); | |
85 | |
86 network_request_.reset(new NetworkRequest(network_config->session())); | |
87 } | |
88 | |
89 virtual void TearDown() {} | |
90 | |
91 virtual void OnProgress(int bytes, int bytes_total, int, const TCHAR*) { | |
92 UNREFERENCED_PARAMETER(bytes); | |
93 UNREFERENCED_PARAMETER(bytes_total); | |
94 NET_LOG(L3, (_T("[downloading %d of %d]"), bytes, bytes_total)); | |
95 } | |
96 | |
97 virtual void OnRequestBegin() { | |
98 NET_LOG(L3, (_T("[download starts]"))); | |
99 } | |
100 | |
101 virtual void OnRequestRetryScheduled(time64 next_retry_time) { | |
102 UNREFERENCED_PARAMETER(next_retry_time); | |
103 | |
104 time64 now = GetCurrent100NSTime(); | |
105 ASSERT1(next_retry_time > now); | |
106 | |
107 NET_LOG(L3, (_T("\n[Download will retry in %d seconds]\n"), | |
108 CeilingDivide(next_retry_time - now, kSecsTo100ns))); | |
109 } | |
110 | |
111 static void CancelCallback(QueueTimer* queue_timer) { | |
112 ASSERT_TRUE(queue_timer); | |
113 ASSERT_TRUE(queue_timer->ctx()); | |
114 void* ctx = queue_timer->ctx(); | |
115 NetworkRequestTest* test = static_cast<NetworkRequestTest*>(ctx); | |
116 | |
117 const TCHAR* msg = _T("CancelCallback"); | |
118 ASSERT_HRESULT_SUCCEEDED(test->network_request_->Cancel()); | |
119 } | |
120 | |
121 // http get. | |
122 void HttpGetHelper() { | |
123 std::vector<uint8> response; | |
124 CString url = _T("http://www.google.com/robots.txt"); | |
125 network_request_->set_num_retries(2); | |
126 EXPECT_HRESULT_SUCCEEDED(network_request_->Get(url, &response)); | |
127 | |
128 int http_status = network_request_->http_status_code(); | |
129 EXPECT_TRUE(http_status == HTTP_STATUS_OK || | |
130 http_status == HTTP_STATUS_PARTIAL_CONTENT); | |
131 } | |
132 | |
133 // https get. | |
134 void HttpsGetHelper() { | |
135 std::vector<uint8> response; | |
136 CString url = _T("https://www.google.com/robots.txt"); | |
137 network_request_->set_num_retries(2); | |
138 EXPECT_HRESULT_SUCCEEDED(network_request_->Get(url, &response)); | |
139 | |
140 int http_status = network_request_->http_status_code(); | |
141 EXPECT_TRUE(http_status == HTTP_STATUS_OK || | |
142 http_status == HTTP_STATUS_PARTIAL_CONTENT); | |
143 } | |
144 | |
145 // http post. | |
146 void HttpPostHelper() { | |
147 std::vector<uint8> response; | |
148 | |
149 CString url = _T("http://tools.google.com/service/update2"); | |
150 // Post a buffer. | |
151 const uint8 request[] = "<o:gupdate xmlns:o=\"http://www.google.com/update2/
request\" testsource=\"dev\"/>"; // NOLINT | |
152 network_request_->set_num_retries(2); | |
153 EXPECT_HRESULT_SUCCEEDED(network_request_->Post(url, | |
154 request, | |
155 arraysize(request) - 1, | |
156 &response)); | |
157 | |
158 int http_status = network_request_->http_status_code(); | |
159 EXPECT_TRUE(http_status == HTTP_STATUS_OK || | |
160 http_status == HTTP_STATUS_PARTIAL_CONTENT); | |
161 | |
162 // Post an UTF8 string. | |
163 CStringA utf8_request(reinterpret_cast<const char*>(request)); | |
164 EXPECT_HRESULT_SUCCEEDED(network_request_->PostUtf8String(url, | |
165 utf8_request, | |
166 &response)); | |
167 http_status = network_request_->http_status_code(); | |
168 EXPECT_TRUE(http_status == HTTP_STATUS_OK || | |
169 http_status == HTTP_STATUS_PARTIAL_CONTENT); | |
170 | |
171 // Post a Unicode string. | |
172 CString unicode_request(reinterpret_cast<const char*>(request)); | |
173 EXPECT_HRESULT_SUCCEEDED(network_request_->PostString(url, | |
174 unicode_request, | |
175 &response)); | |
176 http_status = network_request_->http_status_code(); | |
177 EXPECT_TRUE(http_status == HTTP_STATUS_OK || | |
178 http_status == HTTP_STATUS_PARTIAL_CONTENT); | |
179 } | |
180 | |
181 // Download http file. | |
182 void DownloadHelper() { | |
183 CString url = _T("http://dl.google.com/update2/UpdateData.bin"); | |
184 | |
185 CString temp_dir = app_util::GetTempDir(); | |
186 CString temp_file; | |
187 EXPECT_TRUE(::GetTempFileName(temp_dir, _T("tmp"), 0, | |
188 CStrBuf(temp_file, MAX_PATH))); | |
189 network_request_->set_num_retries(2); | |
190 network_request_->set_low_priority(true); | |
191 network_request_->set_callback(this); | |
192 EXPECT_HRESULT_SUCCEEDED(network_request_->DownloadFile(url, temp_file)); | |
193 EXPECT_TRUE(::DeleteFile(temp_file)); | |
194 | |
195 int http_status = network_request_->http_status_code(); | |
196 EXPECT_TRUE(http_status == HTTP_STATUS_OK || | |
197 http_status == HTTP_STATUS_PARTIAL_CONTENT); | |
198 } | |
199 | |
200 void MultipleRequestsHelper() { | |
201 std::vector<uint8> response; | |
202 | |
203 CString url = _T("http://tools.google.com/service/update2"); | |
204 const uint8 request[] = "<o:gupdate xmlns:o=\"http://www.google.com/update2/
request\" testsource=\"dev\"/>"; // NOLINT | |
205 for (size_t i = 0; i != 3; ++i) { | |
206 EXPECT_HRESULT_SUCCEEDED(network_request_->Post(url, | |
207 request, | |
208 arraysize(request) - 1, | |
209 &response)); | |
210 | |
211 int http_status = network_request_->http_status_code(); | |
212 EXPECT_TRUE(http_status == HTTP_STATUS_OK || | |
213 http_status == HTTP_STATUS_PARTIAL_CONTENT); | |
214 } | |
215 } | |
216 | |
217 void PostRequestHelper() { | |
218 std::vector<uint8> response; | |
219 CString url = _T("http://tools.google.com/service/update2"); | |
220 CString request = _T("<o:gupdate xmlns:o=\"http://www.google.com/update2/req
uest\" testsource=\"dev\"/>"); // NOLINT | |
221 EXPECT_HRESULT_SUCCEEDED(PostRequest(network_request_.get(), | |
222 true, | |
223 url, | |
224 request, | |
225 &response)); | |
226 } | |
227 | |
228 void PostRequestNegativeTestHelper() { | |
229 std::vector<uint8> response; | |
230 CString url = _T("http://no_such_host.google.com/service/update2"); | |
231 CString request = _T("<o:gupdate xmlns:o=\"http://www.google.com/update2/req
uest\" testsource=\"dev\"/>"); // NOLINT | |
232 EXPECT_HRESULT_FAILED(PostRequest(network_request_.get(), | |
233 true, | |
234 url, | |
235 request, | |
236 &response)); | |
237 } | |
238 | |
239 void RetriesNegativeTestHelper() { | |
240 // Try a direct connection to a non-existent host and keep retrying until | |
241 // the retries are used up. Urlmon request is using IE's settings. | |
242 // Therefore, it is possible a proxy is used. In this case, the http | |
243 // response is '503 Service Unavailable'. | |
244 ProxyConfig config; | |
245 network_request_->set_proxy_configuration(&config); | |
246 network_request_->set_num_retries(2); | |
247 network_request_->set_time_between_retries(10); // 10 miliseconds. | |
248 std::vector<uint8> response; | |
249 | |
250 CString url = _T("http://nohost/nofile"); | |
251 | |
252 // One request plus 2 retries after 10 and 20 miliseconds respectively. | |
253 HRESULT hr = network_request_->Get(url, &response); | |
254 EXPECT_TRUE(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_NAME_NOT_RESOLVED) || | |
255 hr == INET_E_RESOURCE_NOT_FOUND || | |
256 hr == HRESULTFromHttpStatusCode(503)); | |
257 } | |
258 | |
259 void CancelTest_GetHelper() { | |
260 HANDLE timer_queue = ::CreateTimerQueue(); | |
261 ASSERT_TRUE(timer_queue); | |
262 ON_SCOPE_EXIT(::DeleteTimerQueueEx, timer_queue, INVALID_HANDLE_VALUE); | |
263 | |
264 QueueTimer queue_timer(timer_queue, | |
265 &NetworkRequestTest::CancelCallback, | |
266 this); | |
267 ASSERT_HRESULT_SUCCEEDED(queue_timer.Start(200, 0, WT_EXECUTEONLYONCE)); | |
268 | |
269 // Try a direct connection to a non-existent host and keep retrying until | |
270 // canceled by the timer. | |
271 ProxyConfig config; | |
272 network_request_->set_proxy_configuration(&config); | |
273 network_request_->set_num_retries(10); | |
274 network_request_->set_time_between_retries(10); // 10 miliseconds. | |
275 std::vector<uint8> response; | |
276 | |
277 CString url = _T("http://nohost/nofile"); | |
278 | |
279 EXPECT_EQ(GOOPDATE_E_CANCELLED, | |
280 network_request_->Get(url, &response)); | |
281 | |
282 EXPECT_EQ(GOOPDATE_E_CANCELLED, | |
283 network_request_->Get(url, &response)); | |
284 } | |
285 | |
286 scoped_ptr<NetworkRequest> network_request_; | |
287 static HANDLE token_; | |
288 }; | |
289 | |
290 HANDLE NetworkRequestTest::token_ = NULL; | |
291 | |
292 // http get. | |
293 TEST_F(NetworkRequestTest, HttpGet) { | |
294 network_request_->AddHttpRequest(new SimpleRequest); | |
295 HttpGetHelper(); | |
296 } | |
297 | |
298 // http get. | |
299 TEST_F(NetworkRequestTest, HttpGetUrlmon) { | |
300 network_request_->AddHttpRequest(new UrlmonRequest); | |
301 HttpGetHelper(); | |
302 } | |
303 | |
304 // https get. | |
305 TEST_F(NetworkRequestTest, HttpsGet) { | |
306 network_request_->AddHttpRequest(new SimpleRequest); | |
307 HttpsGetHelper(); | |
308 } | |
309 | |
310 // https get. | |
311 TEST_F(NetworkRequestTest, HttpsGetUrlmon) { | |
312 network_request_->AddHttpRequest(new UrlmonRequest); | |
313 HttpsGetHelper(); | |
314 } | |
315 | |
316 // http post. | |
317 TEST_F(NetworkRequestTest, HttpPost) { | |
318 network_request_->AddHttpRequest(new CupRequest(new SimpleRequest)); | |
319 network_request_->AddHttpRequest(new SimpleRequest); | |
320 HttpPostHelper(); | |
321 } | |
322 | |
323 // http post. | |
324 TEST_F(NetworkRequestTest, HttpPostUrlmon) { | |
325 network_request_->AddHttpRequest(new CupRequest(new UrlmonRequest)); | |
326 network_request_->AddHttpRequest(new UrlmonRequest); | |
327 HttpPostHelper(); | |
328 } | |
329 | |
330 // Download http file. | |
331 TEST_F(NetworkRequestTest, Download) { | |
332 BitsRequest* bits_request(new BitsRequest); | |
333 // Bits specific settings. | |
334 // | |
335 // Hardcode for now the min value, just to see how it works. | |
336 // TODO(omaha): expose properties to NetworkRequest. | |
337 bits_request->set_minimum_retry_delay(60); | |
338 bits_request->set_no_progress_timeout(5); | |
339 | |
340 network_request_->AddHttpRequest(bits_request); | |
341 network_request_->AddHttpRequest(new SimpleRequest); | |
342 DownloadHelper(); | |
343 } | |
344 | |
345 // Download http file. | |
346 TEST_F(NetworkRequestTest, DownloadUrlmon) { | |
347 BitsRequest* bits_request(new BitsRequest); | |
348 // Bits specific settings. | |
349 bits_request->set_minimum_retry_delay(60); | |
350 bits_request->set_no_progress_timeout(5); | |
351 | |
352 network_request_->AddHttpRequest(bits_request); | |
353 network_request_->AddHttpRequest(new UrlmonRequest); | |
354 DownloadHelper(); | |
355 } | |
356 | |
357 TEST_F(NetworkRequestTest, MultipleRequests) { | |
358 network_request_->AddHttpRequest(new CupRequest(new SimpleRequest)); | |
359 MultipleRequestsHelper(); | |
360 } | |
361 | |
362 TEST_F(NetworkRequestTest, MultipleRequestsUrlmon) { | |
363 network_request_->AddHttpRequest(new CupRequest(new UrlmonRequest)); | |
364 MultipleRequestsHelper(); | |
365 } | |
366 | |
367 TEST_F(NetworkRequestTest, PostRequest) { | |
368 network_request_->AddHttpRequest(new SimpleRequest); | |
369 PostRequestHelper(); | |
370 } | |
371 | |
372 TEST_F(NetworkRequestTest, PostRequestUrlmon) { | |
373 network_request_->AddHttpRequest(new UrlmonRequest); | |
374 PostRequestHelper(); | |
375 } | |
376 | |
377 TEST_F(NetworkRequestTest, PostRequestNegativeTest) { | |
378 network_request_->AddHttpRequest(new SimpleRequest); | |
379 PostRequestNegativeTestHelper(); | |
380 } | |
381 | |
382 TEST_F(NetworkRequestTest, PostRequestNegativeTestUrlmon) { | |
383 network_request_->AddHttpRequest(new UrlmonRequest); | |
384 PostRequestNegativeTestHelper(); | |
385 } | |
386 | |
387 TEST_F(NetworkRequestTest, RetriesNegativeTest) { | |
388 network_request_->AddHttpRequest(new SimpleRequest); | |
389 RetriesNegativeTestHelper(); | |
390 } | |
391 | |
392 TEST_F(NetworkRequestTest, RetriesNegativeTestUrlmon) { | |
393 network_request_->AddHttpRequest(new UrlmonRequest); | |
394 RetriesNegativeTestHelper(); | |
395 } | |
396 | |
397 // Network request can't be reused once canceled. | |
398 TEST_F(NetworkRequestTest, CancelTest_CannotReuse) { | |
399 network_request_->Cancel(); | |
400 std::vector<uint8> response; | |
401 | |
402 CString url = _T("https://www.google.com/robots.txt"); | |
403 EXPECT_EQ(GOOPDATE_E_CANCELLED, | |
404 network_request_->Get(url, &response)); | |
405 } | |
406 | |
407 TEST_F(NetworkRequestTest, CancelTest_DownloadFile) { | |
408 HANDLE timer_queue = ::CreateTimerQueue(); | |
409 ASSERT_TRUE(timer_queue); | |
410 ON_SCOPE_EXIT(::DeleteTimerQueueEx, timer_queue, INVALID_HANDLE_VALUE); | |
411 | |
412 QueueTimer queue_timer(timer_queue, | |
413 &NetworkRequestTest::CancelCallback, | |
414 this); | |
415 ASSERT_HRESULT_SUCCEEDED(queue_timer.Start(200, 0, WT_EXECUTEONLYONCE)); | |
416 | |
417 // Try a direct connection to a non-existent host and keep retrying until | |
418 // canceled by the timer. | |
419 ProxyConfig config; | |
420 network_request_->set_proxy_configuration(&config); | |
421 | |
422 BitsRequest* bits_request(new BitsRequest); | |
423 bits_request->set_minimum_retry_delay(60); | |
424 bits_request->set_no_progress_timeout(5); | |
425 network_request_->AddHttpRequest(bits_request); | |
426 network_request_->set_num_retries(10); | |
427 network_request_->set_time_between_retries(10); // 10 miliseconds. | |
428 std::vector<uint8> response; | |
429 | |
430 CString url = _T("http://nohost/nofile"); | |
431 | |
432 EXPECT_EQ(GOOPDATE_E_CANCELLED, | |
433 network_request_->DownloadFile(url, _T("c:\\foo"))); | |
434 | |
435 EXPECT_EQ(GOOPDATE_E_CANCELLED, | |
436 network_request_->DownloadFile(url, _T("c:\\foo"))); | |
437 } | |
438 | |
439 TEST_F(NetworkRequestTest, CancelTest_Get) { | |
440 network_request_->AddHttpRequest(new SimpleRequest); | |
441 CancelTest_GetHelper(); | |
442 } | |
443 | |
444 } // namespace omaha | |
445 | |
OLD | NEW |