Backing out broken marionette update

This commit is contained in:
Malini Das 2013-04-01 11:19:52 -04:00
Родитель 6ce8141676
Коммит 03e7bef90e
22 изменённых файлов: 172 добавлений и 618 удалений

Просмотреть файл

@ -2,7 +2,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from marionette import Marionette, HTMLElement, Actions, MultiActions
from marionette import Marionette, HTMLElement
from marionette_test import MarionetteTestCase, CommonTestCase
from marionette_touch import MarionetteTouchMixin
from emulator import Emulator

Просмотреть файл

@ -42,10 +42,9 @@ class LogcatProc(ProcessHandlerMixin):
class Emulator(object):
deviceRe = re.compile(r"^emulator-(\d+)(\s*)(.*)$")
_default_res = '320x480'
def __init__(self, homedir=None, noWindow=False, logcat_dir=None,
arch="x86", emulatorBinary=None, res=None, sdcard=None,
arch="x86", emulatorBinary=None, res='480x800', sdcard=None,
userdata=None):
self.port = None
self.dm = None
@ -61,7 +60,7 @@ class Emulator(object):
self.logcat_proc = None
self.arch = arch
self.binary = emulatorBinary
self.res = res or self._default_res
self.res = res
self.battery = EmulatorBattery(self)
self.geo = EmulatorGeo(self)
self.screen = EmulatorScreen(self)
@ -337,10 +336,7 @@ waitFor(
# setup DNS fix for networking
self._run_adb(['shell', 'setprop', 'net.dns1', '10.0.2.3'])
def setup(self, marionette, gecko_path=None, busybox=None):
if busybox:
self.install_busybox(busybox)
def setup(self, marionette, gecko_path=None):
if gecko_path:
self.install_gecko(gecko_path, marionette)
@ -364,6 +360,8 @@ waitFor(
# gecko in order to avoid an adb bug in which adb will sometimes
# hang indefinitely while copying large files to the system
# partition.
push_attempts = 10
print 'installing gecko binaries...'
# see bug 809437 for the path that lead to this madness
@ -372,7 +370,18 @@ waitFor(
self._run_adb(['remount'])
self.dm.removeDir('/data/local/b2g')
self.dm.mkDir('/data/local/b2g')
self.dm.pushDir(gecko_path, '/data/local/b2g', retryLimit=10)
for root, dirs, files in os.walk(gecko_path):
for filename in files:
rel_path = os.path.relpath(os.path.join(root, filename), gecko_path)
data_local_file = os.path.join('/data/local/b2g', rel_path)
for retry in range(1, push_attempts + 1):
print 'pushing', data_local_file, '(attempt %s of %s)' % (retry, push_attempts)
try:
self.dm.pushFile(os.path.join(root, filename), data_local_file)
break
except DMError:
if retry == push_attempts:
raise
self.dm.shellCheckOutput(['stop', 'b2g'])
@ -381,11 +390,15 @@ waitFor(
rel_path = os.path.relpath(os.path.join(root, filename), gecko_path)
data_local_file = os.path.join('/data/local/b2g', rel_path)
system_b2g_file = os.path.join('/system/b2g', rel_path)
print 'copying', data_local_file, 'to', system_b2g_file
self.dm.shellCheckOutput(['dd',
'if=%s' % data_local_file,
'of=%s' % system_b2g_file])
try:
self.dm.shellCheckOutput(['dd',
'if=%s' % data_local_file,
'of=%s' % system_b2g_file])
except DMError:
if retry == push_attempts:
raise
self.restart_b2g()
except (DMError, MarionetteException):
@ -402,9 +415,16 @@ waitFor(
def install_busybox(self, busybox):
self._run_adb(['remount'])
push_attempts = 10
remote_file = "/system/bin/busybox"
print 'pushing %s' % remote_file
self.dm.pushFile(busybox, remote_file, retryLimit=10)
for retry in range(1, push_attempts+1):
print 'pushing', remote_file, '(attempt %s of %s)' % (retry, push_attempts)
try:
self.dm.pushFile(busybox, remote_file)
break
except DMError:
if retry == push_attempts:
raise
self._run_adb(['shell', 'cd /system/bin; chmod 555 busybox; for x in `./busybox --list`; do ln -s ./busybox $x; done'])
self.dm._verifyZip()

Просмотреть файл

@ -2,37 +2,10 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
class ErrorCodes(object):
SUCCESS = 0
NO_SUCH_ELEMENT = 7
NO_SUCH_FRAME = 8
UNKNOWN_COMMAND = 9
STALE_ELEMENT_REFERENCE = 10
ELEMENT_NOT_VISIBLE = 11
INVALID_ELEMENT_STATE = 12
UNKNOWN_ERROR = 13
ELEMENT_IS_NOT_SELECTABLE = 15
JAVASCRIPT_ERROR = 17
XPATH_LOOKUP_ERROR = 19
TIMEOUT = 21
NO_SUCH_WINDOW = 23
INVALID_COOKIE_DOMAIN = 24
UNABLE_TO_SET_COOKIE = 25
UNEXPECTED_ALERT_OPEN = 26
NO_ALERT_OPEN = 27
SCRIPT_TIMEOUT = 28
INVALID_ELEMENT_COORDINATES = 29
INVALID_SELECTOR = 32
MOVE_TARGET_OUT_OF_BOUNDS = 34
INVALID_XPATH_SELECTOR = 51
INVALID_XPATH_SELECTOR_RETURN_TYPER = 52
INVALID_RESPONSE = 53
MARIONETTE_ERROR = 500
class MarionetteException(Exception):
def __init__(self, message=None, status=ErrorCodes.MARIONETTE_ERROR, stacktrace=None):
def __init__(self, message=None, status=500, stacktrace=None):
self.msg = message
self.status = status
self.stacktrace = stacktrace
@ -75,9 +48,7 @@ class ScriptTimeoutException(MarionetteException):
pass
class ElementNotVisibleException(MarionetteException):
def __init__(self, message="Element is not currently visible and may not be manipulated",
status=ErrorCodes.ELEMENT_NOT_VISIBLE, stacktrace=None):
MarionetteException.__init__(self, message, status, stacktrace)
pass
class NoSuchFrameException(MarionetteException):
pass
@ -100,3 +71,29 @@ class InvalidSelectorException(MarionetteException):
class MoveTargetOutOfBoundsException(MarionetteException):
pass
class ErrorCodes(object):
SUCCESS = 0
NO_SUCH_ELEMENT = 7
NO_SUCH_FRAME = 8
UNKNOWN_COMMAND = 9
STALE_ELEMENT_REFERENCE = 10
ELEMENT_NOT_VISIBLE = 11
INVALID_ELEMENT_STATE = 12
UNKNOWN_ERROR = 13
ELEMENT_IS_NOT_SELECTABLE = 15
JAVASCRIPT_ERROR = 17
XPATH_LOOKUP_ERROR = 19
TIMEOUT = 21
NO_SUCH_WINDOW = 23
INVALID_COOKIE_DOMAIN = 24
UNABLE_TO_SET_COOKIE = 25
UNEXPECTED_ALERT_OPEN = 26
NO_ALERT_OPEN = 27
SCRIPT_TIMEOUT = 28
INVALID_ELEMENT_COORDINATES = 29
INVALID_SELECTOR = 32
MOVE_TARGET_OUT_OF_BOUNDS = 34
INVALID_XPATH_SELECTOR = 51
INVALID_XPATH_SELECTOR_RETURN_TYPER = 52
INVALID_RESPONSE = 53

Просмотреть файл

@ -21,8 +21,6 @@ class GeckoInstance(object):
"marionette.defaultPrefs.port": 2828,
"browser.warnOnQuit": False}
profile = {"preferences": prefs, "restore":False}
else:
profile = {"profile": profile}
print "starting runner"
self.runner = Runner.create(binary=self.bin, profile_args=profile, cmdargs=['-no-remote'])
self.runner.start()

Просмотреть файл

@ -62,9 +62,6 @@ class HTMLElement(object):
def release(self, touch_id, x=None, y=None):
return self.marionette._send_message('release', 'ok', element=self.id, touchId=touch_id, x=x, y=y)
def cancel_touch(self, touch_id):
return self.marionette._send_message('cancelTouch', 'ok', element=self.id, touchId=touch_id)
@property
def text(self):
return self.marionette._send_message('getElementText', 'value', element=self.id)
@ -134,28 +131,9 @@ class Actions(object):
self.action_chain.append(['wait', time])
return self
def cancel(self):
self.action_chain.append(['cancel'])
return self
def perform(self):
return self.marionette._send_message('actionChain', 'ok', value=self.action_chain)
class MultiActions(object):
def __init__(self, marionette):
self.multi_actions = []
self.max_length = 0
self.marionette = marionette
def add(self, action):
self.multi_actions.append(action.action_chain)
if len(action.action_chain) > self.max_length:
self.max_length = len(action.action_chain)
return self
def perform(self):
return self.marionette._send_message('multiAction', 'ok', value=self.multi_actions, max_length=self.max_length)
class Marionette(object):
CONTEXT_CHROME = 'chrome'
@ -166,7 +144,7 @@ class Marionette(object):
def __init__(self, host='localhost', port=2828, bin=None, profile=None,
emulator=None, sdcard=None, emulatorBinary=None,
emulatorImg=None, emulator_res=None, gecko_path=None,
emulatorImg=None, emulator_res='480x800', gecko_path=None,
connectToRunningEmulator=False, homedir=None, baseurl=None,
noWindow=False, logcat_dir=None, busybox=None):
self.host = host
@ -185,10 +163,6 @@ class Marionette(object):
self._test_name = None
if bin:
port = int(self.port)
if not Marionette.is_port_available(port, host=self.host):
ex_msg = "%s:%d is unavailable." % (self.host, port)
raise MarionetteException(message=ex_msg)
self.instance = GeckoInstance(host=self.host, port=self.port,
bin=self.bin, profile=self.profile)
self.instance.start()
@ -217,9 +191,9 @@ class Marionette(object):
self.client = MarionetteClient(self.host, self.port)
if emulator:
self.emulator.setup(self,
gecko_path=gecko_path,
busybox=busybox)
self.emulator.setup(self, gecko_path=gecko_path)
if busybox:
self.emulator.install_busybox(busybox)
def __del__(self):
if self.emulator:
@ -229,18 +203,6 @@ class Marionette(object):
for qemu in self.extra_emulators:
qemu.emulator.close()
@staticmethod
def is_port_available(port, host=''):
port = int(port)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((host, port))
return True
except socket.error:
return False
finally:
s.close()
@classmethod
def getMarionetteOrExit(cls, *args, **kwargs):
try:
@ -521,7 +483,7 @@ class Marionette(object):
return unwrapped
def execute_js_script(self, script, script_args=None, async=True, new_sandbox=True, special_powers=False, script_timeout=None):
def execute_js_script(self, script, script_args=None, async=True, new_sandbox=True, special_powers=False):
if script_args is None:
script_args = []
args = self.wrapArguments(script_args)
@ -531,11 +493,10 @@ class Marionette(object):
args=args,
async=async,
newSandbox=new_sandbox,
specialPowers=special_powers,
scriptTimeout=script_timeout)
specialPowers=special_powers)
return self.unwrapValue(response)
def execute_script(self, script, script_args=None, new_sandbox=True, special_powers=False, script_timeout=None):
def execute_script(self, script, script_args=None, new_sandbox=True, special_powers=False):
if script_args is None:
script_args = []
args = self.wrapArguments(script_args)
@ -544,11 +505,10 @@ class Marionette(object):
value=script,
args=args,
newSandbox=new_sandbox,
specialPowers=special_powers,
scriptTimeout=script_timeout)
specialPowers=special_powers)
return self.unwrapValue(response)
def execute_async_script(self, script, script_args=None, new_sandbox=True, special_powers=False, script_timeout=None):
def execute_async_script(self, script, script_args=None, new_sandbox=True, special_powers=False):
if script_args is None:
script_args = []
args = self.wrapArguments(script_args)
@ -557,8 +517,7 @@ class Marionette(object):
value=script,
args=args,
newSandbox=new_sandbox,
specialPowers=special_powers,
scriptTimeout=script_timeout)
specialPowers=special_powers)
return self.unwrapValue(response)
def find_element(self, method, target, id=None):

