| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium 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 #ifndef NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ | 5 #ifndef NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ |
| 6 #define NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ | 6 #define NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ |
| 7 | 7 |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 | 9 |
| 10 #include <sstream> | 10 #include <sstream> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/file_path.h" | 14 #include "base/file_path.h" |
| 15 #include "base/file_util.h" | 15 #include "base/file_util.h" |
| 16 #include "base/logging.h" |
| 16 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
| 17 #include "base/path_service.h" | 18 #include "base/path_service.h" |
| 18 #include "base/platform_thread.h" | 19 #include "base/platform_thread.h" |
| 19 #include "base/process_util.h" | 20 #include "base/process_util.h" |
| 20 #include "base/string_util.h" | 21 #include "base/string_util.h" |
| 21 #include "base/thread.h" | 22 #include "base/thread.h" |
| 22 #include "base/time.h" | 23 #include "base/time.h" |
| 23 #include "base/waitable_event.h" | 24 #include "base/waitable_event.h" |
| 24 #include "net/base/io_buffer.h" | 25 #include "net/base/io_buffer.h" |
| 25 #include "net/base/net_errors.h" | 26 #include "net/base/net_errors.h" |
| 27 #include "net/base/ssl_test_util.h" |
| 26 #include "net/http/http_network_layer.h" | 28 #include "net/http/http_network_layer.h" |
| 27 #include "net/url_request/url_request.h" | 29 #include "net/url_request/url_request.h" |
| 28 #include "net/proxy/proxy_service.h" | 30 #include "net/proxy/proxy_service.h" |
| 29 #include "testing/gtest/include/gtest/gtest.h" | 31 #include "testing/gtest/include/gtest/gtest.h" |
| 30 #include "googleurl/src/url_util.h" | 32 #include "googleurl/src/url_util.h" |
| 31 | 33 |
| 32 const int kHTTPDefaultPort = 1337; | 34 const int kHTTPDefaultPort = 1337; |
| 33 const int kFTPDefaultPort = 1338; | 35 const int kFTPDefaultPort = 1338; |
| 34 | 36 |
| 35 const std::string kDefaultHostName("localhost"); | 37 const std::string kDefaultHostName("localhost"); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 std::string data_received_; | 205 std::string data_received_; |
| 204 | 206 |
| 205 // our read buffer | 207 // our read buffer |
| 206 scoped_refptr<net::IOBuffer> buf_; | 208 scoped_refptr<net::IOBuffer> buf_; |
| 207 }; | 209 }; |
| 208 | 210 |
| 209 // This object bounds the lifetime of an external python-based HTTP/FTP server | 211 // This object bounds the lifetime of an external python-based HTTP/FTP server |
| 210 // that can provide various responses useful for testing. | 212 // that can provide various responses useful for testing. |
| 211 class BaseTestServer : public base::RefCounted<BaseTestServer> { | 213 class BaseTestServer : public base::RefCounted<BaseTestServer> { |
| 212 protected: | 214 protected: |
| 213 BaseTestServer() | 215 BaseTestServer() { } |
| 214 : process_handle_(NULL) { | |
| 215 } | |
| 216 | 216 |
| 217 public: | 217 public: |
| 218 virtual ~BaseTestServer() { | |
| 219 if (!IsFinished()) | |
| 220 if (!WaitToFinish(1000)) | |
| 221 Kill(); | |
| 222 } | |
| 223 | |
| 224 bool IsFinished() { | |
| 225 return WaitToFinish(0); | |
| 226 } | |
| 227 | |
| 228 void Kill() { | |
| 229 if (process_handle_) { | |
| 230 #if defined(OS_WIN) | |
| 231 base::KillProcess(process_handle_, 0, true); | |
| 232 #elif defined(OS_POSIX) | |
| 233 // Make sure the process has exited and clean up the process to avoid | |
| 234 // a zombie. | |
| 235 kill(process_handle_, SIGINT); | |
| 236 waitpid(process_handle_, 0, 0); | |
| 237 #endif | |
| 238 base::CloseProcessHandle(process_handle_); | |
| 239 process_handle_ = NULL; | |
| 240 } | |
| 241 } | |
| 242 | |
| 243 bool WaitToFinish(int milliseconds) { | |
| 244 if (process_handle_ == 0) | |
| 245 return true; | |
| 246 bool ret = base::WaitForSingleProcess(process_handle_, milliseconds); | |
| 247 if (ret) { | |
| 248 base::CloseProcessHandle(process_handle_); | |
| 249 process_handle_ = NULL; | |
| 250 } | |
| 251 | |
| 252 return ret; | |
| 253 } | |
| 254 | |
| 255 GURL TestServerPage(const std::string& base_address, | 218 GURL TestServerPage(const std::string& base_address, |
| 256 const std::string& path) { | 219 const std::string& path) { |
| 257 return GURL(base_address + path); | 220 return GURL(base_address + path); |
| 258 } | 221 } |
| 259 | 222 |
| 260 GURL TestServerPage(const std::string& path) { | 223 GURL TestServerPage(const std::string& path) { |
| 261 return GURL(base_address_ + path); | 224 return GURL(base_address_ + path); |
| 262 } | 225 } |
| 263 | 226 |
| 264 GURL TestServerPageW(const std::wstring& path) { | 227 GURL TestServerPageW(const std::wstring& path) { |
| 265 return GURL(base_address_ + WideToUTF8(path)); | 228 return GURL(base_address_ + WideToUTF8(path)); |
| 266 } | 229 } |
| 267 | 230 |
| 268 void SetPythonPaths() { | 231 virtual bool MakeGETRequest(const std::string& page_name) = 0; |
| 269 #if defined(OS_WIN) | |
| 270 // Set up PYTHONPATH so that Python is able to find the in-tree copy of | |
| 271 // pyftpdlib. | |
| 272 static bool set_python_path = false; | |
| 273 if (!set_python_path) { | |
| 274 FilePath pyftpdlib_path; | |
| 275 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &pyftpdlib_path)); | |
| 276 pyftpdlib_path = pyftpdlib_path.Append(L"third_party"); | |
| 277 pyftpdlib_path = pyftpdlib_path.Append(L"pyftpdlib"); | |
| 278 | 232 |
| 279 const wchar_t kPythonPath[] = L"PYTHONPATH"; | 233 protected: |
| 280 wchar_t python_path_c[1024]; | 234 bool Start(net::TestServerLauncher::Protocol protocol, |
| 281 if (GetEnvironmentVariable(kPythonPath, python_path_c, 1023) > 0) { | 235 const std::string& host_name, int port, |
| 282 // PYTHONPATH is already set, append to it. | 236 const FilePath& document_root, |
| 283 std::wstring python_path(python_path_c); | 237 const FilePath& cert_path) { |
| 284 python_path.append(L":"); | 238 std::string blank; |
| 285 python_path.append(pyftpdlib_path.value()); | 239 return Start(protocol, host_name, port, document_root, cert_path, |
| 286 SetEnvironmentVariableW(kPythonPath, python_path.c_str()); | 240 blank, blank); |
| 287 } else { | |
| 288 SetEnvironmentVariableW(kPythonPath, pyftpdlib_path.value().c_str()); | |
| 289 } | |
| 290 | |
| 291 set_python_path = true; | |
| 292 } | |
| 293 #elif defined(OS_POSIX) | |
| 294 // Set up PYTHONPATH so that Python is able to find the in-tree copy of | |
| 295 // tlslite and pyftpdlib. | |
| 296 static bool set_python_path = false; | |
| 297 if (!set_python_path) { | |
| 298 FilePath tlslite_path; | |
| 299 FilePath pyftpdlib_path; | |
| 300 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &tlslite_path)); | |
| 301 tlslite_path = tlslite_path.Append("third_party"); | |
| 302 tlslite_path = tlslite_path.Append("tlslite"); | |
| 303 | |
| 304 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &pyftpdlib_path)); | |
| 305 pyftpdlib_path = pyftpdlib_path.Append("third_party"); | |
| 306 pyftpdlib_path = pyftpdlib_path.Append("pyftpdlib"); | |
| 307 | |
| 308 const char kPythonPath[] = "PYTHONPATH"; | |
| 309 char* python_path_c = getenv(kPythonPath); | |
| 310 if (python_path_c) { | |
| 311 // PYTHONPATH is already set, append to it. | |
| 312 std::string python_path(python_path_c); | |
| 313 python_path.append(":"); | |
| 314 python_path.append(tlslite_path.value()); | |
| 315 python_path.append(":"); | |
| 316 python_path.append(pyftpdlib_path.value()); | |
| 317 setenv(kPythonPath, python_path.c_str(), 1); | |
| 318 } else { | |
| 319 std::string python_path = tlslite_path.value().c_str(); | |
| 320 python_path.append(":"); | |
| 321 python_path.append(pyftpdlib_path.value()); | |
| 322 setenv(kPythonPath, python_path.c_str(), 1); | |
| 323 } | |
| 324 set_python_path = true; | |
| 325 } | |
| 326 #endif | |
| 327 } | 241 } |
| 328 | 242 |
| 329 void SetAppPath(const std::string& host_name, int port, | 243 bool Start(net::TestServerLauncher::Protocol protocol, |
| 330 const std::wstring& document_root, const std::string& scheme, | 244 const std::string& host_name, int port, |
| 331 std::wstring* testserver_path, std::wstring* test_data_directory) { | 245 const FilePath& document_root, |
| 332 port_str_ = IntToString(port); | 246 const FilePath& cert_path, |
| 333 if (url_user_.empty()) { | 247 const std::string& url_user, |
| 334 base_address_ = scheme + "://" + host_name + ":" + port_str_ + "/"; | 248 const std::string& url_password) { |
| 249 if (!launcher_.Start(protocol, |
| 250 host_name, port, document_root, cert_path)) |
| 251 return false; |
| 252 |
| 253 std::string scheme; |
| 254 if (protocol == net::TestServerLauncher::ProtoFTP) |
| 255 scheme = "ftp"; |
| 256 else |
| 257 scheme = "http"; |
| 258 if (!cert_path.empty()) |
| 259 scheme.push_back('s'); |
| 260 |
| 261 std::string port_str = IntToString(port); |
| 262 if (url_user.empty()) { |
| 263 base_address_ = scheme + "://" + host_name + ":" + port_str + "/"; |
| 335 } else { | 264 } else { |
| 336 if (url_password_.empty()) | 265 if (url_password.empty()) |
| 337 base_address_ = scheme + "://" + url_user_ + "@" + | 266 base_address_ = scheme + "://" + url_user + "@" + |
| 338 host_name + ":" + port_str_ + "/"; | 267 host_name + ":" + port_str + "/"; |
| 339 else | 268 else |
| 340 base_address_ = scheme + "://" + url_user_ + ":" + url_password_ + | 269 base_address_ = scheme + "://" + url_user + ":" + url_password + |
| 341 "@" + host_name + ":" + port_str_ + "/"; | 270 "@" + host_name + ":" + port_str + "/"; |
| 342 } | 271 } |
| 343 | |
| 344 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, testserver_path)); | |
| 345 file_util::AppendToPath(testserver_path, L"net"); | |
| 346 file_util::AppendToPath(testserver_path, L"tools"); | |
| 347 file_util::AppendToPath(testserver_path, L"testserver"); | |
| 348 file_util::AppendToPath(testserver_path, L"testserver.py"); | |
| 349 | |
| 350 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &python_runtime_)); | |
| 351 file_util::AppendToPath(&python_runtime_, L"third_party"); | |
| 352 file_util::AppendToPath(&python_runtime_, L"python_24"); | |
| 353 file_util::AppendToPath(&python_runtime_, L"python.exe"); | |
| 354 | |
| 355 PathService::Get(base::DIR_SOURCE_ROOT, test_data_directory); | |
| 356 std::wstring normalized_document_root = document_root; | |
| 357 | |
| 358 #if defined(OS_WIN) | |
| 359 // It is just for windows only and have no effect on other OS | |
| 360 std::replace(normalized_document_root.begin(), | |
| 361 normalized_document_root.end(), | |
| 362 L'/', FilePath::kSeparators[0]); | |
| 363 #endif | |
| 364 if (!normalized_document_root.empty()) | |
| 365 file_util::AppendToPath(test_data_directory, normalized_document_root); | |
| 366 data_directory_ = *test_data_directory; | |
| 367 } | |
| 368 | |
| 369 #if defined(OS_WIN) | |
| 370 void LaunchApp(const std::wstring& command_line) { | |
| 371 ASSERT_TRUE(base::LaunchApp(command_line, false, true, &process_handle_)) << | |
| 372 "Failed to launch " << command_line; | |
| 373 } | |
| 374 #elif defined(OS_POSIX) | |
| 375 void LaunchApp(const std::vector<std::string>& command_line) { | |
| 376 base::file_handle_mapping_vector fds_empty; | |
| 377 ASSERT_TRUE(base::LaunchApp(command_line, fds_empty, false, | |
| 378 &process_handle_)) << | |
| 379 "Failed to launch " << command_line[0] << " ..."; | |
| 380 } | |
| 381 #endif | |
| 382 | |
| 383 virtual bool MakeGETRequest(const std::string& page_name) = 0; | |
| 384 | |
| 385 // Verify that the Server is actually started. | |
| 386 // Otherwise tests can fail if they run faster than Python can start. | |
| 387 bool VerifyLaunchApp(const std::string& page_name) { | |
| 388 int retries = 10; | |
| 389 bool success; | |
| 390 while ((success = MakeGETRequest(page_name)) == false && retries > 0) { | |
| 391 retries--; | |
| 392 PlatformThread::Sleep(500); | |
| 393 } | |
| 394 if (!success) | |
| 395 return false; | |
| 396 return true; | 272 return true; |
| 397 } | 273 } |
| 398 | 274 |
| 399 std::wstring GetDataDirectory() { | |
| 400 return data_directory_; | |
| 401 } | |
| 402 | |
| 403 protected: | |
| 404 // Used by MakeGETRequest to implement sync load behavior. | 275 // Used by MakeGETRequest to implement sync load behavior. |
| 405 class SyncTestDelegate : public TestDelegate { | 276 class SyncTestDelegate : public TestDelegate { |
| 406 public: | 277 public: |
| 407 SyncTestDelegate() : event_(false, false), success_(false) { | 278 SyncTestDelegate() : event_(false, false), success_(false) { |
| 408 } | 279 } |
| 409 virtual void OnResponseCompleted(URLRequest* request) { | 280 virtual void OnResponseCompleted(URLRequest* request) { |
| 410 MessageLoop::current()->DeleteSoon(FROM_HERE, request); | 281 MessageLoop::current()->DeleteSoon(FROM_HERE, request); |
| 411 success_ = request->status().is_success(); | 282 success_ = request->status().is_success(); |
| 412 event_.Signal(); | 283 event_.Signal(); |
| 413 } | 284 } |
| 414 bool Wait(int64 secs) { | 285 bool Wait(int64 secs) { |
| 415 TimeDelta td = TimeDelta::FromSeconds(secs); | 286 TimeDelta td = TimeDelta::FromSeconds(secs); |
| 416 if (event_.TimedWait(td)) | 287 if (event_.TimedWait(td)) |
| 417 return true; | 288 return true; |
| 418 return false; | 289 return false; |
| 419 } | 290 } |
| 420 bool did_succeed() const { return success_; } | 291 bool did_succeed() const { return success_; } |
| 421 private: | 292 private: |
| 422 base::WaitableEvent event_; | 293 base::WaitableEvent event_; |
| 423 bool success_; | 294 bool success_; |
| 424 DISALLOW_COPY_AND_ASSIGN(SyncTestDelegate); | 295 DISALLOW_COPY_AND_ASSIGN(SyncTestDelegate); |
| 425 }; | 296 }; |
| 297 net::TestServerLauncher launcher_; |
| 426 | 298 |
| 427 std::string host_name_; | |
| 428 std::string base_address_; | 299 std::string base_address_; |
| 429 std::string url_user_; | |
| 430 std::string url_password_; | |
| 431 std::wstring python_runtime_; | |
| 432 std::wstring data_directory_; | |
| 433 base::ProcessHandle process_handle_; | |
| 434 std::string port_str_; | |
| 435 | |
| 436 }; | 300 }; |
| 437 | 301 |
| 302 |
| 303 // HTTP |
| 438 class HTTPTestServer : public BaseTestServer { | 304 class HTTPTestServer : public BaseTestServer { |
| 439 protected: | 305 protected: |
| 440 explicit HTTPTestServer() : loop_(NULL) { | 306 explicit HTTPTestServer() : loop_(NULL) { |
| 441 } | 307 } |
| 442 | 308 |
| 443 public: | 309 public: |
| 444 // Creates and returns a new HTTPTestServer. If |loop| is non-null, requests | 310 // Creates and returns a new HTTPTestServer. If |loop| is non-null, requests |
| 445 // are serviced on it, otherwise a new thread and message loop are created. | 311 // are serviced on it, otherwise a new thread and message loop are created. |
| 446 static HTTPTestServer* CreateServer(const std::wstring& document_root, | 312 static HTTPTestServer* CreateServer(const std::wstring& document_root, |
| 447 MessageLoop* loop) { | 313 MessageLoop* loop) { |
| 448 HTTPTestServer* test_server = new HTTPTestServer(); | 314 HTTPTestServer* test_server = new HTTPTestServer(); |
| 449 test_server->loop_ = loop; | 315 test_server->loop_ = loop; |
| 450 if (!test_server->Init(kDefaultHostName, kHTTPDefaultPort, document_root)) { | 316 FilePath no_cert; |
| 317 FilePath docroot = FilePath::FromWStringHack(document_root); |
| 318 if (!test_server->Start(net::TestServerLauncher::ProtoHTTP, |
| 319 kDefaultHostName, kHTTPDefaultPort, docroot, no_cert)) { |
| 451 delete test_server; | 320 delete test_server; |
| 452 return NULL; | 321 return NULL; |
| 453 } | 322 } |
| 454 return test_server; | 323 return test_server; |
| 455 } | 324 } |
| 456 | 325 |
| 457 bool Init(const std::string& host_name, int port, | |
| 458 const std::wstring& document_root) { | |
| 459 std::wstring testserver_path; | |
| 460 std::wstring test_data_directory; | |
| 461 host_name_ = host_name; | |
| 462 #if defined(OS_WIN) | |
| 463 std::wstring command_line; | |
| 464 #elif defined(OS_POSIX) | |
| 465 std::vector<std::string> command_line; | |
| 466 #endif | |
| 467 | |
| 468 // Set PYTHONPATH for tlslite and pyftpdlib | |
| 469 SetPythonPaths(); | |
| 470 SetAppPath(host_name, port, document_root, scheme(), | |
| 471 &testserver_path, &test_data_directory); | |
| 472 SetCommandLineOption(testserver_path, test_data_directory, &command_line); | |
| 473 LaunchApp(command_line); | |
| 474 if (!VerifyLaunchApp("hello.html")) { | |
| 475 LOG(ERROR) << "Webserver not starting properly"; | |
| 476 return false; | |
| 477 } | |
| 478 return true; | |
| 479 } | |
| 480 | |
| 481 // A subclass may wish to send the request in a different manner | 326 // A subclass may wish to send the request in a different manner |
| 482 virtual bool MakeGETRequest(const std::string& page_name) { | 327 virtual bool MakeGETRequest(const std::string& page_name) { |
| 483 const GURL& url = TestServerPage(page_name); | 328 const GURL& url = TestServerPage(page_name); |
| 484 | 329 |
| 485 // Spin up a background thread for this request so that we have access to | 330 // Spin up a background thread for this request so that we have access to |
| 486 // an IO message loop, and in cases where this thread already has an IO | 331 // an IO message loop, and in cases where this thread already has an IO |
| 487 // message loop, we also want to avoid spinning a nested message loop. | 332 // message loop, we also want to avoid spinning a nested message loop. |
| 488 SyncTestDelegate d; | 333 SyncTestDelegate d; |
| 489 { | 334 { |
| 490 MessageLoop* loop = loop_; | 335 MessageLoop* loop = loop_; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 509 } | 354 } |
| 510 | 355 |
| 511 static void StartGETRequest(const GURL& url, URLRequest::Delegate* delegate) { | 356 static void StartGETRequest(const GURL& url, URLRequest::Delegate* delegate) { |
| 512 URLRequest* request = new URLRequest(url, delegate); | 357 URLRequest* request = new URLRequest(url, delegate); |
| 513 request->set_context(new TestURLRequestContext()); | 358 request->set_context(new TestURLRequestContext()); |
| 514 request->set_method("GET"); | 359 request->set_method("GET"); |
| 515 request->Start(); | 360 request->Start(); |
| 516 EXPECT_TRUE(request->is_pending()); | 361 EXPECT_TRUE(request->is_pending()); |
| 517 } | 362 } |
| 518 | 363 |
| 519 virtual ~HTTPTestServer() { | |
| 520 Stop(); | |
| 521 } | |
| 522 | |
| 523 void Stop() { | |
| 524 if (IsFinished()) | |
| 525 return; | |
| 526 | |
| 527 // here we append the time to avoid problems where the kill page | |
| 528 // is being cached rather than being executed on the server | |
| 529 std::string page_name = StringPrintf("kill?%u", | |
| 530 static_cast<int>(base::Time::Now().ToInternalValue())); | |
| 531 int retry_count = 5; | |
| 532 while (retry_count > 0) { | |
| 533 bool r = MakeGETRequest(page_name); | |
| 534 // BUG #1048625 causes the kill GET to fail. For now we just retry. | |
| 535 // Once the bug is fixed, we should remove the while loop and put back | |
| 536 // the following DCHECK. | |
| 537 // DCHECK(r); | |
| 538 if (r) | |
| 539 break; | |
| 540 retry_count--; | |
| 541 } | |
| 542 // Make sure we were successfull in stopping the testserver. | |
| 543 DCHECK(retry_count > 0); | |
| 544 } | |
| 545 | |
| 546 virtual std::string scheme() { return "http"; } | 364 virtual std::string scheme() { return "http"; } |
| 547 | 365 |
| 548 #if defined(OS_WIN) | |
| 549 virtual void SetCommandLineOption(const std::wstring& testserver_path, | |
| 550 const std::wstring& test_data_directory, | |
| 551 std::wstring* command_line ) { | |
| 552 command_line->append(L"\"" + python_runtime_ + L"\" " + L"\"" + | |
| 553 testserver_path + L"\" --port=" + UTF8ToWide(port_str_) + | |
| 554 L" --data-dir=\"" + test_data_directory + L"\""); | |
| 555 } | |
| 556 #elif defined(OS_POSIX) | |
| 557 virtual void SetCommandLineOption(const std::wstring& testserver_path, | |
| 558 const std::wstring& test_data_directory, | |
| 559 std::vector<std::string>* command_line) { | |
| 560 command_line->push_back("python"); | |
| 561 command_line->push_back(WideToUTF8(testserver_path)); | |
| 562 command_line->push_back("--port=" + port_str_); | |
| 563 command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory)); | |
| 564 } | |
| 565 #endif | |
| 566 | |
| 567 private: | 366 private: |
| 568 // If non-null a background thread isn't created and instead this message loop | 367 // If non-null a background thread isn't created and instead this message loop |
| 569 // is used. | 368 // is used. |
| 570 MessageLoop* loop_; | 369 MessageLoop* loop_; |
| 571 }; | 370 }; |
| 572 | 371 |
| 573 class HTTPSTestServer : public HTTPTestServer { | 372 class HTTPSTestServer : public HTTPTestServer { |
| 574 protected: | 373 protected: |
| 575 explicit HTTPSTestServer(const std::wstring& cert_path) | 374 explicit HTTPSTestServer() { |
| 576 : cert_path_(cert_path) { | |
| 577 } | 375 } |
| 578 | 376 |
| 579 public: | 377 public: |
| 580 static HTTPSTestServer* CreateServer(const std::string& host_name, int port, | 378 // Create a server with a valid certificate |
| 581 const std::wstring& document_root, | 379 // TODO(dkegel): HTTPSTestServer should not require an instance to specify |
| 582 const std::wstring& cert_path) { | 380 // stock test certificates |
| 583 HTTPSTestServer* test_server = new HTTPSTestServer(cert_path); | 381 static HTTPSTestServer* CreateGoodServer(const std::wstring& document_root) { |
| 584 if (!test_server->Init(host_name, port, document_root)) { | 382 HTTPSTestServer* test_server = new HTTPSTestServer(); |
| 383 FilePath docroot = FilePath::FromWStringHack(document_root); |
| 384 FilePath certpath = test_server->launcher_.GetOKCertPath(); |
| 385 if (!test_server->Start(net::TestServerLauncher::ProtoHTTP, |
| 386 net::TestServerLauncher::kHostName, |
| 387 net::TestServerLauncher::kOKHTTPSPort, |
| 388 docroot, certpath)) { |
| 585 delete test_server; | 389 delete test_server; |
| 586 return NULL; | 390 return NULL; |
| 587 } | 391 } |
| 588 return test_server; | 392 return test_server; |
| 589 } | 393 } |
| 590 | 394 |
| 591 #if defined(OS_WIN) | 395 // Create a server with an up to date certificate for the wrong hostname |
| 592 virtual void SetCommandLineOption(const std::wstring& testserver_path, | 396 // for this host |
| 593 const std::wstring& test_data_directory, | 397 static HTTPSTestServer* CreateMismatchedServer( |
| 594 std::wstring* command_line ) { | 398 const std::wstring& document_root) { |
| 595 command_line->append(L"\"" + python_runtime_ + L"\" " + L"\"" + | 399 HTTPSTestServer* test_server = new HTTPSTestServer(); |
| 596 testserver_path + L"\"" + L" --port=" + | 400 FilePath docroot = FilePath::FromWStringHack(document_root); |
| 597 UTF8ToWide(port_str_) + L" --data-dir=\"" + | 401 FilePath certpath = test_server->launcher_.GetOKCertPath(); |
| 598 test_data_directory + L"\""); | 402 if (!test_server->Start(net::TestServerLauncher::ProtoHTTP, |
| 599 if (!cert_path_.empty()) { | 403 net::TestServerLauncher::kMismatchedHostName, |
| 600 command_line->append(L" --https=\""); | 404 net::TestServerLauncher::kOKHTTPSPort, |
| 601 command_line->append(cert_path_); | 405 docroot, certpath)) { |
| 602 command_line->append(L"\""); | 406 delete test_server; |
| 407 return NULL; |
| 408 } |
| 409 return test_server; |
| 410 } |
| 411 |
| 412 // Create a server with an expired certificate |
| 413 static HTTPSTestServer* CreateExpiredServer( |
| 414 const std::wstring& document_root) { |
| 415 HTTPSTestServer* test_server = new HTTPSTestServer(); |
| 416 FilePath docroot = FilePath::FromWStringHack(document_root); |
| 417 FilePath certpath = test_server->launcher_.GetExpiredCertPath(); |
| 418 if (!test_server->Start(net::TestServerLauncher::ProtoHTTP, |
| 419 net::TestServerLauncher::kHostName, |
| 420 net::TestServerLauncher::kBadHTTPSPort, |
| 421 docroot, certpath)) { |
| 422 delete test_server; |
| 423 return NULL; |
| 603 } | 424 } |
| 425 return test_server; |
| 604 } | 426 } |
| 605 #elif defined(OS_POSIX) | |
| 606 virtual void SetCommandLineOption(const std::wstring& testserver_path, | |
| 607 const std::wstring& test_data_directory, | |
| 608 std::vector<std::string>* command_line) { | |
| 609 command_line->push_back("python"); | |
| 610 command_line->push_back(WideToUTF8(testserver_path)); | |
| 611 command_line->push_back("--port=" + port_str_); | |
| 612 command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory)); | |
| 613 if (!cert_path_.empty()) | |
| 614 command_line->push_back("--https=" + WideToUTF8(cert_path_)); | |
| 615 } | |
| 616 #endif | |
| 617 | 427 |
| 618 virtual std::string scheme() { return "https"; } | 428 // Create a server with an arbitrary certificate |
| 429 static HTTPSTestServer* CreateServer(const std::string& host_name, int port, |
| 430 const std::wstring& document_root, |
| 431 const std::wstring& cert_path) { |
| 432 HTTPSTestServer* test_server = new HTTPSTestServer(); |
| 433 FilePath docroot = FilePath::FromWStringHack(document_root); |
| 434 FilePath certpath = FilePath::FromWStringHack(cert_path); |
| 435 if (!test_server->Start(net::TestServerLauncher::ProtoHTTP, |
| 436 host_name, port, docroot, certpath)) { |
| 437 delete test_server; |
| 438 return NULL; |
| 439 } |
| 440 return test_server; |
| 441 } |
| 619 | 442 |
| 620 virtual ~HTTPSTestServer() { | 443 virtual ~HTTPSTestServer() { |
| 621 } | 444 } |
| 622 | 445 |
| 623 protected: | 446 protected: |
| 624 std::wstring cert_path_; | 447 std::wstring cert_path_; |
| 625 }; | 448 }; |
| 626 | 449 |
| 627 | 450 |
| 628 class FTPTestServer : public BaseTestServer { | 451 class FTPTestServer : public BaseTestServer { |
| 629 protected: | 452 public: |
| 630 FTPTestServer() { | 453 FTPTestServer() { |
| 631 } | 454 } |
| 632 | 455 |
| 633 public: | 456 static FTPTestServer* CreateServer(const std::wstring& document_root) { |
| 634 FTPTestServer(const std::string& url_user, const std::string& url_password) { | 457 std::string blank; |
| 635 url_user_ = url_user; | 458 return CreateServer(document_root, blank, blank); |
| 636 url_password_ = url_password; | |
| 637 } | 459 } |
| 638 | 460 |
| 639 static FTPTestServer* CreateServer(const std::wstring& document_root) { | 461 static FTPTestServer* CreateServer(const std::wstring& document_root, |
| 462 const std::string& url_user, |
| 463 const std::string& url_password) { |
| 640 FTPTestServer* test_server = new FTPTestServer(); | 464 FTPTestServer* test_server = new FTPTestServer(); |
| 641 if (!test_server->Init(kDefaultHostName, kFTPDefaultPort, document_root)) { | 465 FilePath docroot = FilePath::FromWStringHack(document_root); |
| 466 FilePath no_cert; |
| 467 if (!test_server->Start(net::TestServerLauncher::ProtoFTP, |
| 468 kDefaultHostName, kFTPDefaultPort, docroot, no_cert, |
| 469 url_user, url_password)) { |
| 642 delete test_server; | 470 delete test_server; |
| 643 return NULL; | 471 return NULL; |
| 644 } | 472 } |
| 645 return test_server; | 473 return test_server; |
| 646 } | 474 } |
| 647 | 475 |
| 648 static FTPTestServer* CreateServer(const std::wstring& document_root, | 476 virtual bool MakeGETRequest(const std::string& page_name) { |
| 649 const std::string& url_user, | 477 const GURL& url = TestServerPage(base_address_, page_name); |
| 650 const std::string& url_password) { | |
| 651 FTPTestServer* test_server = new FTPTestServer(url_user, url_password); | |
| 652 if (!test_server->Init(kDefaultHostName, kFTPDefaultPort, document_root)) { | |
| 653 delete test_server; | |
| 654 return NULL; | |
| 655 } | |
| 656 return test_server; | |
| 657 } | |
| 658 | |
| 659 bool Init(const std::string& host_name, int port, | |
| 660 const std::wstring& document_root) { | |
| 661 std::wstring testserver_path; | |
| 662 std::wstring test_data_directory; | |
| 663 host_name_ = host_name; | |
| 664 | |
| 665 #if defined(OS_WIN) | |
| 666 std::wstring command_line; | |
| 667 #elif defined(OS_POSIX) | |
| 668 std::vector<std::string> command_line; | |
| 669 #endif | |
| 670 | |
| 671 // Set PYTHONPATH for tlslite and pyftpdlib | |
| 672 SetPythonPaths(); | |
| 673 SetAppPath(kDefaultHostName, port, document_root, scheme(), | |
| 674 &testserver_path, &test_data_directory); | |
| 675 SetCommandLineOption(testserver_path, test_data_directory, &command_line); | |
| 676 LaunchApp(command_line); | |
| 677 if (!VerifyLaunchApp("/LICENSE")) { | |
| 678 LOG(ERROR) << "FTPServer not starting properly."; | |
| 679 return false; | |
| 680 } | |
| 681 return true; | |
| 682 } | |
| 683 | |
| 684 virtual ~FTPTestServer() { | |
| 685 Stop(); | |
| 686 } | |
| 687 | |
| 688 void Stop() { | |
| 689 if (IsFinished()) | |
| 690 return; | |
| 691 | |
| 692 const std::string base_address = scheme() + "://" + host_name_ + ":" + | |
| 693 port_str_ + "/"; | |
| 694 const GURL& url = TestServerPage(base_address, "kill"); | |
| 695 TestDelegate d; | 478 TestDelegate d; |
| 696 URLRequest request(url, &d); | 479 URLRequest request(url, &d); |
| 697 request.set_context(new TestURLRequestContext()); | 480 request.set_context(new TestURLRequestContext()); |
| 698 request.set_method("GET"); | |
| 699 request.Start(); | |
| 700 EXPECT_TRUE(request.is_pending()); | |
| 701 | |
| 702 MessageLoop::current()->Run(); | |
| 703 } | |
| 704 | |
| 705 virtual std::string scheme() { return "ftp"; } | |
| 706 | |
| 707 virtual bool MakeGETRequest(const std::string& page_name) { | |
| 708 const std::string base_address = scheme() + "://" + host_name_ + ":" + | |
| 709 port_str_ + "/"; | |
| 710 const GURL& url = TestServerPage(base_address, page_name); | |
| 711 TestDelegate d; | |
| 712 URLRequest request(url, &d); | |
| 713 request.set_context(new TestURLRequestContext()); | |
| 714 request.set_method("GET"); | 481 request.set_method("GET"); |
| 715 request.Start(); | 482 request.Start(); |
| 716 EXPECT_TRUE(request.is_pending()); | 483 EXPECT_TRUE(request.is_pending()); |
| 717 | 484 |
| 718 MessageLoop::current()->Run(); | 485 MessageLoop::current()->Run(); |
| 719 if (request.is_pending()) | 486 if (request.is_pending()) |
| 720 return false; | 487 return false; |
| 721 | 488 |
| 722 return true; | 489 return true; |
| 723 } | 490 } |
| 724 | 491 |
| 725 #if defined(OS_WIN) | |
| 726 virtual void SetCommandLineOption(const std::wstring& testserver_path, | |
| 727 const std::wstring& test_data_directory, | |
| 728 std::wstring* command_line ) { | |
| 729 command_line->append(L"\"" + python_runtime_ + L"\" " + L"\"" + | |
| 730 testserver_path + L"\"" + L" -f " + L" --port=" + | |
| 731 UTF8ToWide(port_str_) + L" --data-dir=\"" + | |
| 732 test_data_directory + L"\""); | |
| 733 } | |
| 734 #elif defined(OS_POSIX) | |
| 735 virtual void SetCommandLineOption(const std::wstring& testserver_path, | |
| 736 const std::wstring& test_data_directory, | |
| 737 std::vector<std::string>* command_line) { | |
| 738 command_line->push_back("python"); | |
| 739 command_line->push_back(WideToUTF8(testserver_path)); | |
| 740 command_line->push_back(" -f "); | |
| 741 command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory)); | |
| 742 command_line->push_back("--port=" + port_str_); | |
| 743 } | |
| 744 #endif | |
| 745 }; | 492 }; |
| 746 | 493 |
| 747 #endif // NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ | 494 #endif // NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ |
| OLD | NEW |