|
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 |
|
5 import ConfigParser |
|
6 import os |
|
7 import sys |
|
8 import tempfile |
|
9 import traceback |
|
10 |
|
11 # We need to know our current directory so that we can serve our test files from it. |
|
12 here = os.path.abspath(os.path.dirname(__file__)) |
|
13 |
|
14 from automation import Automation |
|
15 from b2gautomation import B2GRemoteAutomation |
|
16 from b2g_desktop import run_desktop_reftests |
|
17 from runreftest import RefTest |
|
18 from runreftest import ReftestOptions |
|
19 from remotereftest import ReftestServer |
|
20 |
|
21 from mozdevice import DeviceManagerADB, DMError |
|
22 from marionette import Marionette |
|
23 import moznetwork |
|
24 |
|
25 class B2GOptions(ReftestOptions): |
|
26 |
|
27 def __init__(self, automation=None, **kwargs): |
|
28 defaults = {} |
|
29 if not automation: |
|
30 automation = B2GRemoteAutomation(None, "fennec", context_chrome=True) |
|
31 |
|
32 ReftestOptions.__init__(self, automation) |
|
33 |
|
34 self.add_option("--browser-arg", action="store", |
|
35 type = "string", dest = "browser_arg", |
|
36 help = "Optional command-line arg to pass to the browser") |
|
37 defaults["browser_arg"] = None |
|
38 |
|
39 self.add_option("--b2gpath", action="store", |
|
40 type = "string", dest = "b2gPath", |
|
41 help = "path to B2G repo or qemu dir") |
|
42 defaults["b2gPath"] = None |
|
43 |
|
44 self.add_option("--marionette", action="store", |
|
45 type = "string", dest = "marionette", |
|
46 help = "host:port to use when connecting to Marionette") |
|
47 defaults["marionette"] = None |
|
48 |
|
49 self.add_option("--emulator", action="store", |
|
50 type="string", dest = "emulator", |
|
51 help = "Architecture of emulator to use: x86 or arm") |
|
52 defaults["emulator"] = None |
|
53 self.add_option("--emulator-res", action="store", |
|
54 type="string", dest = "emulator_res", |
|
55 help = "Emulator resolution of the format '<width>x<height>'") |
|
56 defaults["emulator_res"] = None |
|
57 |
|
58 self.add_option("--no-window", action="store_true", |
|
59 dest = "noWindow", |
|
60 help = "Pass --no-window to the emulator") |
|
61 defaults["noWindow"] = False |
|
62 |
|
63 self.add_option("--adbpath", action="store", |
|
64 type = "string", dest = "adbPath", |
|
65 help = "path to adb") |
|
66 defaults["adbPath"] = "adb" |
|
67 |
|
68 self.add_option("--deviceIP", action="store", |
|
69 type = "string", dest = "deviceIP", |
|
70 help = "ip address of remote device to test") |
|
71 defaults["deviceIP"] = None |
|
72 |
|
73 self.add_option("--devicePort", action="store", |
|
74 type = "string", dest = "devicePort", |
|
75 help = "port of remote device to test") |
|
76 defaults["devicePort"] = 20701 |
|
77 |
|
78 self.add_option("--remote-logfile", action="store", |
|
79 type = "string", dest = "remoteLogFile", |
|
80 help = "Name of log file on the device relative to the device root. PLEASE ONLY USE A FILENAME.") |
|
81 defaults["remoteLogFile"] = None |
|
82 |
|
83 self.add_option("--remote-webserver", action = "store", |
|
84 type = "string", dest = "remoteWebServer", |
|
85 help = "ip address where the remote web server is hosted at") |
|
86 defaults["remoteWebServer"] = None |
|
87 |
|
88 self.add_option("--http-port", action = "store", |
|
89 type = "string", dest = "httpPort", |
|
90 help = "ip address where the remote web server is hosted at") |
|
91 defaults["httpPort"] = automation.DEFAULT_HTTP_PORT |
|
92 |
|
93 self.add_option("--ssl-port", action = "store", |
|
94 type = "string", dest = "sslPort", |
|
95 help = "ip address where the remote web server is hosted at") |
|
96 defaults["sslPort"] = automation.DEFAULT_SSL_PORT |
|
97 |
|
98 self.add_option("--pidfile", action = "store", |
|
99 type = "string", dest = "pidFile", |
|
100 help = "name of the pidfile to generate") |
|
101 defaults["pidFile"] = "" |
|
102 self.add_option("--gecko-path", action="store", |
|
103 type="string", dest="geckoPath", |
|
104 help="the path to a gecko distribution that should " |
|
105 "be installed on the emulator prior to test") |
|
106 defaults["geckoPath"] = None |
|
107 self.add_option("--logcat-dir", action="store", |
|
108 type="string", dest="logcat_dir", |
|
109 help="directory to store logcat dump files") |
|
110 defaults["logcat_dir"] = None |
|
111 self.add_option('--busybox', action='store', |
|
112 type='string', dest='busybox', |
|
113 help="Path to busybox binary to install on device") |
|
114 defaults['busybox'] = None |
|
115 self.add_option("--httpd-path", action = "store", |
|
116 type = "string", dest = "httpdPath", |
|
117 help = "path to the httpd.js file") |
|
118 defaults["httpdPath"] = None |
|
119 self.add_option("--profile", action="store", |
|
120 type="string", dest="profile", |
|
121 help="for desktop testing, the path to the " |
|
122 "gaia profile to use") |
|
123 defaults["profile"] = None |
|
124 self.add_option("--desktop", action="store_true", |
|
125 dest="desktop", |
|
126 help="Run the tests on a B2G desktop build") |
|
127 defaults["desktop"] = False |
|
128 defaults["remoteTestRoot"] = "/data/local/tests" |
|
129 defaults["logFile"] = "reftest.log" |
|
130 defaults["autorun"] = True |
|
131 defaults["closeWhenDone"] = True |
|
132 defaults["testPath"] = "" |
|
133 defaults["runTestsInParallel"] = False |
|
134 |
|
135 self.set_defaults(**defaults) |
|
136 |
|
137 def verifyRemoteOptions(self, options): |
|
138 if options.runTestsInParallel: |
|
139 self.error("Cannot run parallel tests here") |
|
140 |
|
141 if not options.remoteTestRoot: |
|
142 options.remoteTestRoot = self.automation._devicemanager.getDeviceRoot() + "/reftest" |
|
143 options.remoteProfile = options.remoteTestRoot + "/profile" |
|
144 |
|
145 productRoot = options.remoteTestRoot + "/" + self.automation._product |
|
146 if options.utilityPath == self.automation.DIST_BIN: |
|
147 options.utilityPath = productRoot + "/bin" |
|
148 |
|
149 if options.remoteWebServer == None: |
|
150 if os.name != "nt": |
|
151 options.remoteWebServer = moznetwork.get_ip() |
|
152 else: |
|
153 print "ERROR: you must specify a --remote-webserver=<ip address>\n" |
|
154 return None |
|
155 |
|
156 options.webServer = options.remoteWebServer |
|
157 |
|
158 if options.geckoPath and not options.emulator: |
|
159 self.error("You must specify --emulator if you specify --gecko-path") |
|
160 |
|
161 if options.logcat_dir and not options.emulator: |
|
162 self.error("You must specify --emulator if you specify --logcat-dir") |
|
163 |
|
164 #if not options.emulator and not options.deviceIP: |
|
165 # print "ERROR: you must provide a device IP" |
|
166 # return None |
|
167 |
|
168 if options.remoteLogFile == None: |
|
169 options.remoteLogFile = "reftest.log" |
|
170 |
|
171 options.localLogName = options.remoteLogFile |
|
172 options.remoteLogFile = options.remoteTestRoot + '/' + options.remoteLogFile |
|
173 |
|
174 # Ensure that the options.logfile (which the base class uses) is set to |
|
175 # the remote setting when running remote. Also, if the user set the |
|
176 # log file name there, use that instead of reusing the remotelogfile as above. |
|
177 if (options.logFile): |
|
178 # If the user specified a local logfile name use that |
|
179 options.localLogName = options.logFile |
|
180 options.logFile = options.remoteLogFile |
|
181 |
|
182 # Only reset the xrePath if it wasn't provided |
|
183 if options.xrePath == None: |
|
184 options.xrePath = options.utilityPath |
|
185 options.xrePath = os.path.abspath(options.xrePath) |
|
186 |
|
187 if options.pidFile != "": |
|
188 f = open(options.pidFile, 'w') |
|
189 f.write("%s" % os.getpid()) |
|
190 f.close() |
|
191 |
|
192 # httpd-path is specified by standard makefile targets and may be specified |
|
193 # on the command line to select a particular version of httpd.js. If not |
|
194 # specified, try to select the one from from the xre bundle, as required in bug 882932. |
|
195 if not options.httpdPath: |
|
196 options.httpdPath = os.path.join(options.xrePath, "components") |
|
197 |
|
198 return options |
|
199 |
|
200 |
|
201 class ProfileConfigParser(ConfigParser.RawConfigParser): |
|
202 """Subclass of RawConfigParser that outputs .ini files in the exact |
|
203 format expected for profiles.ini, which is slightly different |
|
204 than the default format. |
|
205 """ |
|
206 |
|
207 def optionxform(self, optionstr): |
|
208 return optionstr |
|
209 |
|
210 def write(self, fp): |
|
211 if self._defaults: |
|
212 fp.write("[%s]\n" % ConfigParser.DEFAULTSECT) |
|
213 for (key, value) in self._defaults.items(): |
|
214 fp.write("%s=%s\n" % (key, str(value).replace('\n', '\n\t'))) |
|
215 fp.write("\n") |
|
216 for section in self._sections: |
|
217 fp.write("[%s]\n" % section) |
|
218 for (key, value) in self._sections[section].items(): |
|
219 if key == "__name__": |
|
220 continue |
|
221 if (value is not None) or (self._optcre == self.OPTCRE): |
|
222 key = "=".join((key, str(value).replace('\n', '\n\t'))) |
|
223 fp.write("%s\n" % (key)) |
|
224 fp.write("\n") |
|
225 |
|
226 class B2GRemoteReftest(RefTest): |
|
227 |
|
228 _devicemanager = None |
|
229 localProfile = None |
|
230 remoteApp = '' |
|
231 profile = None |
|
232 |
|
233 def __init__(self, automation, devicemanager, options, scriptDir): |
|
234 RefTest.__init__(self, automation) |
|
235 self._devicemanager = devicemanager |
|
236 self.runSSLTunnel = False |
|
237 self.remoteTestRoot = options.remoteTestRoot |
|
238 self.remoteProfile = options.remoteProfile |
|
239 self.automation.setRemoteProfile(self.remoteProfile) |
|
240 self.localLogName = options.localLogName |
|
241 self.remoteLogFile = options.remoteLogFile |
|
242 self.bundlesDir = '/system/b2g/distribution/bundles' |
|
243 self.userJS = '/data/local/user.js' |
|
244 self.remoteMozillaPath = '/data/b2g/mozilla' |
|
245 self.remoteProfilesIniPath = os.path.join(self.remoteMozillaPath, 'profiles.ini') |
|
246 self.originalProfilesIni = None |
|
247 self.scriptDir = scriptDir |
|
248 self.SERVER_STARTUP_TIMEOUT = 90 |
|
249 if self.automation.IS_DEBUG_BUILD: |
|
250 self.SERVER_STARTUP_TIMEOUT = 180 |
|
251 |
|
252 def cleanup(self, profileDir): |
|
253 # Pull results back from device |
|
254 if (self.remoteLogFile): |
|
255 try: |
|
256 self._devicemanager.getFile(self.remoteLogFile, self.localLogName) |
|
257 except: |
|
258 print "ERROR: We were not able to retrieve the info from %s" % self.remoteLogFile |
|
259 sys.exit(5) |
|
260 |
|
261 # Delete any bundled extensions |
|
262 if profileDir: |
|
263 extensionDir = os.path.join(profileDir, 'extensions', 'staged') |
|
264 for filename in os.listdir(extensionDir): |
|
265 try: |
|
266 self._devicemanager._checkCmd(['shell', 'rm', '-rf', |
|
267 os.path.join(self.bundlesDir, filename)]) |
|
268 except DMError: |
|
269 pass |
|
270 |
|
271 # Restore the original profiles.ini. |
|
272 if self.originalProfilesIni: |
|
273 try: |
|
274 if not self.automation._is_emulator: |
|
275 self.restoreProfilesIni() |
|
276 os.remove(self.originalProfilesIni) |
|
277 except: |
|
278 pass |
|
279 |
|
280 if not self.automation._is_emulator: |
|
281 self._devicemanager.removeFile(self.remoteLogFile) |
|
282 self._devicemanager.removeDir(self.remoteProfile) |
|
283 self._devicemanager.removeDir(self.remoteTestRoot) |
|
284 |
|
285 # Restore the original user.js. |
|
286 self._devicemanager._checkCmd(['shell', 'rm', '-f', self.userJS]) |
|
287 self._devicemanager._checkCmd(['shell', 'dd', 'if=%s.orig' % self.userJS, 'of=%s' % self.userJS]) |
|
288 |
|
289 # We've restored the original profile, so reboot the device so that |
|
290 # it gets picked up. |
|
291 self.automation.rebootDevice() |
|
292 |
|
293 RefTest.cleanup(self, profileDir) |
|
294 if getattr(self, 'pidFile', '') != '': |
|
295 try: |
|
296 os.remove(self.pidFile) |
|
297 os.remove(self.pidFile + ".xpcshell.pid") |
|
298 except: |
|
299 print "Warning: cleaning up pidfile '%s' was unsuccessful from the test harness" % self.pidFile |
|
300 |
|
301 def findPath(self, paths, filename = None): |
|
302 for path in paths: |
|
303 p = path |
|
304 if filename: |
|
305 p = os.path.join(p, filename) |
|
306 if os.path.exists(self.getFullPath(p)): |
|
307 return path |
|
308 return None |
|
309 |
|
310 def startWebServer(self, options): |
|
311 """ Create the webserver on the host and start it up """ |
|
312 remoteXrePath = options.xrePath |
|
313 remoteProfilePath = self.remoteProfile |
|
314 remoteUtilityPath = options.utilityPath |
|
315 localAutomation = Automation() |
|
316 localAutomation.IS_WIN32 = False |
|
317 localAutomation.IS_LINUX = False |
|
318 localAutomation.IS_MAC = False |
|
319 localAutomation.UNIXISH = False |
|
320 hostos = sys.platform |
|
321 if hostos in ['mac', 'darwin']: |
|
322 localAutomation.IS_MAC = True |
|
323 elif hostos in ['linux', 'linux2']: |
|
324 localAutomation.IS_LINUX = True |
|
325 localAutomation.UNIXISH = True |
|
326 elif hostos in ['win32', 'win64']: |
|
327 localAutomation.BIN_SUFFIX = ".exe" |
|
328 localAutomation.IS_WIN32 = True |
|
329 |
|
330 paths = [options.xrePath, |
|
331 localAutomation.DIST_BIN, |
|
332 self.automation._product, |
|
333 os.path.join('..', self.automation._product)] |
|
334 options.xrePath = self.findPath(paths) |
|
335 if options.xrePath == None: |
|
336 print "ERROR: unable to find xulrunner path for %s, please specify with --xre-path" % (os.name) |
|
337 sys.exit(1) |
|
338 paths.append("bin") |
|
339 paths.append(os.path.join("..", "bin")) |
|
340 |
|
341 xpcshell = "xpcshell" |
|
342 if (os.name == "nt"): |
|
343 xpcshell += ".exe" |
|
344 |
|
345 if (options.utilityPath): |
|
346 paths.insert(0, options.utilityPath) |
|
347 options.utilityPath = self.findPath(paths, xpcshell) |
|
348 if options.utilityPath == None: |
|
349 print "ERROR: unable to find utility path for %s, please specify with --utility-path" % (os.name) |
|
350 sys.exit(1) |
|
351 |
|
352 xpcshell = os.path.join(options.utilityPath, xpcshell) |
|
353 if self.automation.elf_arm(xpcshell): |
|
354 raise Exception('xpcshell at %s is an ARM binary; please use ' |
|
355 'the --utility-path argument to specify the path ' |
|
356 'to a desktop version.' % xpcshell) |
|
357 |
|
358 options.serverProfilePath = tempfile.mkdtemp() |
|
359 self.server = ReftestServer(localAutomation, options, self.scriptDir) |
|
360 retVal = self.server.start() |
|
361 if retVal: |
|
362 return retVal |
|
363 |
|
364 if (options.pidFile != ""): |
|
365 f = open(options.pidFile + ".xpcshell.pid", 'w') |
|
366 f.write("%s" % self.server._process.pid) |
|
367 f.close() |
|
368 |
|
369 retVal = self.server.ensureReady(self.SERVER_STARTUP_TIMEOUT) |
|
370 if retVal: |
|
371 return retVal |
|
372 |
|
373 options.xrePath = remoteXrePath |
|
374 options.utilityPath = remoteUtilityPath |
|
375 options.profilePath = remoteProfilePath |
|
376 return 0 |
|
377 |
|
378 def stopWebServer(self, options): |
|
379 if hasattr(self, 'server'): |
|
380 self.server.stop() |
|
381 |
|
382 def restoreProfilesIni(self): |
|
383 # restore profiles.ini on the device to its previous state |
|
384 if not self.originalProfilesIni or not os.access(self.originalProfilesIni, os.F_OK): |
|
385 raise DMError('Unable to install original profiles.ini; file not found: %s', |
|
386 self.originalProfilesIni) |
|
387 |
|
388 self._devicemanager.pushFile(self.originalProfilesIni, self.remoteProfilesIniPath) |
|
389 |
|
390 def updateProfilesIni(self, profilePath): |
|
391 # update profiles.ini on the device to point to the test profile |
|
392 self.originalProfilesIni = tempfile.mktemp() |
|
393 self._devicemanager.getFile(self.remoteProfilesIniPath, self.originalProfilesIni) |
|
394 |
|
395 config = ProfileConfigParser() |
|
396 config.read(self.originalProfilesIni) |
|
397 for section in config.sections(): |
|
398 if 'Profile' in section: |
|
399 config.set(section, 'IsRelative', 0) |
|
400 config.set(section, 'Path', profilePath) |
|
401 |
|
402 newProfilesIni = tempfile.mktemp() |
|
403 with open(newProfilesIni, 'wb') as configfile: |
|
404 config.write(configfile) |
|
405 |
|
406 self._devicemanager.pushFile(newProfilesIni, self.remoteProfilesIniPath) |
|
407 try: |
|
408 os.remove(newProfilesIni) |
|
409 except: |
|
410 pass |
|
411 |
|
412 |
|
413 def createReftestProfile(self, options, reftestlist): |
|
414 profile = RefTest.createReftestProfile(self, options, reftestlist, |
|
415 server=options.remoteWebServer, |
|
416 special_powers=False) |
|
417 profileDir = profile.profile |
|
418 |
|
419 prefs = {} |
|
420 # Turn off the locale picker screen |
|
421 prefs["browser.firstrun.show.localepicker"] = False |
|
422 prefs["browser.homescreenURL"] = "app://test-container.gaiamobile.org/index.html" |
|
423 prefs["browser.manifestURL"] = "app://test-container.gaiamobile.org/manifest.webapp" |
|
424 prefs["browser.tabs.remote"] = False |
|
425 prefs["dom.ipc.tabs.disabled"] = False |
|
426 prefs["dom.mozBrowserFramesEnabled"] = True |
|
427 prefs["font.size.inflation.emPerLine"] = 0 |
|
428 prefs["font.size.inflation.minTwips"] = 0 |
|
429 prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org" |
|
430 prefs["reftest.browser.iframe.enabled"] = False |
|
431 prefs["reftest.remote"] = True |
|
432 prefs["reftest.uri"] = "%s" % reftestlist |
|
433 # Set a future policy version to avoid the telemetry prompt. |
|
434 prefs["toolkit.telemetry.prompted"] = 999 |
|
435 prefs["toolkit.telemetry.notifiedOptOut"] = 999 |
|
436 |
|
437 # Set the extra prefs. |
|
438 profile.set_preferences(prefs) |
|
439 |
|
440 # Copy the profile to the device. |
|
441 self._devicemanager.removeDir(self.remoteProfile) |
|
442 try: |
|
443 self._devicemanager.pushDir(profileDir, self.remoteProfile) |
|
444 except DMError: |
|
445 print "Automation Error: Unable to copy profile to device." |
|
446 raise |
|
447 |
|
448 # Copy the extensions to the B2G bundles dir. |
|
449 extensionDir = os.path.join(profileDir, 'extensions', 'staged') |
|
450 # need to write to read-only dir |
|
451 self._devicemanager._checkCmd(['remount']) |
|
452 for filename in os.listdir(extensionDir): |
|
453 self._devicemanager._checkCmd(['shell', 'rm', '-rf', |
|
454 os.path.join(self.bundlesDir, filename)]) |
|
455 try: |
|
456 self._devicemanager.pushDir(extensionDir, self.bundlesDir) |
|
457 except DMError: |
|
458 print "Automation Error: Unable to copy extensions to device." |
|
459 raise |
|
460 |
|
461 # In B2G, user.js is always read from /data/local, not the profile |
|
462 # directory. Backup the original user.js first so we can restore it. |
|
463 self._devicemanager._checkCmd(['shell', 'rm', '-f', '%s.orig' % self.userJS]) |
|
464 self._devicemanager._checkCmd(['shell', 'dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS]) |
|
465 self._devicemanager.pushFile(os.path.join(profileDir, "user.js"), self.userJS) |
|
466 |
|
467 self.updateProfilesIni(self.remoteProfile) |
|
468 |
|
469 options.profilePath = self.remoteProfile |
|
470 return profile |
|
471 |
|
472 def copyExtraFilesToProfile(self, options, profile): |
|
473 profileDir = profile.profile |
|
474 RefTest.copyExtraFilesToProfile(self, options, profile) |
|
475 try: |
|
476 self._devicemanager.pushDir(profileDir, options.remoteProfile) |
|
477 except DMError: |
|
478 print "Automation Error: Failed to copy extra files to device" |
|
479 raise |
|
480 |
|
481 def getManifestPath(self, path): |
|
482 return path |
|
483 |
|
484 |
|
485 def run_remote_reftests(parser, options, args): |
|
486 auto = B2GRemoteAutomation(None, "fennec", context_chrome=True) |
|
487 |
|
488 # create our Marionette instance |
|
489 kwargs = {} |
|
490 if options.emulator: |
|
491 kwargs['emulator'] = options.emulator |
|
492 auto.setEmulator(True) |
|
493 if options.noWindow: |
|
494 kwargs['noWindow'] = True |
|
495 if options.geckoPath: |
|
496 kwargs['gecko_path'] = options.geckoPath |
|
497 if options.logcat_dir: |
|
498 kwargs['logcat_dir'] = options.logcat_dir |
|
499 if options.busybox: |
|
500 kwargs['busybox'] = options.busybox |
|
501 if options.symbolsPath: |
|
502 kwargs['symbols_path'] = options.symbolsPath |
|
503 if options.emulator_res: |
|
504 kwargs['emulator_res'] = options.emulator_res |
|
505 if options.b2gPath: |
|
506 kwargs['homedir'] = options.b2gPath |
|
507 if options.marionette: |
|
508 host,port = options.marionette.split(':') |
|
509 kwargs['host'] = host |
|
510 kwargs['port'] = int(port) |
|
511 marionette = Marionette.getMarionetteOrExit(**kwargs) |
|
512 auto.marionette = marionette |
|
513 |
|
514 if options.emulator: |
|
515 dm = marionette.emulator.dm |
|
516 else: |
|
517 # create the DeviceManager |
|
518 kwargs = {'adbPath': options.adbPath, |
|
519 'deviceRoot': options.remoteTestRoot} |
|
520 if options.deviceIP: |
|
521 kwargs.update({'host': options.deviceIP, |
|
522 'port': options.devicePort}) |
|
523 dm = DeviagerADB(**kwargs) |
|
524 auto.setDeviceManager(dm) |
|
525 |
|
526 options = parser.verifyRemoteOptions(options) |
|
527 |
|
528 if (options == None): |
|
529 print "ERROR: Invalid options specified, use --help for a list of valid options" |
|
530 sys.exit(1) |
|
531 |
|
532 # TODO fix exception |
|
533 if not options.ignoreWindowSize: |
|
534 parts = dm.getInfo('screen')['screen'][0].split() |
|
535 width = int(parts[0].split(':')[1]) |
|
536 height = int(parts[1].split(':')[1]) |
|
537 if (width < 1366 or height < 1050): |
|
538 print "ERROR: Invalid screen resolution %sx%s, please adjust to 1366x1050 or higher" % (width, height) |
|
539 return 1 |
|
540 |
|
541 auto.setProduct("b2g") |
|
542 auto.test_script = os.path.join(here, 'b2g_start_script.js') |
|
543 auto.test_script_args = [options.remoteWebServer, options.httpPort] |
|
544 auto.logFinish = "REFTEST TEST-START | Shutdown" |
|
545 |
|
546 reftest = B2GRemoteReftest(auto, dm, options, here) |
|
547 options = parser.verifyCommonOptions(options, reftest) |
|
548 |
|
549 logParent = os.path.dirname(options.remoteLogFile) |
|
550 dm.mkDir(logParent); |
|
551 auto.setRemoteLog(options.remoteLogFile) |
|
552 auto.setServerInfo(options.webServer, options.httpPort, options.sslPort) |
|
553 |
|
554 # Hack in a symbolic link for jsreftest |
|
555 os.system("ln -s %s %s" % (os.path.join('..', 'jsreftest'), os.path.join(here, 'jsreftest'))) |
|
556 |
|
557 # Dynamically build the reftest URL if possible, beware that args[0] should exist 'inside' the webroot |
|
558 manifest = args[0] |
|
559 if os.path.exists(os.path.join(here, args[0])): |
|
560 manifest = "http://%s:%s/%s" % (options.remoteWebServer, options.httpPort, args[0]) |
|
561 elif os.path.exists(args[0]): |
|
562 manifestPath = os.path.abspath(args[0]).split(here)[1].strip('/') |
|
563 manifest = "http://%s:%s/%s" % (options.remoteWebServer, options.httpPort, manifestPath) |
|
564 else: |
|
565 print "ERROR: Could not find test manifest '%s'" % manifest |
|
566 return 1 |
|
567 |
|
568 # Start the webserver |
|
569 retVal = 1 |
|
570 try: |
|
571 retVal = reftest.startWebServer(options) |
|
572 if retVal: |
|
573 return retVal |
|
574 procName = options.app.split('/')[-1] |
|
575 if (dm.processExist(procName)): |
|
576 dm.killProcess(procName) |
|
577 |
|
578 cmdlineArgs = ["-reftest", manifest] |
|
579 if getattr(options, 'bootstrap', False): |
|
580 cmdlineArgs = [] |
|
581 |
|
582 retVal = reftest.runTests(manifest, options, cmdlineArgs) |
|
583 except: |
|
584 print "Automation Error: Exception caught while running tests" |
|
585 traceback.print_exc() |
|
586 reftest.stopWebServer(options) |
|
587 try: |
|
588 reftest.cleanup(None) |
|
589 except: |
|
590 pass |
|
591 return 1 |
|
592 |
|
593 reftest.stopWebServer(options) |
|
594 return retVal |
|
595 |
|
596 def main(args=sys.argv[1:]): |
|
597 parser = B2GOptions() |
|
598 options, args = parser.parse_args(args) |
|
599 |
|
600 if options.desktop: |
|
601 return run_desktop_reftests(parser, options, args) |
|
602 return run_remote_reftests(parser, options, args) |
|
603 |
|
604 |
|
605 if __name__ == "__main__": |
|
606 sys.exit(main()) |
|
607 |