mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 873591 - Make better errors for execute_script failures, r=mdas
This commit is contained in:
parent
8ec6ea7e2b
commit
5b221bb19d
@ -3,9 +3,11 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from client import MarionetteClient
|
||||
from application_cache import ApplicationCache
|
||||
@ -602,26 +604,34 @@ class Marionette(object):
|
||||
if script_args is None:
|
||||
script_args = []
|
||||
args = self.wrapArguments(script_args)
|
||||
stack = traceback.extract_stack()
|
||||
frame = stack[-2:-1][0] # grab the second-to-last frame
|
||||
response = self._send_message('executeScript',
|
||||
'value',
|
||||
'value',
|
||||
value=script,
|
||||
args=args,
|
||||
newSandbox=new_sandbox,
|
||||
specialPowers=special_powers,
|
||||
scriptTimeout=script_timeout)
|
||||
scriptTimeout=script_timeout,
|
||||
line=int(frame[1]),
|
||||
filename=os.path.basename(frame[0]))
|
||||
return self.unwrapValue(response)
|
||||
|
||||
def execute_async_script(self, script, script_args=None, new_sandbox=True, special_powers=False, script_timeout=None):
|
||||
if script_args is None:
|
||||
script_args = []
|
||||
args = self.wrapArguments(script_args)
|
||||
stack = traceback.extract_stack()
|
||||
frame = stack[-2:-1][0] # grab the second-to-last frame
|
||||
response = self._send_message('executeAsyncScript',
|
||||
'value',
|
||||
value=script,
|
||||
args=args,
|
||||
newSandbox=new_sandbox,
|
||||
specialPowers=special_powers,
|
||||
scriptTimeout=script_timeout)
|
||||
scriptTimeout=script_timeout,
|
||||
line=int(frame[1]),
|
||||
filename=os.path.basename(frame[0]))
|
||||
return self.unwrapValue(response)
|
||||
|
||||
def find_element(self, method, target, id=None):
|
||||
|
@ -55,8 +55,14 @@ class TestExecuteAsyncContent(MarionetteTestCase):
|
||||
self.assertEqual(self.marionette.execute_async_script("marionetteScriptFinished()"), None)
|
||||
|
||||
def test_execute_js_exception(self):
|
||||
self.assertRaises(JavascriptException,
|
||||
self.marionette.execute_async_script, "foo(bar);")
|
||||
try:
|
||||
self.marionette.execute_async_script("""
|
||||
let a = 1;
|
||||
foo(bar);
|
||||
""")
|
||||
self.assertFalse(True)
|
||||
except JavascriptException, inst:
|
||||
self.assertTrue('foo(bar)' in inst.stacktrace)
|
||||
|
||||
def test_execute_async_js_exception(self):
|
||||
self.assertRaises(JavascriptException,
|
||||
|
@ -6,6 +6,16 @@ from marionette_test import MarionetteTestCase
|
||||
from errors import JavascriptException, MarionetteException
|
||||
|
||||
class TestExecuteContent(MarionetteTestCase):
|
||||
def test_stack_trace(self):
|
||||
try:
|
||||
self.marionette.execute_script("""
|
||||
let a = 1;
|
||||
return b;
|
||||
""")
|
||||
self.assertFalse(True)
|
||||
except JavascriptException, inst:
|
||||
self.assertTrue('return b' in inst.stacktrace)
|
||||
|
||||
def test_execute_simple(self):
|
||||
self.assertEqual(1, self.marionette.execute_script("return 1;"))
|
||||
|
||||
@ -43,13 +53,13 @@ let prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
|
||||
self.marionette.execute_script("global.barfoo = [42, 23];")
|
||||
self.assertEqual(self.marionette.execute_script("return global.barfoo;", new_sandbox=False), [42, 23])
|
||||
|
||||
|
||||
def test_that_we_can_pass_in_floats(self):
|
||||
expected_result = 1.2
|
||||
result = self.marionette.execute_script("return arguments[0]",
|
||||
[expected_result])
|
||||
self.assertTrue(isinstance(result, float))
|
||||
self.assertEqual(result, expected_result)
|
||||
expected_result = 1.2
|
||||
result = self.marionette.execute_script("return arguments[0]",
|
||||
[expected_result])
|
||||
self.assertTrue(isinstance(result, float))
|
||||
self.assertEqual(result, expected_result)
|
||||
|
||||
class TestExecuteChrome(TestExecuteContent):
|
||||
def setUp(self):
|
||||
|
@ -279,6 +279,36 @@ function resetValues() {
|
||||
mouseEventsOnly = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an error message for a JavaScript exception thrown during
|
||||
* execute_(async_)script.
|
||||
*
|
||||
* This will generate a [msg, trace] pair like:
|
||||
*
|
||||
* ['ReferenceError: foo is not defined',
|
||||
* 'execute_script @test_foo.py, line 10
|
||||
* inline javascript, line 2
|
||||
* src: "return foo;"']
|
||||
*
|
||||
* @param error An Error object passed to a catch() clause.
|
||||
fnName The name of the function to use in the stack trace message
|
||||
(e.g., 'execute_script').
|
||||
pythonFile The filename of the test file containing the Marionette
|
||||
command that caused this exception to occur.
|
||||
pythonLine The line number of the above test file.
|
||||
script The JS script being executed in text form.
|
||||
*/
|
||||
function createStackMessage(error, fnName, pythonFile, pythonLine, script) {
|
||||
let python_stack = fnName + " @" + pythonFile + ", line " + pythonLine;
|
||||
let stack = error.stack.split("\n");
|
||||
let line = stack[0].substr(stack[0].lastIndexOf(':') + 1);
|
||||
let msg = error.name + ": " + error.message;
|
||||
let trace = python_stack +
|
||||
"\ninline javascript, line " + line +
|
||||
"\nsrc: \"" + script.split("\n")[line] + "\"";
|
||||
return [msg, trace];
|
||||
}
|
||||
|
||||
/*
|
||||
* Marionette Methods
|
||||
*/
|
||||
@ -384,7 +414,7 @@ function executeScript(msg, directInject) {
|
||||
let data = NetUtil.readInputStreamToString(stream, stream.available());
|
||||
script = data + script;
|
||||
}
|
||||
let res = Cu.evalInSandbox(script, sandbox, "1.8");
|
||||
let res = Cu.evalInSandbox(script, sandbox, "1.8", "dummy file" ,0);
|
||||
sendSyncMessage("Marionette:shareData",
|
||||
{log: elementManager.wrapValue(marionetteLogObj.getLogs())});
|
||||
marionetteLogObj.clearLogs();
|
||||
@ -406,16 +436,16 @@ function executeScript(msg, directInject) {
|
||||
return;
|
||||
}
|
||||
|
||||
let scriptSrc = "let __marionetteFunc = function(){" + script + "};" +
|
||||
"__marionetteFunc.apply(null, __marionetteParams);";
|
||||
script = "let __marionetteFunc = function(){" + script + "};" +
|
||||
"__marionetteFunc.apply(null, __marionetteParams);";
|
||||
if (importedScripts.exists()) {
|
||||
let stream = Components.classes["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Components.interfaces.nsIFileInputStream);
|
||||
stream.init(importedScripts, -1, 0, 0);
|
||||
let data = NetUtil.readInputStreamToString(stream, stream.available());
|
||||
scriptSrc = data + scriptSrc;
|
||||
script = data + script;
|
||||
}
|
||||
let res = Cu.evalInSandbox(scriptSrc, sandbox, "1.8");
|
||||
let res = Cu.evalInSandbox(script, sandbox, "1.8", "dummy file", 0);
|
||||
sendSyncMessage("Marionette:shareData",
|
||||
{log: elementManager.wrapValue(marionetteLogObj.getLogs())});
|
||||
marionetteLogObj.clearLogs();
|
||||
@ -424,7 +454,12 @@ function executeScript(msg, directInject) {
|
||||
}
|
||||
catch (e) {
|
||||
// 17 = JavascriptException
|
||||
sendError(e.name + ': ' + e.message, 17, e.stack, asyncTestCommandId);
|
||||
let error = createStackMessage(e,
|
||||
"execute_script",
|
||||
msg.json.filename,
|
||||
msg.json.line,
|
||||
script);
|
||||
sendError(error[0], 17, error[1], asyncTestCommandId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -531,11 +566,15 @@ function executeWithCallback(msg, useFinish) {
|
||||
let data = NetUtil.readInputStreamToString(stream, stream.available());
|
||||
scriptSrc = data + scriptSrc;
|
||||
}
|
||||
Cu.evalInSandbox(scriptSrc, sandbox, "1.8");
|
||||
Cu.evalInSandbox(scriptSrc, sandbox, "1.8", "dummy file", 0);
|
||||
} catch (e) {
|
||||
// 17 = JavascriptException
|
||||
sandbox.asyncComplete(e.name + ': ' + e.message, 17,
|
||||
e.stack, asyncTestCommandId);
|
||||
let error = createStackMessage(e,
|
||||
"execute_async_script",
|
||||
msg.json.filename,
|
||||
msg.json.line,
|
||||
scriptSrc);
|
||||
sandbox.asyncComplete(error[0], 17, error[1], asyncTestCommandId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,6 +380,37 @@ MarionetteServerConnection.prototype = {
|
||||
this.sendToClient({from:this.actorID, error: error_msg}, command_id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates an error message for a JavaScript exception thrown during
|
||||
* execute_(async_)script.
|
||||
*
|
||||
* This will generate a [msg, trace] pair like:
|
||||
*
|
||||
* ['ReferenceError: foo is not defined',
|
||||
* 'execute_script @test_foo.py, line 10
|
||||
* inline javascript, line 2
|
||||
* src: "return foo;"']
|
||||
*
|
||||
* @param error An Error object passed to a catch() clause.
|
||||
fnName The name of the function to use in the stack trace message
|
||||
(e.g., 'execute_script').
|
||||
pythonFile The filename of the test file containing the Marionette
|
||||
command that caused this exception to occur.
|
||||
pythonLine The line number of the above test file.
|
||||
script The JS script being executed in text form.
|
||||
*/
|
||||
createStackMessage: function MDA_createStackMessage(error, fnName, pythonFile,
|
||||
pythonLine, script) {
|
||||
let python_stack = fnName + " @" + pythonFile + ", line " + pythonLine;
|
||||
let stack = error.stack.split("\n");
|
||||
let line = stack[0].substr(stack[0].lastIndexOf(':') + 1);
|
||||
let msg = error.name + ": " + error.message;
|
||||
let trace = python_stack +
|
||||
"\ninline javascript, line " + line +
|
||||
"\nsrc: \"" + script.split("\n")[line] + "\"";
|
||||
return [msg, trace];
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the current active window
|
||||
*
|
||||
@ -737,7 +768,7 @@ MarionetteServerConnection.prototype = {
|
||||
script = data + script;
|
||||
}
|
||||
|
||||
let res = Cu.evalInSandbox(script, sandbox, "1.8");
|
||||
let res = Cu.evalInSandbox(script, sandbox, "1.8", "dummy file", 0);
|
||||
|
||||
if (directInject && !async &&
|
||||
(res == undefined || res.passed == undefined)) {
|
||||
@ -765,6 +796,7 @@ MarionetteServerConnection.prototype = {
|
||||
execute: function MDA_execute(aRequest, directInject) {
|
||||
let timeout = aRequest.scriptTimeout ? aRequest.scriptTimeout : this.scriptTimeout;
|
||||
let command_id = this.command_id = this.getCommandId();
|
||||
let script;
|
||||
this.logRequest("execute", aRequest);
|
||||
if (aRequest.newSandbox == undefined) {
|
||||
//if client does not send a value in newSandbox,
|
||||
@ -778,7 +810,9 @@ MarionetteServerConnection.prototype = {
|
||||
args: aRequest.args,
|
||||
newSandbox: aRequest.newSandbox,
|
||||
timeout: timeout,
|
||||
specialPowers: aRequest.specialPowers
|
||||
specialPowers: aRequest.specialPowers,
|
||||
filename: aRequest.filename,
|
||||
line: aRequest.line
|
||||
},
|
||||
command_id);
|
||||
return;
|
||||
@ -801,7 +835,6 @@ MarionetteServerConnection.prototype = {
|
||||
return marionette.generate_results();
|
||||
};
|
||||
|
||||
let script;
|
||||
if (directInject) {
|
||||
script = aRequest.value;
|
||||
}
|
||||
@ -815,7 +848,12 @@ MarionetteServerConnection.prototype = {
|
||||
false, command_id, timeout);
|
||||
}
|
||||
catch (e) {
|
||||
this.sendError(e.name + ': ' + e.message, 17, e.stack, command_id);
|
||||
let error = this.createStackMessage(e,
|
||||
"execute_script",
|
||||
aRequest.filename,
|
||||
aRequest.line,
|
||||
script);
|
||||
this.sendError(error[0], 17, error[1], command_id);
|
||||
}
|
||||
},
|
||||
|
||||
@ -894,6 +932,7 @@ MarionetteServerConnection.prototype = {
|
||||
executeWithCallback: function MDA_executeWithCallback(aRequest, directInject) {
|
||||
let timeout = aRequest.scriptTimeout ? aRequest.scriptTimeout : this.scriptTimeout;
|
||||
let command_id = this.command_id = this.getCommandId();
|
||||
let script;
|
||||
this.logRequest("executeWithCallback", aRequest);
|
||||
if (aRequest.newSandbox == undefined) {
|
||||
//if client does not send a value in newSandbox,
|
||||
@ -909,7 +948,9 @@ MarionetteServerConnection.prototype = {
|
||||
id: this.command_id,
|
||||
newSandbox: aRequest.newSandbox,
|
||||
timeout: timeout,
|
||||
specialPowers: aRequest.specialPowers
|
||||
specialPowers: aRequest.specialPowers,
|
||||
filename: aRequest.filename,
|
||||
line: aRequest.line
|
||||
},
|
||||
command_id);
|
||||
return;
|
||||
@ -924,7 +965,7 @@ MarionetteServerConnection.prototype = {
|
||||
timeout, this.testName);
|
||||
marionette.command_id = this.command_id;
|
||||
|
||||
function chromeAsyncReturnFunc(value, status) {
|
||||
function chromeAsyncReturnFunc(value, status, stacktrace) {
|
||||
if (that._emu_cbs && Object.keys(that._emu_cbs).length) {
|
||||
value = "Emulator callback still pending when finish() called";
|
||||
status = 500;
|
||||
@ -946,7 +987,7 @@ MarionetteServerConnection.prototype = {
|
||||
marionette.command_id);
|
||||
}
|
||||
else {
|
||||
let error_msg = {message: value, status: status, stacktrace: null};
|
||||
let error_msg = {message: value, status: status, stacktrace: stacktrace};
|
||||
that.sendToClient({from: that.actorID, error: error_msg},
|
||||
marionette.command_id);
|
||||
}
|
||||
@ -982,7 +1023,6 @@ MarionetteServerConnection.prototype = {
|
||||
_chromeSandbox.returnFunc = chromeAsyncReturnFunc;
|
||||
_chromeSandbox.finish = chromeAsyncFinish;
|
||||
|
||||
let script;
|
||||
if (directInject) {
|
||||
script = aRequest.value;
|
||||
}
|
||||
@ -996,7 +1036,12 @@ MarionetteServerConnection.prototype = {
|
||||
this.executeScriptInSandbox(_chromeSandbox, script, directInject,
|
||||
true, command_id, timeout);
|
||||
} catch (e) {
|
||||
chromeAsyncReturnFunc(e.name + ": " + e.message, 17);
|
||||
let error = this.createStackMessage(e,
|
||||
"execute_async_script",
|
||||
aRequest.filename,
|
||||
aRequest.line,
|
||||
script);
|
||||
chromeAsyncReturnFunc(error[0], 17, error[1]);
|
||||
}
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user