| 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 |