summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authorbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-14 01:28:59 +0000
committerbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-14 01:28:59 +0000
commit8aa928c3e83ffa86f45ff44debc48a4aece5983a (patch)
treeb9288d9c99f46ecfddb3e198f1bddb89d4abaa4e /native_client_sdk
parent8ca64d42684fa5d7304805a9225f6880a5cb2fa6 (diff)
downloadchromium_src-8aa928c3e83ffa86f45ff44debc48a4aece5983a.zip
chromium_src-8aa928c3e83ffa86f45ff44debc48a4aece5983a.tar.gz
chromium_src-8aa928c3e83ffa86f45ff44debc48a4aece5983a.tar.bz2
[NaCl SDK] Add listening for POST to /ok or /fail to httpd.py.
This will allow us to XHR from example code to test. BUG=139415 TBR=noelallen@chromium.org NOTRY=true Review URL: https://chromiumcodereview.appspot.com/11360235 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@167561 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
-rwxr-xr-xnative_client_sdk/src/tools/httpd.py30
-rwxr-xr-xnative_client_sdk/src/tools/run.py6
-rwxr-xr-xnative_client_sdk/src/tools/tests/chrome_mock.py48
-rwxr-xr-xnative_client_sdk/src/tools/tests/test_httpd.py115
4 files changed, 134 insertions, 65 deletions
diff --git a/native_client_sdk/src/tools/httpd.py b/native_client_sdk/src/tools/httpd.py
index 0e2ef67..8057f91 100755
--- a/native_client_sdk/src/tools/httpd.py
+++ b/native_client_sdk/src/tools/httpd.py
@@ -41,6 +41,7 @@ class PluggableHTTPServer(BaseHTTPServer.HTTPServer):
def __init__(self, *args, **kwargs):
BaseHTTPServer.HTTPServer.__init__(self, *args)
self.serve_dir = kwargs.get('serve_dir', '.')
+ self.test_mode = kwargs.get('test_mode', False)
self.delegate_map = {}
self.running = True
self.result = 0
@@ -108,6 +109,13 @@ class PluggableHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
logging.info('No handler found for path %s. Using default.' % url_path)
return delegate
+ def _SendNothingAndDie(self, result=0):
+ self.send_response(200, 'OK')
+ self.send_header('Content-type', 'text/html')
+ self.send_header('Content-length', '0')
+ self.end_headers()
+ self.server.Shutdown(result)
+
def send_head(self):
delegate = self._FindDelegateForURL(self.path)
if delegate:
@@ -124,11 +132,7 @@ class PluggableHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
if query:
params = urlparse.parse_qs(query)
if '1' in params.get('quit', None):
- self.send_response(200, 'OK')
- self.send_header('Content-type', 'text/html')
- self.send_header('Content-length', '0')
- self.end_headers()
- self.server.Shutdown()
+ self._SendNothingAndDie()
return
delegate = self._FindDelegateForURL(self.path)
@@ -146,18 +150,23 @@ class PluggableHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
return self.base_do_POST()
def base_do_POST(self):
- pass
+ if self.server.test_mode:
+ if self.path == '/ok':
+ self._SendNothingAndDie(0)
+ elif self.path == '/fail':
+ self._SendNothingAndDie(1)
class LocalHTTPServer(object):
"""Class to start a local HTTP server as a child process."""
- def __init__(self, dirname, port):
+ def __init__(self, dirname, port, test_mode):
parent_conn, child_conn = multiprocessing.Pipe()
self.process = multiprocessing.Process(
target=_HTTPServerProcess,
args=(child_conn, dirname, port, {
'serve_dir': dirname,
+ 'test_mode': test_mode,
}))
self.process.start()
if parent_conn.poll(10): # wait 10 seconds
@@ -270,11 +279,16 @@ def main(args):
parser.add_option('--no_dir_check',
help='No check to ensure serving from safe directory.',
dest='do_safe_check', action='store_false', default=True)
+ parser.add_option('--test-mode',
+ help='Listen for posts to /ok or /fail and shut down the server with '
+ ' errorcodes 0 and 1 respectively.',
+ dest='test_mode', action='store_true')
options, args = parser.parse_args(args)
if options.do_safe_check:
SanityCheckDirectory(options.serve_dir)
- server = LocalHTTPServer(options.serve_dir, int(options.port))
+ server = LocalHTTPServer(options.serve_dir, int(options.port),
+ options.test_mode)
# Serve until the client tells us to stop. When it does, it will give us an
# errorcode.
diff --git a/native_client_sdk/src/tools/run.py b/native_client_sdk/src/tools/run.py
index 3fbd0e0..b2e859f 100755
--- a/native_client_sdk/src/tools/run.py
+++ b/native_client_sdk/src/tools/run.py
@@ -31,12 +31,16 @@ def main(args):
parser.add_option('-E',
help='Add environment variables when launching the executable.',
dest='environ', action='append', default=[])
+ parser.add_option('--test-mode',
+ help='Listen for posts to /ok or /fail and shut down the server with '
+ ' errorcodes 0 and 1 respectively.',
+ dest='test_mode', action='store_true')
options, args = parser.parse_args(args)
if not args:
parser.error('No executable given.')
# 0 means use an ephemeral port.
- server = httpd.LocalHTTPServer(options.serve_dir, 0)
+ server = httpd.LocalHTTPServer(options.serve_dir, 0, options.test_mode)
print 'Serving %s on %s...' % (options.serve_dir, server.GetURL(''))
env = copy.copy(os.environ)
diff --git a/native_client_sdk/src/tools/tests/chrome_mock.py b/native_client_sdk/src/tools/tests/chrome_mock.py
new file mode 100755
index 0000000..cd20e88
--- /dev/null
+++ b/native_client_sdk/src/tools/tests/chrome_mock.py
@@ -0,0 +1,48 @@
+#!/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.
+
+import optparse
+import sys
+import time
+import urllib2
+
+def PrintAndFlush(s):
+ print s
+ sys.stdout.flush()
+
+def main(args):
+ parser = optparse.OptionParser(usage='%prog [options] <URL to load>')
+ parser.add_option('--post', help='POST to URL.', dest='post',
+ action='store_true')
+ parser.add_option('--get', help='GET to URL.', dest='get',
+ action='store_true')
+ parser.add_option('--sleep',
+ help='Number of seconds to sleep after reading URL',
+ dest='sleep', default=0)
+ parser.add_option('--expect-to-be-killed', help='If set, the script will warn'
+ ' if it isn\'t killed before it finishes sleeping.',
+ dest='expect_to_be_killed', action='store_true')
+ options, args = parser.parse_args(args)
+ if len(args) != 1:
+ parser.error('Expected URL to load.')
+
+ PrintAndFlush('Starting %s.' % sys.argv[0])
+
+ if options.post:
+ urllib2.urlopen(args[0], data='').read()
+ elif options.get:
+ urllib2.urlopen(args[0]).read()
+ else:
+ # Do nothing but wait to be killed.
+ pass
+
+ time.sleep(float(options.sleep))
+
+ if options.expect_to_be_killed:
+ PrintAndFlush('Done sleeping. Expected to be killed.')
+ sys.exit(0)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/native_client_sdk/src/tools/tests/test_httpd.py b/native_client_sdk/src/tools/tests/test_httpd.py
index 83390d1..01ff155 100755
--- a/native_client_sdk/src/tools/tests/test_httpd.py
+++ b/native_client_sdk/src/tools/tests/test_httpd.py
@@ -4,10 +4,10 @@
# found in the LICENSE file.
import os
-import re
+import Queue
import sys
import subprocess
-import tempfile
+import threading
import unittest
import urllib2
@@ -21,7 +21,7 @@ import httpd
class HTTPDTest(unittest.TestCase):
def setUp(self):
- self.server = httpd.LocalHTTPServer('.', 0)
+ self.server = httpd.LocalHTTPServer('.', 0, False)
def tearDown(self):
self.server.Shutdown()
@@ -35,74 +35,77 @@ class HTTPDTest(unittest.TestCase):
class RunTest(unittest.TestCase):
def setUp(self):
self.process = None
- self.tempscript = None
def tearDown(self):
if self.process and self.process.returncode is None:
self.process.kill()
- if self.tempscript:
- os.remove(self.tempscript)
- def _Run(self, args=None):
+ @staticmethod
+ def _SubprocessThread(process, queue):
+ stdout, stderr = process.communicate()
+ queue.put((process.returncode, stdout, stderr))
+
+ def _Run(self, args=None, timeout=None):
args = args or []
run_py = os.path.join(PARENT_DIR, 'run.py')
cmd = [sys.executable, run_py]
cmd.extend(args)
self.process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
- stdout, stderr = self.process.communicate()
- try:
- self.assertEqual(0, self.process.returncode)
- except AssertionError:
- print 'subprocess failed: %s:\nstdout: %s\nstderr:%s\n' % (
- ' '.join(cmd), stdout, stderr)
- return stdout
-
- def _WriteTempScript(self, script):
- fd, filename = tempfile.mkstemp(suffix='.py')
- lines = script.splitlines()
- assert len(lines[0]) == 0 # First line is always empty.
- # Count the number of spaces after the first newline.
- m = re.match(r'\s*', lines[1])
- assert m
- indent = len(m.group(0))
- script = '\n'.join(line[indent:] for line in lines[1:])
-
- os.write(fd, script)
- os.close(fd)
- self.tempscript = filename
+ queue = Queue.Queue()
+ thread = threading.Thread(target=RunTest._SubprocessThread,
+ args=(self.process, queue))
+ thread.daemon = True
+ thread.start()
+ thread.join(timeout)
+ if not thread.is_alive():
+ returncode, stdout, stderr = queue.get(False)
+ return returncode, stdout, stderr
+
+ return -1, None, None
+
+ def _GetChromeMockArgs(self, page, http_request_type, sleep,
+ expect_to_be_killed=True):
+ args = ['--test-mode']
+ if page:
+ args.extend(['-P', page])
+ args.append('--')
+ args.extend([sys.executable, os.path.join(SCRIPT_DIR, 'chrome_mock.py')])
+ if http_request_type:
+ args.append('--' + http_request_type)
+ if sleep:
+ args.extend(['--sleep', str(sleep)])
+ if expect_to_be_killed:
+ args.append('--expect-to-be-killed')
+ return args
def testQuit(self):
- self._WriteTempScript(r"""
- import sys
- import time
- import urllib2
-
- print 'running tempscript'
- sys.stdout.flush()
- f = urllib2.urlopen(sys.argv[-1] + '?quit=1')
- f.read()
- f.close()
- time.sleep(10)
-
- # Should be killed before this prints.
- print 'Not killed yet.'
- sys.stdout.flush()
- sys.exit(0)
- """)
- stdout = self._Run(['--', sys.executable, self.tempscript])
- self.assertTrue('running tempscript' in stdout)
- self.assertTrue("Not killed yet" not in stdout)
+ args = self._GetChromeMockArgs('?quit=1', 'get', sleep=10)
+ _, stdout, _ = self._Run(args, timeout=20)
+ self.assertTrue('Starting' in stdout)
+ self.assertTrue('Expected to be killed' not in stdout)
def testSubprocessDies(self):
- self._WriteTempScript(r"""
- import sys
- print 'running tempscript'
- sys.stdout.flush()
- sys.exit(1)
- """)
- stdout = self._Run(['--', sys.executable, self.tempscript])
- self.assertTrue('running tempscript' in stdout)
+ args = self._GetChromeMockArgs(page=None, http_request_type=None, sleep=0,
+ expect_to_be_killed=False)
+ returncode, stdout, _ = self._Run(args, timeout=10)
+ self.assertNotEqual(-1, returncode)
+ self.assertTrue('Starting' in stdout)
+
+ def testPostOk(self):
+ args = self._GetChromeMockArgs('ok', 'post', sleep=10)
+ returncode, stdout, _ = self._Run(args, timeout=20)
+ self.assertEqual(0, returncode)
+ self.assertTrue('Starting' in stdout)
+ self.assertTrue('Expected to be killed' not in stdout)
+
+ def testPostFail(self):
+ args = self._GetChromeMockArgs('fail', 'post', sleep=10)
+ returncode, stdout, _ = self._Run(args, timeout=20)
+ self.assertEqual(1, returncode)
+ self.assertTrue('Starting' in stdout)
+ self.assertTrue('Expected to be killed' not in stdout)
+
if __name__ == '__main__':
unittest.main()