Browse files

Merge pull request #355 from ihanson/multimechanize

Multi-Mechanize tests
  • Loading branch information...
2 parents b9eadaa + ec60ac2 commit e40d6c4385cdf791cc3a8ac169112e5eeb231171 @jasongrout jasongrout committed Feb 28, 2013
View
5 .gitignore
@@ -1,10 +1,13 @@
*.pyc
*~
doc/_build/*
-static/jmol
+tests/multimechanize/results/
+sqlite.db
config.py
# generated web files
+submodules/jsmin-bin
+static/jmol
static/all*
static/codemirror.js
static/jquery.min.js
View
19 handlers.py
@@ -100,19 +100,19 @@ def post(self):
logger.info("Starting session: %s"%timer)
kernel_id = yield gen.Task(km.new_session_async)
data = {"ws_url": ws_url, "kernel_id": kernel_id}
- if self.request.headers["Accept"] == "application/json":
+ if "frame" not in self.request.headers:
self.set_header("Access-Control-Allow-Origin", "*");
else:
data = '<script>parent.postMessage(%s,"*");</script>' % (json.dumps(data),)
self.set_header("Content-Type", "text/html")
self.write(data)
self.finish()
- get = post
class KernelConnection(sockjs.tornado.SockJSConnection):
def __init__(self, session):
self.session = session
super(KernelConnection, self).__init__(session)
+
def on_open(self, request):
self.channels = {}
@@ -128,6 +128,11 @@ def on_message(self, message):
self.channels[kernel]["iopub"].open(kernel)
self.channels[kernel][channel].on_message(message)
+ def on_close(self):
+ for channel in self.channels.itervalues():
+ channel["shell"].on_close()
+ channel["iopub"].on_close()
+
KernelRouter = sockjs.tornado.SockJSRouter(KernelConnection, "/sockjs")
class SageCellHandler(tornado.web.RequestHandler):
@@ -172,7 +177,7 @@ def post(self):
retval["query"] = db.new_exec_msg(message)
except:
pass
- if self.request.headers["Accept"] == "application/json":
+ if "frame" not in self.request.headers:
self.set_header("Access-Control-Allow-Origin", "*");
else:
retval = '<script>parent.postMessage(%s,"*");</script>' % (json.dumps(retval),)
@@ -252,9 +257,6 @@ def finish_request(self):
self.set_header("Access-Control-Allow-Origin", "*")
self.write(retval)
self.finish()
-
- get = post
-
class ZMQStreamHandler(object):
"""
@@ -301,6 +303,9 @@ def _on_zmq_reply(self, msg_list):
def _output_message(self, message):
raise NotImplementedError
+ def on_close(self):
+ self.km.end_session(self.kernel_id)
+
class ShellHandler(ZMQStreamHandler):
"""
This handles the websocket-ZMQ bridge for the shell
@@ -344,6 +349,7 @@ def on_message(self, message):
def on_close(self):
if self.shell_stream is not None and not self.shell_stream.closed():
self.shell_stream.close()
+ super(ShellHandler, self).on_close()
class IOPubHandler(ZMQStreamHandler):
"""
@@ -377,6 +383,7 @@ def on_close(self):
self.iopub_stream.close()
if self.hb_stream is not None and not self.hb_stream.closed():
self.stop_hb()
+ super(IOPubHandler, self).on_close()
def start_hb(self, callback):
"""
View
5 static/embedded_sagecell.js
@@ -191,7 +191,7 @@ processEnvironments: false}\n\
// many prerequisites that have been smashed together into all.min.js
load({"src": sagecell.URLs.root + "static/all.min.js"})
});
- }, undefined, "text/html");
+ }, undefined);
};
sagecell.sagecell_dependencies_callback = function () {
@@ -512,7 +512,7 @@ sagecell.initCell = (function (sagecellInfo, k) {
return sagecellInfo;
});
-sagecell.sendRequest = function (method, url, data, callback, files, accept) {
+sagecell.sendRequest = function (method, url, data, callback, files) {
method = method.toUpperCase();
var hasFiles = false;
if (files === undefined) {
@@ -559,7 +559,6 @@ sagecell.sendRequest = function (method, url, data, callback, files, accept) {
if (window.FormData || !(isXDomain || hasFiles)) {
// If an XMLHttpRequest is possible, use it
xhr.open(method, url, true);
- xhr.setRequestHeader("Accept", accept || "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 /* DONE */) {
callback(xhr.responseText);
View
12 tests/multimechanize/config.cfg
@@ -0,0 +1,12 @@
+[global]
+run_time = 300
+rampup = 10
+results_ts_interval = 3
+
+[user_group-1]
+threads = 350
+script = simple_session.py
+
+[user_group-2]
+threads = 150
+script = interact_session.py
View
76 tests/multimechanize/test_scripts/client.py
@@ -0,0 +1,76 @@
+import urllib2
+import websocket
+import json
+import uuid
+
+root = "http://localhost:8888"
+
+class SageCellSession(object):
+ def __init__(self):
+ f = urllib2.urlopen("%s/kernel" % (root,), "")
+ data = json.loads(f.read())
+ f.close()
+ self.kernel_id = data["kernel_id"]
+ self.ws_url = data["ws_url"]
+ self.iopub = websocket.create_connection("%skernel/%s/iopub" % (self.ws_url, self.kernel_id))
+ self.shell = websocket.create_connection("%skernel/%s/shell" % (self.ws_url, self.kernel_id))
+ self.session_id = str(uuid.uuid4())
+
+ def __del__(self):
+ self.close()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, etype, value, traceback):
+ self.close()
+
+ def execute(self, code):
+ content = {"code": code,
+ "silent": False,
+ "user_variables": [],
+ "user_expressions": {"_sagecell_files": "sys._sage_.new_files()"},
+ "allow_stdin": False}
+ self.send_msg("execute_request", content)
+
+ def update_interact(self, interact_id, values):
+ self.execute("sys._sage_.update_interact(%r, %r)" % (interact_id, values))
+
+ def send_msg(self, msg_type, content):
+ msg = {"header": {"msg_id": str(uuid.uuid4()),
+ "username": "username",
+ "session": self.session_id,
+ "msg_type": msg_type
+ },
+ "metadata": {},
+ "content": content,
+ "parent_header":{}
+ }
+ self.shell.send(json.dumps(msg))
+
+ def close(self):
+ self.iopub.close()
+ self.shell.close()
+
+ def iopub_recv(self):
+ return json.loads(self.iopub.recv())
+
+ def shell_recv(self):
+ return json.loads(self.shell.recv())
+
+def load_root():
+ resources = ["/", "/static/root.css", "/static/jquery.min.js",
+ "/static/embedded_sagecell.js",
+ "/static/jquery-ui/css/sagecell/jquery-ui-1.8.21.custom.css",
+ "/static/colorpicker/css/colorpicker.css",
+ "/static/all.min.css", "/static/mathjax/MathJax.js",
+ "/static/sagelogo.png", "/static/spinner.gif",
+ "/sagecell.html", "/static/all.min.js",
+ "/static/mathjax/config/TeX-AMS-MML_HTMLorMML.js",
+ "/static/mathjax/images/MenuArrow-15.png",
+ "/static/jquery-ui/css/sagecell/images/ui-bg_highlight-hard_60_99bbff_1x100.png",
+ "/static/mathjax/extensions/jsMath2jax.js",
+ "/static/jquery-ui/css/sagecell/images/ui-bg_highlight-hard_90_99bbff_1x100.png"]
+ for r in resources:
+ f = urllib2.urlopen(root + r)
+ assert f.code == 200, "Bad response: HTTP %d" % (f.code,)
View
61 tests/multimechanize/test_scripts/interact_session.py
@@ -0,0 +1,61 @@
+#! /usr/bin/env python
+
+import client
+import time
+import random
+
+computation = """@interact
+def f(x=(1, 100, 1)):
+ print x^2"""
+
+class Transaction(object):
+ """
+ A transaction that simulates loading the page
+ and manipulating an interact
+ """
+
+ def __init__(self):
+ self.custom_timers = {}
+
+ def run(self):
+ t = time.time()
+ client.load_root()
+ self.custom_timers["root load"] = time.time() - t
+ time.sleep(5)
+ t = time.time()
+ with client.SageCellSession() as s:
+ self.custom_timers["initial connection"] = time.time() - t
+ t = time.time()
+ s.execute(computation)
+ output = ""
+ while True:
+ msg = s.iopub_recv()
+ if msg["header"]["msg_type"] == "status" and msg["content"]["execution_state"] == "idle":
+ break
+ elif msg["header"]["msg_type"] == "display_data" and "application/sage-interact" in msg["content"]["data"]:
+ interact_id = msg["content"]["data"]["application/sage-interact"]["new_interact_id"]
+ elif msg["header"]["msg_type"] == "stream" and msg["content"]["name"] == "stdout" and msg["metadata"]["interact_id"] == interact_id:
+ output += msg["content"]["data"]
+ assert output == "1\n", "Incorrect output: %r" % (output,)
+ times = []
+ self.custom_timers["initial computation"] = time.time() - t
+ for i in xrange(10):
+ time.sleep(1)
+ num = random.randint(1, 100)
+ t = time.time()
+ s.update_interact(interact_id, {"x": num})
+ output = ""
+ while True:
+ msg = s.iopub_recv()
+ if msg["header"]["msg_type"] == "status" and msg["content"]["execution_state"] == "idle":
+ break
+ elif msg["header"]["msg_type"] == "stream" and msg["content"]["name"] == "stdout" and msg["metadata"]["interact_id"] == interact_id:
+ output += msg["content"]["data"]
+ assert int(output.strip()) == num * num, "Incorrect output: %r" % (output,)
+ times.append(time.time() - t)
+ self.custom_timers["interact update (average of 10)"] = sum(times) / len(times)
+
+if __name__ == "__main__":
+ t = Transaction()
+ t.run()
+ print t.custom_timers
View
41 tests/multimechanize/test_scripts/simple_session.py
@@ -0,0 +1,41 @@
+#! /usr/bin/env python
+
+import client
+import time
+import random
+
+class Transaction(object):
+ """
+ A transaction that simulates loading the page
+ and performing a simple addition
+ """
+
+ def __init__(self):
+ self.custom_timers = {}
+
+ def run(self):
+ t = time.time()
+ client.load_root()
+ self.custom_timers["root load"] = time.time() - t
+ time.sleep(5)
+ t = time.time()
+ with client.SageCellSession() as s:
+ self.custom_timers["initial connection"] = time.time() - t
+ t = time.time()
+ num1 = random.randint(1, 10 ** 20)
+ num2 = random.randint(1, 10 ** 20)
+ s.execute("print %d + %d" % (num1, num2))
+ output = ""
+ while True:
+ msg = s.iopub_recv()
+ if msg["header"]["msg_type"] == "status" and msg["content"]["execution_state"] == "idle":
+ break
+ elif msg["header"]["msg_type"] == "stream" and msg["content"]["name"] == "stdout":
+ output += msg["content"]["data"]
+ assert int(output.strip()) == num1 + num2, "Incorrect output: %r" % (output,)
+ self.custom_timers["computation"] = time.time() - t
+
+if __name__ == "__main__":
+ t = Transaction()
+ t.run()
+ print t.custom_timers
View
2 trusted_kernel_manager.py
@@ -288,6 +288,8 @@ def end_session(self, kernel_id):
:arg str kernel_id: the id of the kernel you want to kill
"""
+ if not kernel_id in self._kernels:
+ return
comp_id = self._kernels[kernel_id]["comp_id"]
def cb(reply):
if (reply["type"] == "error"):

0 comments on commit e40d6c4

Please sign in to comment.