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

Side by Side Diff: net/url_request/url_request_unittest.h

Issue 16490: Add FTP unit test in preparation for portable FTP implementation.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « net/tools/testserver/testserver.py ('k') | net/url_request/url_request_unittest.cc » ('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) 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 13
13 #include "base/file_path.h" 14 #include "base/file_path.h"
14 #include "base/file_util.h" 15 #include "base/file_util.h"
15 #include "base/message_loop.h" 16 #include "base/message_loop.h"
16 #include "base/path_service.h" 17 #include "base/path_service.h"
17 #include "base/platform_thread.h" 18 #include "base/platform_thread.h"
18 #include "base/process_util.h" 19 #include "base/process_util.h"
19 #include "base/string_util.h" 20 #include "base/string_util.h"
20 #include "base/thread.h" 21 #include "base/thread.h"
21 #include "base/time.h" 22 #include "base/time.h"
22 #include "base/waitable_event.h" 23 #include "base/waitable_event.h"
23 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
24 #include "net/http/http_network_layer.h" 25 #include "net/http/http_network_layer.h"
25 #include "net/url_request/url_request.h" 26 #include "net/url_request/url_request.h"
26 #include "net/proxy/proxy_service.h" 27 #include "net/proxy/proxy_service.h"
27 #include "testing/gtest/include/gtest/gtest.h" 28 #include "testing/gtest/include/gtest/gtest.h"
28 #include "googleurl/src/url_util.h" 29 #include "googleurl/src/url_util.h"
29 30
30 const int kDefaultPort = 1337; 31 const int kHTTPDefaultPort = 1337;
32 const int kFTPDefaultPort = 1338;
33
31 const std::string kDefaultHostName("localhost"); 34 const std::string kDefaultHostName("localhost");
32 35
33 // This URLRequestContext does not use a local cache. 36 // This URLRequestContext does not use a local cache.
34 class TestURLRequestContext : public URLRequestContext { 37 class TestURLRequestContext : public URLRequestContext {
35 public: 38 public:
36 TestURLRequestContext() { 39 TestURLRequestContext() {
37 proxy_service_ = net::ProxyService::CreateNull(); 40 proxy_service_ = net::ProxyService::CreateNull();
38 http_transaction_factory_ = 41 http_transaction_factory_ =
39 net::HttpNetworkLayer::CreateFactory(proxy_service_); 42 net::HttpNetworkLayer::CreateFactory(proxy_service_);
40 } 43 }
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 int received_bytes_count_; 186 int received_bytes_count_;
184 int received_redirect_count_; 187 int received_redirect_count_;
185 bool received_data_before_response_; 188 bool received_data_before_response_;
186 bool request_failed_; 189 bool request_failed_;
187 std::string data_received_; 190 std::string data_received_;
188 191
189 // our read buffer 192 // our read buffer
190 char buf_[4096]; 193 char buf_[4096];
191 }; 194 };
192 195
193 // This object bounds the lifetime of an external python-based HTTP server 196 // This object bounds the lifetime of an external python-based HTTP/FTP server
194 // that can provide various responses useful for testing. 197 // that can provide various responses useful for testing.
195 class TestServer : public base::ProcessFilter { 198 class BaseTestServer : public base::ProcessFilter,
196 public: 199 public base::RefCounted<BaseTestServer> {
197 TestServer(const std::wstring& document_root) 200 protected:
198 : process_handle_(NULL), 201 BaseTestServer()
199 is_shutdown_(true) { 202 : process_handle_(NULL) {
200 Init(kDefaultHostName, kDefaultPort, document_root, std::wstring());
201 } 203 }
202 204
203 virtual ~TestServer() { 205 public:
204 Shutdown(); 206 virtual ~BaseTestServer() {
207 if (process_handle_) {
208 #if defined(OS_WIN)
209 CloseHandle(process_handle_);
210 #endif
211 process_handle_ = NULL;
212 }
213 // Make sure we don't leave any stray testserver processes laying around.
214 std::wstring testserver_name =
215 file_util::GetFilenameFromPath(python_runtime_);
216 base::CleanupProcesses(testserver_name, 10000, 1, this);
217 EXPECT_EQ(0, base::GetProcessCount(testserver_name, this));
205 } 218 }
206 219
207 // Implementation of ProcessFilter 220 // Implementation of ProcessFilter
208 virtual bool Includes(uint32 pid, uint32 parent_pid) const { 221 virtual bool Includes(uint32 pid, uint32 parent_pid) const {
209 // This function may be called after Shutdown(), in which process_handle_ is 222 // Since no process handle is set, it can't be included in the filter.
210 // set to NULL. Since no process handle is set, it can't be included in the
211 // filter.
212 if (!process_handle_) 223 if (!process_handle_)
213 return false; 224 return false;
214 // TODO(port): rationalize return value of GetProcId 225 // TODO(port): rationalize return value of GetProcId
215 return pid == (uint32)base::GetProcId(process_handle_); 226 return pid == static_cast<uint32>(base::GetProcId(process_handle_));
216 } 227 }
217 228
218 GURL TestServerPage(const std::string& path) { 229 GURL TestServerPage(const std::string& path) {
219 return GURL(base_address_ + path); 230 return GURL(base_address_ + path);
220 } 231 }
221 232
222 GURL TestServerPageW(const std::wstring& path) { 233 GURL TestServerPageW(const std::wstring& path) {
223 return GURL(base_address_ + WideToUTF8(path)); 234 return GURL(base_address_ + WideToUTF8(path));
224 } 235 }
225 236
226 // A subclass may wish to send the request in a different manner 237 void SetPythonPaths() {
227 virtual bool MakeGETRequest(const std::string& page_name) { 238 #if defined(OS_WIN)
228 const GURL& url = TestServerPage(page_name); 239 // Set up PYTHONPATH so that Python is able to find the in-tree copy of
240 // pyftpdlib.
241 static bool set_python_path = false;
242 if (!set_python_path) {
243 FilePath pyftpdlib_path;
244 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &pyftpdlib_path));
245 pyftpdlib_path = pyftpdlib_path.Append(L"third_party");
246 pyftpdlib_path = pyftpdlib_path.Append(L"pyftpdlib");
229 247
230 // Spin up a background thread for this request so that we have access to 248 const wchar_t kPythonPath[] = L"PYTHONPATH";
231 // an IO message loop, and in cases where this thread already has an IO 249 wchar_t python_path_c[1024];
232 // message loop, we also want to avoid spinning a nested message loop. 250 if (GetEnvironmentVariable(kPythonPath, python_path_c, 1023) > 0) {
233 251 // PYTHONPATH is already set, append to it.
234 SyncTestDelegate d; 252 std::wstring python_path(python_path_c);
235 { 253 python_path.append(L":");
236 base::Thread io_thread("MakeGETRequest"); 254 python_path.append(pyftpdlib_path.value());
237 base::Thread::Options options; 255 SetEnvironmentVariableW(kPythonPath, python_path.c_str());
238 options.message_loop_type = MessageLoop::TYPE_IO; 256 } else {
239 io_thread.StartWithOptions(options); 257 SetEnvironmentVariableW(kPythonPath, pyftpdlib_path.value().c_str());
240 io_thread.message_loop()->PostTask(FROM_HERE, NewRunnableFunction( 258 }
241 &TestServer::StartGETRequest, url, &d)); 259
242 d.Wait(); 260 set_python_path = true;
243 } 261 }
244 return d.did_succeed();
245 }
246
247 bool init_successful() const { return init_successful_; }
248
249 protected:
250 struct ManualInit {};
251
252 // Used by subclasses that need to defer initialization until they are fully
253 // constructed. The subclass should call Init once it is ready (usually in
254 // its constructor).
255 TestServer(ManualInit)
256 : process_handle_(NULL),
257 init_successful_(false),
258 is_shutdown_(true) {
259 }
260
261 virtual std::string scheme() { return std::string("http"); }
262
263 // This is in a separate function so that we can have assertions and so that
264 // subclasses can call this later.
265 void Init(const std::string& host_name, int port,
266 const std::wstring& document_root,
267 const std::wstring& cert_path) {
268 std::stringstream ss;
269 std::string port_str;
270 ss << (port ? port : kDefaultPort);
271 ss >> port_str;
272 base_address_ = scheme() + "://" + host_name + ":" + port_str + "/";
273
274 std::wstring testserver_path;
275 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &testserver_path));
276 file_util::AppendToPath(&testserver_path, L"net");
277 file_util::AppendToPath(&testserver_path, L"tools");
278 file_util::AppendToPath(&testserver_path, L"testserver");
279 file_util::AppendToPath(&testserver_path, L"testserver.py");
280
281 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &python_runtime_));
282 file_util::AppendToPath(&python_runtime_, L"third_party");
283 file_util::AppendToPath(&python_runtime_, L"python_24");
284 file_util::AppendToPath(&python_runtime_, L"python.exe");
285
286 std::wstring test_data_directory;
287 PathService::Get(base::DIR_SOURCE_ROOT, &test_data_directory);
288 std::wstring normalized_document_root = document_root;
289 #if defined(OS_WIN)
290 std::replace(normalized_document_root.begin(),
291 normalized_document_root.end(),
292 L'/', FilePath::kSeparators[0]);
293 #endif
294 file_util::AppendToPath(&test_data_directory, normalized_document_root);
295
296 #if defined(OS_WIN)
297 std::wstring command_line =
298 L"\"" + python_runtime_ + L"\" " + L"\"" + testserver_path +
299 L"\" --port=" + UTF8ToWide(port_str) + L" --data-dir=\"" +
300 test_data_directory + L"\"";
301 if (!cert_path.empty()) {
302 command_line.append(L" --https=\"");
303 command_line.append(cert_path);
304 command_line.append(L"\"");
305 }
306
307 ASSERT_TRUE(
308 base::LaunchApp(command_line, false, true, &process_handle_)) <<
309 "Failed to launch " << command_line;
310 #elif defined(OS_POSIX) 262 #elif defined(OS_POSIX)
311 // Set up PYTHONPATH so that Python is able to find the in-tree copy of 263 // Set up PYTHONPATH so that Python is able to find the in-tree copy of
312 // tlslite. 264 // tlslite and pyftpdlib.
313
314 static bool set_python_path = false; 265 static bool set_python_path = false;
315 if (!set_python_path) { 266 if (!set_python_path) {
316 FilePath tlslite_path; 267 FilePath tlslite_path;
268 FilePath pyftpdlib_path;
317 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &tlslite_path)); 269 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &tlslite_path));
318 tlslite_path = tlslite_path.Append("third_party"); 270 tlslite_path = tlslite_path.Append("third_party");
319 tlslite_path = tlslite_path.Append("tlslite"); 271 tlslite_path = tlslite_path.Append("tlslite");
320 272
273 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &pyftpdlib_path));
274 pyftpdlib_path = pyftpdlib_path.Append("third_party");
275 pyftpdlib_path = pyftpdlib_path.Append("pyftpdlib");
276
321 const char kPythonPath[] = "PYTHONPATH"; 277 const char kPythonPath[] = "PYTHONPATH";
322 char* python_path_c = getenv(kPythonPath); 278 char* python_path_c = getenv(kPythonPath);
323 if (python_path_c) { 279 if (python_path_c) {
324 // PYTHONPATH is already set, append to it. 280 // PYTHONPATH is already set, append to it.
325 std::string python_path(python_path_c); 281 std::string python_path(python_path_c);
326 python_path.append(":"); 282 python_path.append(":");
327 python_path.append(tlslite_path.value()); 283 python_path.append(tlslite_path.value());
284 python_path.append(":");
285 python_path.append(pyftpdlib_path.value());
328 setenv(kPythonPath, python_path.c_str(), 1); 286 setenv(kPythonPath, python_path.c_str(), 1);
329 } else { 287 } else {
330 setenv(kPythonPath, tlslite_path.value().c_str(), 1); 288 std::string python_path = tlslite_path.value().c_str();
289 python_path.append(":");
290 python_path.append(pyftpdlib_path.value());
291 setenv(kPythonPath, python_path.c_str(), 1);
331 } 292 }
332
333 set_python_path = true; 293 set_python_path = true;
334 } 294 }
295 #endif
296 }
335 297
336 std::vector<std::string> command_line; 298 void SetAppPath(const std::string& host_name, int port,
337 command_line.push_back("python"); 299 const std::wstring& document_root, const std::string& scheme,
338 command_line.push_back(WideToUTF8(testserver_path)); 300 std::wstring* testserver_path, std::wstring* test_data_directory) {
339 command_line.push_back("--port=" + port_str); 301 port_str_ = IntToString(port);
340 command_line.push_back("--data-dir=" + WideToUTF8(test_data_directory)); 302 if (url_user_.empty()) {
341 if (!cert_path.empty()) 303 base_address_ = scheme + "://" + host_name + ":" + port_str_ + "/";
342 command_line.push_back("--https=" + WideToUTF8(cert_path)); 304 } else {
305 if (url_password_.empty())
306 base_address_ = scheme + "://" + url_user_ + "@" +
307 host_name + ":" + port_str_ + "/";
308 else
309 base_address_ = scheme + "://" + url_user_ + ":" + url_password_ +
310 "@" + host_name + ":" + port_str_ + "/";
311 }
343 312
344 base::file_handle_mapping_vector no_mappings; 313 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, testserver_path));
345 ASSERT_TRUE( 314 file_util::AppendToPath(testserver_path, L"net");
346 base::LaunchApp(command_line, no_mappings, false, &process_handle_)) << 315 file_util::AppendToPath(testserver_path, L"tools");
347 "Failed to launch " << command_line[0] << " ..."; 316 file_util::AppendToPath(testserver_path, L"testserver");
317 file_util::AppendToPath(testserver_path, L"testserver.py");
318
319 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &python_runtime_));
320 file_util::AppendToPath(&python_runtime_, L"third_party");
321 file_util::AppendToPath(&python_runtime_, L"python_24");
322 file_util::AppendToPath(&python_runtime_, L"python.exe");
323
324 PathService::Get(base::DIR_SOURCE_ROOT, test_data_directory);
325 std::wstring normalized_document_root = document_root;
326
327 #if defined(OS_WIN)
328 // It is just for windows only and have no effect on other OS
329 std::replace(normalized_document_root.begin(),
330 normalized_document_root.end(),
331 L'/', FilePath::kSeparators[0]);
332 #endif
333 if (!normalized_document_root.empty())
334 file_util::AppendToPath(test_data_directory, normalized_document_root);
335
336 }
337
338 #if defined(OS_WIN)
339 void LaunchApp(const std::wstring& command_line) {
340 ASSERT_TRUE(base::LaunchApp(command_line, false, true, &process_handle_)) <<
341 "Failed to launch " << command_line;
342 }
343 #elif defined(OS_POSIX)
344 void LaunchApp(const std::vector<std::string>& command_line) {
345 ASSERT_TRUE(base::LaunchApp(command_line, false, true, &process_handle_)) <<
346 "Failed to launch " << command_line[0] << " ...";
347 }
348 #endif 348 #endif
349 349
350 // Verify that the webserver is actually started. 350 virtual bool MakeGETRequest(const std::string& page_name) = 0;
351 // Otherwise tests can fail if they run faster than Python can start. 351
352 // Verify that the Server is actually started.
353 // Otherwise tests can fail if they run faster than Python can start.
354 bool VerifyLaunchApp(const std::string& page_name) {
352 int retries = 10; 355 int retries = 10;
353 bool success; 356 bool success;
354 while ((success = MakeGETRequest("hello.html")) == false && retries > 0) { 357 while ((success = MakeGETRequest(page_name)) == false && retries > 0) {
355 retries--; 358 retries--;
356 PlatformThread::Sleep(500); 359 PlatformThread::Sleep(500);
357 } 360 }
358 ASSERT_TRUE(success) << "Webserver not starting properly."; 361 if (!success)
359 362 return false;
360 init_successful_ = true; 363 return true;
361 is_shutdown_ = false;
362 } 364 }
363 365
364 void Shutdown() { 366 protected:
365 if (is_shutdown_)
366 return;
367
368 // here we append the time to avoid problems where the kill page
369 // is being cached rather than being executed on the server
370 std::ostringstream page_name;
371 page_name << "kill?" << (unsigned int)(base::Time::Now().ToInternalValue());
372 int retry_count = 5;
373 while (retry_count > 0) {
374 bool r = MakeGETRequest(page_name.str());
375 // BUG #1048625 causes the kill GET to fail. For now we just retry.
376 // Once the bug is fixed, we should remove the while loop and put back
377 // the following DCHECK.
378 // DCHECK(r);
379 if (r)
380 break;
381 retry_count--;
382 }
383 // Make sure we were successfull in stopping the testserver.
384 DCHECK(retry_count > 0);
385
386 if (process_handle_) {
387 #if defined(OS_WIN)
388 CloseHandle(process_handle_);
389 #endif
390 process_handle_ = NULL;
391 }
392
393 // Make sure we don't leave any stray testserver processes laying around.
394 std::wstring testserver_name =
395 file_util::GetFilenameFromPath(python_runtime_);
396 base::CleanupProcesses(testserver_name, 10000, 1, this);
397 EXPECT_EQ(0, base::GetProcessCount(testserver_name, this));
398
399 is_shutdown_ = true;
400 }
401
402 private:
403 // Used by MakeGETRequest to implement sync load behavior. 367 // Used by MakeGETRequest to implement sync load behavior.
404 class SyncTestDelegate : public TestDelegate { 368 class SyncTestDelegate : public TestDelegate {
405 public: 369 public:
406 SyncTestDelegate() : event_(false, false), success_(false) { 370 SyncTestDelegate() : event_(false, false), success_(false) {
407 } 371 }
408 virtual void OnResponseCompleted(URLRequest* request) { 372 virtual void OnResponseCompleted(URLRequest* request) {
409 MessageLoop::current()->DeleteSoon(FROM_HERE, request); 373 MessageLoop::current()->DeleteSoon(FROM_HERE, request);
410 success_ = request->status().is_success(); 374 success_ = request->status().is_success();
411 event_.Signal(); 375 event_.Signal();
412 } 376 }
413 void Wait() { event_.Wait(); } 377 void Wait() { event_.Wait(); }
414 bool did_succeed() const { return success_; } 378 bool did_succeed() const { return success_; }
415 private: 379 private:
416 base::WaitableEvent event_; 380 base::WaitableEvent event_;
417 bool success_; 381 bool success_;
418 DISALLOW_COPY_AND_ASSIGN(SyncTestDelegate); 382 DISALLOW_COPY_AND_ASSIGN(SyncTestDelegate);
419 }; 383 };
384
385 std::string base_address_;
386 std::string url_user_;
387 std::string url_password_;
388 std::wstring python_runtime_;
389 base::ProcessHandle process_handle_;
390 std::string port_str_;
391 };
392
393 class HTTPTestServer : public BaseTestServer {
394 protected:
395 HTTPTestServer() {
396 }
397
398 public:
399 static HTTPTestServer* CreateServer(const std::wstring& document_root) {
400 HTTPTestServer* test_server = new HTTPTestServer();
401 if (!test_server->Init(kDefaultHostName, kHTTPDefaultPort, document_root)) {
402 delete test_server;
403 return NULL;
404 }
405 return test_server;
406 }
407
408 bool Init(const std::string& host_name, int port,
409 const std::wstring& document_root) {
410 std::wstring testserver_path;
411 std::wstring test_data_directory;
412 #if defined(OS_WIN)
413 std::wstring command_line;
414 #elif defined(OS_POSIX)
415 std::vector<std::string> command_line;
416 #endif
417
418 // Set PYTHONPATH for tlslite and pyftpdlib
419 SetPythonPaths();
420 SetAppPath(kDefaultHostName, port, document_root, scheme(),
421 &testserver_path, &test_data_directory);
422 SetCommandLineOption(testserver_path, test_data_directory, &command_line);
423 LaunchApp(command_line);
424 if (!VerifyLaunchApp("hello.html")) {
425 LOG(ERROR) << "Webserver not starting properly";
426 return false;
427 }
428 return true;
429 }
430
431 // A subclass may wish to send the request in a different manner
432 virtual bool MakeGETRequest(const std::string& page_name) {
433 const GURL& url = TestServerPage(page_name);
434
435 // Spin up a background thread for this request so that we have access to
436 // an IO message loop, and in cases where this thread already has an IO
437 // message loop, we also want to avoid spinning a nested message loop.
438 SyncTestDelegate d;
439 {
440 base::Thread io_thread("MakeGETRequest");
441 base::Thread::Options options;
442 options.message_loop_type = MessageLoop::TYPE_IO;
443 io_thread.StartWithOptions(options);
444 io_thread.message_loop()->PostTask(FROM_HERE, NewRunnableFunction(
445 &HTTPTestServer::StartGETRequest, url, &d));
446 d.Wait();
447 }
448 return d.did_succeed();
449 }
450
420 static void StartGETRequest(const GURL& url, URLRequest::Delegate* delegate) { 451 static void StartGETRequest(const GURL& url, URLRequest::Delegate* delegate) {
421 URLRequest* request = new URLRequest(url, delegate); 452 URLRequest* request = new URLRequest(url, delegate);
422 request->set_context(new TestURLRequestContext()); 453 request->set_context(new TestURLRequestContext());
423 request->set_method("GET"); 454 request->set_method("GET");
424 request->Start(); 455 request->Start();
425 EXPECT_TRUE(request->is_pending()); 456 EXPECT_TRUE(request->is_pending());
426 } 457 }
427 458
428 std::string base_address_; 459 virtual ~HTTPTestServer() {
429 std::wstring python_runtime_; 460 // here we append the time to avoid problems where the kill page
430 base::ProcessHandle process_handle_; 461 // is being cached rather than being executed on the server
431 bool init_successful_; 462 std::string page_name = StringPrintf("kill?%u",
432 bool is_shutdown_; 463 static_cast<int>(base::Time::Now().ToInternalValue()));
464 int retry_count = 5;
465 while (retry_count > 0) {
466 bool r = MakeGETRequest(page_name);
467 // BUG #1048625 causes the kill GET to fail. For now we just retry.
468 // Once the bug is fixed, we should remove the while loop and put back
469 // the following DCHECK.
470 // DCHECK(r);
471 if (r)
472 break;
473 retry_count--;
474 }
475 // Make sure we were successfull in stopping the testserver.
476 DCHECK(retry_count > 0);
477 }
478
479 virtual std::string scheme() { return "http"; }
480
481 #if defined(OS_WIN)
482 virtual void SetCommandLineOption(const std::wstring& testserver_path,
483 const std::wstring& test_data_directory,
484 std::wstring* command_line ) {
485 command_line->append(L"\"" + python_runtime_ + L"\" " + L"\"" +
486 testserver_path + L"\" --port=" + UTF8ToWide(port_str_) +
487 L" --data-dir=\"" + test_data_directory + L"\"");
488 }
489 #elif defined(OS_POSIX)
490 virtual void SetCommandLineOption(const std::wstring& testserver_path,
491 const std::wstring& test_data_directory,
492 std::vector<std::string>* command_line) {
493 command_line->push_back("python");
494 command_line->push_back(WideToUTF8(testserver_path));
495 command_line->push_back("--port=" + port_str_);
496 command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory));
497 }
498 #endif
433 }; 499 };
434 500
435 class HTTPSTestServer : public TestServer { 501 class HTTPSTestServer : public HTTPTestServer {
502 protected:
503 explicit HTTPSTestServer(const std::wstring& cert_path)
504 : cert_path_(cert_path) {
505 }
506
436 public: 507 public:
437 HTTPSTestServer(const std::string& host_name, int port, 508 static HTTPSTestServer* CreateServer(const std::string& host_name, int port,
438 const std::wstring& document_root, 509 const std::wstring& document_root,
439 const std::wstring& cert_path) : TestServer(ManualInit()) { 510 const std::wstring& cert_path) {
440 Init(host_name, port, document_root, cert_path); 511 HTTPSTestServer* test_server = new HTTPSTestServer(cert_path);
441 } 512 if (!test_server->Init(host_name, port, document_root)) {
442 513 delete test_server;
443 virtual std::string scheme() { return std::string("https"); } 514 return NULL;
515 }
516 return test_server;
517 }
518
519 #if defined(OS_WIN)
520 virtual void SetCommandLineOption(const std::wstring& testserver_path,
521 const std::wstring& test_data_directory,
522 std::wstring* command_line ) {
523 command_line->append(L"\"" + python_runtime_ + L"\" " + L"\"" +
524 testserver_path + L"\"" + L" --port=" +
525 UTF8ToWide(port_str_) + L" --data-dir=\"" +
526 test_data_directory + L"\"");
527 if (!cert_path_.empty()) {
528 command_line->append(L" --https=\"");
529 command_line->append(cert_path_);
530 command_line->append(L"\"");
531 }
532 }
533 #elif defined(OS_POSIX)
534 virtual void SetCommandLineOption(const std::wstring& testserver_path,
535 const std::wstring& test_data_directory,
536 std::vector<std::string>* command_line) {
537 command_line->push_back("python");
538 command_line->push_back(WideToUTF8(testserver_path));
539 command_line->push_back("--port=" + port_str_);
540 command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory));
541 if (!cert_path_.empty())
542 command_line->push_back("--https=" + WideToUTF8(cert_path_));
543 }
544 #endif
545
546 virtual std::string scheme() { return "https"; }
547
548 virtual ~HTTPSTestServer() {
549 }
550
551 protected:
552 std::wstring cert_path_;
444 }; 553 };
445 554
555
556 class FTPTestServer : public BaseTestServer {
557 protected:
558 FTPTestServer() {
559 }
560
561 public:
562 FTPTestServer(const std::string& url_user, const std::string& url_password) {
563 url_user_ = url_user;
564 url_password_ = url_password;
565 }
566
567 static FTPTestServer* CreateServer(const std::wstring& document_root) {
568 FTPTestServer* test_server = new FTPTestServer();
569 if (!test_server->Init(kDefaultHostName, kFTPDefaultPort, document_root)) {
570 delete test_server;
571 return NULL;
572 }
573 return test_server;
574 }
575
576 static FTPTestServer* CreateServer(const std::wstring& document_root,
577 const std::string& url_user,
578 const std::string& url_password) {
579 FTPTestServer* test_server = new FTPTestServer(url_user, url_password);
580 if (!test_server->Init(kDefaultHostName, kFTPDefaultPort, document_root)) {
581 delete test_server;
582 return NULL;
583 }
584 return test_server;
585 }
586
587 bool Init(const std::string& host_name, int port,
588 const std::wstring& document_root) {
589 std::wstring testserver_path;
590 std::wstring test_data_directory;
591
592 #if defined(OS_WIN)
593 std::wstring command_line;
594 #elif defined(OS_POSIX)
595 std::vector<std::string> command_line;
596 #endif
597
598 // Set PYTHONPATH for tlslite and pyftpdlib
599 SetPythonPaths();
600 SetAppPath(kDefaultHostName, port, document_root, scheme(),
601 &testserver_path, &test_data_directory);
602 SetCommandLineOption(testserver_path, test_data_directory, &command_line);
603 LaunchApp(command_line);
604 if (!VerifyLaunchApp("/LICENSE")) {
605 LOG(ERROR) << "FTPServer not starting properly.";
606 return false;
607 }
608 return true;
609 }
610
611 virtual ~FTPTestServer() {
612 int retry_count = 5;
613 while (retry_count > 0) {
614 bool r = MakeGETRequest("kill");
615 // BUG #1048625 causes the kill GET to fail. For now we just retry.
616 // Once the bug is fixed, we should remove the while loop and put back
617 // the following DCHECK.
618 // DCHECK(r);
619 if (r)
620 break;
621 retry_count--;
622 }
623 // Make sure we were successfull in stopping the testserver.
624 DCHECK(retry_count > 0);
625 }
626
627 virtual std::string scheme() { return "ftp"; }
628
629 virtual bool MakeGETRequest(const std::string& page_name) {
630 const GURL& url = TestServerPage(page_name);
631 TestDelegate d;
632 URLRequest request(url, &d);
633 request.set_context(new TestURLRequestContext());
634 request.set_method("GET");
635 request.Start();
636 EXPECT_TRUE(request.is_pending());
637
638 MessageLoop::current()->Run();
639 if (request.is_pending())
640 return false;
641
642 return true;
643 }
644
645 #if defined(OS_WIN)
646 virtual void SetCommandLineOption(const std::wstring& testserver_path,
647 const std::wstring& test_data_directory,
648 std::wstring* command_line ) {
649 command_line->append(L"\"" + python_runtime_ + L"\" " + L"\"" +
650 testserver_path + L"\"" + L" -f " + L" --port=" +
651 UTF8ToWide(port_str_) + L" --data-dir=\"" +
652 test_data_directory + L"\"");
653 }
654 #elif defined(OS_POSIX)
655 virtual void SetCommandLineOption(const std::wstring& testserver_path,
656 const std::wstring& test_data_directory,
657 std::vector<std::string>* command_line) {
658 command_line->push_back("python");
659 command_line->push_back(" -f ");
660 command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory));
661 command_line->push_back("--port=" + port_str_);
662 command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory));
663 }
664 #endif
665 };
666
446 #endif // NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ 667 #endif // NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_
447
OLDNEW
« no previous file with comments | « net/tools/testserver/testserver.py ('k') | net/url_request/url_request_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698