Bug 754216 - Control the emulator from within Marionette JS scripts. r=jgriffin DONTBUILD because NPOTB

This commit is contained in:
Philipp von Weitershausen 2012-05-18 13:30:43 -07:00
parent 370603a9a2
commit cf43882096
10 changed files with 136 additions and 10 deletions

View File

@ -169,11 +169,27 @@ class Marionette(object):
self.port = self.client.port = port
raise TimeoutException(message='socket.timeout', status=21, stacktrace=None)
# Process any emulator commands that are sent from a script
# while it's executing.
while response.get("emulator_cmd"):
response = self._handle_emulator_cmd(response)
if (response_key == 'ok' and response.get('ok') == True) or response_key in response:
return response[response_key]
else:
self._handle_error(response)
def _handle_emulator_cmd(self, response):
cmd = response.get("emulator_cmd")
if not cmd or not self.emulator:
raise MarionetteException(message="No emulator in this test to run "
"command against.")
cmd = cmd.encode("ascii")
result = self.emulator._run_telnet(cmd)
return self.client.send({"type": "emulatorCmdResult",
"id": response.get("id"),
"result": result})
def _handle_error(self, response):
if 'error' in response and isinstance(response['error'], dict):
status = response['error'].get('status', 500)

View File

@ -151,6 +151,10 @@ class MarionetteJSTestCase(CommonTestCase):
context = context.group(3)
self.marionette.set_context(context)
if context != "chrome":
page = self.marionette.absolute_url("empty.html")
self.marionette.navigate(page)
timeout = self.timeout_re.search(js)
if timeout:
timeout = timeout.group(3)

View File

@ -0,0 +1,20 @@
from marionette_test import MarionetteTestCase
from errors import JavascriptException, MarionetteException
class TestEmulatorContent(MarionetteTestCase):
def test_emulator_cmd(self):
self.marionette.set_script_timeout(10000)
expected = ["gsm voice state: home",
"gsm data state: home",
"OK"]
result = self.marionette.execute_async_script("""
runEmulatorCmd("gsm status", marionetteScriptFinished)
""");
self.assertEqual(result, expected)
class TestEmulatorChrome(TestEmulatorContent):
def setUp(self):
super(TestEmulatorChrome, self).setUp()
self.marionette.set_context("chrome")

View File

@ -7,5 +7,8 @@ MARIONETTE_TIMEOUT = 1000;
is(2, 2, "test for is()");
isnot(2, 3, "test for isnot()");
ok(2 == 2, "test for ok()");
is(window.location.pathname.slice(-10), "empty.html");
setTimeout(finish, 100);

View File

@ -10,6 +10,7 @@ b2g = false
b2g = false
[test_log.py]
[test_emulator.py]
[test_execute_async_script.py]
[test_execute_script.py]
[test_simpletest_fail.js]

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<title>Marionette Test</title>
</head>
<body>
</body>
</html>

View File

@ -1,4 +1,4 @@
<!doctype html>
<!DOCTYPE html>
<html>
<head>
<title>Marionette Test</title>

View File

