Bug 1058158 - run b2g marionette tests in test container, r=jgriffin

This commit is contained in:
Malini Das 2014-08-28 17:34:50 -04:00
parent 969d23129d
commit a13b5b4dbc
17 changed files with 127 additions and 202 deletions

View File

@ -24,6 +24,9 @@ from errors import (
)
from marionette import Marionette
from mozlog.structured.structuredlog import get_default_logger
from wait import Wait
from expected import element_present, element_not_present
class SkipTest(Exception):
"""
@ -79,10 +82,10 @@ def expectedFailure(func):
def skip_if_b2g(target):
def wrapper(self, *args, **kwargs):
if not hasattr(self.marionette, 'b2g') or not self.marionette.b2g:
if not self.marionette.session_capabilities['device'] == 'qemu':
return target(self, *args, **kwargs)
else:
sys.stderr.write('skipping ... ')
raise SkipTest('skipping due to b2g')
return wrapper
def parameterized(func_suffix, *args, **kwargs):
@ -379,6 +382,12 @@ permissions.forEach(function (perm) {
self.marionette.timeouts(self.marionette.TIMEOUT_PAGE, self.marionette.timeout)
else:
self.marionette.timeouts(self.marionette.TIMEOUT_PAGE, 30000)
if hasattr(self, 'test_container') and self.test_container:
self.switch_into_test_container()
else:
if self.marionette.session_capabilities.has_key('b2g') \
and self.marionette.session_capabilities['b2g'] == True:
self.close_test_container()
def tearDown(self):
pass
@ -406,6 +415,96 @@ permissions.forEach(function (perm) {
pass
self.marionette = None
def switch_into_test_container(self):
self.marionette.set_context("content")
frame = None
try:
frame = self.marionette.find_element(
'css selector',
'iframe[src*="app://test-container.gaiamobile.org/index.html"]'
)
except NoSuchElementException:
result = self.marionette.execute_async_script("""
if((navigator.mozSettings == undefined) || (navigator.mozSettings == null) || (navigator.mozApps == undefined) || (navigator.mozApps == null)) {
marionetteScriptFinished(false);
return;
}
let setReq = navigator.mozSettings.createLock().set({'lockscreen.enabled': false});
setReq.onsuccess = function() {
let appsReq = navigator.mozApps.mgmt.getAll();
appsReq.onsuccess = function() {
let apps = appsReq.result;
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
if (app.manifest.name === 'Test Container') {
app.launch();
window.addEventListener('apploadtime', function apploadtime(){
window.removeEventListener('apploadtime', apploadtime);
marionetteScriptFinished(true);
});
return;
}
}
marionetteScriptFinished(false);
}
appsReq.onerror = function() {
marionetteScriptFinished(false);
}
}
setReq.onerror = function() {
marionetteScriptFinished(false);
}""", script_timeout=60000)
self.assertTrue(result)
frame = Wait(self.marionette, timeout=10, interval=0.2).until(element_present(
'css selector',
'iframe[src*="app://test-container.gaiamobile.org/index.html"]'
))
self.marionette.switch_to_frame(frame)
def close_test_container(self):
self.marionette.set_context("content")
self.marionette.switch_to_frame()
result = self.marionette.execute_async_script("""
if((navigator.mozSettings == undefined) || (navigator.mozSettings == null) || (navigator.mozApps == undefined) || (navigator.mozApps == null)) {
marionetteScriptFinished(false);
return;
}
let setReq = navigator.mozSettings.createLock().set({'lockscreen.enabled': false});
setReq.onsuccess = function() {
let appsReq = navigator.mozApps.mgmt.getAll();
appsReq.onsuccess = function() {
let apps = appsReq.result;
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
if (app.manifest.name === 'Test Container') {
let manager = window.wrappedJSObject.AppWindowManager || window.wrappedJSObject.WindowManager;
if (!manager) {
marionetteScriptFinished(false);
return;
}
manager.kill(app.origin);
marionetteScriptFinished(true);
return;
}
}
marionetteScriptFinished(false);
}
appsReq.onerror = function() {
marionetteScriptFinished(false);
}
}
setReq.onerror = function() {
marionetteScriptFinished(false);
}""", script_timeout=60000)
frame = Wait(self.marionette, timeout=10, interval=0.2).until(element_not_present(
'css selector',
'iframe[src*="app://test-container.gaiamobile.org/index.html"]'
))
class MarionetteTestCase(CommonTestCase):
match_re = re.compile(r"test_(.*)\.py$")
@ -418,6 +517,7 @@ class MarionetteTestCase(CommonTestCase):
self.methodName = methodName
self.filepath = filepath
self.testvars = kwargs.pop('testvars', None)
self.test_container = kwargs.pop('test_container', False)
CommonTestCase.__init__(self, methodName, **kwargs)
@classmethod
@ -488,7 +588,7 @@ class MarionetteJSTestCase(CommonTestCase):
self.jsFile = jsFile
self._marionette_weakref = marionette_weakref
self.marionette = None
self.oop = kwargs.pop('oop')
self.test_container = kwargs.pop('test_container', False)
CommonTestCase.__init__(self, methodName)
@classmethod
@ -512,54 +612,6 @@ class MarionetteJSTestCase(CommonTestCase):
head = open(os.path.join(os.path.dirname(self.jsFile), head_js), 'r')
js = head.read() + js;
if self.oop:
print 'running oop'
frame = None
try:
frame = self.marionette.find_element(
'css selector',
'iframe[src*="app://test-container.gaiamobile.org/index.html"]'
)
except NoSuchElementException:
result = self.marionette.execute_async_script("""
let setReq = navigator.mozSettings.createLock().set({'lockscreen.enabled': false});
setReq.onsuccess = function() {
let appsReq = navigator.mozApps.mgmt.getAll();
appsReq.onsuccess = function() {
let apps = appsReq.result;
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
if (app.manifest.name === 'Test Container') {
app.launch();
window.addEventListener('apploadtime', function apploadtime(){
window.removeEventListener('apploadtime', apploadtime);
marionetteScriptFinished(true);
});
return;
}
}
marionetteScriptFinished(false);
}
appsReq.onerror = function() {
marionetteScriptFinished(false);
}
}
setReq.onerror = function() {
marionetteScriptFinished(false);
}""", script_timeout=60000)
self.assertTrue(result)
frame = self.marionette.find_element(
'css selector',
'iframe[src*="app://test-container.gaiamobile.org/index.html"]'
)
self.marionette.switch_to_frame(frame)
main_process = self.marionette.execute_script("""
return SpecialPowers.isMainProcess();
""")
self.assertFalse(main_process)
context = self.context_re.search(js)
if context:
context = context.group(3)
@ -628,8 +680,5 @@ setReq.onerror = function() {
self.loglines = self.marionette.get_logs()
raise
if self.oop:
self.marionette.switch_to_frame()
self.marionette.execute_script("log('TEST-END: %s');" % self.jsFile.replace('\\', '\\\\'))
self.marionette.test_name = None

View File

@ -696,7 +696,7 @@ class BaseMarionetteTestRunner(object):
self.logger.suite_end()
def add_test(self, test, expected='pass', oop=None):
def add_test(self, test, expected='pass', test_container=False):
filepath = os.path.abspath(test)
if os.path.isdir(filepath):
@ -719,8 +719,7 @@ class BaseMarionetteTestRunner(object):
else:
testargs.update({ atype: 'true' })
# testarg_oop = either None, 'true' or 'false'.
testarg_oop = testargs.get('oop')
testarg_b2g = bool(testargs.get('b2g'))
file_ext = os.path.splitext(os.path.split(filepath)[-1])[1]
@ -740,11 +739,6 @@ class BaseMarionetteTestRunner(object):
else:
unfiltered_tests.append(test)
# Don't filter tests with "oop" flag because manifest parser can't
# handle it well.
if testarg_oop is not None:
del testargs['oop']
target_tests = manifest.get(tests=unfiltered_tests, **testargs)
for test in unfiltered_tests:
if test['path'] not in [x['path'] for x in target_tests]:
@ -755,54 +749,21 @@ class BaseMarionetteTestRunner(object):
if not os.path.exists(i["path"]):
raise IOError("test file: %s does not exist" % i["path"])
# manifest_oop is either 'false', 'true' or 'both'. Anything
# else implies 'false'.
manifest_oop = i.get('oop', 'false')
# We only add an oop test when following conditions are met:
# 1) It's written by javascript because we have only
# MarionetteJSTestCase that supports oop mode.
# 2) we're running with "--type=+oop" or no "--type=-oop", which
# follows testarg_oop is either None or 'true' and must not
# be 'false'.
# 3) When no "--type=[+-]oop" is applied, all active tests are
# included in target_tests, so we must filter out those
# really capable of running in oop mode. Besides, oop tests
# must be explicitly specified for backward compatibility. So
# test manifest_oop equals to either 'both' or 'true'.
file_ext = os.path.splitext(os.path.split(i['path'])[-1])[-1]
if (file_ext == '.js' and
testarg_oop != 'false' and
(manifest_oop == 'both' or manifest_oop == 'true')):
self.add_test(i["path"], i["expected"], True)
# We only add an in-process test when following conditions are
# met:
# 1) we're running with "--type=-oop" or no "--type=+oop", which
# follows testarg_oop is either None or 'false' and must not
# be 'true'.
# 2) When no "--type=[+-]oop" is applied, all active tests are
# included in target_tests, so we must filter out those
# really capable of running in in-process mode.
if (testarg_oop != 'true' and
(manifest_oop == 'both' or manifest_oop != 'true')):
self.add_test(i["path"], i["expected"], False)
test_container = False
if i.get('test_container') and i.get('test_container') == 'true' and testarg_b2g:
test_container = True
self.add_test(i["path"], i["expected"], test_container)
return
if oop is None:
# This test is added by directory enumeration or directly specified
# in argument list. We have no manifest information here so we just
# respect the "--type=[+-]oop" argument here.
oop = file_ext == '.js' and testarg_oop == 'true'
self.tests.append({'filepath': filepath, 'expected': expected, 'test_container': test_container})
self.tests.append({'filepath': filepath, 'expected': expected, 'oop': oop})
def run_test(self, filepath, expected, oop):
def run_test(self, filepath, expected, test_container):
testloader = unittest.TestLoader()
suite = unittest.TestSuite()
self.test_kwargs['expected'] = expected
self.test_kwargs['oop'] = oop
self.test_kwargs['test_container'] = test_container
mod_name = os.path.splitext(os.path.split(filepath)[-1])[0]
for handler in self.test_handlers:
if handler.match(os.path.basename(filepath)):
@ -843,7 +804,7 @@ class BaseMarionetteTestRunner(object):
random.shuffle(tests)
for test in tests:
self.run_test(test['filepath'], test['expected'], test['oop'])
self.run_test(test['filepath'], test['expected'], test['test_container'])
if self.marionette.check_for_crash():
break
@ -862,11 +823,7 @@ class BaseMarionetteTestRunner(object):
len(self.tests)))
self.tests = chunks[self.this_chunk - 1]
oop_tests = [x for x in self.tests if x.get('oop')]
self.run_test_set(oop_tests)
in_process_tests = [x for x in self.tests if not x.get('oop')]
self.run_test_set(in_process_tests)
self.run_test_set(self.tests)
def cleanup(self):
if self.httpd:

View File

@ -13,6 +13,7 @@ skip = false
; marionette unit tests
[include:unit/unit-tests.ini]
test_container = true
; webapi tests
[include:../../../../../dom/bluetooth/tests/marionette/manifest.ini]

View File

@ -1,16 +0,0 @@
[DEFAULT]
qemu = false
browser = false
b2g = true
skip = false
oop = both
[test_success_both2.js]
; oop unspecified
[test_success_in_non_oop.js]
oop = false
[test_success_in_oop.js]
oop = true
[test_success_both.js]
oop = both

View File

@ -1,16 +0,0 @@
[DEFAULT]
qemu = false
browser = false
b2g = true
skip = false
oop = false
[test_success_in_non_oop2.js]
; oop unspecified
[test_success_in_non_oop.js]
oop = false
[test_success_in_oop.js]
oop = true
[test_success_both.js]
oop = both

View File

@ -1,16 +0,0 @@
[DEFAULT]
qemu = false
browser = false
b2g = true
skip = false
oop = true
[test_success_in_oop2.js]
; oop unspecified
[test_success_in_non_oop.js]
oop = false
[test_success_in_oop.js]
oop = true
[test_success_both.js]
oop = both

View File

@ -1,14 +0,0 @@
[DEFAULT]
qemu = false
browser = false
b2g = true
skip = false
[test_success_in_non_oop2.js]
; oop unspecified
[test_success_in_non_oop.js]
oop = false
[test_success_in_oop.js]
oop = true
[test_success_both.js]
oop = both

View File

@ -1,10 +0,0 @@
[DEFAULT]
qemu = false
browser = false
b2g = true
skip = false
[include:manifest-oop-unspecified.ini]
[include:manifest-oop-both.ini]
[include:manifest-oop-true.ini]
[include:manifest-oop-false.ini]

View File

@ -1,3 +0,0 @@
MARIONETTE_TIMEOUT = 60000;
ok(true, "Always success");
finish();

View File

@ -1,3 +0,0 @@
MARIONETTE_TIMEOUT = 60000;
ok(true, "Always success");
finish();

View File

@ -1,3 +0,0 @@
MARIONETTE_TIMEOUT = 60000;
ok(SpecialPowers.isMainProcess(), "SpecialPowers.isMainProcess()");
finish();

View File

@ -1,3 +0,0 @@
MARIONETTE_TIMEOUT = 60000;
ok(SpecialPowers.isMainProcess(), "SpecialPowers.isMainProcess()");
finish();

View File

@ -1,3 +0,0 @@
MARIONETTE_TIMEOUT = 60000;
ok(!SpecialPowers.isMainProcess(), "SpecialPowers.isMainProcess()");
finish();

View File

@ -1,3 +0,0 @@
MARIONETTE_TIMEOUT = 60000;
ok(!SpecialPowers.isMainProcess(), "SpecialPowers.isMainProcess()");
finish();

View File

@ -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 MarionetteException, TimeoutException
class TestNavigate(MarionetteTestCase):
@ -61,6 +61,7 @@ class TestNavigate(MarionetteTestCase):
self.assertTrue(self.marionette.execute_script("return window.document.getElementById('someDiv') == undefined;"))
''' Disabled due to Bug 977899
@skip_if_b2g
def test_navigate_frame(self):
self.marionette.navigate(self.marionette.absolute_url("test_iframe.html"))
self.marionette.switch_to_frame(0)

View File

@ -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
class TestSpecialPowersContent(MarionetteTestCase):
@ -10,6 +10,8 @@ class TestSpecialPowersContent(MarionetteTestCase):
testpref = "testing.marionette.contentcharpref"
testvalue = "blabla"
# fails in b2g's test-container: "Error getting pref", Bug 1060061
@skip_if_b2g
def test_prefs(self):
result = self.marionette.execute_script("""
SpecialPowers.setCharPref("%(pref)s", "%(value)s");

View File

@ -18,6 +18,7 @@ skip = false
[test_expectedfail.py]
expected = fail
[test_import_script.py]
b2g = false
[test_import_script_reuse_window.py]
b2g = false
[test_click.py]
@ -65,16 +66,19 @@ b2g = true
browser = false
[test_gesture.py]
disabled = "Bug 1060060"
b2g = true
browser = false
[test_single_finger.py]
disabled = "Bug 1060060"
b2g = true
browser = false
[test_single_finger_desktop.py]
b2g = false
[test_multi_finger.py]
disabled = "Bug 1060060"
b2g = true
browser = false
@ -87,7 +91,9 @@ browser = false
[test_switch_frame.py]
b2g = false
[test_switch_frame_chrome.py]
b2g = false
[test_switch_remote_frame.py]
b2g = false
[test_pagesource.py]
b2g = false
@ -110,6 +116,7 @@ b2g = false
[test_date_time_value.py]
[test_getactiveframe_oop.py]
disabled = "Bug 925688"
b2g = false
[test_submit.py]
[test_chrome_async_finish.js]
[test_screen_orientation.py]
@ -122,5 +129,3 @@ browser = false
b2g = false
[test_set_window_size.py]
b2g = false
[include:oop/manifest.ini]