Просмотреть файл

@ -3,7 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import os
from errors import ElementNotVisibleException
"""
Adds touch support in Marionette
@ -18,28 +17,20 @@ class MarionetteTouchMixin(object):
self.library_name = library_name or "SyntheticGestures"
self.import_script(self.library)
def check_element(self, element):
if not element.is_displayed():
raise ElementNotVisibleException
def tap(self, element):
self.check_element(element)
# we pass in touch/mouse/click events if mouse_event_shim.js isn't included in the gaia app
# otherwise, we just send touch events. See Bug 829566
send_all = self.execute_script("return typeof window.wrappedJSObject.MouseEventShim === 'undefined';")
self.execute_script("%s.tap(arguments[0], null, null, null, null, arguments[1]);" % self.library_name, [element, send_all])
def double_tap(self, element):
self.check_element(element)
self.execute_script("%s.dbltap(arguments[0]);" % self.library_name, [element])
def long_press(self, element, holdtime=2000):
self.check_element(element)
#I'm adding holdtime, since we have support for this, and we don't have chaining yet
self.execute_script("%s.hold.apply(this, arguments);" % self.library_name, [element, holdtime, 0, 0, 0, 0, 0])
def flick(self, element, x1, y1, x2, y2, duration=200):
self.check_element(element)
# there's 'flick' which is pixels per second, but I'd rather have the library support it than piece it together here.
self.execute_script("%s.swipe.apply(this, arguments);" % self.library_name, [element, x1, y1, x2, y2, duration])

Просмотреть файл

@ -13,11 +13,10 @@ import socket
import sys
import time
import platform
import moznetwork
import xml.dom.minidom as dom
from manifestparser import TestManifest
from mozhttpd import MozHttpd
from mozhttpd import iface, MozHttpd
from marionette import Marionette
from marionette_test import MarionetteJSTestCase, MarionetteTestCase
@ -66,7 +65,7 @@ class MarionetteTestResult(unittest._TextTestResult):
return
self.stream.writeln('START LOG:')
for line in testcase.loglines:
self.stream.writeln(' '.join(line).encode('ascii', 'replace'))
self.stream.writeln(' '.join(line))
self.stream.writeln('END LOG:')
def getPerfData(self, test):
@ -212,11 +211,11 @@ class MarionetteTestRunner(object):
self.perf = perf
self.perfserv = perfserv
self.gecko_path = gecko_path
self.testvars = {}
self.testvars = None
self.tree = tree
self.device = device
if testvars:
if testvars is not None:
if not os.path.exists(testvars):
raise Exception('--testvars file does not exist')
@ -240,7 +239,6 @@ class MarionetteTestRunner(object):
os.mkdir(self.logcat_dir)
# for XML output
self.testvars['xml_output'] = self.xml_output
self.results = []
def reset_test_stats(self):
@ -251,7 +249,7 @@ class MarionetteTestRunner(object):
self.perfrequest = None
def start_httpd(self):
host = moznetwork.get_ip()
host = iface.get_lan_ip()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("",0))
port = s.getsockname()[1]
@ -584,7 +582,7 @@ def parse_options():
help = "Use a specific image file instead of a fresh one")
parser.add_option('--emulator-res',
action = 'store', dest = 'emulator_res',
default = None, type= 'str',
default = '480x800', type= 'str',
help = 'Set a custom resolution for the emulator. '
'Example: "480x800"')
parser.add_option("--no-window",
@ -636,6 +634,11 @@ def parse_options():
parser.add_option('--tree', dest='tree', action='store',
default='b2g',
help='the tree that the revsion parameter refers to')
parser.add_option('--load-early', dest='load_early', action='store_true',
default=False,
help='on an emulator, causes Marionette to load earlier '
'in the startup process than it otherwise would; needed '
'for testing WebAPIs')
options, tests = parser.parse_args()
@ -657,12 +660,11 @@ def parse_options():
# check for valid resolution string, strip whitespaces
try:
if options.emulator_res:
dims = options.emulator_res.split('x')
assert len(dims) == 2
width = str(int(dims[0]))
height = str(int(dims[1]))
options.emulator_res = 'x'.join([width, height])
dims = options.emulator_res.split('x')
assert len(dims) == 2
width = str(int(dims[0]))
height = str(int(dims[1]))
options.emulator_res = 'x'.join([width, height])
except:
raise ValueError('Invalid emulator resolution format. '
'Should be like "480x800".')

Просмотреть файл

@ -1,27 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import time
from marionette_test import MarionetteTestCase
from marionette import Actions
class testSingleFinger(MarionetteTestCase):
def test_chain(self):
testTouch = self.marionette.absolute_url("testAction.html")
self.marionette.navigate(testTouch)
button = self.marionette.find_element("id", "mozLinkCancel")
action = Actions(self.marionette)
action.press(button).wait(5).cancel()
action.perform()
time.sleep(15)
self.assertEqual("End", self.marionette.execute_script("return document.getElementById('mozLinkCancel').innerHTML;"))
def test_element(self):
testTouch = self.marionette.absolute_url("testAction.html")
self.marionette.navigate(testTouch)
button = self.marionette.find_element("id", "mozLinkCancel")
new_id = button.press()
button.cancel_touch(new_id)
time.sleep(15)
self.assertEqual("End", self.marionette.execute_script("return document.getElementById('mozLinkCancel').innerHTML;"))

Просмотреть файл

@ -2,7 +2,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from marionette_test import MarionetteTestCase
from marionette_test import MarionetteTestCase, skip_if_b2g
from errors import JavascriptException, MarionetteException, ScriptTimeoutException
class TestExecuteAsyncContent(MarionetteTestCase):
@ -19,10 +19,6 @@ class TestExecuteAsyncContent(MarionetteTestCase):
def test_execute_async_timeout(self):
self.assertRaises(ScriptTimeoutException, self.marionette.execute_async_script, "var x = 1;")
def test_execute_async_unique_timeout(self):
self.assertEqual(2, self.marionette.execute_async_script("setTimeout(function() {marionetteScriptFinished(2);}, 2000);", script_timeout=5000))
self.assertRaises(ScriptTimeoutException, self.marionette.execute_async_script, "setTimeout(function() {marionetteScriptFinished(3);}, 2000);")
def test_no_timeout(self):
self.marionette.set_script_timeout(10000)
self.assertTrue(self.marionette.execute_async_script("""
@ -30,6 +26,7 @@ class TestExecuteAsyncContent(MarionetteTestCase):
setTimeout(function() { callback(true); }, 500);
"""))
@skip_if_b2g
def test_execute_async_unload(self):
self.marionette.set_script_timeout(5000)
unload = """
@ -72,7 +69,7 @@ class TestExecuteAsyncContent(MarionetteTestCase):
self.assertRaises(JavascriptException, self.marionette.execute_async_script, """
let prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
marionetteScriptFinished(4);
marionetteScriptFinished(1);
""")
def test_sandbox_reuse(self):
@ -100,10 +97,11 @@ class TestExecuteAsyncChrome(TestExecuteAsyncContent):
pass
def test_execute_permission(self):
self.assertEqual(5, self.marionette.execute_async_script("""
self.assertEqual(1, self.marionette.execute_async_script("""
var c = Components.classes;
marionetteScriptFinished(5);
marionetteScriptFinished(1);
"""))
def test_sandbox_reuse(self):
pass

Просмотреть файл

@ -1,62 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import time
from marionette_test import MarionetteTestCase
from marionette import MultiActions, Actions
class testSingleFinger(MarionetteTestCase):
def test_move_element(self):
testTouch = self.marionette.absolute_url("testAction.html")
self.marionette.navigate(testTouch)
start = self.marionette.find_element("id", "mozLink")
drop = self.marionette.find_element("id", "mozLinkPos")
ele = self.marionette.find_element("id", "mozLinkCopy")
multi_action = MultiActions(self.marionette)
action1 = Actions(self.marionette)
action2 = Actions(self.marionette)
action1.press(start).move(drop).wait(3).release()
action2.press(ele).wait().release()
multi_action.add(action1).add(action2).perform()
time.sleep(15)
self.assertEqual("Move", self.marionette.execute_script("return document.getElementById('mozLink').innerHTML;"))
self.assertEqual("End", self.marionette.execute_script("return document.getElementById('mozLinkPos').innerHTML;"))
self.assertEqual("End", self.marionette.execute_script("return document.getElementById('mozLinkCopy').innerHTML;"))
def test_move_offset_element(self):
testTouch = self.marionette.absolute_url("testAction.html")
self.marionette.navigate(testTouch)
start = self.marionette.find_element("id", "mozLink")
ele = self.marionette.find_element("id", "mozLinkCopy")
multi_action = MultiActions(self.marionette)
action1 = Actions(self.marionette)
action2 = Actions(self.marionette)
action1.press(start).move_by_offset(0,300).wait().release()
action2.press(ele).wait(5).release()
multi_action.add(action1).add(action2).perform()
time.sleep(15)
self.assertEqual("Move", self.marionette.execute_script("return document.getElementById('mozLink').innerHTML;"))
self.assertEqual("End", self.marionette.execute_script("return document.getElementById('mozLinkPos').innerHTML;"))
self.assertEqual("End", self.marionette.execute_script("return document.getElementById('mozLinkCopy').innerHTML;"))
def test_three_fingers(self):
testTouch = self.marionette.absolute_url("testAction.html")
self.marionette.navigate(testTouch)
start_one = self.marionette.find_element("id", "mozLink")
start_two = self.marionette.find_element("id", "mozLinkStart")
drop_two = self.marionette.find_element("id", "mozLinkEnd")
ele = self.marionette.find_element("id", "mozLinkCopy2")
multi_action = MultiActions(self.marionette)
action1 = Actions(self.marionette)
action2 = Actions(self.marionette)
action3 = Actions(self.marionette)
action1.press(start_one).move_by_offset(0,300).release()
action2.press(ele).wait().wait(5).release()
action3.press(start_two).move(drop_two).wait(2).release()
multi_action.add(action1).add(action2).add(action3).perform()
time.sleep(15)
self.assertEqual("Move", self.marionette.execute_script("return document.getElementById('mozLink').innerHTML;"))
self.assertEqual("End", self.marionette.execute_script("return document.getElementById('mozLinkPos').innerHTML;"))
self.assertTrue(self.marionette.execute_script("return document.getElementById('mozLinkCopy2').innerHTML >= 5000;"))
self.assertTrue(self.marionette.execute_script("return document.getElementById('mozLinkEnd').innerHTML >= 5000;"))

Просмотреть файл

@ -18,7 +18,7 @@ class TestTimeouts(MarionetteTestCase):
self.assertRaises(MarionetteException, self.marionette.navigate, test_html)
def test_pagetimeout_pass(self):
self.marionette.timeouts("page load", 60000)
self.marionette.timeouts("page load", 300)
test_html = self.marionette.absolute_url("test.html")
self.marionette.navigate(test_html)

Просмотреть файл

@ -47,10 +47,6 @@ b2g = false
b2g = true
browser = false
[test_cancel.py]
b2g = true
browser = false
[test_press_release.py]
b2g = true
browser = false
@ -59,10 +55,6 @@ browser = false
b2g = true
browser = false
[test_multi_finger.py]
b2g = true
browser = false
[test_simpletest_pass.js]
[test_simpletest_sanity.py]
[test_simpletest_chrome.js]

Просмотреть файл

@ -286,9 +286,9 @@ var SyntheticGestures = (function() {
// If not specified then the center of the target is used. t is the
// optional amount of time between touchstart and touchend event.
function tap(target, then, x, y, t, sendAll) {
if (!SyntheticGestures.touchSupported || !target.ownerDocument.createTouch) {
if (!SyntheticGestures.touchSupported) {
console.warn('tap: touch events not supported; using mouse instead');
return mousetap(target, then, x, y, t, true);
return mousetap(target, then, x, y, t);
}
if (x == null)
@ -312,7 +312,7 @@ var SyntheticGestures = (function() {
// except that interval is the time between taps rather than the time between
// touchstart and touchend
function dbltap(target, then, x, y, interval) {
if (!SyntheticGestures.touchSupported || !target.ownerDocument.createTouch) {
if (!SyntheticGestures.touchSupported) {
console.warn('dbltap: touch events not supported; using mouse instead');
return mousedbltap(target, then, x, y, interval);
}
@ -347,7 +347,7 @@ var SyntheticGestures = (function() {
// Begin a touch at x1,y1 and hold it for holdtime ms,
// then move smoothly to x2,y2 over movetime ms, and then invoke then().
function hold(target, holdtime, x1, y1, x2, y2, movetime, then) {
if (!SyntheticGestures.touchSupported || !target.ownerDocument.createTouch) {
if (!SyntheticGestures.touchSupported) {
console.warn('hold: touch events not supported; using mouse instead');
return mousehold(target, holdtime, x1, y1, x2, y2, movetime, then);
}

Просмотреть файл

@ -3,14 +3,8 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
VIRTUAL_ENV_VERSION="1.8.2"
PYTHON=$1
# Store the current working directory so we can change back into it after
# preparing the Marionette virtualenv
CWD=$(pwd)
if [ -z "${PYTHON}" ]
then
echo "No python found"
@ -35,17 +29,22 @@ fi
if [ -d $VENV_DIR ]
then
echo "Using virtual environment in $VENV_DIR"
cd $VENV_DIR
. bin/activate
else
echo "Creating a virtual environment in $VENV_DIR"
curl https://raw.github.com/pypa/virtualenv/${VIRTUAL_ENV_VERSION}/virtualenv.py | ${PYTHON} - $VENV_DIR
curl https://raw.github.com/pypa/virtualenv/develop/virtualenv.py | ${PYTHON} - $VENV_DIR
cd $VENV_DIR
. bin/activate
# set up mozbase
git clone git://github.com/mozilla/mozbase.git
cd mozbase
python setup_development.py
fi
. $VENV_DIR/bin/activate
# Updating the marionette_client needs us to change into its package folder.
# Otherwise the call to setup.py will hang
# update the marionette_client
cd $MARIONETTE_HOME
python setup.py develop
cd $CWD
# pop off the python parameter
shift

Просмотреть файл

@ -3,7 +3,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
VIRTUAL_ENV_VERSION="49f40128a9ca3824ebf253eca408596e135cf893"
VIRTUAL_ENV_VERSION="1.8.2"
PYTHON=$1
@ -37,7 +37,7 @@ then
echo "Using virtual environment in $VENV_DIR"
else
echo "Creating a virtual environment (version ${VIRTUAL_ENV_VERSION}) in ${VENV_DIR}"
curl https://raw.github.com/pypa/virtualenv/${VIRTUAL_ENV_VERSION}/virtualenv.py | ${PYTHON} - --no-site-packages $VENV_DIR
curl https://raw.github.com/pypa/virtualenv/${VIRTUAL_ENV_VERSION}/virtualenv.py | ${PYTHON} - $VENV_DIR
fi
. $VENV_DIR/bin/activate

Просмотреть файл

@ -15,40 +15,20 @@
<button id="mozLinkPos" style="position:absolute;left:0px;top:355px;" type="button" allowevents=true>Button2</button>
<!-- "mozLinkCopy" listens for a touchdown and touchup -->
<button id="mozLinkCopy" style="position:absolute;left:0px;top:455px;" type="button" allowevents=true>Button3</button>
<!-- "mozLinkStart" and "mozLinkEnd" work together to perform touchdown on mozLinkStart, horizontal move and then touchup on mozLinkEnd -->
<button id="mozLinkStart" style="position:absolute;left:10px;top:200px;" type="button" allowevents=true>Press</button>
<button id="mozLinkEnd" style="position:absolute;left:140px;top:200px;" type="button" allowevents=true>Release</button>
<!-- "mozLinkCopy2" listens for a touchdown and touchup. It shows the time when it's fired-->
<button id="mozLinkCopy2" style="position:absolute;left:80px;top:455px;" type="button" allowevents=true>Button4</button>
<!-- "mozLinkCancel" listens for a touchdown and touchcancel -->
<button id="mozLinkCancel" style="position:absolute;left:0px;top:255px;" type="button" allowevents=true>Button5</button>
<script type="text/javascript">
window.ready = true;
var press = document.getElementById("mozLink");
var second = document.getElementById("mozLinkCopy");
var third = document.getElementById("mozLinkStart");
var fourth = document.getElementById("mozLinkCopy2");
var fifth = document.getElementById("mozLinkCancel");
// touchmove and touchend must be performed on the same element as touchstart
// here is press for vertical move
press.addEventListener("touchstart", function(){changePressText("mozLink")}, false);
press.addEventListener("touchstart", changePressText, false);
press.addEventListener("touchmove", changeMoveText, false);
press.addEventListener("touchend", changeReleaseText, false);
// here is second for a tap
second.addEventListener("touchstart", function(){changePressText("mozLinkCopy")}, false);
second.addEventListener("touchend", function(){changeClickText("mozLinkCopy")}, false);
// here is third for horizontal move
third.addEventListener("touchstart", function(){changePressText("mozLinkStart")}, false);
third.addEventListener("touchmove", changeHorizontalMove, false);
third.addEventListener("touchend", changeHorizontalRelease, false);
// here is fourth for touch up and down with time shown
fourth.addEventListener("touchstart", changeTimePress, false);
fourth.addEventListener("touchend", changeTimeRelease, false);
// here is fifth for a cancel
fifth.addEventListener("touchstart", function(){changePressText("mozLinkCancel")}, false);
fifth.addEventListener("touchcancel", function(){changeClickText("mozLinkCancel")}, false);
function changePressText(strId) {
var press = document.getElementById(strId);
second.addEventListener("touchstart", changeCopyText, false);
second.addEventListener("touchend", changeClickText, false);
function changePressText() {
var press = document.getElementById("mozLink");
press.innerHTML = "Start";
}
@ -57,44 +37,27 @@
move.innerHTML = "Move";
}
function checkPosition(event, ele) {
function changeReleaseText(event) {
var touches = event.changedTouches;
var clientX = touches[0].clientX;
var clientY = touches[0].clientY;
var release = document.getElementById(ele);
var release = document.getElementById("mozLinkPos");
var boxr = release.getBoundingClientRect();
return (clientY >= boxr.top &&
clientY <= boxr.bottom &&
clientX >= boxr.left &&
clientX <= boxr.right);
}
function changeReleaseText(event) {
if (checkPosition(event, "mozLinkPos")) {
document.getElementById("mozLinkPos").innerHTML = "End";
if (clientY >= boxr.top &&
clientY <= boxr.bottom &&
clientX >= boxr.left &&
clientX <= boxr.right) {
release.innerHTML ="End";
}
}
function changeHorizontalMove() {
var press = document.getElementById("mozLinkStart");
if (press.innerHTML == "Start") {
var d = new Date();
press.innerHTML = d.getTime();
}
function changeCopyText() {
var second = document.getElementById("mozLinkCopy");
second.innerHTML = "Start";
}
function changeHorizontalRelease(event) {
if (checkPosition(event, "mozLinkEnd")) {
var press = document.getElementById("mozLinkStart");
var d = new Date();
var timeDiff = d.getTime() - press.innerHTML;
document.getElementById("mozLinkEnd").innerHTML = timeDiff;
}
}
function changeClickText(strId) {
var second = document.getElementById(strId);
function changeClickText() {
var second = document.getElementById("mozLinkCopy");
if (second.innerHTML == "Start") {
second.innerHTML = "End";
}
@ -102,24 +65,6 @@
second.innerHTML = "Error";
}
}
function changeTimePress() {
var fourth = document.getElementById("mozLinkCopy2");
var d = new Date();
fourth.innerHTML = d.getTime();
}
function changeTimeRelease() {
var fourth = document.getElementById("mozLinkCopy2");
if (fourth.innerHTML != "Button4") {
var d = new Date();
var timeDiff = d.getTime() - fourth.innerHTML;
fourth.innerHTML = timeDiff;
}
else {
fourth.innerHTML = "Error";
}
}
</script>
</body>
</html>

Просмотреть файл

@ -1,7 +1,7 @@
import os
from setuptools import setup, find_packages
version = '0.5.21'
version = '0.5.16'
# get documentation from the README
try:
@ -13,8 +13,7 @@ except (OSError, IOError):
# dependencies
deps = ['manifestdestiny', 'mozhttpd >= 0.3',
'mozprocess >= 0.6', 'mozrunner >= 5.11',
'mozdevice >= 0.12', 'moznetwork >= 0.21',
'mozcrash >= 0.5']
'mozdevice >= 0.12']
setup(name='marionette_client',
version=version,

Просмотреть файл

@ -695,10 +695,10 @@ MarionetteDriverActor.prototype = {
* True if the script is asynchronous
*/
executeScriptInSandbox: function MDA_executeScriptInSandbox(sandbox, script,
directInject, async, command_id, timeout) {
directInject, async, command_id) {
if (directInject && async &&
(timeout == null || timeout == 0)) {
(this.scriptTimeout == null || this.scriptTimeout == 0)) {
this.sendError("Please set a timeout", 21, null, command_id);
return;
}
@ -737,7 +737,6 @@ MarionetteDriverActor.prototype = {
* function body
*/
execute: function MDA_execute(aRequest, directInject) {
let timeout = aRequest.scriptTimeout ? aRequest.scriptTimeout : this.scriptTimeout;
let command_id = this.command_id = this.getCommandId();
this.logRequest("execute", aRequest);
if (aRequest.newSandbox == undefined) {
@ -749,7 +748,7 @@ MarionetteDriverActor.prototype = {
this.sendAsync("executeScript", {value: aRequest.value,
args: aRequest.args,
newSandbox: aRequest.newSandbox,
timeout: timeout,
timeout: this.scriptTimeout,
command_id: command_id,
specialPowers: aRequest.specialPowers});
return;
@ -758,7 +757,7 @@ MarionetteDriverActor.prototype = {
let curWindow = this.getCurrentWindow();
let marionette = new Marionette(this, curWindow, "chrome",
this.marionetteLog, this.marionettePerf,
timeout, this.testName);
this.scriptTimeout, this.testName);
let _chromeSandbox = this.createExecuteSandbox(curWindow,
marionette,
aRequest.args,
@ -783,7 +782,7 @@ MarionetteDriverActor.prototype = {
"func.apply(null, __marionetteParams);";
}
this.executeScriptInSandbox(_chromeSandbox, script, directInject,
false, command_id, timeout);
false, command_id);
}
catch (e) {
this.sendError(e.name + ': ' + e.message, 17, e.stack, command_id);
@ -817,7 +816,6 @@ MarionetteDriverActor.prototype = {
* 'timeout' member will be used as the script timeout if it is given
*/
executeJSScript: function MDA_executeJSScript(aRequest) {
let timeout = aRequest.scriptTimeout ? aRequest.scriptTimeout : this.scriptTimeout;
let command_id = this.command_id = this.getCommandId();
//all pure JS scripts will need to call Marionette.finish() to complete the test.
if (aRequest.newSandbox == undefined) {
@ -838,7 +836,7 @@ MarionetteDriverActor.prototype = {
args: aRequest.args,
newSandbox: aRequest.newSandbox,
async: aRequest.async,
timeout: timeout,
timeout: this.scriptTimeout,
command_id: command_id,
specialPowers: aRequest.specialPowers });
}
@ -860,7 +858,6 @@ MarionetteDriverActor.prototype = {
* function body
*/
executeWithCallback: function MDA_executeWithCallback(aRequest, directInject) {
let timeout = aRequest.scriptTimeout ? aRequest.scriptTimeout : this.scriptTimeout;
let command_id = this.command_id = this.getCommandId();
this.logRequest("executeWithCallback", aRequest);
if (aRequest.newSandbox == undefined) {
@ -874,7 +871,7 @@ MarionetteDriverActor.prototype = {
args: aRequest.args,
id: this.command_id,
newSandbox: aRequest.newSandbox,
timeout: timeout,
timeout: this.scriptTimeout,
command_id: command_id,
specialPowers: aRequest.specialPowers});
return;
@ -883,10 +880,9 @@ MarionetteDriverActor.prototype = {
let curWindow = this.getCurrentWindow();
let original_onerror = curWindow.onerror;
let that = this;
that.timeout = timeout;
let marionette = new Marionette(this, curWindow, "chrome",
this.marionetteLog, this.marionettePerf,
timeout, this.testName);
this.scriptTimeout, this.testName);
marionette.command_id = this.command_id;
function chromeAsyncReturnFunc(value, status) {
@ -941,7 +937,7 @@ MarionetteDriverActor.prototype = {
if (this.timer != null) {
this.timer.initWithCallback(function() {
chromeAsyncReturnFunc("timed out", 28);
}, that.timeout, Ci.nsITimer.TYPE_ONESHOT);
}, that.scriptTimeout, Ci.nsITimer.TYPE_ONESHOT);
}
_chromeSandbox.returnFunc = chromeAsyncReturnFunc;
@ -959,7 +955,7 @@ MarionetteDriverActor.prototype = {
}
this.executeScriptInSandbox(_chromeSandbox, script, directInject,
true, command_id, timeout);
true, command_id);
} catch (e) {
chromeAsyncReturnFunc(e.name + ": " + e.message, 17);
}
@ -1340,35 +1336,10 @@ MarionetteDriverActor.prototype = {
let element = aRequest.element;
let x = aRequest.x;
let y = aRequest.y;
if (this.context == "chrome") {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("press", {value: element,
corx: x,
cory: y,
command_id: this.command_id});
}
},
/**
* Cancel touch
*
* @param object aRequest
* 'element' represents the ID of the element to touch
*/
cancelTouch: function MDA_cancelTouch(aRequest) {
this.command_id = this.getCommandId();
let element = aRequest.element;
let touchId = aRequest.touchId;
if (this.context == "chrome") {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("cancelTouch", {value: element,
touchId: touchId,
command_id: this.command_id});
}
this.sendAsync("press", {value: element,
corx: x,
cory: y,
command_id: this.command_id});
},
/**
@ -1383,16 +1354,11 @@ MarionetteDriverActor.prototype = {
let touchId = aRequest.touchId;
let x = aRequest.x;
let y = aRequest.y;
if (this.context == "chrome") {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("release", {value: element,
touchId: touchId,
corx: x,
cory: y,
command_id: this.command_id});
}
this.sendAsync("release", {value: element,
touchId: touchId,
corx: x,
cory: y,
command_id: this.command_id});
},
/**
@ -1412,27 +1378,6 @@ MarionetteDriverActor.prototype = {
}
},
/**
* multiAction
*
* @param object aRequest
* 'value' represents a nested array: inner array represents each event;
* middle array represents collection of events for each finger
* outer array represents all the fingers
*/
multiAction: function MDA_multiAction(aRequest) {
this.command_id = this.getCommandId();
if (this.context == "chrome") {
this.sendError("Not in Chrome", 500, null, this.command_id);
}
else {
this.sendAsync("multiAction", {value: aRequest.value,
maxlen: aRequest.max_length,
command_id: this.command_id});
}
},
/**
* Find an element using the indicated search strategy.
*
@ -2177,9 +2122,7 @@ MarionetteDriverActor.prototype.requestTypes = {
"doubleTap": MarionetteDriverActor.prototype.doubleTap,
"press": MarionetteDriverActor.prototype.press,
"release": MarionetteDriverActor.prototype.release,
"cancelTouch": MarionetteDriverActor.prototype.cancelTouch,
"actionChain": MarionetteDriverActor.prototype.actionChain,
"multiAction": MarionetteDriverActor.prototype.multiAction,
"executeAsyncScript": MarionetteDriverActor.prototype.executeWithCallback,
"executeJSScript": MarionetteDriverActor.prototype.executeJSScript,
"setSearchTimeout": MarionetteDriverActor.prototype.setSearchTimeout,

Просмотреть файл

@ -64,8 +64,6 @@ let touches = [];
// For assigning unique ids to all touches
let nextTouchId = 1000;
let touchIds = {};
// last touch for each fingerId
let multiLast = {};
// last touch for single finger
let lastTouch = null;
/**
@ -110,9 +108,7 @@ function startListeners() {
addMessageListenerId("Marionette:doubleTap", doubleTap);
addMessageListenerId("Marionette:press", press);
addMessageListenerId("Marionette:release", release);
addMessageListenerId("Marionette:cancelTouch", cancelTouch);
addMessageListenerId("Marionette:actionChain", actionChain);
addMessageListenerId("Marionette:multiAction", multiAction);
addMessageListenerId("Marionette:setSearchTimeout", setSearchTimeout);
addMessageListenerId("Marionette:goUrl", goUrl);
addMessageListenerId("Marionette:getUrl", getUrl);
@ -204,9 +200,7 @@ function deleteSession(msg) {
removeMessageListenerId("Marionette:doubleTap", doubleTap);
removeMessageListenerId("Marionette:press", press);
removeMessageListenerId("Marionette:release", release);
removeMessageListenerId("Marionette:cancelTouch", cancelTouch);
removeMessageListenerId("Marionette:actionChain", actionChain);
removeMessageListenerId("Marionette:multiAction", multiAction);
removeMessageListenerId("Marionette:setSearchTimeout", setSearchTimeout);
removeMessageListenerId("Marionette:goUrl", goUrl);
removeMessageListenerId("Marionette:getTitle", getTitle);
@ -308,11 +302,12 @@ function resetValues() {
* Returns a content sandbox that can be used by the execute_foo functions.
*/
function createExecuteContentSandbox(aWindow, timeout) {
let sandbox = new Cu.Sandbox(aWindow, {sandboxPrototype: aWindow});
let sandbox = new Cu.Sandbox(aWindow);
sandbox.global = sandbox;
sandbox.window = aWindow;
sandbox.document = sandbox.window.document;
sandbox.navigator = sandbox.window.navigator;
sandbox.__proto__ = sandbox.window;
sandbox.testUtils = utils;
let marionette = new Marionette(this, aWindow, "content",
@ -894,29 +889,7 @@ function release(msg) {
sendOk(msg.json.command_id);
}
else {
sendError("Element has not been pressed: no such element", 7, null, command_id);
}
}
catch (e) {
sendError(e.message, e.code, e.stack, msg.json.command_id);
}
}
/**
* Function to cancel a touch event
*/
function cancelTouch(msg) {
let command_id = msg.json.command_id;
try {
let id = msg.json.touchId;
if (id in touchIds) {
let startTouch = touchIds[id];
emitTouchEvent('touchcancel', startTouch);
delete touchIds[id];
sendOk(msg.json.command_id);
}
else {
sendError("Element not previously interacted with", 7, null, command_id);
sendError("Element has not be pressed: InvalidElementCoordinates", 29, null, command_id);
}
}
catch (e) {
@ -933,7 +906,6 @@ function actions(finger, touchId, command_id, i){
i = 0;
}
if (i == finger.length) {
sendOk(command_id);
return;
}
let pack = finger[i];
@ -961,7 +933,6 @@ function actions(finger, touchId, command_id, i){
break;
case 'release':
touch = lastTouch;
lastTouch = null;
emitTouchEvent('touchend', touch);
actions(finger, touchId, command_id, i);
break;
@ -1001,12 +972,6 @@ function actions(finger, touchId, command_id, i){
actions(finger, touchId, command_id, i);
}
break;
case 'cancel':
touch = lastTouch;
emitTouchEvent('touchcancel', touch);
lastTouch = null;
actions(finger, touchId, command_id, i);
break;
}
}
@ -1022,185 +987,7 @@ function actionChain(msg) {
let touchId = nextTouchId++;
// loop the action array [ ['press', id], ['move', id], ['release', id] ]
actions(commandArray, touchId, command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, msg.json.command_id);
}
}
/**
* Function to emit touch events which allow multi touch on the screen
* @param type represents the type of event, touch represents the current touch,touches are all pending touches
*/
function emitMultiEvents(type, touch, touches) {
let target = touch.target;
let doc = target.ownerDocument;
let win = doc.defaultView;
// touches that are in the same document
let documentTouches = doc.createTouchList(touches.filter(function(t) {
return t.target.ownerDocument === doc;
}));
// touches on the same target
let targetTouches = doc.createTouchList(touches.filter(function(t) {
return t.target === target;
}));
// Create changed touches
let changedTouches = doc.createTouchList(touch);
// Create the event object
let event = curWindow.document.createEvent('TouchEvent');
event.initTouchEvent(type,
true,
true,
win,
0,
false, false, false, false,
documentTouches,
targetTouches,
changedTouches);
target.dispatchEvent(event);
}
/**
* Function to dispatch one set of actions
* @param touches represents all pending touches, batchIndex represents the batch we are dispatching right now
*/
function setDispatch(batches, touches, command_id, batchIndex) {
if (typeof batchIndex === "undefined") {
batchIndex = 0;
}
// check if all the sets have been fired
if (batchIndex >= batches.length) {
multiLast = {};
sendOk(command_id);
return;
}
// a set of actions need to be done
let batch = batches[batchIndex];
// each action for some finger
let pack;
// the touch id for the finger (pack)
let touchId;
// command for the finger
let command;
// touch that will be created for the finger
let el;
let corx;
let cory;
let touch;
let lastTouch;
let touchIndex;
let waitTime = 0;
let maxTime = 0;
batchIndex++;
// loop through the batch
for (let i = 0; i < batch.length; i++) {
pack = batch[i];
touchId = pack[0];
command = pack[1];
switch (command) {
case 'press':
el = elementManager.getKnownElement(pack[2], curWindow);
// after this block, the element will be scrolled into view
if (!checkVisible(el, command_id)) {
sendError("Element is not currently visible and may not be manipulated", 11, null, command_id);
return;
}
corx = pack[3];
cory = pack[4];
touch = createATouch(el, corx, cory, touchId);
multiLast[touchId] = touch;
touches.push(touch);
emitMultiEvents('touchstart', touch, touches);
break;
case 'release':
touch = multiLast[touchId];
// the index of the previous touch for the finger may change in the touches array
touchIndex = touches.indexOf(touch);
touches.splice(touchIndex, 1);
emitMultiEvents('touchend', touch, touches);
break;
case 'move':
el = elementManager.getKnownElement(pack[2], curWindow);
lastTouch = multiLast[touchId];
let boxTarget = el.getBoundingClientRect();
let startTarget = lastTouch.target;
let boxStart = startTarget.getBoundingClientRect();
// note here corx and cory are relative to the target, not the viewport
// we always want to touch the center of the element if the element is specified
corx = boxTarget.left - boxStart.left + boxTarget.width * 0.5;
cory = boxTarget.top - boxStart.top + boxTarget.height * 0.5;
touch = createATouch(startTarget, corx, cory, touchId);
touchIndex = touches.indexOf(lastTouch);
touches[touchIndex] = touch;
multiLast[touchId] = touch;
emitMultiEvents('touchmove', touch, touches);
break;
case 'moveByOffset':
el = multiLast[touchId].target;
lastTouch = multiLast[touchId];
touchIndex = touches.indexOf(lastTouch);
let doc = el.ownerDocument;
let win = doc.defaultView;
// since x and y are relative to the last touch, therefore, it's relative to the position of the last touch
let clientX = lastTouch.clientX + pack[2],
clientY = lastTouch.clientY + pack[3];
let pageX = clientX + win.pageXOffset,
pageY = clientY + win.pageYOffset;
let screenX = clientX + win.mozInnerScreenX,
screenY = clientY + win.mozInnerScreenY;
touch = doc.createTouch(win, el, touchId, pageX, pageY, screenX, screenY, clientX, clientY);
touches[touchIndex] = touch;
multiLast[touchId] = touch;
emitMultiEvents('touchmove', touch, touches);
break;
case 'wait':
if (pack[2] != undefined ) {
waitTime = pack[2]*1000;
if (waitTime > maxTime) {
maxTime = waitTime;
}
}
break;
}//end of switch block
}//end of for loop
if (maxTime != 0) {
checkTimer.initWithCallback(function(){setDispatch(batches, touches, command_id, batchIndex);}, maxTime, Ci.nsITimer.TYPE_ONE_SHOT);
}
else {
setDispatch(batches, touches, command_id, batchIndex);
}
}
/**
* Function to start multi-action
*/
function multiAction(msg) {
let command_id = msg.json.command_id;
let args = msg.json.value;
// maxlen is the longest action chain for one finger
let maxlen = msg.json.maxlen;
try {
// unwrap the original nested array
let commandArray = elementManager.convertWrappedArguments(args, curWindow);
let concurrentEvent = [];
let temp;
for (let i = 0; i < maxlen; i++) {
let row = [];
for (let j = 0; j < commandArray.length; j++) {
if (commandArray[j][i] != undefined) {
// add finger id to the front of each action, i.e. [finger_id, action, element]
temp = commandArray[j][i];
temp.unshift(j);
row.push(temp);
}
}
concurrentEvent.push(row);
}
// now concurrent event is made of sets where each set contain a list of actions that need to be fired.
// note: each action belongs to a different finger
// pendingTouches keeps track of current touches that's on the screen
let pendingTouches = [];
setDispatch(concurrentEvent, pendingTouches, command_id);
sendOk(msg.json.command_id);
}
catch (e) {
sendError(e.message, e.code, e.stack, msg.json.command_id);

Просмотреть файл

@ -40,7 +40,6 @@
"layout/forms/test/test_bug446663.html" : "bug446663_a cut - got 123, expected",
"layout/forms/test/test_bug477700.html" : "Typing should work - got , expected Test",
"layout/forms/test/test_bug534785.html" : "timed out",
"layout/forms/test/test_bug549170.html": "Bug 843374",
"layout/forms/test/test_bug563642.html" : "timed out",
"layout/forms/test/test_bug572649.html" : "timed out",
"layout/forms/test/test_bug644542.html" : "timed out",

Просмотреть файл

@ -136,8 +136,15 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
def setupTestDir(self):
print 'pushing %s' % self.xpcDir
self.device.pushDir(self.xpcDir, self.remoteScriptsDir, retryLimit=10)
push_attempts = 10
for retry in range(1, push_attempts+1):
print 'pushing', self.xpcDir, '(attempt %s of %s)' % (retry, push_attempts)
try:
self.device.pushDir(self.xpcDir, self.remoteScriptsDir)
break
except DMError:
if retry == push_attempts:
raise
def buildTestList(self):
xpcshell.XPCShellTests.buildTestList(self)

Просмотреть файл

@ -37,12 +37,19 @@ class B2GXPCShellRemote(XPCShellRemote):
if self.device.useZip:
return XPCShellRemote.setupTestDir(self)
push_attempts = 10
for root, dirs, files in os.walk(self.xpcDir):
for filename in files:
rel_path = os.path.relpath(os.path.join(root, filename), self.xpcDir)
test_file = os.path.join(self.remoteScriptsDir, rel_path)
print 'pushing %s' % test_file
self.device.pushFile(os.path.join(root, filename), test_file, retryLimit=10)
for retry in range(1, push_attempts+1):
print 'pushing', test_file, '(attempt %s of %s)' % (retry, push_attempts)
try:
self.device.pushFile(os.path.join(root, filename), test_file)
break
except DMError:
if retry == push_attempts:
raise
# Overridden
def pushLibs(self):