|
1 # This Source Code Form is subject to the terms of the Mozilla Public |
|
2 # License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 # You can obtain one at http://mozilla.org/MPL/2.0/. |
|
4 from __future__ import print_function, unicode_literals |
|
5 |
|
6 import json |
|
7 import os |
|
8 import signal |
|
9 import sys |
|
10 import threading |
|
11 |
|
12 here = os.path.abspath(os.path.dirname(__file__)) |
|
13 |
|
14 from runreftest import RefTest, ReftestOptions |
|
15 |
|
16 from marionette import Marionette |
|
17 from mozprocess import ProcessHandler |
|
18 from mozrunner import FirefoxRunner |
|
19 import mozinfo |
|
20 import mozlog |
|
21 |
|
22 log = mozlog.getLogger('REFTEST') |
|
23 |
|
24 class B2GDesktopReftest(RefTest): |
|
25 def __init__(self, marionette): |
|
26 RefTest.__init__(self) |
|
27 self.last_test = os.path.basename(__file__) |
|
28 self.marionette = marionette |
|
29 self.profile = None |
|
30 self.runner = None |
|
31 self.test_script = os.path.join(here, 'b2g_start_script.js') |
|
32 self.timeout = None |
|
33 |
|
34 def run_marionette_script(self): |
|
35 assert(self.marionette.wait_for_port()) |
|
36 self.marionette.start_session() |
|
37 self.marionette.set_context(self.marionette.CONTEXT_CHROME) |
|
38 |
|
39 if os.path.isfile(self.test_script): |
|
40 f = open(self.test_script, 'r') |
|
41 self.test_script = f.read() |
|
42 f.close() |
|
43 self.marionette.execute_script(self.test_script) |
|
44 |
|
45 def run_tests(self, test_path, options): |
|
46 reftestlist = self.getManifestPath(test_path) |
|
47 if not reftestlist.startswith('file://'): |
|
48 reftestlist = 'file://%s' % reftestlist |
|
49 |
|
50 self.profile = self.create_profile(options, reftestlist, |
|
51 profile_to_clone=options.profile) |
|
52 env = self.buildBrowserEnv(options, self.profile.profile) |
|
53 kp_kwargs = { 'processOutputLine': [self._on_output], |
|
54 'onTimeout': [self._on_timeout], |
|
55 'kill_on_timeout': False } |
|
56 |
|
57 if not options.debugger: |
|
58 if not options.timeout: |
|
59 if mozinfo.info['debug']: |
|
60 options.timeout = 420 |
|
61 else: |
|
62 options.timeout = 300 |
|
63 self.timeout = options.timeout + 30.0 |
|
64 |
|
65 log.info("%s | Running tests: start.", os.path.basename(__file__)) |
|
66 cmd, args = self.build_command_line(options.app, |
|
67 ignore_window_size=options.ignoreWindowSize, |
|
68 browser_arg=options.browser_arg) |
|
69 self.runner = FirefoxRunner(profile=self.profile, |
|
70 binary=cmd, |
|
71 cmdargs=args, |
|
72 env=env, |
|
73 process_class=ProcessHandler, |
|
74 symbols_path=options.symbolsPath, |
|
75 kp_kwargs=kp_kwargs) |
|
76 |
|
77 status = 0 |
|
78 try: |
|
79 self.runner.start(outputTimeout=self.timeout) |
|
80 log.info("%s | Application pid: %d", |
|
81 os.path.basename(__file__), |
|
82 self.runner.process_handler.pid) |
|
83 |
|
84 # kick starts the reftest harness |
|
85 self.run_marionette_script() |
|
86 status = self.runner.wait() |
|
87 finally: |
|
88 self.runner.check_for_crashes(test_name=self.last_test) |
|
89 self.runner.cleanup() |
|
90 |
|
91 if status > 0: |
|
92 log.testFail("%s | application terminated with exit code %s", |
|
93 self.last_test, status) |
|
94 elif status < 0: |
|
95 log.info("%s | application killed with signal %s", |
|
96 self.last_test, -status) |
|
97 |
|
98 log.info("%s | Running tests: end.", os.path.basename(__file__)) |
|
99 return status |
|
100 |
|
101 def create_profile(self, options, reftestlist, profile_to_clone=None): |
|
102 profile = RefTest.createReftestProfile(self, options, reftestlist, |
|
103 profile_to_clone=profile_to_clone) |
|
104 |
|
105 prefs = {} |
|
106 # Turn off the locale picker screen |
|
107 prefs["browser.firstrun.show.localepicker"] = False |
|
108 prefs["browser.homescreenURL"] = "app://test-container.gaiamobile.org/index.html" |
|
109 prefs["browser.manifestURL"] = "app://test-container.gaiamobile.org/manifest.webapp" |
|
110 prefs["browser.tabs.remote"] = False |
|
111 prefs["dom.ipc.tabs.disabled"] = False |
|
112 prefs["dom.mozBrowserFramesEnabled"] = True |
|
113 prefs["font.size.inflation.emPerLine"] = 0 |
|
114 prefs["font.size.inflation.minTwips"] = 0 |
|
115 prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org" |
|
116 prefs["reftest.browser.iframe.enabled"] = False |
|
117 prefs["reftest.remote"] = False |
|
118 prefs["reftest.uri"] = "%s" % reftestlist |
|
119 # Set a future policy version to avoid the telemetry prompt. |
|
120 prefs["toolkit.telemetry.prompted"] = 999 |
|
121 prefs["toolkit.telemetry.notifiedOptOut"] = 999 |
|
122 |
|
123 # Set the extra prefs. |
|
124 profile.set_preferences(prefs) |
|
125 return profile |
|
126 |
|
127 def build_command_line(self, app, ignore_window_size=False, |
|
128 browser_arg=None): |
|
129 cmd = os.path.abspath(app) |
|
130 args = ['-marionette'] |
|
131 |
|
132 if browser_arg: |
|
133 args += [browser_arg] |
|
134 |
|
135 if not ignore_window_size: |
|
136 args.extend(['--screen', '800x1000']) |
|
137 return cmd, args |
|
138 |
|
139 def _on_output(self, line): |
|
140 print(line) |
|
141 # TODO use structured logging |
|
142 if "TEST-START" in line and "|" in line: |
|
143 self.last_test = line.split("|")[1].strip() |
|
144 |
|
145 def _on_timeout(self): |
|
146 msg = "%s | application timed out after %s seconds with no output" |
|
147 log.testFail(msg % (self.last_test, self.timeout)) |
|
148 |
|
149 # kill process to get a stack |
|
150 self.runner.stop(sig=signal.SIGABRT) |
|
151 |
|
152 |
|
153 def run_desktop_reftests(parser, options, args): |
|
154 kwargs = {} |
|
155 if options.marionette: |
|
156 host, port = options.marionette.split(':') |
|
157 kwargs['host'] = host |
|
158 kwargs['port'] = int(port) |
|
159 marionette = Marionette.getMarionetteOrExit(**kwargs) |
|
160 |
|
161 reftest = B2GDesktopReftest(marionette) |
|
162 |
|
163 options = ReftestOptions.verifyCommonOptions(parser, options, reftest) |
|
164 if options == None: |
|
165 sys.exit(1) |
|
166 |
|
167 # add a -bin suffix if b2g-bin exists, but just b2g was specified |
|
168 if options.app[-4:] != '-bin': |
|
169 if os.path.isfile("%s-bin" % options.app): |
|
170 options.app = "%s-bin" % options.app |
|
171 |
|
172 if options.desktop and not options.profile: |
|
173 raise Exception("must specify --profile when specifying --desktop") |
|
174 |
|
175 sys.exit(reftest.run_tests(args[0], options)) |