diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-07 06:57:04 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-07 06:57:04 +0000 |
commit | 6ca390291e00d32d170a43ddb44d478552bf70b9 (patch) | |
tree | 0157778ea6281546f7fb9a7b7ae776c3023d7e0f | |
parent | 7e691b843959fbe5ca3cb90025107d9ecb7a5f9d (diff) | |
download | chromium_src-6ca390291e00d32d170a43ddb44d478552bf70b9.zip chromium_src-6ca390291e00d32d170a43ddb44d478552bf70b9.tar.gz chromium_src-6ca390291e00d32d170a43ddb44d478552bf70b9.tar.bz2 |
Revert 166344 (SafeBrowsingSystemTest fails on XP:
http://build.chromium.org/p/chromium.win/buildstatus?builder=XP%20Tests%20%281%29&number=21644
http://build.chromium.org/p/chromium.win/buildstatus?builder=XP%20Tests%20%28dbg%29%281%29&number=28760
eg
[10776:10780:1106/215239:1089468:INFO:safe_browsing_test.cc(443)] Start test
browser\safe_browsing\safe_browsing_test.cc(491): error: Value of: ParsePhishingUrls(safe_browsing_helper->response_data(), &phishing_urls)
Actual: false
Expected: true
Google Test trace:
browser\safe_browsing\safe_browsing_test.cc(466): step=2
browser\safe_browsing\safe_browsing_test.cc(492): error: Expected: (phishing_urls.size()) > (0U), actual: 0 vs 0
Google Test trace:
browser\safe_browsing\safe_browsing_test.cc(466): step=2
browser\safe_browsing\safe_browsing_test.cc(517): error: Expected: (safe_browsing_helper->response_data().size()) > (0U), actual: 0 vs 0
Google Test trace:
browser\safe_browsing\safe_browsing_test.cc(466): step=2
browser\safe_browsing\safe_browsing_test.cc(524): error: Value of: safe_browsing_helper->response_data()
Actual: ""
Expected: "yes"
)- Try #2: Run safebrowsing_service_test through the net testserver code.
Allows us to use ephemeral ports.
Original review: https://chromiumcodereview.appspot.com/10073033
BUG=96459,119403
Review URL: https://chromiumcodereview.appspot.com/10918251
TBR=mattm@chromium.org
Review URL: https://codereview.chromium.org/11369114
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@166364 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/safe_browsing/local_safebrowsing_test_server.cc | 61 | ||||
-rw-r--r-- | chrome/browser/safe_browsing/local_safebrowsing_test_server.h | 38 | ||||
-rw-r--r-- | chrome/browser/safe_browsing/safe_browsing_test.cc | 205 | ||||
-rwxr-xr-x | chrome/browser/safe_browsing/safe_browsing_testserver.py | 47 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | net/test/base_test_server.cc | 6 | ||||
-rw-r--r-- | net/test/base_test_server.h | 8 | ||||
-rw-r--r-- | net/test/local_sync_test_server.cc | 3 | ||||
-rw-r--r-- | net/test/local_test_server.cc | 18 | ||||
-rw-r--r-- | net/test/local_test_server.h | 15 | ||||
-rw-r--r-- | net/tools/testserver/run_testserver.cc | 2 | ||||
-rwxr-xr-x | net/tools/testserver/testserver.py | 620 | ||||
-rw-r--r-- | net/tools/testserver/testserver_base.py | 126 |
13 files changed, 500 insertions, 650 deletions
diff --git a/chrome/browser/safe_browsing/local_safebrowsing_test_server.cc b/chrome/browser/safe_browsing/local_safebrowsing_test_server.cc deleted file mode 100644 index c25e4d7..0000000 --- a/chrome/browser/safe_browsing/local_safebrowsing_test_server.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/safe_browsing/local_safebrowsing_test_server.h" - -#include "base/command_line.h" -#include "base/path_service.h" -#include "base/string_number_conversions.h" -#include "base/values.h" -#include "net/test/python_utils.h" -#include "net/test/test_server.h" - -LocalSafeBrowsingTestServer::LocalSafeBrowsingTestServer( - const FilePath& data_file) - : net::LocalTestServer(net::TestServer::TYPE_HTTP, - net::TestServer::kLocalhost, - FilePath()), - data_file_(data_file) { -} - -LocalSafeBrowsingTestServer::~LocalSafeBrowsingTestServer() {} - -bool LocalSafeBrowsingTestServer::GetTestServerPath( - FilePath* testserver_path) const { - FilePath testserver_dir; - if (!PathService::Get(base::DIR_SOURCE_ROOT, &testserver_dir)) { - LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT"; - return false; - } - - testserver_dir = testserver_dir - .Append(FILE_PATH_LITERAL("chrome")) - .Append(FILE_PATH_LITERAL("browser")) - .Append(FILE_PATH_LITERAL("safe_browsing")); - - *testserver_path = testserver_dir.Append(FILE_PATH_LITERAL( - "safe_browsing_testserver.py")); - return true; -} - -bool LocalSafeBrowsingTestServer::SetPythonPath() const { - if (!net::LocalTestServer::SetPythonPath()) - return false; - - // Locate the Python code generated by the protocol buffers compiler. - FilePath pyproto_dir; - if (!GetPyProtoPath(&pyproto_dir)) { - LOG(ERROR) << "Cannot find pyproto dir for generated code."; - return false; - } - - AppendToPythonPath(pyproto_dir.AppendASCII("google")); - return true; -} - -bool LocalSafeBrowsingTestServer::GenerateAdditionalArguments( - base::DictionaryValue* arguments) const { - arguments->SetString("data-file", data_file_.value()); - return true; -} diff --git a/chrome/browser/safe_browsing/local_safebrowsing_test_server.h b/chrome/browser/safe_browsing/local_safebrowsing_test_server.h deleted file mode 100644 index 13d8baf..0000000 --- a/chrome/browser/safe_browsing/local_safebrowsing_test_server.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SAFE_BROWSING_LOCAL_SAFEBROWSING_TEST_SERVER_H_ -#define CHROME_BROWSER_SAFE_BROWSING_LOCAL_SAFEBROWSING_TEST_SERVER_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/file_path.h" -#include "net/test/local_test_server.h" - -// Runs a Python-based safebrowsing test server on the same machine in which the -// LocalSafeBrowsingTestServer runs. -class LocalSafeBrowsingTestServer : public net::LocalTestServer { - public: - // Initialize a safebrowsing server using the given |data_file|. - explicit LocalSafeBrowsingTestServer(const FilePath& data_file); - - virtual ~LocalSafeBrowsingTestServer(); - - virtual bool SetPythonPath() const OVERRIDE; - - // Returns the path to safe_browsing_testserver.py. - virtual bool GetTestServerPath(FilePath* testserver_path) const OVERRIDE; - - protected: - // Adds the --data-file switch. Returns true on success. - virtual bool GenerateAdditionalArguments( - base::DictionaryValue* arguments) const OVERRIDE; - - private: - FilePath data_file_; - - DISALLOW_COPY_AND_ASSIGN(LocalSafeBrowsingTestServer); -}; - -#endif // CHROME_BROWSER_SAFE_BROWSING_LOCAL_SAFEBROWSING_TEST_SERVER_H_ diff --git a/chrome/browser/safe_browsing/safe_browsing_test.cc b/chrome/browser/safe_browsing/safe_browsing_test.cc index c34a952..38b5ce5 100644 --- a/chrome/browser/safe_browsing/safe_browsing_test.cc +++ b/chrome/browser/safe_browsing/safe_browsing_test.cc @@ -32,7 +32,6 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/safe_browsing/local_safebrowsing_test_server.h" #include "chrome/browser/safe_browsing/protocol_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/ui/browser.h" @@ -58,9 +57,10 @@ namespace { const FilePath::CharType kDataFile[] = FILE_PATH_LITERAL("testing_input_nomac.dat"); -const char kUrlVerifyPath[] = "safebrowsing/verify_urls"; -const char kDBVerifyPath[] = "safebrowsing/verify_database"; -const char kTestCompletePath[] = "test_complete"; +const char kUrlVerifyPath[] = "/safebrowsing/verify_urls"; +const char kDBVerifyPath[] = "/safebrowsing/verify_database"; +const char kDBResetPath[] = "/reset"; +const char kTestCompletePath[] = "/test_complete"; struct PhishingUrl { std::string url; @@ -110,6 +110,100 @@ bool ParsePhishingUrls(const std::string& data, } // namespace +class SafeBrowsingTestServer { + public: + explicit SafeBrowsingTestServer(const FilePath& datafile) + : datafile_(datafile), + server_handle_(base::kNullProcessHandle) { + } + + ~SafeBrowsingTestServer() { + EXPECT_EQ(base::kNullProcessHandle, server_handle_); + } + + // Start the python server test suite. + bool Start() { + // Get path to python server script + FilePath testserver_path; + if (!PathService::Get(base::DIR_SOURCE_ROOT, &testserver_path)) { + LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT"; + return false; + } + testserver_path = testserver_path + .Append(FILE_PATH_LITERAL("third_party")) + .Append(FILE_PATH_LITERAL("safe_browsing")) + .Append(FILE_PATH_LITERAL("testing")); + AppendToPythonPath(testserver_path); + FilePath testserver = testserver_path.Append( + FILE_PATH_LITERAL("safebrowsing_test_server.py")); + + FilePath pyproto_code_dir; + if (!GetPyProtoPath(&pyproto_code_dir)) { + LOG(ERROR) << "Failed to get generated python protobuf dir"; + return false; + } + AppendToPythonPath(pyproto_code_dir); + pyproto_code_dir = pyproto_code_dir.Append(FILE_PATH_LITERAL("google")); + AppendToPythonPath(pyproto_code_dir); + + CommandLine cmd_line(CommandLine::NO_PROGRAM); + EXPECT_TRUE(GetPythonCommand(&cmd_line)); + + FilePath datafile = testserver_path.Append(datafile_); + cmd_line.AppendArgPath(testserver); + cmd_line.AppendArg(base::StringPrintf("--port=%d", kPort_)); + cmd_line.AppendArgNative(FILE_PATH_LITERAL("--datafile=") + + datafile.value()); + + base::LaunchOptions options; +#if defined(OS_WIN) + options.start_hidden = true; +#endif + if (!base::LaunchProcess(cmd_line, options, &server_handle_)) { + LOG(ERROR) << "Failed to launch server: " + << cmd_line.GetCommandLineString(); + return false; + } + return true; + } + + // Stop the python server test suite. + bool Stop() { + if (server_handle_ == base::kNullProcessHandle) + return true; + + // First check if the process has already terminated. + if (!base::WaitForSingleProcess(server_handle_, base::TimeDelta()) && + !base::KillProcess(server_handle_, 1, true)) { + VLOG(1) << "Kill failed?"; + return false; + } + + base::CloseProcessHandle(server_handle_); + server_handle_ = base::kNullProcessHandle; + VLOG(1) << "Stopped."; + return true; + } + + static const char* Host() { + return kHost_; + } + + static int Port() { + return kPort_; + } + + private: + static const char kHost_[]; + static const int kPort_; + FilePath datafile_; + base::ProcessHandle server_handle_; + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingTestServer); +}; + +const char SafeBrowsingTestServer::kHost_[] = "localhost"; +const int SafeBrowsingTestServer::kPort_ = 40102; + // This starts the browser and keeps status of states related to SafeBrowsing. class SafeBrowsingServiceTest : public InProcessBrowserTest { public: @@ -203,28 +297,13 @@ class SafeBrowsingServiceTest : public InProcessBrowserTest { return safe_browsing_service_->safe_browsing_thread_->message_loop(); } - const net::TestServer& test_server() const { - return *test_server_; - } - protected: bool InitSafeBrowsingService() { safe_browsing_service_ = g_browser_process->safe_browsing_service(); return safe_browsing_service_ != NULL; } - virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { - FilePath datafile_path; - ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &datafile_path)); - - datafile_path = datafile_path.Append(FILE_PATH_LITERAL("third_party")) - .Append(FILE_PATH_LITERAL("safe_browsing")) - .Append(FILE_PATH_LITERAL("testing")) - .Append(kDataFile); - test_server_.reset(new LocalSafeBrowsingTestServer(datafile_path)); - ASSERT_TRUE(test_server_->Start()); - LOG(INFO) << "server is " << test_server_->host_port_pair().ToString(); - + virtual void SetUpCommandLine(CommandLine* command_line) { // Makes sure the auto update is not triggered. This test will force the // update when needed. command_line->AppendSwitch(switches::kSbDisableAutoUpdate); @@ -244,7 +323,10 @@ class SafeBrowsingServiceTest : public InProcessBrowserTest { switches::kDisableClientSidePhishingDetection); // Point to the testing server for all SafeBrowsing requests. - std::string url_prefix = test_server_->GetURL("safebrowsing").spec(); + std::string url_prefix = + base::StringPrintf("http://%s:%d/safebrowsing", + SafeBrowsingTestServer::Host(), + SafeBrowsingTestServer::Port()); command_line->AppendSwitchASCII(switches::kSbURLPrefix, url_prefix); } @@ -256,8 +338,6 @@ class SafeBrowsingServiceTest : public InProcessBrowserTest { private: SafeBrowsingService* safe_browsing_service_; - scoped_ptr<net::TestServer> test_server_; - // Protects all variables below since they are read on UI thread // but updated on IO thread or safebrowsing thread. base::Lock update_status_mutex_; @@ -363,36 +443,52 @@ class SafeBrowsingServiceTestHelper content::RunMessageLoop(); } + void WaitTillServerReady(const char* host, int port) { + response_status_ = net::URLRequestStatus::FAILED; + GURL url(base::StringPrintf("http://%s:%d%s?test_step=0", + host, port, kDBResetPath)); + // TODO(lzheng): We should have a way to reliably tell when a server is + // ready so we could get rid of the Sleep and retry loop. + while (true) { + if (FetchUrl(url) == net::URLRequestStatus::SUCCESS) + break; + // Wait and try again if last fetch was failed. The loop will hit the + // timeout in OutOfProcTestRunner if the fetch can not get success + // response. + base::PlatformThread::Sleep(TestTimeouts::tiny_timeout()); + } + } + // Calls test server to fetch database for verification. - net::URLRequestStatus::Status FetchDBToVerify( - const net::TestServer& test_server, - int test_step) { + net::URLRequestStatus::Status FetchDBToVerify(const char* host, int port, + int test_step) { // TODO(lzheng): Remove chunk_type=add once it is not needed by the server. - std::string path = base::StringPrintf( - "%s?client=chromium&appver=1.0&pver=2.2&test_step=%d&chunk_type=add", - kDBVerifyPath, test_step); - return FetchUrl(test_server.GetURL(path)); + GURL url(base::StringPrintf( + "http://%s:%d%s?" + "client=chromium&appver=1.0&pver=2.2&test_step=%d&" + "chunk_type=add", + host, port, kDBVerifyPath, test_step)); + return FetchUrl(url); } // Calls test server to fetch URLs for verification. - net::URLRequestStatus::Status FetchUrlsToVerify( - const net::TestServer& test_server, - int test_step) { - std::string path = base::StringPrintf( - "%s?client=chromium&appver=1.0&pver=2.2&test_step=%d", - kUrlVerifyPath, test_step); - return FetchUrl(test_server.GetURL(path)); + net::URLRequestStatus::Status FetchUrlsToVerify(const char* host, int port, + int test_step) { + GURL url(base::StringPrintf( + "http://%s:%d%s?" + "client=chromium&appver=1.0&pver=2.2&test_step=%d", + host, port, kUrlVerifyPath, test_step)); + return FetchUrl(url); } // Calls test server to check if test data is done. E.g.: if there is a // bad URL that server expects test to fetch full hash but the test didn't, // this verification will fail. - net::URLRequestStatus::Status VerifyTestComplete( - const net::TestServer& test_server, - int test_step) { - std::string path = base::StringPrintf( - "%s?test_step=%d", kTestCompletePath, test_step); - return FetchUrl(test_server.GetURL(path)); + net::URLRequestStatus::Status VerifyTestComplete(const char* host, int port, + int test_step) { + GURL url(StringPrintf("http://%s:%d%s?test_step=%d", + host, port, kTestCompletePath, test_step)); + return FetchUrl(url); } // Callback for URLFetcher. @@ -439,8 +535,10 @@ class SafeBrowsingServiceTestHelper // See http://crbug.com/96459 IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, - SafeBrowsingSystemTest) { + DISABLED_SafeBrowsingSystemTest) { LOG(INFO) << "Start test"; + const char* server_host = SafeBrowsingTestServer::Host(); + int server_port = SafeBrowsingTestServer::Port(); ASSERT_TRUE(InitSafeBrowsingService()); net::URLRequestContextGetter* request_context = @@ -448,6 +546,12 @@ IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, scoped_refptr<SafeBrowsingServiceTestHelper> safe_browsing_helper( new SafeBrowsingServiceTestHelper(this, request_context)); int last_step = 0; + FilePath datafile_path = FilePath(kDataFile); + SafeBrowsingTestServer test_server(datafile_path); + ASSERT_TRUE(test_server.Start()); + + // Make sure the server is running. + safe_browsing_helper->WaitTillServerReady(server_host, server_port); // Waits and makes sure safebrowsing update is not happening. // The wait will stop once OnWaitForStatusUpdateDone in @@ -484,7 +588,9 @@ IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, // Fetches URLs to verify and waits till server responses with data. EXPECT_EQ(net::URLRequestStatus::SUCCESS, - safe_browsing_helper->FetchUrlsToVerify(test_server(), step)); + safe_browsing_helper->FetchUrlsToVerify(server_host, + server_port, + step)); std::vector<PhishingUrl> phishing_urls; EXPECT_TRUE(ParsePhishingUrls(safe_browsing_helper->response_data(), @@ -513,13 +619,18 @@ IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, // TODO(lzheng): We should verify the fetched database with local // database to make sure they match. EXPECT_EQ(net::URLRequestStatus::SUCCESS, - safe_browsing_helper->FetchDBToVerify(test_server(), step)); + safe_browsing_helper->FetchDBToVerify(server_host, + server_port, + step)); EXPECT_GT(safe_browsing_helper->response_data().size(), 0U); last_step = step; } // Verifies with server if test is done and waits till server responses. EXPECT_EQ(net::URLRequestStatus::SUCCESS, - safe_browsing_helper->VerifyTestComplete(test_server(), last_step)); + safe_browsing_helper->VerifyTestComplete(server_host, + server_port, + last_step)); EXPECT_EQ("yes", safe_browsing_helper->response_data()); + test_server.Stop(); } diff --git a/chrome/browser/safe_browsing/safe_browsing_testserver.py b/chrome/browser/safe_browsing/safe_browsing_testserver.py deleted file mode 100755 index 674bf5a..0000000 --- a/chrome/browser/safe_browsing/safe_browsing_testserver.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Wraps the upstream safebrowsing_test_server.py to run in Chrome tests.""" - -import os -import sys - -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) - -sys.path.append(os.path.join(BASE_DIR, '..', '..', '..', 'net', - 'tools', 'testserver')) -import testserver_base - - -class ServerRunner(testserver_base.TestServerRunner): - """TestServerRunner for safebrowsing_test_server.py.""" - - def create_server(self, server_data): - sys.path.append(os.path.join(BASE_DIR, '..', '..', '..', 'third_party', - 'safe_browsing', 'testing')) - import safebrowsing_test_server - server = safebrowsing_test_server.SetupServer( - self.options.data_file, self.options.host, self.options.port, - opt_enforce_caching=False, opt_validate_database=True) - print 'Safebrowsing HTTP server started on port %d...' % server.server_port - server_data['port'] = server.server_port - - return server - - def add_options(self): - testserver_base.TestServerRunner.add_options(self) - self.option_parser.add_option('--data-file', dest='data_file', - help='File containing safebrowsing test ' - 'data and expectations') - # TODO(mattm): we define an unnecessary --data-dir option because - # BaseTestServer unconditionally sets --data-dir. This should be removed - # when BaseTestServer is refactored to not contain all the net/ - # test_server.py specific stuff. - self.option_parser.add_option('--data-dir', dest='data_dir', - help='unused') - - -if __name__ == '__main__': - sys.exit(ServerRunner().main()) diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 6e57ff1..3d92d86 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -3767,7 +3767,6 @@ ], 'sources': [ 'app/chrome_dll.rc', - 'browser/safe_browsing/local_safebrowsing_test_server.cc', 'browser/safe_browsing/safe_browsing_test.cc', 'test/base/chrome_test_launcher.cc', ], diff --git a/net/test/base_test_server.cc b/net/test/base_test_server.cc index 9307acf..d13d57c 100644 --- a/net/test/base_test_server.cc +++ b/net/test/base_test_server.cc @@ -390,12 +390,6 @@ bool BaseTestServer::GenerateArguments(base::DictionaryValue* arguments) const { base::Value::CreateIntegerValue(ssl_options_.tls_intolerant)); } } - - return GenerateAdditionalArguments(arguments); -} - -bool BaseTestServer::GenerateAdditionalArguments( - base::DictionaryValue* arguments) const { return true; } diff --git a/net/test/base_test_server.h b/net/test/base_test_server.h index d343f18..9f1290e 100644 --- a/net/test/base_test_server.h +++ b/net/test/base_test_server.h @@ -214,13 +214,7 @@ class BaseTestServer { // Generates a DictionaryValue with the arguments for launching the external // Python test server. - bool GenerateArguments(base::DictionaryValue* arguments) const - WARN_UNUSED_RESULT; - - // Subclasses can override this to add arguments that are specific to their - // own test servers. - virtual bool GenerateAdditionalArguments( - base::DictionaryValue* arguments) const WARN_UNUSED_RESULT; + bool GenerateArguments(base::DictionaryValue* arguments) const; private: void Init(const std::string& host); diff --git a/net/test/local_sync_test_server.cc b/net/test/local_sync_test_server.cc index 432fde1..8d757f8 100644 --- a/net/test/local_sync_test_server.cc +++ b/net/test/local_sync_test_server.cc @@ -29,8 +29,7 @@ LocalSyncTestServer::~LocalSyncTestServer() {} bool LocalSyncTestServer::AddCommandLineArguments( CommandLine* command_line) const { - if (!LocalTestServer::AddCommandLineArguments(command_line)) - return false; + LocalTestServer::AddCommandLineArguments(command_line); if (xmpp_port_ != 0) { std::string xmpp_port_str = base::IntToString(xmpp_port_); command_line->AppendArg("--xmpp-port=" + xmpp_port_str); diff --git a/net/test/local_test_server.cc b/net/test/local_test_server.cc index 53879df..17137a69 100644 --- a/net/test/local_test_server.cc +++ b/net/test/local_test_server.cc @@ -94,19 +94,13 @@ bool LocalTestServer::GetTestServerDirectory(FilePath* directory) { return true; } -bool LocalTestServer::GetTestServerPath(FilePath* testserver_path) const { - if (!GetTestServerDirectory(testserver_path)) - return false; - *testserver_path = testserver_path->Append(FILE_PATH_LITERAL( - "testserver.py")); - return true; -} - bool LocalTestServer::Start() { // Get path to Python server script. FilePath testserver_path; - if (!GetTestServerPath(&testserver_path)) + if (!GetTestServerDirectory(&testserver_path)) return false; + testserver_path = + testserver_path.Append(FILE_PATH_LITERAL("testserver.py")); if (!SetPythonPath()) return false; @@ -165,12 +159,8 @@ bool LocalTestServer::Init(const FilePath& document_root) { return true; } -bool LocalTestServer::SetPythonPath() const { - return SetPythonPathStatic(); -} - // static -bool LocalTestServer::SetPythonPathStatic() { +bool LocalTestServer::SetPythonPath() { FilePath third_party_dir; if (!PathService::Get(base::DIR_SOURCE_ROOT, &third_party_dir)) { LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT"; diff --git a/net/test/local_test_server.h b/net/test/local_test_server.h index 3c6bdde..d8d070e 100644 --- a/net/test/local_test_server.h +++ b/net/test/local_test_server.h @@ -43,26 +43,15 @@ class LocalTestServer : public BaseTestServer { bool Stop(); // Modify PYTHONPATH to contain libraries we need. - virtual bool SetPythonPath() const WARN_UNUSED_RESULT; - - // This is a static version so that RunSyncTest in run_testserver.cc can use - // it. - // TODO(mattm): We should refactor so this isn't necessary (crbug.com/159731). - static bool SetPythonPathStatic() WARN_UNUSED_RESULT; + static bool SetPythonPath() WARN_UNUSED_RESULT; // Returns true if successfully stored the FilePath for the directory of the // testserver python script in |*directory|. static bool GetTestServerDirectory(FilePath* directory) WARN_UNUSED_RESULT; - // Returns true if successfully stored the FilePath for the testserver python - // script in |*testserver_path|. - virtual bool GetTestServerPath(FilePath* testserver_path) const - WARN_UNUSED_RESULT; - // Adds the command line arguments for the Python test server to // |command_line|. Returns true on success. - virtual bool AddCommandLineArguments(CommandLine* command_line) const - WARN_UNUSED_RESULT; + virtual bool AddCommandLineArguments(CommandLine* command_line) const; // Returns the actual path of document root for test cases. This function // should be called by test cases to retrieve the actual document root path. diff --git a/net/tools/testserver/run_testserver.cc b/net/tools/testserver/run_testserver.cc index 2341512..58abe34 100644 --- a/net/tools/testserver/run_testserver.cc +++ b/net/tools/testserver/run_testserver.cc @@ -28,7 +28,7 @@ static void PrintUsage() { // Launches the chromiumsync_test script, testing the --sync functionality. static bool RunSyncTest() { - if (!net::TestServer::SetPythonPathStatic()) { + if (!net::TestServer::SetPythonPath()) { LOG(ERROR) << "Error trying to set python path. Exiting."; return false; } diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py index ba74b691..31fd3c5 100755 --- a/net/tools/testserver/testserver.py +++ b/net/tools/testserver/testserver.py @@ -23,27 +23,30 @@ import httplib import json import logging import minica +import optparse import os import random import re import select import socket import SocketServer +import struct import sys import threading import time import urllib import urlparse +import warnings import zlib import echo_message from mod_pywebsocket.standalone import WebSocketServer import pyftpdlib.ftpserver -import testserver_base import tlslite import tlslite.api -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +if sys.platform == 'win32': + import msvcrt SERVER_HTTP = 0 SERVER_FTP = 1 @@ -56,14 +59,12 @@ SERVER_WEBSOCKET = 6 # Default request queue size for WebSocketServer. _DEFAULT_REQUEST_QUEUE_SIZE = 128 - # Using debug() seems to cause hangs on XP: see http://crbug.com/64515 . debug_output = sys.stderr def debug(string): debug_output.write(string + "\n") debug_output.flush() - class WebSocketOptions: """Holds options for WebSocketServer.""" @@ -87,7 +88,6 @@ class WebSocketOptions: self.tls_client_ca = None self.use_basic_auth = False - class RecordingSSLSessionCache(object): """RecordingSSLSessionCache acts as a TLS session cache and maintains a log of lookups and inserts in order to test session cache behaviours.""" @@ -142,7 +142,6 @@ class OCSPServer(ClientRestrictingServerMixIn, BaseHTTPServer.HTTPServer): self.shutdown() self.thread.join() - class HTTPSServer(tlslite.api.TLSSocketServerMixIn, ClientRestrictingServerMixIn, StoppableHTTPServer): @@ -1982,6 +1981,23 @@ class SyncPageHandler(BasePageHandler): return True +def MakeDataDir(options): + 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 + class OCSPHandler(BasePageHandler): def __init__(self, request, client_address, socket_server): handlers = [self.OCSPResponse] @@ -1997,7 +2013,6 @@ class OCSPHandler(BasePageHandler): self.wfile.write(self.ocsp_response) - class TCPEchoHandler(SocketServer.BaseRequestHandler): """The RequestHandler class for TCP echo server. @@ -2153,288 +2168,319 @@ class BasicAuthProxyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): self._do_common_method() -class ServerRunner(testserver_base.TestServerRunner): - """TestServerRunner for the net test servers.""" +class FileMultiplexer: + def __init__(self, fd1, fd2) : + self.__fd1 = fd1 + self.__fd2 = fd2 - def __init__(self): - super(ServerRunner, self).__init__() - self.__ocsp_server = None - - def __make_data_dir(self): - if self.options.data_dir: - if not os.path.isdir(self.options.data_dir): - raise testserver_base.OptionError('specified data dir not found: ' + - self.options.data_dir + ' exiting...') - my_data_dir = self.options.data_dir - else: - # Create the default path to our data dir, relative to the exe dir. - my_data_dir = os.path.join(BASE_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 create_server(self, server_data): - port = self.options.port - host = self.options.host - - if self.options.server_type == SERVER_HTTP: - if self.options.https: - pem_cert_and_key = None - if self.options.cert_and_key_file: - if not os.path.isfile(self.options.cert_and_key_file): - raise testserver_base.OptionError( - 'specified server cert file not found: ' + - self.options.cert_and_key_file + ' exiting...') - pem_cert_and_key = file(self.options.cert_and_key_file, 'r').read() - else: - # generate a new certificate and run an OCSP server for it. - self.__ocsp_server = OCSPServer((host, 0), OCSPHandler) - print ('OCSP server started on %s:%d...' % - (host, self.__ocsp_server.server_port)) - - ocsp_der = None - ocsp_state = None - - if self.options.ocsp == 'ok': - ocsp_state = minica.OCSP_STATE_GOOD - elif self.options.ocsp == 'revoked': - ocsp_state = minica.OCSP_STATE_REVOKED - elif self.options.ocsp == 'invalid': - ocsp_state = minica.OCSP_STATE_INVALID - elif self.options.ocsp == 'unauthorized': - ocsp_state = minica.OCSP_STATE_UNAUTHORIZED - elif self.options.ocsp == 'unknown': - ocsp_state = minica.OCSP_STATE_UNKNOWN - else: - raise testserver_base.OptionError('unknown OCSP status: ' + - self.options.ocsp_status) - - (pem_cert_and_key, ocsp_der) = minica.GenerateCertKeyAndOCSP( - subject = "127.0.0.1", - ocsp_url = ("http://%s:%d/ocsp" % - (host, self.__ocsp_server.server_port)), - ocsp_state = ocsp_state) - - self.__ocsp_server.ocsp_response = ocsp_der - - for ca_cert in self.options.ssl_client_ca: - if not os.path.isfile(ca_cert): - raise testserver_base.OptionError( - 'specified trusted client CA file not found: ' + ca_cert + - ' exiting...') - server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key, - self.options.ssl_client_auth, - self.options.ssl_client_ca, - self.options.ssl_bulk_cipher, - self.options.record_resume, - self.options.tls_intolerant) - print 'HTTPS server started on %s:%d...' % (host, server.server_port) + def __del__(self) : + self.close() + + def write(self, text) : + self.__fd1.write(text) + self.__fd2.write(text) + + def flush(self) : + self.__fd1.flush() + self.__fd2.flush() + + def close(self): + if self.__fd1 != sys.stdout and self.__fd1 != sys.stderr: + self.__fd1.close() + if self.__fd2 != sys.stdout and self.__fd2 != sys.stderr: + self.__fd2.close() + + +def main(options, _args): + logfile = open('testserver.log', 'w') + sys.stderr = FileMultiplexer(sys.stderr, logfile) + if options.log_to_console: + sys.stdout = FileMultiplexer(sys.stdout, logfile) + else: + sys.stdout = logfile + + port = options.port + host = options.host + + server_data = {} + server_data['host'] = host + + ocsp_server = None + + if options.server_type == SERVER_HTTP: + if options.https: + pem_cert_and_key = None + if options.cert_and_key_file: + if not os.path.isfile(options.cert_and_key_file): + print ('specified server cert file not found: ' + + options.cert_and_key_file + ' exiting...') + return 1 + pem_cert_and_key = file(options.cert_and_key_file, 'r').read() else: - server = HTTPServer((host, port), TestPageHandler) - print 'HTTP server started on %s:%d...' % (host, server.server_port) - - server.data_dir = self.__make_data_dir() - server.file_root_url = self.options.file_root_url - server_data['port'] = server.server_port - server._device_management_handler = None - server.policy_keys = self.options.policy_keys - server.policy_user = self.options.policy_user - server.gdata_auth_token = self.options.auth_token - elif self.options.server_type == SERVER_WEBSOCKET: - # Launch pywebsocket via WebSocketServer. - logger = logging.getLogger() - logger.addHandler(logging.StreamHandler()) - # TODO(toyoshim): Remove following os.chdir. Currently this operation - # is required to work correctly. It should be fixed from pywebsocket side. - os.chdir(self.__make_data_dir()) - websocket_options = WebSocketOptions(host, port, '.') - if self.options.cert_and_key_file: - websocket_options.use_tls = True - websocket_options.private_key = self.options.cert_and_key_file - websocket_options.certificate = self.options.cert_and_key_file - if self.options.ssl_client_auth: - websocket_options.tls_client_auth = True - if len(self.options.ssl_client_ca) != 1: - raise testserver_base.OptionError( - 'one trusted client CA file should be specified') - if not os.path.isfile(self.options.ssl_client_ca[0]): - raise testserver_base.OptionError( - 'specified trusted client CA file not found: ' + - self.options.ssl_client_ca[0] + ' exiting...') - websocket_options.tls_client_ca = self.options.ssl_client_ca[0] - server = WebSocketServer(websocket_options) - print 'WebSocket server started on %s:%d...' % (host, server.server_port) - server_data['port'] = server.server_port - elif self.options.server_type == SERVER_SYNC: - xmpp_port = self.options.xmpp_port - server = SyncHTTPServer((host, port), xmpp_port, SyncPageHandler) - print 'Sync HTTP server started on port %d...' % server.server_port - print 'Sync XMPP server started on port %d...' % server.xmpp_port - server_data['port'] = server.server_port - server_data['xmpp_port'] = server.xmpp_port - elif self.options.server_type == SERVER_TCP_ECHO: - # Used for generating the key (randomly) that encodes the "echo request" - # message. - random.seed() - server = TCPEchoServer((host, port), TCPEchoHandler) - print 'Echo TCP server started on port %d...' % server.server_port - server_data['port'] = server.server_port - elif self.options.server_type == SERVER_UDP_ECHO: - # Used for generating the key (randomly) that encodes the "echo request" - # message. - random.seed() - server = UDPEchoServer((host, port), UDPEchoHandler) - print 'Echo UDP server started on port %d...' % server.server_port - server_data['port'] = server.server_port - elif self.options.server_type == SERVER_BASIC_AUTH_PROXY: - server = HTTPServer((host, port), BasicAuthProxyRequestHandler) - print 'BasicAuthProxy server started on port %d...' % server.server_port - server_data['port'] = server.server_port - elif self.options.server_type == SERVER_FTP: - my_data_dir = self.__make_data_dir() - - # 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 - - # 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 address:port - server = pyftpdlib.ftpserver.FTPServer((host, port), ftp_handler) - server_data['port'] = server.socket.getsockname()[1] - print 'FTP server started on port %d...' % server_data['port'] + # generate a new certificate and run an OCSP server for it. + ocsp_server = OCSPServer((host, 0), OCSPHandler) + print ('OCSP server started on %s:%d...' % + (host, ocsp_server.server_port)) + + ocsp_der = None + ocsp_state = None + + if options.ocsp == 'ok': + ocsp_state = minica.OCSP_STATE_GOOD + elif options.ocsp == 'revoked': + ocsp_state = minica.OCSP_STATE_REVOKED + elif options.ocsp == 'invalid': + ocsp_state = minica.OCSP_STATE_INVALID + elif options.ocsp == 'unauthorized': + ocsp_state = minica.OCSP_STATE_UNAUTHORIZED + elif options.ocsp == 'unknown': + ocsp_state = minica.OCSP_STATE_UNKNOWN + else: + print 'unknown OCSP status: ' + options.ocsp_status + return 1 + + (pem_cert_and_key, ocsp_der) = minica.GenerateCertKeyAndOCSP( + subject = "127.0.0.1", + ocsp_url = ("http://%s:%d/ocsp" % (host, ocsp_server.server_port)), + ocsp_state = ocsp_state) + + ocsp_server.ocsp_response = ocsp_der + + for ca_cert in options.ssl_client_ca: + if not os.path.isfile(ca_cert): + print ('specified trusted client CA file not found: ' + ca_cert + + ' exiting...') + return 1 + server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key, + options.ssl_client_auth, options.ssl_client_ca, + options.ssl_bulk_cipher, options.record_resume, + options.tls_intolerant) + print 'HTTPS server started on %s:%d...' % (host, server.server_port) else: - raise testserver_base.OptionError('unknown server type' + - self.options.server_type) - - return server - - def run_server(self): - if self.__ocsp_server: - self.__ocsp_server.serve_forever_on_thread() - - testserver_base.TestServerRunner.run_server(self) - - if self.__ocsp_server: - self.__ocsp_server.stop_serving() - - def add_options(self): - testserver_base.TestServerRunner.add_options(self) - self.option_parser.add_option('-f', '--ftp', action='store_const', - const=SERVER_FTP, default=SERVER_HTTP, - dest='server_type', - help='start up an FTP server.') - self.option_parser.add_option('--sync', action='store_const', - const=SERVER_SYNC, default=SERVER_HTTP, - dest='server_type', - help='start up a sync server.') - self.option_parser.add_option('--tcp-echo', action='store_const', - const=SERVER_TCP_ECHO, default=SERVER_HTTP, - dest='server_type', - help='start up a tcp echo server.') - self.option_parser.add_option('--udp-echo', action='store_const', - const=SERVER_UDP_ECHO, default=SERVER_HTTP, - dest='server_type', - help='start up a udp echo server.') - self.option_parser.add_option('--basic-auth-proxy', action='store_const', - const=SERVER_BASIC_AUTH_PROXY, - default=SERVER_HTTP, dest='server_type', - help='start up a proxy server which requires ' - 'basic authentication.') - self.option_parser.add_option('--websocket', action='store_const', - const=SERVER_WEBSOCKET, default=SERVER_HTTP, - dest='server_type', - help='start up a WebSocket server.') - self.option_parser.add_option('--xmpp-port', default='0', type='int', - help='Port used by the XMPP server. If ' - 'unspecified, the XMPP server will listen on ' - 'an ephemeral port.') - self.option_parser.add_option('--data-dir', dest='data_dir', - help='Directory from which to read the ' - 'files.') - self.option_parser.add_option('--https', action='store_true', - dest='https', help='Specify that https ' - 'should be used.') - self.option_parser.add_option('--cert-and-key-file', - dest='cert_and_key_file', help='specify the ' - 'path to the file containing the certificate ' - 'and private key for the server in PEM ' - 'format') - self.option_parser.add_option('--ocsp', dest='ocsp', default='ok', - help='The type of OCSP response generated ' - 'for the automatically generated ' - 'certificate. One of [ok,revoked,invalid]') - self.option_parser.add_option('--tls-intolerant', dest='tls_intolerant', - default='0', type='int', - help='If nonzero, certain TLS connections ' - 'will be aborted in order to test version ' - 'fallback. 1 means all TLS versions will be ' - 'aborted. 2 means TLS 1.1 or higher will be ' - 'aborted. 3 means TLS 1.2 or higher will be ' - 'aborted.') - self.option_parser.add_option('--https-record-resume', - dest='record_resume', const=True, - default=False, action='store_const', - help='Record resumption cache events rather ' - 'than resuming as normal. Allows the use of ' - 'the /ssl-session-cache request') - self.option_parser.add_option('--ssl-client-auth', action='store_true', - help='Require SSL client auth on every ' - 'connection.') - self.option_parser.add_option('--ssl-client-ca', action='append', - default=[], help='Specify that the client ' - 'certificate request should include the CA ' - 'named in the subject of the DER-encoded ' - 'certificate contained in the specified ' - 'file. This option may appear multiple ' - 'times, indicating multiple CA names should ' - 'be sent in the request.') - self.option_parser.add_option('--ssl-bulk-cipher', action='append', - help='Specify the bulk encryption ' - 'algorithm(s) that will be accepted by the ' - 'SSL server. Valid values are "aes256", ' - '"aes128", "3des", "rc4". If omitted, all ' - 'algorithms will be used. This option may ' - 'appear multiple times, indicating ' - 'multiple algorithms should be enabled.'); - self.option_parser.add_option('--file-root-url', default='/files/', - help='Specify a root URL for files served.') - self.option_parser.add_option('--policy-key', action='append', - dest='policy_keys', - help='Specify a path to a PEM-encoded ' - 'private key to use for policy signing. May ' - 'be specified multiple times in order to ' - 'load multipe keys into the server. If the ' - 'server has multiple keys, it will rotate ' - 'through them in at each request a ' - 'round-robin fashion. The server will ' - 'generate a random key if none is specified ' - 'on the command line.') - self.option_parser.add_option('--policy-user', - default='user@example.com', - dest='policy_user', - help='Specify the user name the server ' - 'should report back to the client as the ' - 'user owning the token used for making the ' - 'policy request.') - self.option_parser.add_option('--auth-token', dest='auth_token', - help='Specify the auth token which should be ' - 'used in the authorization header for GData.') - + server = HTTPServer((host, port), TestPageHandler) + print 'HTTP server started on %s:%d...' % (host, server.server_port) + + server.data_dir = MakeDataDir(options) + server.file_root_url = options.file_root_url + server_data['port'] = server.server_port + server._device_management_handler = None + server.policy_keys = options.policy_keys + server.policy_user = options.policy_user + server.gdata_auth_token = options.auth_token + elif options.server_type == SERVER_WEBSOCKET: + # Launch pywebsocket via WebSocketServer. + logger = logging.getLogger() + logger.addHandler(logging.StreamHandler()) + # TODO(toyoshim): Remove following os.chdir. Currently this operation + # is required to work correctly. It should be fixed from pywebsocket side. + os.chdir(MakeDataDir(options)) + websocket_options = WebSocketOptions(host, port, '.') + if options.cert_and_key_file: + websocket_options.use_tls = True + websocket_options.private_key = options.cert_and_key_file + websocket_options.certificate = options.cert_and_key_file + if options.ssl_client_auth: + websocket_options.tls_client_auth = True + if len(options.ssl_client_ca) != 1: + print 'one trusted client CA file should be specified' + return 1 + if not os.path.isfile(options.ssl_client_ca[0]): + print ('specified trusted client CA file not found: ' + + options.ssl_client_ca[0] + ' exiting...') + return 1 + websocket_options.tls_client_ca = options.ssl_client_ca[0] + server = WebSocketServer(websocket_options) + print 'WebSocket server started on %s:%d...' % (host, server.server_port) + server_data['port'] = server.server_port + elif options.server_type == SERVER_SYNC: + xmpp_port = options.xmpp_port + server = SyncHTTPServer((host, port), xmpp_port, SyncPageHandler) + print 'Sync HTTP server started on port %d...' % server.server_port + print 'Sync XMPP server started on port %d...' % server.xmpp_port + server_data['port'] = server.server_port + server_data['xmpp_port'] = server.xmpp_port + elif options.server_type == SERVER_TCP_ECHO: + # Used for generating the key (randomly) that encodes the "echo request" + # message. + random.seed() + server = TCPEchoServer((host, port), TCPEchoHandler) + print 'Echo TCP server started on port %d...' % server.server_port + server_data['port'] = server.server_port + elif options.server_type == SERVER_UDP_ECHO: + # Used for generating the key (randomly) that encodes the "echo request" + # message. + random.seed() + server = UDPEchoServer((host, port), UDPEchoHandler) + print 'Echo UDP server started on port %d...' % server.server_port + server_data['port'] = server.server_port + elif options.server_type == SERVER_BASIC_AUTH_PROXY: + server = HTTPServer((host, port), BasicAuthProxyRequestHandler) + print 'BasicAuthProxy server started on port %d...' % server.server_port + server_data['port'] = server.server_port + # means FTP Server + else: + my_data_dir = MakeDataDir(options) + + # 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 + + # 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 address:port + server = pyftpdlib.ftpserver.FTPServer((host, port), ftp_handler) + server_data['port'] = server.socket.getsockname()[1] + print 'FTP server started on port %d...' % server_data['port'] + + # Notify the parent that we've started. (BaseServer subclasses + # bind their sockets on construction.) + if options.startup_pipe is not None: + server_data_json = json.dumps(server_data) + server_data_len = len(server_data_json) + print 'sending server_data: %s (%d bytes)' % ( + server_data_json, server_data_len) + if sys.platform == 'win32': + fd = msvcrt.open_osfhandle(options.startup_pipe, 0) + else: + fd = options.startup_pipe + startup_pipe = os.fdopen(fd, "w") + # First write the data length as an unsigned 4-byte value. This + # is _not_ using network byte ordering since the other end of the + # pipe is on the same machine. + startup_pipe.write(struct.pack('=L', server_data_len)) + startup_pipe.write(server_data_json) + startup_pipe.close() + + if ocsp_server is not None: + ocsp_server.serve_forever_on_thread() + + try: + server.serve_forever() + except KeyboardInterrupt: + print 'shutting down server' + if ocsp_server is not None: + ocsp_server.stop_serving() + server.stop = True + + return 0 if __name__ == '__main__': - sys.exit(ServerRunner().main()) + option_parser = optparse.OptionParser() + option_parser.add_option("-f", '--ftp', action='store_const', + const=SERVER_FTP, default=SERVER_HTTP, + dest='server_type', + help='start up an FTP server.') + option_parser.add_option('', '--sync', action='store_const', + const=SERVER_SYNC, default=SERVER_HTTP, + dest='server_type', + help='start up a sync server.') + option_parser.add_option('', '--tcp-echo', action='store_const', + const=SERVER_TCP_ECHO, default=SERVER_HTTP, + dest='server_type', + help='start up a tcp echo server.') + option_parser.add_option('', '--udp-echo', action='store_const', + const=SERVER_UDP_ECHO, default=SERVER_HTTP, + dest='server_type', + help='start up a udp echo server.') + option_parser.add_option('', '--basic-auth-proxy', action='store_const', + const=SERVER_BASIC_AUTH_PROXY, default=SERVER_HTTP, + dest='server_type', + help='start up a proxy server which requires basic ' + 'authentication.') + option_parser.add_option('', '--websocket', action='store_const', + const=SERVER_WEBSOCKET, default=SERVER_HTTP, + dest='server_type', + help='start up a WebSocket server.') + option_parser.add_option('', '--log-to-console', action='store_const', + const=True, default=False, + dest='log_to_console', + help='Enables or disables sys.stdout logging to ' + 'the console.') + option_parser.add_option('', '--port', default='0', type='int', + help='Port used by the server. If unspecified, the ' + 'server will listen on an ephemeral port.') + option_parser.add_option('', '--xmpp-port', default='0', type='int', + help='Port used by the XMPP server. If unspecified, ' + 'the XMPP server will listen on an ephemeral port.') + option_parser.add_option('', '--data-dir', dest='data_dir', + help='Directory from which to read the files.') + option_parser.add_option('', '--https', action='store_true', dest='https', + help='Specify that https should be used.') + option_parser.add_option('', '--cert-and-key-file', dest='cert_and_key_file', + help='specify the path to the file containing the ' + 'certificate and private key for the server in PEM ' + 'format') + option_parser.add_option('', '--ocsp', dest='ocsp', default='ok', + help='The type of OCSP response generated for the ' + 'automatically generated certificate. One of ' + '[ok,revoked,invalid]') + option_parser.add_option('', '--tls-intolerant', dest='tls_intolerant', + default='0', type='int', + help='If nonzero, certain TLS connections will be' + ' aborted in order to test version fallback. 1' + ' means all TLS versions will be aborted. 2 means' + ' TLS 1.1 or higher will be aborted. 3 means TLS' + ' 1.2 or higher will be aborted.') + option_parser.add_option('', '--https-record-resume', dest='record_resume', + const=True, default=False, action='store_const', + help='Record resumption cache events rather than' + ' resuming as normal. Allows the use of the' + ' /ssl-session-cache request') + option_parser.add_option('', '--ssl-client-auth', action='store_true', + help='Require SSL client auth on every connection.') + option_parser.add_option('', '--ssl-client-ca', action='append', default=[], + help='Specify that the client certificate request ' + 'should include the CA named in the subject of ' + 'the DER-encoded certificate contained in the ' + 'specified file. This option may appear multiple ' + 'times, indicating multiple CA names should be ' + 'sent in the request.') + option_parser.add_option('', '--ssl-bulk-cipher', action='append', + help='Specify the bulk encryption algorithm(s)' + 'that will be accepted by the SSL server. Valid ' + 'values are "aes256", "aes128", "3des", "rc4". If ' + 'omitted, all algorithms will be used. This ' + 'option may appear multiple times, indicating ' + 'multiple algorithms should be enabled.') + option_parser.add_option('', '--file-root-url', default='/files/', + help='Specify a root URL for files served.') + option_parser.add_option('', '--startup-pipe', type='int', + dest='startup_pipe', + help='File handle of pipe to parent process') + option_parser.add_option('', '--policy-key', action='append', + dest='policy_keys', + help='Specify a path to a PEM-encoded private key ' + 'to use for policy signing. May be specified ' + 'multiple times in order to load multipe keys into ' + 'the server. If ther server has multiple keys, it ' + 'will rotate through them in at each request a ' + 'round-robin fashion. The server will generate a ' + 'random key if none is specified on the command ' + 'line.') + option_parser.add_option('', '--policy-user', default='user@example.com', + dest='policy_user', + help='Specify the user name the server should ' + 'report back to the client as the user owning the ' + 'token used for making the policy request.') + option_parser.add_option('', '--host', default='127.0.0.1', + dest='host', + help='Hostname or IP upon which the server will ' + 'listen. Client connections will also only be ' + 'allowed from this address.') + option_parser.add_option('', '--auth-token', dest='auth_token', + help='Specify the auth token which should be used' + 'in the authorization header for GData.') + main_options, main_args = option_parser.parse_args() + + sys.exit(main(main_options, main_args)) diff --git a/net/tools/testserver/testserver_base.py b/net/tools/testserver/testserver_base.py deleted file mode 100644 index 076943e..0000000 --- a/net/tools/testserver/testserver_base.py +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import json -import optparse -import os -import struct -import sys -import warnings - -# Ignore deprecation warnings, they make our output more cluttered. -warnings.filterwarnings("ignore", category=DeprecationWarning) - -if sys.platform == 'win32': - import msvcrt - - -class Error(Exception): - """Error class for this module.""" - - -class OptionError(Error): - """Error for bad command line options.""" - - -class FileMultiplexer(object): - def __init__(self, fd1, fd2) : - self.__fd1 = fd1 - self.__fd2 = fd2 - - def __del__(self) : - if self.__fd1 != sys.stdout and self.__fd1 != sys.stderr: - self.__fd1.close() - if self.__fd2 != sys.stdout and self.__fd2 != sys.stderr: - self.__fd2.close() - - def write(self, text) : - self.__fd1.write(text) - self.__fd2.write(text) - - def flush(self) : - self.__fd1.flush() - self.__fd2.flush() - - -class TestServerRunner(object): - """Runs a test server and communicates with the controlling C++ test code. - - Subclasses should override the create_server method to create their server - object, and the add_options method to add their own options. - """ - - def __init__(self): - self.option_parser = optparse.OptionParser() - self.add_options() - - def main(self): - self.options, self.args = self.option_parser.parse_args() - - logfile = open('testserver.log', 'w') - sys.stderr = FileMultiplexer(sys.stderr, logfile) - if self.options.log_to_console: - sys.stdout = FileMultiplexer(sys.stdout, logfile) - else: - sys.stdout = logfile - - server_data = { - 'host': self.options.host, - } - self.server = self.create_server(server_data) - self._notify_startup_complete(server_data) - self.run_server() - - def create_server(self, server_data): - """Creates a server object and returns it. - - Must populate server_data['port'], and can set additional server_data - elements if desired.""" - raise NotImplementedError() - - def run_server(self): - try: - self.server.serve_forever() - except KeyboardInterrupt: - print 'shutting down server' - self.server.stop = True - - def add_options(self): - self.option_parser.add_option('--startup-pipe', type='int', - dest='startup_pipe', - help='File handle of pipe to parent process') - self.option_parser.add_option('--log-to-console', action='store_const', - const=True, default=False, - dest='log_to_console', - help='Enables or disables sys.stdout logging ' - 'to the console.') - self.option_parser.add_option('--port', default=0, type='int', - help='Port used by the server. If ' - 'unspecified, the server will listen on an ' - 'ephemeral port.') - self.option_parser.add_option('--host', default='127.0.0.1', - dest='host', - help='Hostname or IP upon which the server ' - 'will listen. Client connections will also ' - 'only be allowed from this address.') - - def _notify_startup_complete(self, server_data): - # Notify the parent that we've started. (BaseServer subclasses - # bind their sockets on construction.) - if self.options.startup_pipe is not None: - server_data_json = json.dumps(server_data) - server_data_len = len(server_data_json) - print 'sending server_data: %s (%d bytes)' % ( - server_data_json, server_data_len) - if sys.platform == 'win32': - fd = msvcrt.open_osfhandle(self.options.startup_pipe, 0) - else: - fd = self.options.startup_pipe - startup_pipe = os.fdopen(fd, "w") - # First write the data length as an unsigned 4-byte value. This - # is _not_ using network byte ordering since the other end of the - # pipe is on the same machine. - startup_pipe.write(struct.pack('=L', server_data_len)) - startup_pipe.write(server_data_json) - startup_pipe.close() |