summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-04 16:48:26 +0000
committerkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-04 16:48:26 +0000
commit9650ea1b907196736da51be053992c50152d0882 (patch)
tree953602199162d3ac9120c816e888a820c839dc83
parent39be34adcfe428dd7a0ad132b23796d9be24a7fd (diff)
downloadchromium_src-9650ea1b907196736da51be053992c50152d0882.zip
chromium_src-9650ea1b907196736da51be053992c50152d0882.tar.gz
chromium_src-9650ea1b907196736da51be053992c50152d0882.tar.bz2
Add method for shutting down ChromeDriver gracefully.
Merge webdriver_tests into chromedriver_tests. BUG=none TEST=none Review URL: http://codereview.chromium.org/6368068 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73809 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/test/webdriver/chromedriver_launcher.py146
-rwxr-xr-xchrome/test/webdriver/chromedriver_tests.py163
-rw-r--r--chrome/test/webdriver/server.cc84
-rw-r--r--chrome/test/webdriver/webdriver_tests.py241
-rw-r--r--third_party/mongoose/README.chromium3
-rw-r--r--third_party/mongoose/mongoose.c7
6 files changed, 344 insertions, 300 deletions
diff --git a/chrome/test/webdriver/chromedriver_launcher.py b/chrome/test/webdriver/chromedriver_launcher.py
index 1777525..fb6d35b 100644
--- a/chrome/test/webdriver/chromedriver_launcher.py
+++ b/chrome/test/webdriver/chromedriver_launcher.py
@@ -12,15 +12,11 @@ For ChromeDriver documentation, refer to:
import logging
import os
import platform
+import signal
import subprocess
import sys
-
-if sys.version_info < (2,6):
- # Subprocess.Popen.kill is not available prior to 2.6.
- if platform.system() == 'Windows':
- import win32api
- else:
- import signal
+import threading
+import urllib2
class ChromeDriverLauncher:
@@ -39,35 +35,31 @@ class ChromeDriverLauncher:
self._port = port
if self._exe_path is None:
self._exe_path = ChromeDriverLauncher.LocateExe()
+ if self._exe_path is None:
+ raise RuntimeError('ChromeDriver exe could not be found in its default '
+ 'location. Searched in following directories: ' +
+ ', '.join(self.DefaultExeLocations()))
if self._root_path is None:
self._root_path = '.'
- if self._port is None:
- self._port = 9515
self._root_path = os.path.abspath(self._root_path)
self._process = None
if not os.path.exists(self._exe_path):
raise RuntimeError('ChromeDriver exe not found at: ' + self._exe_path)
+
+ os.environ['PATH'] = os.path.dirname(self._exe_path) + os.environ['PATH']
self.Start()
@staticmethod
- def LocateExe():
- """Attempts to locate the ChromeDriver executable.
-
- This searches the current directory, then checks the appropriate build
- locations according to platform.
+ def DefaultExeLocations():
+ """Returns the paths that are used to find the ChromeDriver executable.
Returns:
- absolute path to the ChromeDriver executable, or None if not found
+ a list of directories that would be searched for the executable
"""
- exe_name = 'chromedriver'
- if platform.system() == 'Windows':
- exe_name += '.exe'
- if os.path.exists(exe_name):
- return os.path.abspath(exe_name)
-
script_dir = os.path.dirname(__file__)
- chrome_src = os.path.join(script_dir, os.pardir, os.pardir, os.pardir)
+ chrome_src = os.path.abspath(os.path.join(
+ script_dir, os.pardir, os.pardir, os.pardir))
bin_dirs = {
'linux2': [ os.path.join(chrome_src, 'out', 'Debug'),
os.path.join(chrome_src, 'sconsbuild', 'Debug'),
@@ -80,7 +72,23 @@ class ChromeDriverLauncher:
os.path.join(chrome_src, 'chrome', 'Release'),
os.path.join(chrome_src, 'build', 'Release')],
}
- for dir in bin_dirs.get(sys.platform, []):
+ return [os.getcwd()] + bin_dirs.get(sys.platform, [])
+
+ @staticmethod
+ def LocateExe():
+ """Attempts to locate the ChromeDriver executable.
+
+ This searches the current directory, then checks the appropriate build
+ locations according to platform.
+
+ Returns:
+ absolute path to the ChromeDriver executable, or None if not found
+ """
+ exe_name = 'chromedriver'
+ if platform.system() == 'Windows':
+ exe_name += '.exe'
+
+ for dir in ChromeDriverLauncher.DefaultExeLocations():
path = os.path.join(dir, exe_name)
if os.path.exists(path):
return os.path.abspath(path)
@@ -90,38 +98,96 @@ class ChromeDriverLauncher:
"""Starts a new ChromeDriver process.
Kills a previous one if it is still running.
+
+ Raises:
+ RuntimeError if ChromeDriver does not start
"""
+ def _WaitForLaunchResult(stdout, started_event, launch_result):
+ """Reads from the stdout of ChromeDriver and parses the launch result.
+
+ Args:
+ stdout: handle to ChromeDriver's standard output
+ started_event: condition variable to notify when the launch result
+ has been parsed
+ launch_result: dictionary to add the result of this launch to
+ """
+ status_line = stdout.readline()
+ started_event.acquire()
+ try:
+ launch_result['success'] = status_line.startswith('Started')
+ launch_result['status_line'] = status_line
+ if launch_result['success']:
+ port_line = stdout.readline()
+ launch_result['port'] = int(port_line.split('=')[1])
+ started_event.notify()
+ finally:
+ started_event.release()
+
if self._process is not None:
self.Kill()
- proc = subprocess.Popen([self._exe_path,
- '--port=%d' % self._port,
- '--root="%s"' % self._root_path])
+
+ chromedriver_args = [self._exe_path, '--root=%s' % self._root_path]
+ if self._port is not None:
+ chromedriver_args += ['--port=%d' % self._port]
+ proc = subprocess.Popen(chromedriver_args,
+ stdout=subprocess.PIPE)
if proc is None:
raise RuntimeError('ChromeDriver cannot be started')
- logging.info('Started chromedriver at port %s' % self._port)
self._process = proc
+ # Wait for ChromeDriver to be initialized before returning.
+ launch_result = {}
+ started_event = threading.Condition()
+ started_event.acquire()
+ spawn_thread = threading.Thread(
+ target=_WaitForLaunchResult,
+ args=(proc.stdout, started_event, launch_result))
+ spawn_thread.start()
+ started_event.wait(20)
+ timed_out = 'success' not in launch_result
+ started_event.release()
+ if timed_out:
+ raise RuntimeError('ChromeDriver did not respond')
+ elif not launch_result['success']:
+ raise RuntimeError('ChromeDriver failed to launch: ' +
+ launch_result['status_line'])
+ self._port = launch_result['port']
+ logging.info('ChromeDriver running on port %s' % self._port)
+
def Kill(self):
"""Kills a currently running ChromeDriver process, if it is running."""
+ def _WaitForShutdown(process, shutdown_event):
+ """Waits for the process to quit and then notifies."""
+ process.wait()
+ shutdown_event.acquire()
+ shutdown_event.notify()
+ shutdown_event.release()
+
if self._process is None:
return
- if sys.version_info < (2,6):
- # From http://stackoverflow.com/questions/1064335
+ try:
+ urllib2.urlopen(self.GetURL() + '/shutdown').close()
+ except urllib2.URLError:
+ # Could not shutdown. Kill.
+ pid = self._process.pid
if platform.system() == 'Windows':
- PROCESS_TERMINATE = 1
- handle = win32api.OpenProcess(PROCESS_TERMINATE, False,
- self._process.pid)
- win32api.TerminateProcess(handle, -1)
- win32api.CloseHandle(handle)
+ subprocess.call(['taskkill.exe', '/T', '/F', '/PID', str(pid)])
else:
- os.kill(self._process.pid, signal.SIGKILL)
- else:
- self._process.kill()
+ os.kill(pid, signal.SIGTERM)
+
+ # Wait for ChromeDriver process to exit before returning.
+ # Even if we had to kill the process above, we still should call wait
+ # to cleanup the zombie.
+ shutdown_event = threading.Condition()
+ shutdown_event.acquire()
+ wait_thread = threading.Thread(
+ target=_WaitForShutdown,
+ args=(self._process, shutdown_event))
+ wait_thread.start()
+ shutdown_event.wait(10)
+ shutdown_event.release()
self._process = None
- def __del__(self):
- self.Kill()
-
def GetURL(self):
return 'http://localhost:' + str(self._port)
diff --git a/chrome/test/webdriver/chromedriver_tests.py b/chrome/test/webdriver/chromedriver_tests.py
index 2e99b14..0dd0ecf 100755
--- a/chrome/test/webdriver/chromedriver_tests.py
+++ b/chrome/test/webdriver/chromedriver_tests.py
@@ -10,9 +10,13 @@ If your test is testing a specific part of the WebDriver API, consider adding
it to the appropriate place in the WebDriver tree instead.
"""
+import platform
import os
+import simplejson as json
import sys
import unittest
+import urllib2
+import urlparse
from chromedriver_launcher import ChromeDriverLauncher
import chromedriver_paths
@@ -23,14 +27,171 @@ sys.path += [chromedriver_paths.PYTHON_BINDINGS]
from selenium.webdriver.remote.webdriver import WebDriver
-class ChromeDriverTest(unittest.TestCase):
+class Request(urllib2.Request):
+ """Extends urllib2.Request to support all HTTP request types."""
+
+ def __init__(self, url, method=None, data=None):
+ """Initialise a new HTTP request.
+
+ Arguments:
+ url: The full URL to send the request to.
+ method: The HTTP request method to use; defaults to 'GET'.
+ data: The data to send with the request as a string. Defaults to
+ None and is ignored if |method| is not 'POST' or 'PUT'.
+ """
+ if method is None:
+ method = data is not None and 'POST' or 'GET'
+ elif method not in ('POST', 'PUT'):
+ data = None
+ self.method = method
+ urllib2.Request.__init__(self, url, data=data)
+
+ def get_method(self):
+ """Returns the HTTP method used by this request."""
+ return self.method
+
+
+def SendRequest(url, method=None, data=None):
+ """Sends a HTTP request to the WebDriver server.
+
+ Return values and exceptions raised are the same as those of
+ |urllib2.urlopen|.
+
+ Arguments:
+ url: The full URL to send the request to.
+ method: The HTTP request method to use; defaults to 'GET'.
+ data: The data to send with the request as a string. Defaults to
+ None and is ignored if |method| is not 'POST' or 'PUT'.
+
+ Returns:
+ A file-like object.
+ """
+ request = Request(url, method=method, data=data)
+ request.add_header('Accept', 'application/json')
+ opener = urllib2.build_opener(urllib2.HTTPRedirectHandler())
+ return opener.open(request)
+
+
+class BasicTest(unittest.TestCase):
+ """Basic ChromeDriver tests."""
+
def setUp(self):
self._launcher = ChromeDriverLauncher()
+ def tearDown(self):
+ self._launcher.Kill()
+
+ def testShouldReturn404WhenSentAnUnknownCommandURL(self):
+ request_url = self._launcher.GetURL() + '/foo'
+ try:
+ SendRequest(request_url, method='GET')
+ self.fail('Should have raised a urllib.HTTPError for returned 404')
+ except urllib2.HTTPError, expected:
+ self.assertEquals(404, expected.code)
+
+ def testShouldReturnHTTP405WhenSendingANonPostToTheSessionURL(self):
+ request_url = self._launcher.GetURL() + '/session'
+ try:
+ SendRequest(request_url, method='GET')
+ self.fail('Should have raised a urllib.HTTPError for returned 405')
+ except urllib2.HTTPError, expected:
+ self.assertEquals(405, expected.code)
+ self.assertEquals('POST', expected.hdrs['Allow'])
+
+ def testShouldGetA404WhenAttemptingToDeleteAnUnknownSession(self):
+ request_url = self._launcher.GetURL() + '/session/unkown_session_id'
+ try:
+ SendRequest(request_url, method='DELETE')
+ self.fail('Should have raised a urllib.HTTPError for returned 404')
+ except urllib2.HTTPError, expected:
+ self.assertEquals(404, expected.code)
+
+ def testCanStartChromeDriverOnSpecificPort(self):
+ launcher = ChromeDriverLauncher(port=9520)
+ self.assertEquals(9520, launcher.GetPort())
+ driver = WebDriver(launcher.GetURL(), 'chrome', 'any')
+ driver.quit()
+
+
+class SessionTest(unittest.TestCase):
+ """Tests dealing with WebDriver sessions."""
+
+ def setUp(self):
+ self._launcher = ChromeDriverLauncher()
+
+ def tearDown(self):
+ self._launcher.Kill()
+
+ def testCreatingSessionShouldRedirectToCorrectURL(self):
+ request_url = self._launcher.GetURL() + '/session'
+ response = SendRequest(request_url, method='POST', data='{}')
+ self.assertEquals(200, response.code)
+ self.session_url = response.geturl() # TODO(jleyba): verify this URL?
+
+ data = json.loads(response.read())
+ self.assertTrue(isinstance(data, dict))
+ self.assertEquals(0, data['status'])
+
+ url_parts = urlparse.urlparse(self.session_url)[2].split('/')
+ self.assertEquals(3, len(url_parts))
+ self.assertEquals('', url_parts[0])
+ self.assertEquals('session', url_parts[1])
+ self.assertEquals(data['sessionId'], url_parts[2])
+
+ def testShouldBeGivenCapabilitiesWhenStartingASession(self):
+ driver = WebDriver(self._launcher.GetURL(), 'chrome', 'any')
+ capabilities = driver.capabilities
+
+ self.assertEquals('chrome', capabilities['browserName'])
+ self.assertTrue(capabilities['javascriptEnabled'])
+
+ # Value depends on what version the server is starting.
+ self.assertTrue('version' in capabilities)
+ self.assertTrue(
+ isinstance(capabilities['version'], unicode),
+ 'Expected a %s, but was %s' % (unicode,
+ type(capabilities['version'])))
+
+ system = platform.system()
+ if system == 'Linux':
+ self.assertEquals('linux', capabilities['platform'].lower())
+ elif system == 'Windows':
+ self.assertEquals('windows', capabilities['platform'].lower())
+ elif system == 'Darwin':
+ self.assertEquals('mac', capabilities['platform'].lower())
+ else:
+ # No python on ChromeOS, so we won't have a platform value, but
+ # the server will know and return the value accordingly.
+ self.assertEquals('chromeos', capabilities['platform'].lower())
+ driver.quit()
+
def testSessionCreationDeletion(self):
driver = WebDriver(self._launcher.GetURL(), 'chrome', 'any')
driver.quit()
+ def testMultipleSessionCreationDeletion(self):
+ for i in range(10):
+ driver = WebDriver(self._launcher.GetURL(), 'chrome', 'any')
+ driver.quit()
+
+ def testSessionCommandsAfterSessionDeletionReturn404(self):
+ driver = WebDriver(self._launcher.GetURL(), 'chrome', 'any')
+ session_id = driver.session_id
+ driver.quit()
+ try:
+ response = SendRequest(self._launcher.GetURL() + '/session/' + session_id,
+ method='GET')
+ self.fail('Should have thrown 404 exception')
+ except urllib2.HTTPError, expected:
+ self.assertEquals(404, expected.code)
+
+ def testMultipleConcurrentSessions(self):
+ drivers = []
+ for i in range(10):
+ drivers += [WebDriver(self._launcher.GetURL(), 'chrome', 'any')]
+ for driver in drivers:
+ driver.quit()
+
if __name__ == '__main__':
unittest.main(module='chromedriver_tests',
diff --git a/chrome/test/webdriver/server.cc b/chrome/test/webdriver/server.cc
index 6409524..2994477 100644
--- a/chrome/test/webdriver/server.cc
+++ b/chrome/test/webdriver/server.cc
@@ -17,11 +17,15 @@
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/string_number_conversions.h"
#include "base/scoped_ptr.h"
+#include "base/string_split.h"
#include "base/string_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/utf_string_conversions.h"
-
+#include "chrome/common/chrome_paths.h"
#include "chrome/test/webdriver/dispatch.h"
#include "chrome/test/webdriver/session_manager.h"
#include "chrome/test/webdriver/utility_functions.h"
@@ -55,12 +59,25 @@ signal_handler(int sig_num) {
}
namespace webdriver {
+
+void Shutdown(struct mg_connection* connection,
+ const struct mg_request_info* request_info,
+ void* user_data) {
+ base::WaitableEvent* shutdown_event =
+ reinterpret_cast<base::WaitableEvent*>(user_data);
+ mg_printf(connection, "HTTP/1.1 200 OK\r\n\r\n");
+ shutdown_event->Signal();
+}
+
template <typename CommandType>
void SetCallback(struct mg_context* ctx, const char* pattern) {
mg_set_uri_callback(ctx, pattern, &Dispatch<CommandType>, NULL);
}
-void InitCallbacks(struct mg_context* ctx) {
+void InitCallbacks(struct mg_context* ctx,
+ base::WaitableEvent* shutdown_event) {
+ mg_set_uri_callback(ctx, "/shutdown", &Shutdown, shutdown_event);
+
SetCallback<CreateSession>(ctx, "/session");
SetCallback<BackCommand>(ctx, "/session/*/back");
SetCallback<ExecuteCommand>(ctx, "/session/*/execute");
@@ -72,7 +89,7 @@ void InitCallbacks(struct mg_context* ctx) {
SetCallback<SpeedCommand>(ctx, "/session/*/speed");
// WebElement commands
- SetCallback<ImplicitWaitCommand>(ctx, "/session/*/timeouts/implicit_wait");
+ SetCallback<ImplicitWaitCommand>(ctx, "/session/*/timeouts/implicit_wait");
SetCallback<FindOneElementCommand>(ctx, "/session/*/element");
SetCallback<FindManyElementsCommand>(ctx, "/session/*/elements");
SetCallback<FindOneElementCommand>(ctx, "/session/*/element/*/element");
@@ -84,13 +101,32 @@ void InitCallbacks(struct mg_context* ctx) {
}
} // namespace webdriver
+// Configures mongoose according to the given command line flags.
+// Returns true on success.
+bool SetMongooseOptions(struct mg_context* ctx,
+ const std::string& port,
+ const std::string& root) {
+ if (!mg_set_option(ctx, "ports", port.c_str())) {
+ std::cout << "ChromeDriver cannot bind to port ("
+ << port.c_str() << ")" << std::endl;
+ return false;
+ }
+ if (root.length())
+ mg_set_option(ctx, "root", root.c_str());
+ // Lower the default idle time to 1 second. Idle time refers to how long a
+ // worker thread will wait for new connections before exiting.
+ // This is so mongoose quits in a reasonable amount of time.
+ mg_set_option(ctx, "idle_time", "1");
+ return true;
+}
+
// Sets up and runs the Mongoose HTTP server for the JSON over HTTP
// protcol of webdriver. The spec is located at:
// http://code.google.com/p/selenium/wiki/JsonWireProtocol.
int main(int argc, char *argv[]) {
struct mg_context *ctx;
base::AtExitManager exit;
- std::string port = "9515";
+ base::WaitableEvent shutdown_event(false, false);
#ifdef OS_POSIX
CommandLine cmd_line = CommandLine(argc, argv);
#elif OS_WIN
@@ -111,9 +147,20 @@ int main(int argc, char *argv[]) {
#endif
srand((unsigned int)time(NULL));
- if (cmd_line.HasSwitch(std::string("port"))) {
- port = cmd_line.GetSwitchValueASCII(std::string("port"));
- }
+ // Register Chrome's path provider so that the AutomationProxy will find our
+ // built Chrome.
+ chrome::RegisterPathProvider();
+ TestTimeouts::Initialize();
+
+ // Parse command line flags.
+ std::string port = "9515";
+ std::string root;
+ if (cmd_line.HasSwitch("port"))
+ port = cmd_line.GetSwitchValueASCII("port");
+ // By default, mongoose serves files from the current working directory. The
+ // 'root' flag allows the user to specify a different location to serve from.
+ if (cmd_line.HasSwitch("root"))
+ root = cmd_line.GetSwitchValueASCII("root");
VLOG(1) << "Using port: " << port;
webdriver::SessionManager* session = webdriver::SessionManager::GetInstance();
@@ -123,14 +170,24 @@ int main(int argc, char *argv[]) {
// Listen on port 9515 or port specified on command line.
// TODO(jmikhail) Maybe add port 9516 as a secure connection.
ctx = mg_start();
- mg_set_option(ctx, "ports", port.c_str());
+ if (!SetMongooseOptions(ctx, port, root)) {
+ mg_stop(ctx);
+ return 1;
+ }
- webdriver::InitCallbacks(ctx);
+ webdriver::InitCallbacks(ctx, &shutdown_event);
- std::cout << "Starting server on port: " << port << std::endl;
- // The default behavior is to run this service forever.
- while (true)
- base::PlatformThread::Sleep(3600);
+ // The tests depend on parsing the first line ChromeDriver outputs,
+ // so all other logging should happen after this.
+ std::cout << "Started ChromeDriver" << std::endl
+ << "port=" << port << std::endl;
+
+ if (root.length()) {
+ VLOG(1) << "Serving files from the current working directory";
+ }
+
+ // Run until we receive command to shutdown.
+ shutdown_event.Wait();
// We should not reach here since the service should never quit.
// TODO(jmikhail): register a listener for SIGTERM and break the
@@ -138,4 +195,3 @@ int main(int argc, char *argv[]) {
mg_stop(ctx);
return (EXIT_SUCCESS);
}
-
diff --git a/chrome/test/webdriver/webdriver_tests.py b/chrome/test/webdriver/webdriver_tests.py
deleted file mode 100644
index 2d95871..0000000
--- a/chrome/test/webdriver/webdriver_tests.py
+++ /dev/null
@@ -1,241 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2010 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.
-
-try:
- import json
-except ImportError: # < 2.6
- import simplejson as json
-
-import os
-import optparse
-import platform
-import subprocess
-import sys
-import time
-import unittest
-import urllib2
-from urlparse import urlparse
-
-if sys.version_info[0] <= 2 and sys.version_info[1] < 6:
- # subprocess.Popen.kill is not available prior to 2.6.
- if platform.system() == 'Windows':
- import win32api
- else:
- import signal
-
-
-WEBDRIVER_EXE = os.path.abspath(os.path.join('.', 'chromedriver'))
-if platform.system() == 'Windows':
- WEBDRIVER_EXE = '%s.exe' % WEBDRIVER_EXE
-WEBDRIVER_PORT = 8080
-WEBDRIVER_SERVER_URL = None
-WEBDRIVER_PROCESS = None
-
-
-def setUpModule():
- """Starts the webdriver server, if necessary."""
- global WEBDRIVER_SERVER_URL
- global WEBDRIVER_PROCESS
- if not WEBDRIVER_SERVER_URL:
- WEBDRIVER_SERVER_URL = 'http://localhost:%d' % WEBDRIVER_PORT
- WEBDRIVER_PROCESS = subprocess.Popen([WEBDRIVER_EXE,
- '--port=%d' % WEBDRIVER_PORT])
- time.sleep(3)
-
-
-def tearDownModule():
- """Kills the WebDriver server, if it was started for testing."""
- global WEBDRIVER_PROCESS
- if WEBDRIVER_PROCESS:
- if sys.version_info[0] <= 2 and sys.version_info[1] < 6:
- # From http://stackoverflow.com/questions/1064335
- if platform.system() == 'Windows':
- PROCESS_TERMINATE = 1
- handle = win32api.OpenProcess(PROCESS_TERMINATE, False,
- WEBDRIVER_PROCESS.pid)
- win32api.TerminateProcess(handle, -1)
- win32api.CloseHandle(handle)
- else:
- os.kill(WEBDRIVER_PROCESS.pid, signal.SIGKILL)
- else:
- WEBDRIVER_PROCESS.kill()
-
-
-class Request(urllib2.Request):
- """Extends urllib2.Request to support all HTTP request types."""
-
- def __init__(self, url, method=None, data=None):
- """Initialise a new HTTP request.
-
- Arguments:
- url: The full URL to send the request to.
- method: The HTTP request method to use; defaults to 'GET'.
- data: The data to send with the request as a string. Defaults to
- None and is ignored if |method| is not 'POST' or 'PUT'.
- """
- if method is None:
- method = data is not None and 'POST' or 'GET'
- elif method not in ('POST', 'PUT'):
- data = None
- self.method = method
- urllib2.Request.__init__(self, url, data=data)
-
- def get_method(self):
- """Returns the HTTP method used by this request."""
- return self.method
-
-
-def SendRequest(url, method=None, data=None):
- """Sends a HTTP request to the WebDriver server.
-
- Return values and exceptions raised are the same as those of
- |urllib2.urlopen|.
-
- Arguments:
- url: The full URL to send the request to.
- method: The HTTP request method to use; defaults to 'GET'.
- data: The data to send with the request as a string. Defaults to
- None and is ignored if |method| is not 'POST' or 'PUT'.
-
- Returns:
- A file-like object.
- """
- request = Request(url, method=method, data=data)
- request.add_header('Accept', 'application/json')
- opener = urllib2.build_opener(urllib2.HTTPRedirectHandler())
- return opener.open(request)
-
-
-class WebDriverSessionlessTest(unittest.TestCase):
- """Tests against the WebDriver REST protocol that do not require creating
- a session with the WebDriver server.
- """
-
- def testShouldReturn404WhenSentAnUnknownCommandURL(self):
- request_url = '%s/foo' % WEBDRIVER_SERVER_URL
- try:
- SendRequest(request_url, method='GET')
- self.fail('Should have raised a urllib.HTTPError for returned 404')
- except urllib2.HTTPError, expected:
- self.assertEquals(404, expected.code)
-
- def testShouldReturnHTTP405WhenSendingANonPostToTheSessionURL(self):
- request_url = '%s/session' % WEBDRIVER_SERVER_URL
- try:
- SendRequest(request_url, method='GET')
- self.fail('Should have raised a urllib.HTTPError for returned 405')
- except urllib2.HTTPError, expected:
- self.assertEquals(405, expected.code)
- self.assertEquals('POST', expected.hdrs['Allow'])
-
- def testShouldGetA404WhenAttemptingToDeleteAnUnknownSession(self):
- request_url = '%s/session/unknown_session_id' % WEBDRIVER_SERVER_URL
- try:
- SendRequest(request_url, method='DELETE')
- self.fail('Should have raised a urllib.HTTPError for returned 404')
- except urllib2.HTTPError, expected:
- self.assertEquals(404, expected.code)
-
-
-class SessionTest(unittest.TestCase):
- """Tests requiring an active WebDriver session."""
-
- def setUp(self):
- self.session_url = None
-
- def tearDown(self):
- if self.session_url:
- response = SendRequest(self.session_url, method='DELETE')
- try:
- self.assertEquals(200, response.code)
- finally:
- response.close()
-
- def testShouldBeGivenCapabilitiesWhenStartingASession(self):
- request_url = '%s/session' % WEBDRIVER_SERVER_URL
- response = SendRequest(request_url, method='POST', data='{}')
- try:
- self.assertEquals(200, response.code)
- self.session_url = response.geturl() # TODO(jleyba): verify this URL?
-
- data = json.loads(response.read())
- self.assertTrue(isinstance(data, dict))
- self.assertEquals(0, data['status'])
-
- url_parts = urlparse(self.session_url)[2].split('/')
- self.assertEquals(3, len(url_parts))
- self.assertEquals('', url_parts[0])
- self.assertEquals('session', url_parts[1])
- self.assertEquals(data['sessionId'], url_parts[2])
-
- capabilities = data['value']
- self.assertTrue(isinstance(capabilities, dict))
-
- self.assertEquals('chrome', capabilities['browserName'])
- self.assertTrue(capabilities['javascriptEnabled'])
-
- # Value depends on what version the server is starting.
- self.assertTrue('version' in capabilities)
- self.assertTrue(
- isinstance(capabilities['version'], unicode),
- 'Expected a %s, but was %s' % (unicode,
- type(capabilities['version'])))
-
- system = platform.system()
- if system == 'Linux':
- self.assertEquals('linux', capabilities['platform'].lower())
- elif system == 'Windows':
- self.assertEquals('windows', capabilities['platform'].lower())
- elif system == 'Darwin':
- self.assertEquals('mac', capabilities['platform'].lower())
- else:
- # No python on ChromeOS, so we won't have a platform value, but
- # the server will know and return the value accordingly.
- self.assertEquals('chromeos', capabilities['platform'].lower())
- finally:
- response.close()
-
-
-if __name__ == '__main__':
- parser = optparse.OptionParser('%prog [options]')
- parser.add_option('-u', '--url', dest='url', action='store',
- type='string', default=None,
- help=('Specifies the URL of a remote WebDriver server to '
- 'test against. If not specified, a server will be '
- 'started on localhost according to the --exe and '
- '--port flags'))
- parser.add_option('-e', '--exe', dest='exe', action='store',
- type='string', default=None,
- help=('Path to the WebDriver server executable that should '
- 'be started for testing; This flag is ignored if '
- '--url is provided for a remote server.'))
- parser.add_option('-p', '--port', dest='port', action='store',
- type='int', default=8080,
- help=('The port to start the WebDriver server executable '
- 'on; This flag is ignored if --url is provided for a '
- 'remote server.'))
-
- (options, args) = parser.parse_args()
- # Strip out our flags so unittest.main() correct parses the remaining
- sys.argv = sys.argv[:1]
- sys.argv.extend(args)
-
- if options.url:
- WEBDRIVER_SERVER_URL = options.url
- else:
- if options.port:
- WEBDRIVER_PORT = options.port
- if options.exe:
- WEBDRIVER_EXE = options.exe
- if not os.path.exists(WEBDRIVER_EXE):
- parser.error('WebDriver server executable not found:\n\t%s\n'
- 'Please specify a valid path with the --exe flag.'
- % WEBDRIVER_EXE)
-
- setUpModule()
- try:
- unittest.main()
- finally:
- tearDownModule()
diff --git a/third_party/mongoose/README.chromium b/third_party/mongoose/README.chromium
index c8561bf..c1bf3ca 100644
--- a/third_party/mongoose/README.chromium
+++ b/third_party/mongoose/README.chromium
@@ -26,3 +26,6 @@ Note: There is no make file for this project, it's compiled directly in
the chrome versoin of webdriver found under the directory:
src/chrome/test/webdriver
+Local modifications:
+-Do not check for OS_POSIX, instead just check that it is not windows.
+
diff --git a/third_party/mongoose/mongoose.c b/third_party/mongoose/mongoose.c
index 8078e63..24874e5 100644
--- a/third_party/mongoose/mongoose.c
+++ b/third_party/mongoose/mongoose.c
@@ -4479,10 +4479,10 @@ get_socket(struct mg_context *ctx, struct socket *sp)
ctx->num_idle++;
while (ctx->sq_head == ctx->sq_tail) {
ts.tv_nsec = 0;
-#ifdef OS_POSIX
- ts.tv_sec = time(NULL) + atoi(ctx->options[OPT_IDLE_TIME]) + 1;
-#elif _WIN32
+#ifdef _WIN32
ts.tv_sec = (long) (time(NULL) + atoi(ctx->options[OPT_IDLE_TIME]) + 1);
+#else
+ ts.tv_sec = time(NULL) + atoi(ctx->options[OPT_IDLE_TIME]) + 1;
#endif
if (pthread_cond_timedwait(&ctx->empty_cond,
&ctx->thr_mutex, &ts) != 0) {
@@ -4747,4 +4747,3 @@ mg_start(void)
return (ctx);
}
-