@ -131,6 +131,7 @@ function MarionetteDriverActor(aConnection)
this.messageManager.addMessageListener("Marionette:testLog", this);
this.messageManager.addMessageListener("Marionette:register", this);
this.messageManager.addMessageListener("Marionette:goUrl", this);
this.messageManager.addMessageListener("Marionette:runEmulatorCmd", this);
}
MarionetteDriverActor.prototype = {
@ -165,8 +166,13 @@ MarionetteDriverActor.prototype = {
*/
sendToClient: function MDA_sendToClient(msg, command_id) {
logger.info("sendToClient: " + JSON.stringify(msg) + ", " + command_id + ", " + this.command_id);
if (command_id == undefined || command_id == this.command_id) {
if (this.command_id != null &&
command_id != null &&
this.command_id != command_id) {
return;
}
this.conn.send(msg);
if (command_id != null) {
this.command_id = null;
}
},
@ -506,7 +512,7 @@ MarionetteDriverActor.prototype = {
}
let curWindow = this.getCurrentWindow();
let marionette = new Marionette(false, curWindow, "chrome", this.marionetteLog);
let marionette = new Marionette(this, curWindow, "chrome", this.marionetteLog);
let _chromeSandbox = this.createExecuteSandbox(curWindow, marionette, aRequest.args);
if (!_chromeSandbox)
return;
@ -613,7 +619,7 @@ MarionetteDriverActor.prototype = {
let curWindow = this.getCurrentWindow();
let original_onerror = curWindow.onerror;
let that = this;
let marionette = new Marionette(true, curWindow, "chrome", this.marionetteLog);
let marionette = new Marionette(this, curWindow, "chrome", this.marionetteLog);
marionette.command_id = this.command_id;
function chromeAsyncReturnFunc(value, status) {
@ -1181,9 +1187,41 @@ MarionetteDriverActor.prototype = {
this.messageManager.removeMessageListener("Marionette:testLog", this);
this.messageManager.removeMessageListener("Marionette:register", this);
this.messageManager.removeMessageListener("Marionette:goUrl", this);
this.messageManager.removeMessageListener("Marionette:runEmulatorCmd", this);
this.curBrowser = null;
},
_emu_cb_id: 0,
_emu_cbs: null,
runEmulatorCmd: function runEmulatorCmd(cmd, callback) {
if (typeof callback != "function") {
throw "Need to provide callback function!";
}
if (!this._emu_cbs) {
this._emu_cbs = {};
}
this._emu_cbs[this._emu_cb_id] = callback;
this.sendToClient({emulator_cmd: cmd, id: this._emu_cb_id});
this._emu_cb_id += 1;
},
emulatorCmdResult: function emulatorCmdResult(message) {
if (this.context != "chrome") {
this.sendAsync("emulatorCmdResult", message);
return;
}
let cb = this._emu_cbs[message.id];
delete this._emu_cbs[message.id];
try {
cb(message.result);
}
catch(e) {
this.sendError(e.message, e.num, e.stack);
return;
}
},
/**
* Receives all messages from content messageManager
*/
@ -1210,6 +1248,9 @@ MarionetteDriverActor.prototype = {
//log messages from tests
this.marionetteLog.addLogs(message.json.value);
break;
case "Marionette:runEmulatorCmd":
this.sendToClient(message.json);
break;
case "Marionette:register":
// This code processes the content listener's registration information
// and either accepts the listener, or ignores it
@ -1269,7 +1310,8 @@ MarionetteDriverActor.prototype.requestTypes = {
"getWindows": MarionetteDriverActor.prototype.getWindows,
"switchToFrame": MarionetteDriverActor.prototype.switchToFrame,
"switchToWindow": MarionetteDriverActor.prototype.switchToWindow,
"deleteSession": MarionetteDriverActor.prototype.deleteSession
"deleteSession": MarionetteDriverActor.prototype.deleteSession,
"emulatorCmdResult": MarionetteDriverActor.prototype.emulatorCmdResult
};
/**

View File

@ -101,6 +101,7 @@ function startListeners() {
addMessageListenerId("Marionette:switchToFrame", switchToFrame);
addMessageListenerId("Marionette:deleteSession", deleteSession);
addMessageListenerId("Marionette:sleepSession", sleepSession);
addMessageListenerId("Marionette:emulatorCmdResult", emulatorCmdResult);
}
/**
@ -158,6 +159,7 @@ function deleteSession(msg) {
removeMessageListenerId("Marionette:switchToFrame", switchToFrame);
removeMessageListenerId("Marionette:deleteSession", deleteSession);
removeMessageListenerId("Marionette:sleepSession", sleepSession);
removeMessageListenerId("Marionette:emulatorCmdResult", emulatorCmdResult);
this.elementManager.reset();
}
@ -237,7 +239,7 @@ function createExecuteContentSandbox(aWindow) {
sandbox.__proto__ = sandbox.window;
sandbox.testUtils = utils;
let marionette = new Marionette(false, aWindow, "content", marionetteLogObj);
let marionette = new Marionette(this, aWindow, "content", marionetteLogObj);
sandbox.marionette = marionette;
marionette.exports.forEach(function(fn) {
sandbox[fn] = marionette[fn].bind(marionette);
@ -688,5 +690,29 @@ function switchToFrame(msg) {
sandbox = null;
}
let _emu_cb_id = 0;
let _emu_cbs = {};
function runEmulatorCmd(cmd, callback) {
if (typeof callback != "function") {
throw "Need to provide callback function!";
}
_emu_cbs[_emu_cb_id] = callback;
sendAsyncMessage("Marionette:runEmulatorCmd", {emulator_cmd: cmd, id: _emu_cb_id});
_emu_cb_id += 1;
}
function emulatorCmdResult(msg) {
let message = msg.json;
let cb = _emu_cbs[message.id];
delete _emu_cbs[message.id];
try {
cb(message.result);
}
catch(e) {
sendError(e.message, e.num, e.stack);
return;
}
}
//call register self when we get loaded
registerSelf();

View File

@ -5,8 +5,8 @@
* The Marionette object, passed to the script context.
*/
function Marionette(is_async, window, context, logObj) {
this.is_async = is_async;
function Marionette(scope, window, context, logObj) {
this.scope = scope;
this.window = window;
this.tests = [];
this.logObj = logObj;
@ -15,7 +15,8 @@ function Marionette(is_async, window, context, logObj) {
}
Marionette.prototype = {
exports: ['ok', 'is', 'isnot', 'log', 'getLogs', 'generate_results', 'waitFor'],
exports: ['ok', 'is', 'isnot', 'log', 'getLogs', 'generate_results', 'waitFor',
'runEmulatorCmd'],
ok: function Marionette__ok(condition, name, diag) {
let test = {'result': !!condition, 'name': name, 'diag': diag};
@ -134,5 +135,10 @@ Marionette.prototype = {
}
this.window.setTimeout(this.waitFor.bind(this), 100, callback, test, timeout);
},
runEmulatorCmd: function runEmulatorCmd(cmd, callback) {
this.scope.runEmulatorCmd(cmd, callback);
},
};