Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
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
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 import mozinfo
6 import moznetwork
7 import optparse
8 import os
9 import tempfile
11 from automationutils import addCommonOptions, isURL
12 from mozprofile import DEFAULT_PORTS
14 here = os.path.abspath(os.path.dirname(__file__))
16 try:
17 from mozbuild.base import MozbuildObject
18 build_obj = MozbuildObject.from_environment(cwd=here)
19 except ImportError:
20 build_obj = None
22 __all__ = ["MochitestOptions", "B2GOptions"]
24 VMWARE_RECORDING_HELPER_BASENAME = "vmwarerecordinghelper"
26 class MochitestOptions(optparse.OptionParser):
27 """Usage instructions for runtests.py.
28 All arguments are optional.
29 If --chrome is specified, chrome tests will be run instead of web content tests.
30 If --browser-chrome is specified, browser-chrome tests will be run instead of web content tests.
31 See <http://mochikit.com/doc/html/MochiKit/Logging.html> for details on the logging levels.
32 """
34 LOG_LEVELS = ("DEBUG", "INFO", "WARNING", "ERROR", "FATAL")
35 LEVEL_STRING = ", ".join(LOG_LEVELS)
36 mochitest_options = [
37 [["--close-when-done"],
38 { "action": "store_true",
39 "dest": "closeWhenDone",
40 "default": False,
41 "help": "close the application when tests are done running",
42 }],
43 [["--appname"],
44 { "action": "store",
45 "type": "string",
46 "dest": "app",
47 "default": None,
48 "help": "absolute path to application, overriding default",
49 }],
50 [["--utility-path"],
51 { "action": "store",
52 "type": "string",
53 "dest": "utilityPath",
54 "default": build_obj.bindir if build_obj is not None else None,
55 "help": "absolute path to directory containing utility programs (xpcshell, ssltunnel, certutil)",
56 }],
57 [["--certificate-path"],
58 { "action": "store",
59 "type": "string",
60 "dest": "certPath",
61 "help": "absolute path to directory containing certificate store to use testing profile",
62 "default": os.path.join(build_obj.topsrcdir, 'build', 'pgo', 'certs') if build_obj is not None else None,
63 }],
64 [["--log-file"],
65 { "action": "store",
66 "type": "string",
67 "dest": "logFile",
68 "metavar": "FILE",
69 "help": "file to which logging occurs",
70 "default": "",
71 }],
72 [["--hide-subtests"],
73 { "action": "store_true",
74 "dest": "hide_subtests",
75 "help": "only show subtest log output if there was a failure",
76 "default": False,
77 }],
78 [["--autorun"],
79 { "action": "store_true",
80 "dest": "autorun",
81 "help": "start running tests when the application starts",
82 "default": False,
83 }],
84 [["--timeout"],
85 { "type": "int",
86 "dest": "timeout",
87 "help": "per-test timeout in seconds",
88 "default": None,
89 }],
90 [["--total-chunks"],
91 { "type": "int",
92 "dest": "totalChunks",
93 "help": "how many chunks to split the tests up into",
94 "default": None,
95 }],
96 [["--this-chunk"],
97 { "type": "int",
98 "dest": "thisChunk",
99 "help": "which chunk to run",
100 "default": None,
101 }],
102 [["--chunk-by-dir"],
103 { "type": "int",
104 "dest": "chunkByDir",
105 "help": "group tests together in the same chunk that are in the same top chunkByDir directories",
106 "default": 0,
107 }],
108 [["--shuffle"],
109 { "dest": "shuffle",
110 "action": "store_true",
111 "help": "randomize test order",
112 "default": False,
113 }],
114 [["--console-level"],
115 { "action": "store",
116 "type": "choice",
117 "dest": "consoleLevel",
118 "choices": LOG_LEVELS,
119 "metavar": "LEVEL",
120 "help": "one of %s to determine the level of console "
121 "logging" % LEVEL_STRING,
122 "default": None,
123 }],
124 [["--file-level"],
125 { "action": "store",
126 "type": "choice",
127 "dest": "fileLevel",
128 "choices": LOG_LEVELS,
129 "metavar": "LEVEL",
130 "help": "one of %s to determine the level of file "
131 "logging if a file has been specified, defaulting "
132 "to INFO" % LEVEL_STRING,
133 "default": "INFO",
134 }],
135 [["--chrome"],
136 { "action": "store_true",
137 "dest": "chrome",
138 "help": "run chrome Mochitests",
139 "default": False,
140 }],
141 [["--ipcplugins"],
142 { "action": "store_true",
143 "dest": "ipcplugins",
144 "help": "run ipcplugins Mochitests",
145 "default": False,
146 }],
147 [["--test-path"],
148 { "action": "store",
149 "type": "string",
150 "dest": "testPath",
151 "help": "start in the given directory's tests",
152 "default": "",
153 }],
154 [["--start-at"],
155 { "action": "store",
156 "type": "string",
157 "dest": "startAt",
158 "help": "skip over tests until reaching the given test",
159 "default": "",
160 }],
161 [["--end-at"],
162 { "action": "store",
163 "type": "string",
164 "dest": "endAt",
165 "help": "don't run any tests after the given one",
166 "default": "",
167 }],
168 [["--browser-chrome"],
169 { "action": "store_true",
170 "dest": "browserChrome",
171 "help": "run browser chrome Mochitests",
172 "default": False,
173 }],
174 [["--subsuite"],
175 { "action": "store",
176 "dest": "subsuite",
177 "help": "subsuite of tests to run",
178 "default": "",
179 }],
180 [["--webapprt-content"],
181 { "action": "store_true",
182 "dest": "webapprtContent",
183 "help": "run WebappRT content tests",
184 "default": False,
185 }],
186 [["--webapprt-chrome"],
187 { "action": "store_true",
188 "dest": "webapprtChrome",
189 "help": "run WebappRT chrome tests",
190 "default": False,
191 }],
192 [["--a11y"],
193 { "action": "store_true",
194 "dest": "a11y",
195 "help": "run accessibility Mochitests",
196 "default": False,
197 }],
198 [["--setenv"],
199 { "action": "append",
200 "type": "string",
201 "dest": "environment",
202 "metavar": "NAME=VALUE",
203 "help": "sets the given variable in the application's "
204 "environment",
205 "default": [],
206 }],
207 [["--exclude-extension"],
208 { "action": "append",
209 "type": "string",
210 "dest": "extensionsToExclude",
211 "help": "excludes the given extension from being installed "
212 "in the test profile",
213 "default": [],
214 }],
215 [["--browser-arg"],
216 { "action": "append",
217 "type": "string",
218 "dest": "browserArgs",
219 "metavar": "ARG",
220 "help": "provides an argument to the test application",
221 "default": [],
222 }],
223 [["--leak-threshold"],
224 { "action": "store",
225 "type": "int",
226 "dest": "leakThreshold",
227 "metavar": "THRESHOLD",
228 "help": "fail if the number of bytes leaked through "
229 "refcounted objects (or bytes in classes with "
230 "MOZ_COUNT_CTOR and MOZ_COUNT_DTOR) is greater "
231 "than the given number",
232 "default": 0,
233 }],
234 [["--fatal-assertions"],
235 { "action": "store_true",
236 "dest": "fatalAssertions",
237 "help": "abort testing whenever an assertion is hit "
238 "(requires a debug build to be effective)",
239 "default": False,
240 }],
241 [["--extra-profile-file"],
242 { "action": "append",
243 "dest": "extraProfileFiles",
244 "help": "copy specified files/dirs to testing profile",
245 "default": [],
246 }],
247 [["--install-extension"],
248 { "action": "append",
249 "dest": "extensionsToInstall",
250 "help": "install the specified extension in the testing profile."
251 "The extension file's name should be <id>.xpi where <id> is"
252 "the extension's id as indicated in its install.rdf."
253 "An optional path can be specified too.",
254 "default": [],
255 }],
256 [["--profile-path"],
257 { "action": "store",
258 "type": "string",
259 "dest": "profilePath",
260 "help": "Directory where the profile will be stored."
261 "This directory will be deleted after the tests are finished",
262 "default": tempfile.mkdtemp(),
263 }],
264 [["--testing-modules-dir"],
265 { "action": "store",
266 "type": "string",
267 "dest": "testingModulesDir",
268 "help": "Directory where testing-only JS modules are located.",
269 "default": None,
270 }],
271 [["--use-vmware-recording"],
272 { "action": "store_true",
273 "dest": "vmwareRecording",
274 "help": "enables recording while the application is running "
275 "inside a VMware Workstation 7.0 or later VM",
276 "default": False,
277 }],
278 [["--repeat"],
279 { "action": "store",
280 "type": "int",
281 "dest": "repeat",
282 "metavar": "REPEAT",
283 "help": "repeats the test or set of tests the given number of times, ie: repeat: 1 will run the test twice.",
284 "default": 0,
285 }],
286 [["--run-until-failure"],
287 { "action": "store_true",
288 "dest": "runUntilFailure",
289 "help": "Run tests repeatedly and stops on the first time a test fails. "
290 "Default cap is 30 runs, which can be overwritten with the --repeat parameter.",
291 "default": False,
292 }],
293 [["--run-only-tests"],
294 { "action": "store",
295 "type": "string",
296 "dest": "runOnlyTests",
297 "help": "JSON list of tests that we only want to run. [DEPRECATED- please use --test-manifest]",
298 "default": None,
299 }],
300 [["--test-manifest"],
301 { "action": "store",
302 "type": "string",
303 "dest": "testManifest",
304 "help": "JSON list of tests to specify 'runtests'. Old format for mobile specific tests",
305 "default": None,
306 }],
307 [["--manifest"],
308 { "action": "store",
309 "type": "string",
310 "dest": "manifestFile",
311 "help": ".ini format of tests to run.",
312 "default": None,
313 }],
314 [["--failure-file"],
315 { "action": "store",
316 "type": "string",
317 "dest": "failureFile",
318 "help": "Filename of the output file where we can store a .json list of failures to be run in the future with --run-only-tests.",
319 "default": None,
320 }],
321 [["--run-slower"],
322 { "action": "store_true",
323 "dest": "runSlower",
324 "help": "Delay execution between test files.",
325 "default": False,
326 }],
327 [["--metro-immersive"],
328 { "action": "store_true",
329 "dest": "immersiveMode",
330 "help": "launches tests in immersive browser",
331 "default": False,
332 }],
333 [["--httpd-path"],
334 { "action": "store",
335 "type": "string",
336 "dest": "httpdPath",
337 "default": None,
338 "help": "path to the httpd.js file",
339 }],
340 [["--setpref"],
341 { "action": "append",
342 "type": "string",
343 "default": [],
344 "dest": "extraPrefs",
345 "metavar": "PREF=VALUE",
346 "help": "defines an extra user preference",
347 }],
348 [["--jsdebugger"],
349 { "action": "store_true",
350 "default": False,
351 "dest": "jsdebugger",
352 "help": "open the browser debugger",
353 }],
354 [["--debug-on-failure"],
355 { "action": "store_true",
356 "default": False,
357 "dest": "debugOnFailure",
358 "help": "breaks execution and enters the JS debugger on a test failure. Should be used together with --jsdebugger."
359 }],
360 [["--e10s"],
361 { "action": "store_true",
362 "default": False,
363 "dest": "e10s",
364 "help": "Run tests with electrolysis preferences and test filtering enabled.",
365 }],
366 [["--dmd-path"],
367 { "action": "store",
368 "default": None,
369 "dest": "dmdPath",
370 "help": "Specifies the path to the directory containing the shared library for DMD.",
371 }],
372 [["--dump-output-directory"],
373 { "action": "store",
374 "default": None,
375 "dest": "dumpOutputDirectory",
376 "help": "Specifies the directory in which to place dumped memory reports.",
377 }],
378 [["--dump-about-memory-after-test"],
379 { "action": "store_true",
380 "default": False,
381 "dest": "dumpAboutMemoryAfterTest",
382 "help": "Produce an about:memory dump after each test in the directory specified "
383 "by --dump-output-directory."
384 }],
385 [["--dump-dmd-after-test"],
386 { "action": "store_true",
387 "default": False,
388 "dest": "dumpDMDAfterTest",
389 "help": "Produce a DMD dump after each test in the directory specified "
390 "by --dump-output-directory."
391 }],
392 [["--slowscript"],
393 { "action": "store_true",
394 "default": False,
395 "dest": "slowscript",
396 "help": "Do not set the JS_DISABLE_SLOW_SCRIPT_SIGNALS env variable; "
397 "when not set, recoverable but misleading SIGSEGV instances "
398 "may occur in Ion/Odin JIT code."
399 }],
400 [["--screenshot-on-fail"],
401 { "action": "store_true",
402 "default": False,
403 "dest": "screenshotOnFail",
404 "help": "Take screenshots on all test failures. Set $MOZ_UPLOAD_DIR to a directory for storing the screenshots."
405 }],
406 [["--quiet"],
407 { "action": "store_true",
408 "default": False,
409 "dest": "quiet",
410 "help": "Do not print test log lines unless a failure occurs."
411 }],
412 [["--pidfile"],
413 { "action": "store",
414 "type": "string",
415 "dest": "pidFile",
416 "help": "name of the pidfile to generate",
417 "default": "",
418 }],
419 ]
421 def __init__(self, **kwargs):
423 optparse.OptionParser.__init__(self, **kwargs)
424 for option, value in self.mochitest_options:
425 self.add_option(*option, **value)
426 addCommonOptions(self)
427 self.set_usage(self.__doc__)
429 def verifyOptions(self, options, mochitest):
430 """ verify correct options and cleanup paths """
432 mozinfo.update({"e10s": options.e10s}) # for test manifest parsing.
434 if options.app is None:
435 if build_obj is not None:
436 options.app = build_obj.get_binary_path()
437 else:
438 self.error("could not find the application path, --appname must be specified")
440 if options.totalChunks is not None and options.thisChunk is None:
441 self.error("thisChunk must be specified when totalChunks is specified")
443 if options.totalChunks:
444 if not 1 <= options.thisChunk <= options.totalChunks:
445 self.error("thisChunk must be between 1 and totalChunks")
447 if options.xrePath is None:
448 # default xrePath to the app path if not provided
449 # but only if an app path was explicitly provided
450 if options.app != self.defaults['app']:
451 options.xrePath = os.path.dirname(options.app)
452 elif build_obj is not None:
453 # otherwise default to dist/bin
454 options.xrePath = build_obj.bindir
455 else:
456 self.error("could not find xre directory, --xre-path must be specified")
458 # allow relative paths
459 options.xrePath = mochitest.getFullPath(options.xrePath)
460 options.profilePath = mochitest.getFullPath(options.profilePath)
461 options.app = mochitest.getFullPath(options.app)
462 if options.dmdPath is not None:
463 options.dmdPath = mochitest.getFullPath(options.dmdPath)
465 if not os.path.exists(options.app):
466 msg = """\
467 Error: Path %(app)s doesn't exist.
468 Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
469 self.error(msg % {"app": options.app})
470 return None
472 if options.utilityPath:
473 options.utilityPath = mochitest.getFullPath(options.utilityPath)
475 if options.certPath:
476 options.certPath = mochitest.getFullPath(options.certPath)
478 if options.symbolsPath and not isURL(options.symbolsPath):
479 options.symbolsPath = mochitest.getFullPath(options.symbolsPath)
481 # Set server information on the options object
482 options.webServer = '127.0.0.1'
483 options.httpPort = DEFAULT_PORTS['http']
484 options.sslPort = DEFAULT_PORTS['https']
485 # options.webSocketPort = DEFAULT_PORTS['ws']
486 options.webSocketPort = str(9988) # <- http://hg.mozilla.org/mozilla-central/file/b871dfb2186f/build/automation.py.in#l30
487 # The default websocket port is incorrect in mozprofile; it is
488 # set to the SSL proxy setting. See:
489 # see https://bugzilla.mozilla.org/show_bug.cgi?id=916517
491 if options.vmwareRecording:
492 if not mozinfo.isWin:
493 self.error("use-vmware-recording is only supported on Windows.")
494 mochitest.vmwareHelperPath = os.path.join(
495 options.utilityPath, VMWARE_RECORDING_HELPER_BASENAME + ".dll")
496 if not os.path.exists(mochitest.vmwareHelperPath):
497 self.error("%s not found, cannot automate VMware recording." %
498 mochitest.vmwareHelperPath)
500 if options.testManifest and options.runOnlyTests:
501 self.error("Please use --test-manifest only and not --run-only-tests")
503 if options.runOnlyTests:
504 if not os.path.exists(os.path.abspath(os.path.join(here, options.runOnlyTests))):
505 self.error("unable to find --run-only-tests file '%s'" % options.runOnlyTests)
506 options.runOnly = True
507 options.testManifest = options.runOnlyTests
508 options.runOnlyTests = None
510 if options.manifestFile and options.testManifest:
511 self.error("Unable to support both --manifest and --test-manifest/--run-only-tests at the same time")
513 if options.webapprtContent and options.webapprtChrome:
514 self.error("Only one of --webapprt-content and --webapprt-chrome may be given.")
516 if options.jsdebugger:
517 options.extraPrefs += [
518 "devtools.debugger.remote-enabled=true",
519 "devtools.debugger.chrome-enabled=true",
520 "devtools.chrome.enabled=true",
521 "devtools.debugger.prompt-connection=false"
522 ]
523 options.autorun = False
525 if options.debugOnFailure and not options.jsdebugger:
526 self.error("--debug-on-failure should be used together with --jsdebugger.")
528 # Try to guess the testing modules directory.
529 # This somewhat grotesque hack allows the buildbot machines to find the
530 # modules directory without having to configure the buildbot hosts. This
531 # code should never be executed in local runs because the build system
532 # should always set the flag that populates this variable. If buildbot ever
533 # passes this argument, this code can be deleted.
534 if options.testingModulesDir is None:
535 possible = os.path.join(here, os.path.pardir, 'modules')
537 if os.path.isdir(possible):
538 options.testingModulesDir = possible
540 # Even if buildbot is updated, we still want this, as the path we pass in
541 # to the app must be absolute and have proper slashes.
542 if options.testingModulesDir is not None:
543 options.testingModulesDir = os.path.normpath(options.testingModulesDir)
545 if not os.path.isabs(options.testingModulesDir):
546 options.testingModulesDir = os.path.abspath(options.testingModulesDir)
548 if not os.path.isdir(options.testingModulesDir):
549 self.error('--testing-modules-dir not a directory: %s' %
550 options.testingModulesDir)
552 options.testingModulesDir = options.testingModulesDir.replace('\\', '/')
553 if options.testingModulesDir[-1] != '/':
554 options.testingModulesDir += '/'
556 if options.immersiveMode:
557 if not mozinfo.isWin:
558 self.error("immersive is only supported on Windows 8 and up.")
559 mochitest.immersiveHelperPath = os.path.join(
560 options.utilityPath, "metrotestharness.exe")
561 if not os.path.exists(mochitest.immersiveHelperPath):
562 self.error("%s not found, cannot launch immersive tests." %
563 mochitest.immersiveHelperPath)
565 if options.runUntilFailure:
566 if not options.repeat:
567 options.repeat = 29
569 if options.dumpOutputDirectory is None:
570 options.dumpOutputDirectory = tempfile.gettempdir()
572 if options.dumpAboutMemoryAfterTest or options.dumpDMDAfterTest:
573 if not os.path.isdir(options.dumpOutputDirectory):
574 self.error('--dump-output-directory not a directory: %s' %
575 options.dumpOutputDirectory)
577 return options
580 class B2GOptions(MochitestOptions):
581 b2g_options = [
582 [["--b2gpath"],
583 { "action": "store",
584 "type": "string",
585 "dest": "b2gPath",
586 "help": "path to B2G repo or qemu dir",
587 "default": None,
588 }],
589 [["--desktop"],
590 { "action": "store_true",
591 "dest": "desktop",
592 "help": "Run the tests on a B2G desktop build",
593 "default": False,
594 }],
595 [["--marionette"],
596 { "action": "store",
597 "type": "string",
598 "dest": "marionette",
599 "help": "host:port to use when connecting to Marionette",
600 "default": None,
601 }],
602 [["--emulator"],
603 { "action": "store",
604 "type": "string",
605 "dest": "emulator",
606 "help": "Architecture of emulator to use: x86 or arm",
607 "default": None,
608 }],
609 [["--wifi"],
610 { "action": "store",
611 "type": "string",
612 "dest": "wifi",
613 "help": "Devine wifi configuration for on device mochitest",
614 "default": False,
615 }],
616 [["--sdcard"],
617 { "action": "store",
618 "type": "string",
619 "dest": "sdcard",
620 "help": "Define size of sdcard: 1MB, 50MB...etc",
621 "default": "10MB",
622 }],
623 [["--no-window"],
624 { "action": "store_true",
625 "dest": "noWindow",
626 "help": "Pass --no-window to the emulator",
627 "default": False,
628 }],
629 [["--adbpath"],
630 { "action": "store",
631 "type": "string",
632 "dest": "adbPath",
633 "help": "path to adb",
634 "default": "adb",
635 }],
636 [["--deviceIP"],
637 { "action": "store",
638 "type": "string",
639 "dest": "deviceIP",
640 "help": "ip address of remote device to test",
641 "default": None,
642 }],
643 [["--devicePort"],
644 { "action": "store",
645 "type": "string",
646 "dest": "devicePort",
647 "help": "port of remote device to test",
648 "default": 20701,
649 }],
650 [["--remote-logfile"],
651 { "action": "store",
652 "type": "string",
653 "dest": "remoteLogFile",
654 "help": "Name of log file on the device relative to the device root. \
655 PLEASE ONLY USE A FILENAME.",
656 "default" : None,
657 }],
658 [["--remote-webserver"],
659 { "action": "store",
660 "type": "string",
661 "dest": "remoteWebServer",
662 "help": "ip address where the remote web server is hosted at",
663 "default": None,
664 }],
665 [["--http-port"],
666 { "action": "store",
667 "type": "string",
668 "dest": "httpPort",
669 "help": "ip address where the remote web server is hosted at",
670 "default": None,
671 }],
672 [["--ssl-port"],
673 { "action": "store",
674 "type": "string",
675 "dest": "sslPort",
676 "help": "ip address where the remote web server is hosted at",
677 "default": None,
678 }],
679 [["--gecko-path"],
680 { "action": "store",
681 "type": "string",
682 "dest": "geckoPath",
683 "help": "the path to a gecko distribution that should \
684 be installed on the emulator prior to test",
685 "default": None,
686 }],
687 [["--profile"],
688 { "action": "store",
689 "type": "string",
690 "dest": "profile",
691 "help": "for desktop testing, the path to the \
692 gaia profile to use",
693 "default": None,
694 }],
695 [["--logcat-dir"],
696 { "action": "store",
697 "type": "string",
698 "dest": "logcat_dir",
699 "help": "directory to store logcat dump files",
700 "default": None,
701 }],
702 [['--busybox'],
703 { "action": 'store',
704 "type": 'string',
705 "dest": 'busybox',
706 "help": "Path to busybox binary to install on device",
707 "default": None,
708 }],
709 [['--profile-data-dir'],
710 { "action": 'store',
711 "type": 'string',
712 "dest": 'profile_data_dir',
713 "help": "Path to a directory containing preference and other \
714 data to be installed into the profile",
715 "default": os.path.join(here, 'profile_data'),
716 }],
717 ]
719 def __init__(self):
720 MochitestOptions.__init__(self)
722 for option in self.b2g_options:
723 self.add_option(*option[0], **option[1])
725 defaults = {}
726 defaults["httpPort"] = DEFAULT_PORTS['http']
727 defaults["sslPort"] = DEFAULT_PORTS['https']
728 defaults["remoteTestRoot"] = "/data/local/tests"
729 defaults["logFile"] = "mochitest.log"
730 defaults["autorun"] = True
731 defaults["closeWhenDone"] = True
732 defaults["testPath"] = ""
733 defaults["extensionsToExclude"] = ["specialpowers"]
734 self.set_defaults(**defaults)
736 def verifyRemoteOptions(self, options):
737 if options.remoteWebServer == None:
738 if os.name != "nt":
739 options.remoteWebServer = moznetwork.get_ip()
740 else:
741 self.error("You must specify a --remote-webserver=<ip address>")
742 options.webServer = options.remoteWebServer
744 if options.geckoPath and not options.emulator:
745 self.error("You must specify --emulator if you specify --gecko-path")
747 if options.logcat_dir and not options.emulator:
748 self.error("You must specify --emulator if you specify --logcat-dir")
750 if not os.path.isdir(options.xrePath):
751 self.error("--xre-path '%s' is not a directory" % options.xrePath)
752 xpcshell = os.path.join(options.xrePath, 'xpcshell')
753 if not os.access(xpcshell, os.F_OK):
754 self.error('xpcshell not found at %s' % xpcshell)
755 if self.elf_arm(xpcshell):
756 self.error('--xre-path points to an ARM version of xpcshell; it '
757 'should instead point to a version that can run on '
758 'your desktop')
760 if options.pidFile != "":
761 f = open(options.pidFile, 'w')
762 f.write("%s" % os.getpid())
763 f.close()
765 return options
767 def verifyOptions(self, options, mochitest):
768 # since we are reusing verifyOptions, it will exit if App is not found
769 temp = options.app
770 options.app = __file__
771 tempPort = options.httpPort
772 tempSSL = options.sslPort
773 tempIP = options.webServer
774 options = MochitestOptions.verifyOptions(self, options, mochitest)
775 options.webServer = tempIP
776 options.app = temp
777 options.sslPort = tempSSL
778 options.httpPort = tempPort
780 return options
782 def elf_arm(self, filename):
783 data = open(filename, 'rb').read(20)
784 return data[:4] == "\x7fELF" and ord(data[18]) == 40 # EM_ARM