diff options
author | erikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-08 20:45:27 +0000 |
---|---|---|
committer | erikkay@google.com <erikkay@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-08 20:45:27 +0000 |
commit | dd26501ef315e241911a31a8a98027c9bbb65560 (patch) | |
tree | 1c02dfce0035199f0c073ebf793607d6e7934be5 /net | |
parent | 7ecec17feb965bab7cd348ab16a9da8d772f70dc (diff) | |
download | chromium_src-dd26501ef315e241911a31a8a98027c9bbb65560.zip chromium_src-dd26501ef315e241911a31a8a98027c9bbb65560.tar.gz chromium_src-dd26501ef315e241911a31a8a98027c9bbb65560.tar.bz2 |
Add FTP unit test in preparation for portable FTP implementation.
Clean up test server code.
Originally from issue 12939, written by Ibrar Ahmed (ibrar.ahmed@gmail.com)
(take 2)
Review URL: http://codereview.chromium.org/17040
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@7755 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/proxy/proxy_script_fetcher_unittest.cc | 40 | ||||
-rw-r--r-- | net/tools/testserver/testserver.py | 97 | ||||
-rw-r--r-- | net/url_request/url_request_unittest.cc | 291 | ||||
-rw-r--r-- | net/url_request/url_request_unittest.h | 573 |
4 files changed, 722 insertions, 279 deletions
diff --git a/net/proxy/proxy_script_fetcher_unittest.cc b/net/proxy/proxy_script_fetcher_unittest.cc index 8507a86..2139b6c 100644 --- a/net/proxy/proxy_script_fetcher_unittest.cc +++ b/net/proxy/proxy_script_fetcher_unittest.cc @@ -181,23 +181,25 @@ TEST_F(ProxyScriptFetcherTest, FileUrl) { // Note that all mime types are allowed for PAC file, to be consistent // with other browsers. TEST_F(ProxyScriptFetcherTest, HttpMimeType) { - TestServer server(kDocRoot); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(kDocRoot); + ASSERT_TRUE(NULL != server.get()); SynchFetcher pac_fetcher; { // Fetch a PAC with mime type "text/plain" - GURL url = server.TestServerPage("files/pac.txt"); + GURL url = server->TestServerPage("files/pac.txt"); FetchResult result = pac_fetcher.Fetch(url); EXPECT_EQ(net::OK, result.code); EXPECT_EQ("-pac.txt-\n", result.bytes); } { // Fetch a PAC with mime type "text/html" - GURL url = server.TestServerPage("files/pac.html"); + GURL url = server->TestServerPage("files/pac.html"); FetchResult result = pac_fetcher.Fetch(url); EXPECT_EQ(net::OK, result.code); EXPECT_EQ("-pac.html-\n", result.bytes); } { // Fetch a PAC with mime type "application/x-ns-proxy-autoconfig" - GURL url = server.TestServerPage("files/pac.nsproxy"); + GURL url = server->TestServerPage("files/pac.nsproxy"); FetchResult result = pac_fetcher.Fetch(url); EXPECT_EQ(net::OK, result.code); EXPECT_EQ("-pac.nsproxy-\n", result.bytes); @@ -205,17 +207,19 @@ TEST_F(ProxyScriptFetcherTest, HttpMimeType) { } TEST_F(ProxyScriptFetcherTest, HttpStatusCode) { - TestServer server(kDocRoot); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(kDocRoot); + ASSERT_TRUE(NULL != server.get()); SynchFetcher pac_fetcher; { // Fetch a PAC which gives a 500 -- FAIL - GURL url = server.TestServerPage("files/500.pac"); + GURL url = server->TestServerPage("files/500.pac"); FetchResult result = pac_fetcher.Fetch(url); EXPECT_EQ(net::ERR_PAC_STATUS_NOT_OK, result.code); EXPECT_TRUE(result.bytes.empty()); } { // Fetch a PAC which gives a 404 -- FAIL - GURL url = server.TestServerPage("files/404.pac"); + GURL url = server->TestServerPage("files/404.pac"); FetchResult result = pac_fetcher.Fetch(url); EXPECT_EQ(net::ERR_PAC_STATUS_NOT_OK, result.code); EXPECT_TRUE(result.bytes.empty()); @@ -223,19 +227,23 @@ TEST_F(ProxyScriptFetcherTest, HttpStatusCode) { } TEST_F(ProxyScriptFetcherTest, ContentDisposition) { - TestServer server(kDocRoot); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(kDocRoot); + ASSERT_TRUE(NULL != server.get()); SynchFetcher pac_fetcher; // Fetch PAC scripts via HTTP with a Content-Disposition header -- should // have no effect. - GURL url = server.TestServerPage("files/downloadable.pac"); + GURL url = server->TestServerPage("files/downloadable.pac"); FetchResult result = pac_fetcher.Fetch(url); EXPECT_EQ(net::OK, result.code); EXPECT_EQ("-downloadable.pac-\n", result.bytes); } TEST_F(ProxyScriptFetcherTest, TooLarge) { - TestServer server(kDocRoot); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(kDocRoot); + ASSERT_TRUE(NULL != server.get()); SynchFetcher pac_fetcher; // Set the maximum response size to 50 bytes. @@ -243,7 +251,7 @@ TEST_F(ProxyScriptFetcherTest, TooLarge) { // These two URLs are the same file, but are http:// vs file:// GURL urls[] = { - server.TestServerPage("files/large-pac.nsproxy"), + server->TestServerPage("files/large-pac.nsproxy"), GetTestFileUrl("large-pac.nsproxy") }; @@ -260,7 +268,7 @@ TEST_F(ProxyScriptFetcherTest, TooLarge) { net::ProxyScriptFetcher::SetSizeConstraintForUnittest(prev_size); { // Make sure we can still fetch regular URLs. - GURL url = server.TestServerPage("files/pac.nsproxy"); + GURL url = server->TestServerPage("files/pac.nsproxy"); FetchResult result = pac_fetcher.Fetch(url); EXPECT_EQ(net::OK, result.code); EXPECT_EQ("-pac.nsproxy-\n", result.bytes); @@ -268,7 +276,9 @@ TEST_F(ProxyScriptFetcherTest, TooLarge) { } TEST_F(ProxyScriptFetcherTest, Hang) { - TestServer server(kDocRoot); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(kDocRoot); + ASSERT_TRUE(NULL != server.get()); SynchFetcher pac_fetcher; // Set the timeout period to 0.5 seconds. @@ -277,7 +287,7 @@ TEST_F(ProxyScriptFetcherTest, Hang) { // Try fetching a URL which takes 1.2 seconds. We should abort the request // after 500 ms, and fail with a timeout error. - { GURL url = server.TestServerPage("slow/proxy.pac?1.2"); + { GURL url = server->TestServerPage("slow/proxy.pac?1.2"); FetchResult result = pac_fetcher.Fetch(url); EXPECT_EQ(net::ERR_TIMED_OUT, result.code); EXPECT_TRUE(result.bytes.empty()); @@ -287,7 +297,7 @@ TEST_F(ProxyScriptFetcherTest, Hang) { net::ProxyScriptFetcher::SetTimeoutConstraintForUnittest(prev_timeout); { // Make sure we can still fetch regular URLs. - GURL url = server.TestServerPage("files/pac.nsproxy"); + GURL url = server->TestServerPage("files/pac.nsproxy"); FetchResult result = pac_fetcher.Fetch(url); EXPECT_EQ(net::OK, result.code); EXPECT_EQ("-pac.nsproxy-\n", result.bytes); diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py index 2d3049e..e7124f9 100644 --- a/net/tools/testserver/testserver.py +++ b/net/tools/testserver/testserver.py @@ -24,6 +24,10 @@ import sys import time import tlslite import tlslite.api +import pyftpdlib.ftpserver + +SERVER_HTTP = 0 +SERVER_FTP = 1 debug_output = sys.stderr def debug(str): @@ -863,12 +867,12 @@ class TestPageHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): for handler in self._get_handlers: - if (handler()): + if handler(): return def do_POST(self): for handler in self._post_handlers: - if(handler()): + if handler(): return # called by the redirect handling function when there is no parameter @@ -880,6 +884,23 @@ class TestPageHandler(BaseHTTPServer.BaseHTTPRequestHandler): self.wfile.write('Use <pre>%s?http://dest...</pre>' % redirect_name) self.wfile.write('</body></html>') +def MakeDataDir(): + if options.data_dir: + if not os.path.isdir(options.data_dir): + print 'specified data dir not found: ' + options.data_dir + ' exiting...' + return None + my_data_dir = options.data_dir + else: + # Create the default path to our data dir, relative to the exe dir. + my_data_dir = os.path.dirname(sys.argv[0]) + my_data_dir = os.path.join(my_data_dir, "..", "..", "..", "..", + "test", "data") + + #TODO(ibrar): Must use Find* funtion defined in google\tools + #i.e my_data_dir = FindUpward(my_data_dir, "test", "data") + + return my_data_dir + def main(options, args): # redirect output to a log file so it doesn't spam the unit test output logfile = open('testserver.log', 'w') @@ -887,27 +908,51 @@ def main(options, args): port = options.port - if options.cert: - # let's make sure the cert file exists. - if not os.path.isfile(options.cert): - print 'specified cert file not found: ' + options.cert + ' exiting...' - return - server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert) - print 'HTTPS server started on port %d...' % port - else: - server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler) - print 'HTTP server started on port %d...' % port + if options.server_type == SERVER_HTTP: + if options.cert: + # let's make sure the cert file exists. + if not os.path.isfile(options.cert): + print 'specified cert file not found: ' + options.cert + ' exiting...' + return + server = HTTPSServer(('127.0.0.1', port), TestPageHandler, options.cert) + print 'HTTPS server started on port %d...' % port + else: + server = StoppableHTTPServer(('127.0.0.1', port), TestPageHandler) + print 'HTTP server started on port %d...' % port - if options.data_dir: - if not os.path.isdir(options.data_dir): - print 'specified data dir not found: ' + options.data_dir + ' exiting...' - return - server.data_dir = options.data_dir + server.data_dir = MakeDataDir() + + # means FTP Server else: - # Create the default path to our data dir, relative to the exe dir. - server.data_dir = os.path.dirname(sys.argv[0]) - server.data_dir = os.path.join(server.data_dir, "..", "..", "..", "..", - "test", "data") + my_data_dir = MakeDataDir() + + def line_logger(msg): + if (msg.find("kill") >= 0): + server.stop = True + print 'shutting down server' + sys.exit(0) + + # Instantiate a dummy authorizer for managing 'virtual' users + authorizer = pyftpdlib.ftpserver.DummyAuthorizer() + + # Define a new user having full r/w permissions and a read-only + # anonymous user + authorizer.add_user('chrome', 'chrome', my_data_dir, perm='elradfmw') + + authorizer.add_anonymous(my_data_dir) + + # Instantiate FTP handler class + ftp_handler = pyftpdlib.ftpserver.FTPHandler + ftp_handler.authorizer = authorizer + pyftpdlib.ftpserver.logline = line_logger + + # Define a customized banner (string returned when client connects) + ftp_handler.banner = "pyftpdlib %s based ftpd ready." % pyftpdlib.ftpserver.__ver__ + + # Instantiate FTP server class and listen to 127.0.0.1:port + address = ('127.0.0.1', port) + server = pyftpdlib.ftpserver.FTPServer(address, ftp_handler) + print 'FTP server started on port %d...' % port try: server.serve_forever() @@ -917,15 +962,19 @@ def main(options, args): if __name__ == '__main__': option_parser = optparse.OptionParser() + option_parser.add_option("-f", '--ftp', action='store_const', + const=SERVER_FTP, default=SERVER_HTTP, + dest='server_type', + help='FTP or HTTP server default HTTP') option_parser.add_option('', '--port', default='8888', type='int', help='Port used by the server') - option_parser.add_option('', '--data-dir', dest='data_dir', + option_parser.add_option('', '--data-dir', dest='data_dir', help='Directory from which to read the files') - option_parser.add_option('', '--https', dest='cert', + option_parser.add_option('', '--https', dest='cert', help='Specify that https should be used, specify ' 'the path to the cert containing the private key ' 'the server should use') options, args = option_parser.parse_args() sys.exit(main(options, args)) - +
\ No newline at end of file diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index be26da9..6f965d3 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc @@ -83,11 +83,12 @@ class URLRequestTest : public PlatformTest { }; TEST_F(URLRequestTest, GetTest_NoCache) { - TestServer server(L""); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L""); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; { - TestURLRequest r(server.TestServerPage(""), &d); + TestURLRequest r(server->TestServerPage(""), &d); r.Start(); EXPECT_TRUE(r.is_pending()); @@ -104,11 +105,12 @@ TEST_F(URLRequestTest, GetTest_NoCache) { } TEST_F(URLRequestTest, GetTest) { - TestServer server(L""); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L""); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; { - TestURLRequest r(server.TestServerPage(""), &d); + TestURLRequest r(server->TestServerPage(""), &d); r.Start(); EXPECT_TRUE(r.is_pending()); @@ -127,7 +129,7 @@ TEST_F(URLRequestTest, GetTest) { class HTTPSRequestTest : public testing::Test { protected: HTTPSRequestTest() : util_() {}; - + SSLTestUtil util_; }; @@ -143,14 +145,15 @@ TEST_F(HTTPSRequestTest, MAYBE_HTTPSGetTest) { // a working document root to server the pages / and /hello.html, // so this test doesn't really need to specify a document root. // But if it did, a good one would be net/data/ssl. - HTTPSTestServer https_server(util_.kHostName, util_.kOKHTTPSPort, - L"net/data/ssl", - util_.GetOKCertPath().ToWStringHack()); + scoped_refptr<HTTPSTestServer> server = + HTTPSTestServer::CreateServer(util_.kHostName, util_.kOKHTTPSPort, + L"net/data/ssl", util_.GetOKCertPath().ToWStringHack()); + ASSERT_TRUE(NULL != server.get()); EXPECT_TRUE(util_.CheckCATrusted()); TestDelegate d; { - TestURLRequest r(https_server.TestServerPage(""), &d); + TestURLRequest r(server->TestServerPage(""), &d); r.Start(); EXPECT_TRUE(r.is_pending()); @@ -190,11 +193,16 @@ TEST_F(URLRequestTest, CancelTest) { } TEST_F(URLRequestTest, CancelTest2) { - TestServer server(L""); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L""); + ASSERT_TRUE(NULL != server.get()); + + // error C2446: '!=' : no conversion from 'HTTPTestServer *const ' + // to 'const int' + TestDelegate d; { - TestURLRequest r(server.TestServerPage(""), &d); + TestURLRequest r(server->TestServerPage(""), &d); d.set_cancel_in_response_started(true); @@ -214,11 +222,12 @@ TEST_F(URLRequestTest, CancelTest2) { } TEST_F(URLRequestTest, CancelTest3) { - TestServer server(L""); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L""); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; { - TestURLRequest r(server.TestServerPage(""), &d); + TestURLRequest r(server->TestServerPage(""), &d); d.set_cancel_in_received_data(true); @@ -241,11 +250,12 @@ TEST_F(URLRequestTest, CancelTest3) { } TEST_F(URLRequestTest, CancelTest4) { - TestServer server(L""); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L""); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; { - TestURLRequest r(server.TestServerPage(""), &d); + TestURLRequest r(server->TestServerPage(""), &d); r.Start(); EXPECT_TRUE(r.is_pending()); @@ -266,14 +276,15 @@ TEST_F(URLRequestTest, CancelTest4) { } TEST_F(URLRequestTest, CancelTest5) { - TestServer server(L""); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L""); + ASSERT_TRUE(NULL != server.get()); scoped_refptr<URLRequestContext> context = new URLRequestHttpCacheContext(); // populate cache { TestDelegate d; - URLRequest r(server.TestServerPage("cachetime"), &d); + URLRequest r(server->TestServerPage("cachetime"), &d); r.set_context(context); r.Start(); MessageLoop::current()->Run(); @@ -283,7 +294,7 @@ TEST_F(URLRequestTest, CancelTest5) { // cancel read from cache (see bug 990242) { TestDelegate d; - URLRequest r(server.TestServerPage("cachetime"), &d); + URLRequest r(server->TestServerPage("cachetime"), &d); r.set_context(context); r.Start(); r.Cancel(); @@ -301,9 +312,9 @@ TEST_F(URLRequestTest, CancelTest5) { } TEST_F(URLRequestTest, PostTest) { - TestServer server(L"net/data"); - ASSERT_TRUE(server.init_successful()); - + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data"); + ASSERT_TRUE(NULL != server.get()); const int kMsgSize = 20000; // multiple of 10 const int kIterations = 50; char *uploadBytes = new char[kMsgSize+1]; @@ -327,7 +338,7 @@ TEST_F(URLRequestTest, PostTest) { for (int i = 0; i < kIterations; ++i) { TestDelegate d; - URLRequest r(server.TestServerPage("echo"), &d); + URLRequest r(server->TestServerPage("echo"), &d); r.set_context(context); r.set_method("POST"); @@ -353,11 +364,12 @@ TEST_F(URLRequestTest, PostTest) { } TEST_F(URLRequestTest, PostEmptyTest) { - TestServer server(L"net/data"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data"); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; { - TestURLRequest r(server.TestServerPage("echo"), &d); + TestURLRequest r(server->TestServerPage("echo"), &d); r.set_method("POST"); r.Start(); @@ -377,11 +389,12 @@ TEST_F(URLRequestTest, PostEmptyTest) { } TEST_F(URLRequestTest, PostFileTest) { - TestServer server(L"net/data"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data"); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; { - TestURLRequest r(server.TestServerPage("echo"), &d); + TestURLRequest r(server->TestServerPage("echo"), &d); r.set_method("POST"); std::wstring dir; @@ -409,7 +422,8 @@ TEST_F(URLRequestTest, PostFileTest) { int size = static_cast<int>(longsize); scoped_array<char> buf(new char[size]); - int size_read = static_cast<int>(file_util::ReadFile(path, buf.get(), size)); + int size_read = static_cast<int>(file_util::ReadFile(path, + buf.get(), size)); ASSERT_EQ(size, size_read); ASSERT_EQ(1, d.response_started_count()) << "request failed: " << @@ -506,10 +520,11 @@ TEST_F(URLRequestTest, DISABLED_DnsFailureTest) { } TEST_F(URLRequestTest, ResponseHeadersTest) { - TestServer server(L"net/data/url_request_unittest"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/url_request_unittest"); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; - TestURLRequest req(server.TestServerPage("files/with-headers.html"), &d); + TestURLRequest req(server->TestServerPage("files/with-headers.html"), &d); req.Start(); MessageLoop::current()->Run(); @@ -530,13 +545,14 @@ TEST_F(URLRequestTest, ResponseHeadersTest) { } TEST_F(URLRequestTest, BZip2ContentTest) { - TestServer server(L"net/data/filter_unittests"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/filter_unittests"); + ASSERT_TRUE(NULL != server.get()); // for localhost domain, we also should support bzip2 encoding // first, get the original file TestDelegate d1; - TestURLRequest req1(server.TestServerPage("realfiles/google.txt"), &d1); + TestURLRequest req1(server->TestServerPage("realfiles/google.txt"), &d1); req1.Start(); MessageLoop::current()->Run(); @@ -544,7 +560,7 @@ TEST_F(URLRequestTest, BZip2ContentTest) { // second, get bzip2 content TestDelegate d2; - TestURLRequest req2(server.TestServerPage("realbz2files/google.txt"), &d2); + TestURLRequest req2(server->TestServerPage("realbz2files/google.txt"), &d2); req2.Start(); MessageLoop::current()->Run(); @@ -555,13 +571,14 @@ TEST_F(URLRequestTest, BZip2ContentTest) { } TEST_F(URLRequestTest, BZip2ContentTest_IncrementalHeader) { - TestServer server(L"net/data/filter_unittests"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/filter_unittests"); + ASSERT_TRUE(NULL != server.get()); // for localhost domain, we also should support bzip2 encoding // first, get the original file TestDelegate d1; - TestURLRequest req1(server.TestServerPage("realfiles/google.txt"), &d1); + TestURLRequest req1(server->TestServerPage("realfiles/google.txt"), &d1); req1.Start(); MessageLoop::current()->Run(); @@ -570,7 +587,8 @@ TEST_F(URLRequestTest, BZip2ContentTest_IncrementalHeader) { // second, get bzip2 content. ask the testserver to send the BZ2 header in // two chunks with a delay between them. this tests our fix for bug 867161. TestDelegate d2; - TestURLRequest req2(server.TestServerPage("realbz2files/google.txt?incremental-header"), &d2); + TestURLRequest req2(server->TestServerPage( + "realbz2files/google.txt?incremental-header"), &d2); req2.Start(); MessageLoop::current()->Run(); @@ -654,10 +672,12 @@ TEST_F(URLRequestTest, ResolveShortcutTest) { #endif // defined(OS_WIN) TEST_F(URLRequestTest, ContentTypeNormalizationTest) { - TestServer server(L"net/data/url_request_unittest"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/url_request_unittest"); + ASSERT_TRUE(NULL != server.get()); + TestDelegate d; - TestURLRequest req(server.TestServerPage( + TestURLRequest req(server->TestServerPage( "files/content-type-normalization.html"), &d); req.Start(); MessageLoop::current()->Run(); @@ -701,10 +721,12 @@ TEST_F(URLRequestTest, FileDirCancelTest) { } TEST_F(URLRequestTest, RestrictRedirects) { - TestServer server(L"net/data/url_request_unittest"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/url_request_unittest"); + ASSERT_TRUE(NULL != server.get()); + TestDelegate d; - TestURLRequest req(server.TestServerPage( + TestURLRequest req(server->TestServerPage( "files/redirect-to-file.html"), &d); req.Start(); MessageLoop::current()->Run(); @@ -714,10 +736,11 @@ TEST_F(URLRequestTest, RestrictRedirects) { } TEST_F(URLRequestTest, NoUserPassInReferrer) { - TestServer server(L"net/data/url_request_unittest"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/url_request_unittest"); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; - TestURLRequest req(server.TestServerPage( + TestURLRequest req(server->TestServerPage( "echoheader?Referer"), &d); req.set_referrer("http://user:pass@foo.com/"); req.Start(); @@ -727,12 +750,13 @@ TEST_F(URLRequestTest, NoUserPassInReferrer) { } TEST_F(URLRequestTest, CancelRedirect) { - TestServer server(L"net/data/url_request_unittest"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/url_request_unittest"); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; { d.set_cancel_in_received_redirect(true); - TestURLRequest req(server.TestServerPage( + TestURLRequest req(server->TestServerPage( "files/redirect-test.html"), &d); req.Start(); MessageLoop::current()->Run(); @@ -745,8 +769,9 @@ TEST_F(URLRequestTest, CancelRedirect) { } TEST_F(URLRequestTest, VaryHeader) { - TestServer server(L"net/data/url_request_unittest"); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/url_request_unittest"); + ASSERT_TRUE(NULL != server.get()); scoped_refptr<URLRequestContext> context = new URLRequestHttpCacheContext(); @@ -755,7 +780,7 @@ TEST_F(URLRequestTest, VaryHeader) { // populate the cache { TestDelegate d; - URLRequest req(server.TestServerPage("echoheader?foo"), &d); + URLRequest req(server->TestServerPage("echoheader?foo"), &d); req.set_context(context); req.SetExtraRequestHeaders("foo:1"); req.Start(); @@ -771,7 +796,7 @@ TEST_F(URLRequestTest, VaryHeader) { // expect a cache hit { TestDelegate d; - URLRequest req(server.TestServerPage("echoheader?foo"), &d); + URLRequest req(server->TestServerPage("echoheader?foo"), &d); req.set_context(context); req.SetExtraRequestHeaders("foo:1"); req.Start(); @@ -783,7 +808,7 @@ TEST_F(URLRequestTest, VaryHeader) { // expect a cache miss { TestDelegate d; - URLRequest req(server.TestServerPage("echoheader?foo"), &d); + URLRequest req(server->TestServerPage("echoheader?foo"), &d); req.set_context(context); req.SetExtraRequestHeaders("foo:2"); req.Start(); @@ -795,8 +820,9 @@ TEST_F(URLRequestTest, VaryHeader) { TEST_F(URLRequestTest, BasicAuth) { scoped_refptr<URLRequestContext> context = new URLRequestHttpCacheContext(); - TestServer server(L""); - ASSERT_TRUE(server.init_successful()); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L""); + ASSERT_TRUE(NULL != server.get()); Time response_time; @@ -806,7 +832,7 @@ TEST_F(URLRequestTest, BasicAuth) { d.set_username(L"user"); d.set_password(L"secret"); - URLRequest r(server.TestServerPage("auth-basic"), &d); + URLRequest r(server->TestServerPage("auth-basic"), &d); r.set_context(context); r.Start(); @@ -829,7 +855,7 @@ TEST_F(URLRequestTest, BasicAuth) { d.set_username(L"user"); d.set_password(L"secret"); - URLRequest r(server.TestServerPage("auth-basic"), &d); + URLRequest r(server->TestServerPage("auth-basic"), &d); r.set_context(context); r.set_load_flags(net::LOAD_VALIDATE_CACHE); r.Start(); @@ -849,16 +875,20 @@ TEST_F(URLRequestTest, BasicAuth) { // Content-Type header. // http://code.google.com/p/chromium/issues/detail?id=843 TEST_F(URLRequestTest, Post302RedirectGet) { - TestServer server(L"net/data/url_request_unittest"); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/url_request_unittest"); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; - TestURLRequest req(server.TestServerPage("files/redirect-to-echoall"), &d); + TestURLRequest req(server->TestServerPage("files/redirect-to-echoall"), &d); req.set_method("POST"); // Set headers (some of which are specific to the POST). // ("Content-Length: 10" is just a junk value to make sure it gets stripped). req.SetExtraRequestHeaders( - "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryAADeAA+NAAWMAAwZ\r\n" - "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n" + "Content-Type: multipart/form-data; " + "boundary=----WebKitFormBoundaryAADeAA+NAAWMAAwZ\r\n" + "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9," + "text/plain;q=0.8,image/png,*/*;q=0.5\r\n" "Accept-Language: en-US,en\r\n" "Accept-Charset: ISO-8859-1,*,utf-8\r\n" "Content-Length: 10\r\n" @@ -885,11 +915,126 @@ TEST_F(URLRequestTest, Post302RedirectGet) { } TEST_F(URLRequestTest, Post307RedirectPost) { - TestServer server(L"net/data/url_request_unittest"); + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(L"net/data/url_request_unittest"); + ASSERT_TRUE(NULL != server.get()); TestDelegate d; - TestURLRequest req(server.TestServerPage("files/redirect307-to-echoall"), &d); + TestURLRequest req(server->TestServerPage("files/redirect307-to-echoall"), + &d); req.set_method("POST"); req.Start(); MessageLoop::current()->Run(); EXPECT_EQ(req.method(), "POST"); } + +#if !defined(OS_WIN) + #define MAYBE_FTPGetTestAnonymous DISABLED_FTPGetTestAnonymous + #define MAYBE_FTPGetTest DISABLED_FTPGetTest + #define MAYBE_FTPCheckWrongUser DISABLED_FTPCheckWrongUser + #define MAYBE_FTPCheckWrongPassword DISABLED_FTPCheckWrongPassword +#else + #define MAYBE_FTPGetTestAnonymous FTPGetTestAnonymous + #define MAYBE_FTPGetTest FTPGetTest + #define MAYBE_FTPCheckWrongUser FTPCheckWrongUser + #define MAYBE_FTPCheckWrongPassword FTPCheckWrongPassword +#endif + +TEST_F(URLRequestTest, MAYBE_FTPGetTestAnonymous) { + scoped_refptr<FTPTestServer> server = FTPTestServer::CreateServer(L""); + ASSERT_TRUE(NULL != server.get()); + std::wstring app_path; + PathService::Get(base::DIR_SOURCE_ROOT, &app_path); + app_path.append(L"\\LICENSE"); + TestDelegate d; + { + TestURLRequest r(server->TestServerPage("/LICENSE"), &d); + r.Start(); + EXPECT_TRUE(r.is_pending()); + + MessageLoop::current()->Run(); + + int64 file_size = 0; + file_util::GetFileSize(app_path, &file_size); + + EXPECT_TRUE(!r.is_pending()); + EXPECT_EQ(1, d.response_started_count()); + EXPECT_FALSE(d.received_data_before_response()); + EXPECT_EQ(d.bytes_received(), static_cast<int>(file_size)); + } +} + +TEST_F(URLRequestTest, MAYBE_FTPGetTest) { + scoped_refptr<FTPTestServer> server = + FTPTestServer::CreateServer(L"", "chrome", "chrome"); + ASSERT_TRUE(NULL != server.get()); + std::wstring app_path; + PathService::Get(base::DIR_SOURCE_ROOT, &app_path); + app_path.append(L"\\LICENSE"); + TestDelegate d; + { + TestURLRequest r(server->TestServerPage("/LICENSE"), &d); + r.Start(); + EXPECT_TRUE(r.is_pending()); + + MessageLoop::current()->Run(); + + int64 file_size = 0; + file_util::GetFileSize(app_path, &file_size); + + EXPECT_TRUE(!r.is_pending()); + EXPECT_EQ(1, d.response_started_count()); + EXPECT_FALSE(d.received_data_before_response()); + EXPECT_EQ(d.bytes_received(), static_cast<int>(file_size)); + } +} + +TEST_F(URLRequestTest, MAYBE_FTPCheckWrongPassword) { + scoped_refptr<FTPTestServer> server = + FTPTestServer::CreateServer(L"", "chrome", "wrong_password"); + ASSERT_TRUE(NULL != server.get()); + std::wstring app_path; + PathService::Get(base::DIR_SOURCE_ROOT, &app_path); + app_path.append(L"\\LICENSE"); + TestDelegate d; + { + TestURLRequest r(server->TestServerPage("/LICENSE"), &d); + r.Start(); + EXPECT_TRUE(r.is_pending()); + + MessageLoop::current()->Run(); + + int64 file_size = 0; + file_util::GetFileSize(app_path, &file_size); + + EXPECT_TRUE(!r.is_pending()); + EXPECT_EQ(1, d.response_started_count()); + EXPECT_FALSE(d.received_data_before_response()); + EXPECT_EQ(d.bytes_received(), 0); + } +} + +TEST_F(URLRequestTest, MAYBE_FTPCheckWrongUser) { + scoped_refptr<FTPTestServer> server = + FTPTestServer::CreateServer(L"", "wrong_user", "chrome"); + ASSERT_TRUE(NULL != server.get()); + std::wstring app_path; + PathService::Get(base::DIR_SOURCE_ROOT, &app_path); + app_path.append(L"\\LICENSE"); + TestDelegate d; + { + TestURLRequest r(server->TestServerPage("/LICENSE"), &d); + r.Start(); + EXPECT_TRUE(r.is_pending()); + + MessageLoop::current()->Run(); + + int64 file_size = 0; + file_util::GetFileSize(app_path, &file_size); + + EXPECT_TRUE(!r.is_pending()); + EXPECT_EQ(1, d.response_started_count()); + EXPECT_FALSE(d.received_data_before_response()); + EXPECT_EQ(d.bytes_received(), 0); + } +} + diff --git a/net/url_request/url_request_unittest.h b/net/url_request/url_request_unittest.h index a33be39..c2158aa 100644 --- a/net/url_request/url_request_unittest.h +++ b/net/url_request/url_request_unittest.h @@ -9,6 +9,7 @@ #include <sstream> #include <string> +#include <vector> #include "base/file_path.h" #include "base/file_util.h" @@ -27,9 +28,13 @@ #include "testing/gtest/include/gtest/gtest.h" #include "googleurl/src/url_util.h" -const int kDefaultPort = 1337; +const int kHTTPDefaultPort = 1337; +const int kFTPDefaultPort = 1338; + const std::string kDefaultHostName("localhost"); +using base::TimeDelta; + // This URLRequestContext does not use a local cache. class TestURLRequestContext : public URLRequestContext { public: @@ -190,29 +195,42 @@ class TestDelegate : public URLRequest::Delegate { char buf_[4096]; }; -// This object bounds the lifetime of an external python-based HTTP server +// This object bounds the lifetime of an external python-based HTTP/FTP server // that can provide various responses useful for testing. -class TestServer : public base::ProcessFilter { - public: - TestServer(const std::wstring& document_root) - : process_handle_(NULL), - is_shutdown_(true) { - Init(kDefaultHostName, kDefaultPort, document_root, std::wstring()); +class BaseTestServer : public base::ProcessFilter, + public base::RefCounted<BaseTestServer> { + protected: + BaseTestServer() + : process_handle_(NULL) { } - virtual ~TestServer() { - Shutdown(); + public: + virtual ~BaseTestServer() { + if (process_handle_) { +#if defined(OS_WIN) + CloseHandle(process_handle_); +#endif + process_handle_ = NULL; + } + // Make sure we don't leave any stray testserver processes laying around. + std::wstring testserver_name = + file_util::GetFilenameFromPath(python_runtime_); + base::CleanupProcesses(testserver_name, 10000, 1, this); + EXPECT_EQ(0, base::GetProcessCount(testserver_name, this)); } // Implementation of ProcessFilter virtual bool Includes(uint32 pid, uint32 parent_pid) const { - // This function may be called after Shutdown(), in which process_handle_ is - // set to NULL. Since no process handle is set, it can't be included in the - // filter. + // Since no process handle is set, it can't be included in the filter. if (!process_handle_) return false; // TODO(port): rationalize return value of GetProcId - return pid == (uint32)base::GetProcId(process_handle_); + return pid == static_cast<uint32>(base::GetProcId(process_handle_)); + } + + GURL TestServerPage(const std::string& base_address, + const std::string& path) { + return GURL(base_address + path); } GURL TestServerPage(const std::string& path) { @@ -223,101 +241,46 @@ class TestServer : public base::ProcessFilter { return GURL(base_address_ + WideToUTF8(path)); } - // A subclass may wish to send the request in a different manner - virtual bool MakeGETRequest(const std::string& page_name) { - const GURL& url = TestServerPage(page_name); - - // Spin up a background thread for this request so that we have access to - // an IO message loop, and in cases where this thread already has an IO - // message loop, we also want to avoid spinning a nested message loop. - - SyncTestDelegate d; - { - base::Thread io_thread("MakeGETRequest"); - base::Thread::Options options; - options.message_loop_type = MessageLoop::TYPE_IO; - io_thread.StartWithOptions(options); - io_thread.message_loop()->PostTask(FROM_HERE, NewRunnableFunction( - &TestServer::StartGETRequest, url, &d)); - d.Wait(); - } - return d.did_succeed(); - } - - bool init_successful() const { return init_successful_; } - - protected: - struct ManualInit {}; - - // Used by subclasses that need to defer initialization until they are fully - // constructed. The subclass should call Init once it is ready (usually in - // its constructor). - TestServer(ManualInit) - : process_handle_(NULL), - init_successful_(false), - is_shutdown_(true) { - } - - virtual std::string scheme() { return std::string("http"); } - - // This is in a separate function so that we can have assertions and so that - // subclasses can call this later. - void Init(const std::string& host_name, int port, - const std::wstring& document_root, - const std::wstring& cert_path) { - std::stringstream ss; - std::string port_str; - ss << (port ? port : kDefaultPort); - ss >> port_str; - base_address_ = scheme() + "://" + host_name + ":" + port_str + "/"; - - std::wstring testserver_path; - ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &testserver_path)); - file_util::AppendToPath(&testserver_path, L"net"); - file_util::AppendToPath(&testserver_path, L"tools"); - file_util::AppendToPath(&testserver_path, L"testserver"); - file_util::AppendToPath(&testserver_path, L"testserver.py"); - - ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &python_runtime_)); - file_util::AppendToPath(&python_runtime_, L"third_party"); - file_util::AppendToPath(&python_runtime_, L"python_24"); - file_util::AppendToPath(&python_runtime_, L"python.exe"); - - std::wstring test_data_directory; - PathService::Get(base::DIR_SOURCE_ROOT, &test_data_directory); - std::wstring normalized_document_root = document_root; + void SetPythonPaths() { #if defined(OS_WIN) - std::replace(normalized_document_root.begin(), - normalized_document_root.end(), - L'/', FilePath::kSeparators[0]); -#endif - file_util::AppendToPath(&test_data_directory, normalized_document_root); + // Set up PYTHONPATH so that Python is able to find the in-tree copy of + // pyftpdlib. + static bool set_python_path = false; + if (!set_python_path) { + FilePath pyftpdlib_path; + ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &pyftpdlib_path)); + pyftpdlib_path = pyftpdlib_path.Append(L"third_party"); + pyftpdlib_path = pyftpdlib_path.Append(L"pyftpdlib"); + + const wchar_t kPythonPath[] = L"PYTHONPATH"; + wchar_t python_path_c[1024]; + if (GetEnvironmentVariable(kPythonPath, python_path_c, 1023) > 0) { + // PYTHONPATH is already set, append to it. + std::wstring python_path(python_path_c); + python_path.append(L":"); + python_path.append(pyftpdlib_path.value()); + SetEnvironmentVariableW(kPythonPath, python_path.c_str()); + } else { + SetEnvironmentVariableW(kPythonPath, pyftpdlib_path.value().c_str()); + } -#if defined(OS_WIN) - std::wstring command_line = - L"\"" + python_runtime_ + L"\" " + L"\"" + testserver_path + - L"\" --port=" + UTF8ToWide(port_str) + L" --data-dir=\"" + - test_data_directory + L"\""; - if (!cert_path.empty()) { - command_line.append(L" --https=\""); - command_line.append(cert_path); - command_line.append(L"\""); + set_python_path = true; } - - ASSERT_TRUE( - base::LaunchApp(command_line, false, true, &process_handle_)) << - "Failed to launch " << command_line; #elif defined(OS_POSIX) // Set up PYTHONPATH so that Python is able to find the in-tree copy of - // tlslite. - + // tlslite and pyftpdlib. static bool set_python_path = false; if (!set_python_path) { FilePath tlslite_path; + FilePath pyftpdlib_path; ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &tlslite_path)); tlslite_path = tlslite_path.Append("third_party"); tlslite_path = tlslite_path.Append("tlslite"); + ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &pyftpdlib_path)); + pyftpdlib_path = pyftpdlib_path.Append("third_party"); + pyftpdlib_path = pyftpdlib_path.Append("pyftpdlib"); + const char kPythonPath[] = "PYTHONPATH"; char* python_path_c = getenv(kPythonPath); if (python_path_c) { @@ -325,81 +288,89 @@ class TestServer : public base::ProcessFilter { std::string python_path(python_path_c); python_path.append(":"); python_path.append(tlslite_path.value()); + python_path.append(":"); + python_path.append(pyftpdlib_path.value()); setenv(kPythonPath, python_path.c_str(), 1); } else { - setenv(kPythonPath, tlslite_path.value().c_str(), 1); + std::string python_path = tlslite_path.value().c_str(); + python_path.append(":"); + python_path.append(pyftpdlib_path.value()); + setenv(kPythonPath, python_path.c_str(), 1); } - set_python_path = true; } - - std::vector<std::string> command_line; - command_line.push_back("python"); - command_line.push_back(WideToUTF8(testserver_path)); - command_line.push_back("--port=" + port_str); - command_line.push_back("--data-dir=" + WideToUTF8(test_data_directory)); - if (!cert_path.empty()) - command_line.push_back("--https=" + WideToUTF8(cert_path)); - - base::file_handle_mapping_vector no_mappings; - ASSERT_TRUE( - base::LaunchApp(command_line, no_mappings, false, &process_handle_)) << - "Failed to launch " << command_line[0] << " ..."; #endif + } - // Verify that the webserver is actually started. - // Otherwise tests can fail if they run faster than Python can start. - int retries = 10; - bool success; - while ((success = MakeGETRequest("hello.html")) == false && retries > 0) { - retries--; - PlatformThread::Sleep(500); + void SetAppPath(const std::string& host_name, int port, + const std::wstring& document_root, const std::string& scheme, + std::wstring* testserver_path, std::wstring* test_data_directory) { + port_str_ = IntToString(port); + if (url_user_.empty()) { + base_address_ = scheme + "://" + host_name + ":" + port_str_ + "/"; + } else { + if (url_password_.empty()) + base_address_ = scheme + "://" + url_user_ + "@" + + host_name + ":" + port_str_ + "/"; + else + base_address_ = scheme + "://" + url_user_ + ":" + url_password_ + + "@" + host_name + ":" + port_str_ + "/"; } - ASSERT_TRUE(success) << "Webserver not starting properly."; - init_successful_ = true; - is_shutdown_ = false; - } + ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, testserver_path)); + file_util::AppendToPath(testserver_path, L"net"); + file_util::AppendToPath(testserver_path, L"tools"); + file_util::AppendToPath(testserver_path, L"testserver"); + file_util::AppendToPath(testserver_path, L"testserver.py"); - void Shutdown() { - if (is_shutdown_) - return; + ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &python_runtime_)); + file_util::AppendToPath(&python_runtime_, L"third_party"); + file_util::AppendToPath(&python_runtime_, L"python_24"); + file_util::AppendToPath(&python_runtime_, L"python.exe"); - // here we append the time to avoid problems where the kill page - // is being cached rather than being executed on the server - std::ostringstream page_name; - page_name << "kill?" << (unsigned int)(base::Time::Now().ToInternalValue()); - int retry_count = 5; - while (retry_count > 0) { - bool r = MakeGETRequest(page_name.str()); - // BUG #1048625 causes the kill GET to fail. For now we just retry. - // Once the bug is fixed, we should remove the while loop and put back - // the following DCHECK. - // DCHECK(r); - if (r) - break; - retry_count--; - } - // Make sure we were successfull in stopping the testserver. - DCHECK(retry_count > 0); + PathService::Get(base::DIR_SOURCE_ROOT, test_data_directory); + std::wstring normalized_document_root = document_root; - if (process_handle_) { #if defined(OS_WIN) - CloseHandle(process_handle_); + // It is just for windows only and have no effect on other OS + std::replace(normalized_document_root.begin(), + normalized_document_root.end(), + L'/', FilePath::kSeparators[0]); #endif - process_handle_ = NULL; - } + if (!normalized_document_root.empty()) + file_util::AppendToPath(test_data_directory, normalized_document_root); - // Make sure we don't leave any stray testserver processes laying around. - std::wstring testserver_name = - file_util::GetFilenameFromPath(python_runtime_); - base::CleanupProcesses(testserver_name, 10000, 1, this); - EXPECT_EQ(0, base::GetProcessCount(testserver_name, this)); + } - is_shutdown_ = true; +#if defined(OS_WIN) + void LaunchApp(const std::wstring& command_line) { + ASSERT_TRUE(base::LaunchApp(command_line, false, true, &process_handle_)) << + "Failed to launch " << command_line; } +#elif defined(OS_POSIX) + void LaunchApp(const std::vector<std::string>& command_line) { + ASSERT_TRUE(base::LaunchApp(command_line, false, true, &process_handle_)) << + "Failed to launch " << command_line[0] << " ..."; + } +#endif - private: + virtual bool MakeGETRequest(const std::string& page_name) = 0; + + // Verify that the Server is actually started. + // Otherwise tests can fail if they run faster than Python can start. + bool VerifyLaunchApp(const std::string& page_name) { + int retries = 10; + bool success; + while ((success = MakeGETRequest(page_name)) == false && retries > 0) { + retries--; + PlatformThread::Sleep(500); + } + if (!success) + return false; + return true; + } + + protected: // Used by MakeGETRequest to implement sync load behavior. class SyncTestDelegate : public TestDelegate { public: @@ -410,13 +381,91 @@ class TestServer : public base::ProcessFilter { success_ = request->status().is_success(); event_.Signal(); } - void Wait() { event_.Wait(); } + bool Wait(int64 secs) { + TimeDelta td = TimeDelta::FromSeconds(secs); + if (event_.TimedWait(td)) + return true; + return false; + } bool did_succeed() const { return success_; } private: base::WaitableEvent event_; bool success_; DISALLOW_COPY_AND_ASSIGN(SyncTestDelegate); }; + + std::string host_name_; + std::string base_address_; + std::string url_user_; + std::string url_password_; + std::wstring python_runtime_; + base::ProcessHandle process_handle_; + std::string port_str_; +}; + +class HTTPTestServer : public BaseTestServer { + protected: + HTTPTestServer() { + } + + public: + static HTTPTestServer* CreateServer(const std::wstring& document_root) { + HTTPTestServer* test_server = new HTTPTestServer(); + if (!test_server->Init(kDefaultHostName, kHTTPDefaultPort, document_root)) { + delete test_server; + return NULL; + } + return test_server; + } + + bool Init(const std::string& host_name, int port, + const std::wstring& document_root) { + std::wstring testserver_path; + std::wstring test_data_directory; + host_name_ = host_name; +#if defined(OS_WIN) + std::wstring command_line; +#elif defined(OS_POSIX) + std::vector<std::string> command_line; +#endif + + // Set PYTHONPATH for tlslite and pyftpdlib + SetPythonPaths(); + SetAppPath(host_name, port, document_root, scheme(), + &testserver_path, &test_data_directory); + SetCommandLineOption(testserver_path, test_data_directory, &command_line); + LaunchApp(command_line); + if (!VerifyLaunchApp("hello.html")) { + LOG(ERROR) << "Webserver not starting properly"; + return false; + } + return true; + } + + // A subclass may wish to send the request in a different manner + virtual bool MakeGETRequest(const std::string& page_name) { + const GURL& url = TestServerPage(page_name); + + // Spin up a background thread for this request so that we have access to + // an IO message loop, and in cases where this thread already has an IO + // message loop, we also want to avoid spinning a nested message loop. + SyncTestDelegate d; + { + base::Thread io_thread("MakeGETRequest"); + base::Thread::Options options; + options.message_loop_type = MessageLoop::TYPE_IO; + io_thread.StartWithOptions(options); + io_thread.message_loop()->PostTask(FROM_HERE, NewRunnableFunction( + &HTTPTestServer::StartGETRequest, url, &d)); + + // Build bot wait for only 300 seconds we should ensure wait do not take + // more than 300 seconds + if (!d.Wait(250)) + return false; + } + return d.did_succeed(); + } + static void StartGETRequest(const GURL& url, URLRequest::Delegate* delegate) { URLRequest* request = new URLRequest(url, delegate); request->set_context(new TestURLRequestContext()); @@ -425,23 +474,213 @@ class TestServer : public base::ProcessFilter { EXPECT_TRUE(request->is_pending()); } - std::string base_address_; - std::wstring python_runtime_; - base::ProcessHandle process_handle_; - bool init_successful_; - bool is_shutdown_; + virtual ~HTTPTestServer() { + // here we append the time to avoid problems where the kill page + // is being cached rather than being executed on the server + std::string page_name = StringPrintf("kill?%u", + static_cast<int>(base::Time::Now().ToInternalValue())); + int retry_count = 5; + while (retry_count > 0) { + bool r = MakeGETRequest(page_name); + // BUG #1048625 causes the kill GET to fail. For now we just retry. + // Once the bug is fixed, we should remove the while loop and put back + // the following DCHECK. + // DCHECK(r); + if (r) + break; + retry_count--; + } + // Make sure we were successfull in stopping the testserver. + DCHECK(retry_count > 0); + } + + virtual std::string scheme() { return "http"; } + +#if defined(OS_WIN) + virtual void SetCommandLineOption(const std::wstring& testserver_path, + const std::wstring& test_data_directory, + std::wstring* command_line ) { + command_line->append(L"\"" + python_runtime_ + L"\" " + L"\"" + + testserver_path + L"\" --port=" + UTF8ToWide(port_str_) + + L" --data-dir=\"" + test_data_directory + L"\""); + } +#elif defined(OS_POSIX) + virtual void SetCommandLineOption(const std::wstring& testserver_path, + const std::wstring& test_data_directory, + std::vector<std::string>* command_line) { + command_line->push_back("python"); + command_line->push_back(WideToUTF8(testserver_path)); + command_line->push_back("--port=" + port_str_); + command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory)); + } +#endif }; -class HTTPSTestServer : public TestServer { +class HTTPSTestServer : public HTTPTestServer { + protected: + explicit HTTPSTestServer(const std::wstring& cert_path) + : cert_path_(cert_path) { + } + public: - HTTPSTestServer(const std::string& host_name, int port, - const std::wstring& document_root, - const std::wstring& cert_path) : TestServer(ManualInit()) { - Init(host_name, port, document_root, cert_path); + static HTTPSTestServer* CreateServer(const std::string& host_name, int port, + const std::wstring& document_root, + const std::wstring& cert_path) { + HTTPSTestServer* test_server = new HTTPSTestServer(cert_path); + if (!test_server->Init(host_name, port, document_root)) { + delete test_server; + return NULL; + } + return test_server; + } + +#if defined(OS_WIN) + virtual void SetCommandLineOption(const std::wstring& testserver_path, + const std::wstring& test_data_directory, + std::wstring* command_line ) { + command_line->append(L"\"" + python_runtime_ + L"\" " + L"\"" + + testserver_path + L"\"" + L" --port=" + + UTF8ToWide(port_str_) + L" --data-dir=\"" + + test_data_directory + L"\""); + if (!cert_path_.empty()) { + command_line->append(L" --https=\""); + command_line->append(cert_path_); + command_line->append(L"\""); + } + } +#elif defined(OS_POSIX) + virtual void SetCommandLineOption(const std::wstring& testserver_path, + const std::wstring& test_data_directory, + std::vector<std::string>* command_line) { + command_line->push_back("python"); + command_line->push_back(WideToUTF8(testserver_path)); + command_line->push_back("--port=" + port_str_); + command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory)); + if (!cert_path_.empty()) + command_line->push_back("--https=" + WideToUTF8(cert_path_)); +} +#endif + + virtual std::string scheme() { return "https"; } + + virtual ~HTTPSTestServer() { } - virtual std::string scheme() { return std::string("https"); } + protected: + std::wstring cert_path_; }; -#endif // NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ +class FTPTestServer : public BaseTestServer { + protected: + FTPTestServer() { + } + + public: + FTPTestServer(const std::string& url_user, const std::string& url_password) { + url_user_ = url_user; + url_password_ = url_password; + } + + static FTPTestServer* CreateServer(const std::wstring& document_root) { + FTPTestServer* test_server = new FTPTestServer(); + if (!test_server->Init(kDefaultHostName, kFTPDefaultPort, document_root)) { + delete test_server; + return NULL; + } + return test_server; + } + + static FTPTestServer* CreateServer(const std::wstring& document_root, + const std::string& url_user, + const std::string& url_password) { + FTPTestServer* test_server = new FTPTestServer(url_user, url_password); + if (!test_server->Init(kDefaultHostName, kFTPDefaultPort, document_root)) { + delete test_server; + return NULL; + } + return test_server; + } + + bool Init(const std::string& host_name, int port, + const std::wstring& document_root) { + std::wstring testserver_path; + std::wstring test_data_directory; + host_name_ = host_name; + +#if defined(OS_WIN) + std::wstring command_line; +#elif defined(OS_POSIX) + std::vector<std::string> command_line; +#endif + + // Set PYTHONPATH for tlslite and pyftpdlib + SetPythonPaths(); + SetAppPath(kDefaultHostName, port, document_root, scheme(), + &testserver_path, &test_data_directory); + SetCommandLineOption(testserver_path, test_data_directory, &command_line); + LaunchApp(command_line); + if (!VerifyLaunchApp("/LICENSE")) { + LOG(ERROR) << "FTPServer not starting properly."; + return false; + } + return true; + } + + virtual ~FTPTestServer() { + const std::string base_address = scheme() + "://" + host_name_ + ":" + + port_str_ + "/"; + const GURL& url = TestServerPage(base_address, "kill"); + TestDelegate d; + URLRequest request(url, &d); + request.set_context(new TestURLRequestContext()); + request.set_method("GET"); + request.Start(); + EXPECT_TRUE(request.is_pending()); + + MessageLoop::current()->Run(); + } + + virtual std::string scheme() { return "ftp"; } + + virtual bool MakeGETRequest(const std::string& page_name) { + const std::string base_address = scheme() + "://" + host_name_ + ":" + + port_str_ + "/"; + const GURL& url = TestServerPage(base_address, page_name); + TestDelegate d; + URLRequest request(url, &d); + request.set_context(new TestURLRequestContext()); + request.set_method("GET"); + request.Start(); + EXPECT_TRUE(request.is_pending()); + + MessageLoop::current()->Run(); + if (request.is_pending()) + return false; + + return true; + } + +#if defined(OS_WIN) + virtual void SetCommandLineOption(const std::wstring& testserver_path, + const std::wstring& test_data_directory, + std::wstring* command_line ) { + command_line->append(L"\"" + python_runtime_ + L"\" " + L"\"" + + testserver_path + L"\"" + L" -f " + L" --port=" + + UTF8ToWide(port_str_) + L" --data-dir=\"" + + test_data_directory + L"\""); + } +#elif defined(OS_POSIX) + virtual void SetCommandLineOption(const std::wstring& testserver_path, + const std::wstring& test_data_directory, + std::vector<std::string>* command_line) { + command_line->push_back("python"); + command_line->push_back(WideToUTF8(testserver_path)); + command_line->push_back(" -f "); + command_line->push_back("--data-dir=" + WideToUTF8(test_data_directory)); + command_line->push_back("--port=" + port_str_); + } +#endif +}; + +#endif // NET_URL_REQUEST_URL_REQUEST_UNITTEST_H_ |