3 # Any copyright is dedicated to the Public Domain.
4 # http://creativecommons.org/publicdomain/zero/1.0/
17 from mozlog
import structured
18 from runxpcshelltests
import XPCShellTests
20 TEST_PASS_STRING
= "TEST-PASS"
21 TEST_FAIL_STRING
= "TEST-UNEXPECTED-FAIL"
23 SIMPLE_PASSING_TEST
= "function run_test() { Assert.ok(true); }"
24 SIMPLE_FAILING_TEST
= "function run_test() { Assert.ok(false); }"
25 SIMPLE_PREFCHECK_TEST
= """
27 Assert.ok(Services.prefs.getBoolPref("fake.pref.to.test"));
31 SIMPLE_UNCAUGHT_REJECTION_TEST
= """
33 Promise.reject(new Error("Test rejection."));
39 function run_test() { run_next_test(); }
41 add_test(function test_simple() {
47 ADD_TEST_FAILING
= """
48 function run_test() { run_next_test(); }
50 add_test(function test_failing() {
56 ADD_TEST_UNCAUGHT_REJECTION
= """
57 function run_test() { run_next_test(); }
59 add_test(function test_uncaught_rejection() {
60 Promise.reject(new Error("Test rejection."));
65 CHILD_TEST_PASSING
= """
66 function run_test () { run_next_test(); }
68 add_test(function test_child_simple () {
69 run_test_in_child("test_pass.js");
74 CHILD_TEST_FAILING
= """
75 function run_test () { run_next_test(); }
77 add_test(function test_child_simple () {
78 run_test_in_child("test_fail.js");
83 CHILD_HARNESS_SIMPLE
= """
84 function run_test () { run_next_test(); }
86 add_test(function test_child_assert () {
87 do_load_child_test_harness();
88 do_test_pending("test child assertion");
89 sendCommand("Assert.ok(true);", do_test_finished);
95 function run_test () { run_next_test(); }
97 add_test(function test_child_simple () {
98 do_test_pending("hang test");
99 do_load_child_test_harness();
100 sendCommand("_testLogger.info('CHILD-TEST-STARTED'); " +
101 + "const _TEST_FILE=['test_pass.js']; _execute_test(); ",
107 SIMPLE_LOOPING_TEST
= """
108 function run_test () { run_next_test(); }
110 add_test(function test_loop () {
115 PASSING_TEST_UNICODE
= rb
"""
116 function run_test () { run_next_test(); }
118 add_test(function test_unicode_print () {
119 Assert.equal("\u201c\u201d", "\u201c\u201d");
124 ADD_TASK_SINGLE
= """
125 function run_test() { run_next_test(); }
127 add_task(async function test_task() {
128 await Promise.resolve(true);
129 await Promise.resolve(false);
133 ADD_TASK_MULTIPLE
= """
134 function run_test() { run_next_test(); }
136 add_task(async function test_task() {
137 await Promise.resolve(true);
140 add_task(async function test_2() {
141 await Promise.resolve(true);
145 ADD_TASK_REJECTED
= """
146 function run_test() { run_next_test(); }
148 add_task(async function test_failing() {
149 await Promise.reject(new Error("I fail."));
153 ADD_TASK_REJECTED_UNDEFINED
= """
154 function run_test() { run_next_test(); }
156 add_task(async function test_failing() {
157 await Promise.reject();
161 ADD_TASK_FAILURE_INSIDE
= """
162 function run_test() { run_next_test(); }
164 add_task(async function test() {
165 let result = await Promise.resolve(false);
171 ADD_TASK_RUN_NEXT_TEST
= """
172 function run_test() { run_next_test(); }
174 add_task(function () {
181 ADD_TASK_STACK_TRACE
= """
182 function run_test() { run_next_test(); }
184 add_task(async function this_test_will_fail() {
185 for (let i = 0; i < 10; ++i) {
186 await Promise.resolve();
193 add_task(async function skipMeNot1() {
194 Assert.ok(true, "Well well well.");
197 add_task(async function skipMe1() {
198 Assert.ok(false, "Not skipped after all.");
201 add_task(async function skipMeNot2() {
202 Assert.ok(true, "Well well well.");
205 add_task(async function skipMeNot3() {
206 Assert.ok(true, "Well well well.");
209 add_task(async function skipMe2() {
210 Assert.ok(false, "Not skipped after all.");
214 ADD_TASK_SKIPALL
= """
215 add_task(async function skipMe1() {
216 Assert.ok(false, "Not skipped after all.");
219 add_task(async function skipMe2() {
220 Assert.ok(false, "Not skipped after all.");
223 add_task(async function skipMe3() {
224 Assert.ok(false, "Not skipped after all.");
227 add_task(async function skipMeNot() {
228 Assert.ok(true, "Well well well.");
231 add_task(async function skipMe4() {
232 Assert.ok(false, "Not skipped after all.");
236 ADD_TEST_THROW_STRING
= """
237 function run_test() {do_throw("Passing a string to do_throw")};
240 ADD_TEST_THROW_OBJECT
= """
242 message: "Error object",
243 fileName: "failure.js",
244 stack: "ERROR STACK",
245 toString: function() {return this.message;}
247 function run_test() {do_throw(error)};
250 ADD_TEST_REPORT_OBJECT
= """
252 message: "Error object",
253 fileName: "failure.js",
254 stack: "ERROR STACK",
255 toString: function() {return this.message;}
257 function run_test() {do_report_unexpected_exception(error)};
260 ADD_TEST_VERBOSE
= """
261 function run_test() {info("a message from info")};
264 # A test for genuine JS-generated Error objects
265 ADD_TEST_REPORT_REF_ERROR
= """
266 function run_test() {
269 obj.noSuchFunction();
272 do_report_unexpected_exception(error);
277 # A test for failure to load a test due to a syntax error
278 LOAD_ERROR_SYNTAX_ERROR
= """
282 # A test for failure to load a test due to an error other than a syntax error
283 LOAD_ERROR_OTHER_ERROR
= """
285 no_such_var = "foo"; // assignment to undeclared variable
288 # A test that crashes outright.
290 function run_test () {
291 const { ctypes } = ChromeUtils.importESModule(
292 "resource://gre/modules/ctypes.sys.mjs"
294 let zero = new ctypes.intptr_t(8);
295 let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
300 # A test for asynchronous cleanup functions
302 function run_test() {
303 // The list of checkpoints in the order we encounter them.
304 let checkpoints = [];
306 // Cleanup tasks, in reverse order
307 registerCleanupFunction(function cleanup_checkout() {
308 Assert.equal(checkpoints.join(""), "123456");
309 info("At this stage, the test has succeeded");
310 do_throw("Throwing an error to force displaying the log");
313 registerCleanupFunction(function sync_cleanup_2() {
317 registerCleanupFunction(async function async_cleanup_4() {
322 registerCleanupFunction(async function async_cleanup_3() {
327 registerCleanupFunction(function async_cleanup_2() {
328 let deferred = Promise.withResolvers();
329 executeSoon(deferred.resolve);
330 return deferred.promise.then(function() {
335 registerCleanupFunction(function sync_cleanup() {
339 registerCleanupFunction(function async_cleanup() {
340 let deferred = Promise.withResolvers();
341 executeSoon(deferred.resolve);
342 return deferred.promise.then(function() {
350 # A test to check that add_test() tests run without run_test()
351 NO_RUN_TEST_ADD_TEST
= """
352 add_test(function no_run_test_add_test() {
358 # A test to check that add_task() tests run without run_test()
359 NO_RUN_TEST_ADD_TASK
= """
360 add_task(function no_run_test_add_task() {
365 # A test to check that both add_task() and add_test() work without run_test()
366 NO_RUN_TEST_ADD_TEST_ADD_TASK
= """
367 add_test(function no_run_test_add_test() {
372 add_task(function no_run_test_add_task() {
377 # A test to check that an empty test file without run_test(),
378 # add_test() or add_task() works.
379 NO_RUN_TEST_EMPTY_TEST
= """
380 // This is an empty test file.
383 NO_RUN_TEST_ADD_TEST_FAIL
= """
384 add_test(function no_run_test_add_test_fail() {
390 NO_RUN_TEST_ADD_TASK_FAIL
= """
391 add_task(function no_run_test_add_task_fail() {
396 NO_RUN_TEST_ADD_TASK_MULTIPLE
= """
397 add_task(async function test_task() {
398 await Promise.resolve(true);
401 add_task(async function test_2() {
402 await Promise.resolve(true);
407 function run_test() {
408 Assert.notEqual(typeof mozinfo, undefined);
409 Assert.notEqual(typeof mozinfo.os, undefined);
414 function run_test () { run_next_test(); }
416 add_test(function test_child_mozinfo () {
417 run_test_in_child("test_mozinfo.js");
423 add_task(function headless_true() {
424 Assert.equal(Services.env.get("MOZ_HEADLESS"), "1", "Check MOZ_HEADLESS");
425 Assert.equal(Services.env.get("DISPLAY"), "77", "Check DISPLAY");
430 add_task(function headless_false() {
431 Assert.notEqual(Services.env.get("MOZ_HEADLESS"), "1", "Check MOZ_HEADLESS");
432 Assert.notEqual(Services.env.get("DISPLAY"), "77", "Check DISPLAY");
437 class XPCShellTestsTests(unittest
.TestCase
):
439 Yes, these are unit tests for a unit test harness.
442 def __init__(self
, name
):
443 super(XPCShellTestsTests
, self
).__init
__(name
)
444 from buildconfig
import substs
445 from mozbuild
.base
import MozbuildObject
447 os
.environ
.pop("MOZ_OBJDIR", None)
448 self
.build_obj
= MozbuildObject
.from_environment()
450 objdir
= self
.build_obj
.topobjdir
451 self
.testing_modules
= os
.path
.join(objdir
, "_tests", "modules")
454 self
.xpcshellBin
= os
.path
.join(
457 substs
["MOZ_MACBUNDLE_NAME"],
463 self
.xpcshellBin
= os
.path
.join(objdir
, "dist", "bin", "xpcshell")
465 if sys
.platform
== "win32":
466 self
.xpcshellBin
+= ".exe"
467 self
.utility_path
= os
.path
.join(objdir
, "dist", "bin")
468 self
.symbols_path
= None
469 candidate_path
= os
.path
.join(self
.build_obj
.distdir
, "crashreporter-symbols")
470 if os
.path
.isdir(candidate_path
):
471 self
.symbols_path
= candidate_path
474 self
.log
= six
.StringIO()
475 self
.tempdir
= tempfile
.mkdtemp()
476 logger
= structured
.commandline
.setup_logging(
477 "selftest%s" % id(self
), {}, {"tbpl": self
.log
}
479 self
.x
= XPCShellTests(logger
)
480 self
.x
.harness_timeout
= 30 if not mozinfo
.info
["ccov"] else 60
483 shutil
.rmtree(self
.tempdir
)
484 self
.x
.shutdownNode()
486 def writeFile(self
, name
, contents
, mode
="w"):
488 Write |contents| to a file named |name| in the temp directory,
489 and return the full path to the file.
491 fullpath
= os
.path
.join(self
.tempdir
, name
)
492 with
open(fullpath
, mode
) as f
:
496 def writeManifest(self
, tests
, prefs
=[]):
498 Write an xpcshell.ini in the temp directory and set
499 self.manifest to its pathname. |tests| is a list containing
500 either strings (for test names), or tuples with a test name
501 as the first element and manifest conditions as the following
502 elements. |prefs| is an optional list of prefs in the form of
503 "prefname=prefvalue" strings.
508 '["%s"]' % (t
if isinstance(t
, six
.string_types
) else t
[0])
510 if isinstance(t
, tuple):
511 testlines
.extend(t
[1:])
514 # Append prefs lines as indented inside "prefs=" manifest option.
515 prefslines
.append(' "%s",' % p
)
523 val
+= "\n".join(prefslines
)
525 val
+= "\n".join(testlines
)
526 self
.manifest
= self
.writeFile("xpcshell.toml", val
)
528 def assertTestResult(self
, expected
, shuffle
=False, verbose
=False, headless
=False):
530 Assert that self.x.runTests with manifest=self.manifest
534 kwargs
["app_binary"] = self
.app_binary
535 kwargs
["xpcshell"] = self
.xpcshellBin
536 kwargs
["symbolsPath"] = self
.symbols_path
537 kwargs
["manifest"] = self
.manifest
538 kwargs
["mozInfo"] = mozinfo
.info
539 kwargs
["shuffle"] = shuffle
540 kwargs
["verbose"] = verbose
541 kwargs
["headless"] = headless
542 kwargs
["sequential"] = True
543 kwargs
["testingModulesDir"] = self
.testing_modules
544 kwargs
["utility_path"] = self
.utility_path
548 self
.x
.runTests(kwargs
),
549 msg
="""Tests should have %s, log:
554 % ("passed" if expected
else "failed", self
.log
.getvalue()),
557 def _assertLog(self
, s
, expected
):
558 l
= self
.log
.getvalue()
562 msg
="""Value %s %s in log:
566 % (s
, "expected" if expected
else "not expected", l
),
569 def assertInLog(self
, s
):
571 Assert that the string |s| is contained in self.log.
573 self
._assertLog
(s
, True)
575 def assertNotInLog(self
, s
):
577 Assert that the string |s| is not contained in self.log.
579 self
._assertLog
(s
, False)
583 Check that a simple test without any manifest conditions passes.
585 self
.writeFile("test_basic.js", SIMPLE_PASSING_TEST
)
586 self
.writeManifest(["test_basic.js"])
588 self
.assertTestResult(True)
589 self
.assertEqual(1, self
.x
.testCount
)
590 self
.assertEqual(1, self
.x
.passCount
)
591 self
.assertEqual(0, self
.x
.failCount
)
592 self
.assertEqual(0, self
.x
.todoCount
)
593 self
.assertInLog(TEST_PASS_STRING
)
594 self
.assertNotInLog(TEST_FAIL_STRING
)
598 Check that a simple failing test without any manifest conditions fails.
600 self
.writeFile("test_basic.js", SIMPLE_FAILING_TEST
)
601 self
.writeManifest(["test_basic.js"])
603 self
.assertTestResult(False)
604 self
.assertEqual(1, self
.x
.testCount
)
605 self
.assertEqual(0, self
.x
.passCount
)
606 self
.assertEqual(1, self
.x
.failCount
)
607 self
.assertEqual(0, self
.x
.todoCount
)
608 self
.assertInLog(TEST_FAIL_STRING
)
609 self
.assertNotInLog(TEST_PASS_STRING
)
611 def testPrefsInManifestVerbose(self
):
613 Check prefs configuration option is supported in xpcshell manifests.
615 self
.writeFile("test_prefs.js", SIMPLE_PREFCHECK_TEST
)
616 self
.writeManifest(tests
=["test_prefs.js"], prefs
=["fake.pref.to.test=true"])
618 self
.assertTestResult(True, verbose
=True)
619 self
.assertInLog(TEST_PASS_STRING
)
620 self
.assertNotInLog(TEST_FAIL_STRING
)
621 self
.assertEqual(1, self
.x
.testCount
)
622 self
.assertEqual(1, self
.x
.passCount
)
623 self
.assertInLog("Per-test extra prefs will be set:")
624 self
.assertInLog("fake.pref.to.test=true")
626 def testPrefsInManifestNonVerbose(self
):
628 Check prefs configuration are not logged in non verbose mode.
630 self
.writeFile("test_prefs.js", SIMPLE_PREFCHECK_TEST
)
631 self
.writeManifest(tests
=["test_prefs.js"], prefs
=["fake.pref.to.test=true"])
633 self
.assertTestResult(True, verbose
=False)
634 self
.assertNotInLog("Per-test extra prefs will be set:")
635 self
.assertNotInLog("fake.pref.to.test=true")
638 mozinfo
.isWin
or not mozinfo
.info
.get("debug"),
639 "We don't have a stack fixer on hand for windows.",
641 def testAssertStack(self
):
643 When an assertion is hit, we should produce a useful stack.
648 add_test(function test_asserts_immediately() {
649 Components.classes["@mozilla.org/xpcom/debug;1"]
650 .getService(Components.interfaces.nsIDebug2)
651 .assertion("foo", "assertion failed", "test.js", 1)
657 self
.writeManifest(["test_assert.js"])
658 self
.assertTestResult(False)
660 self
.assertInLog("###!!! ASSERTION")
661 log_lines
= self
.log
.getvalue().splitlines()
663 unknown_pat
= r
"#\d\d\: \?\?\?\[.* \+0x[a-f0-9]+\]"
665 any(re
.search(unknown_pat
, line
) for line
in log_lines
),
666 "An stack frame without symbols was found in\n%s"
667 % pprint
.pformat(log_lines
),
670 any(re
.search(line_pat
, line
) for line
in log_lines
),
671 "No line resembling a stack frame was found in\n%s"
672 % pprint
.pformat(log_lines
),
675 def testChildPass(self
):
677 Check that a simple test running in a child process passes.
679 self
.writeFile("test_pass.js", SIMPLE_PASSING_TEST
)
680 self
.writeFile("test_child_pass.js", CHILD_TEST_PASSING
)
681 self
.writeManifest(["test_child_pass.js"])
683 self
.assertTestResult(True, verbose
=True)
684 self
.assertEqual(1, self
.x
.testCount
)
685 self
.assertEqual(1, self
.x
.passCount
)
686 self
.assertEqual(0, self
.x
.failCount
)
687 self
.assertEqual(0, self
.x
.todoCount
)
688 self
.assertInLog(TEST_PASS_STRING
)
689 self
.assertInLog("CHILD-TEST-STARTED")
690 self
.assertInLog("CHILD-TEST-COMPLETED")
691 self
.assertNotInLog(TEST_FAIL_STRING
)
693 def testChildFail(self
):
695 Check that a simple failing test running in a child process fails.
697 self
.writeFile("test_fail.js", SIMPLE_FAILING_TEST
)
698 self
.writeFile("test_child_fail.js", CHILD_TEST_FAILING
)
699 self
.writeManifest(["test_child_fail.js"])
701 self
.assertTestResult(False)
702 self
.assertEqual(1, self
.x
.testCount
)
703 self
.assertEqual(0, self
.x
.passCount
)
704 self
.assertEqual(1, self
.x
.failCount
)
705 self
.assertEqual(0, self
.x
.todoCount
)
706 self
.assertInLog(TEST_FAIL_STRING
)
707 self
.assertInLog("CHILD-TEST-STARTED")
708 self
.assertInLog("CHILD-TEST-COMPLETED")
709 self
.assertNotInLog(TEST_PASS_STRING
)
711 def testChildHang(self
):
713 Check that incomplete output from a child process results in a
716 self
.writeFile("test_pass.js", SIMPLE_PASSING_TEST
)
717 self
.writeFile("test_child_hang.js", CHILD_TEST_HANG
)
718 self
.writeManifest(["test_child_hang.js"])
720 self
.assertTestResult(False)
721 self
.assertEqual(1, self
.x
.testCount
)
722 self
.assertEqual(0, self
.x
.passCount
)
723 self
.assertEqual(1, self
.x
.failCount
)
724 self
.assertEqual(0, self
.x
.todoCount
)
725 self
.assertInLog(TEST_FAIL_STRING
)
726 self
.assertInLog("CHILD-TEST-STARTED")
727 self
.assertNotInLog("CHILD-TEST-COMPLETED")
728 self
.assertNotInLog(TEST_PASS_STRING
)
732 Checks that calling do_load_child_test_harness without run_test_in_child
733 results in a usable test state. This test has a spurious failure when
734 run using |mach python-test|. See bug 1103226.
736 self
.writeFile("test_child_assertions.js", CHILD_HARNESS_SIMPLE
)
737 self
.writeManifest(["test_child_assertions.js"])
739 self
.assertTestResult(True)
740 self
.assertEqual(1, self
.x
.testCount
)
741 self
.assertEqual(1, self
.x
.passCount
)
742 self
.assertEqual(0, self
.x
.failCount
)
743 self
.assertEqual(0, self
.x
.todoCount
)
744 self
.assertInLog(TEST_PASS_STRING
)
745 self
.assertNotInLog(TEST_FAIL_STRING
)
747 def testSkipForAddTest(self
):
749 Check that add_test is skipped if |skip_if| condition is true
756 }, function test_should_be_skipped() {
762 self
.writeManifest(["test_skip.js"])
763 self
.assertTestResult(True, verbose
=True)
764 self
.assertEqual(1, self
.x
.testCount
)
765 self
.assertEqual(1, self
.x
.passCount
)
766 self
.assertEqual(0, self
.x
.failCount
)
767 self
.assertEqual(0, self
.x
.todoCount
)
768 self
.assertInLog(TEST_PASS_STRING
)
769 self
.assertInLog("TEST-SKIP")
770 self
.assertNotInLog(TEST_FAIL_STRING
)
772 def testNotSkipForAddTask(self
):
774 Check that add_task is not skipped if |skip_if| condition is false
780 skip_if: () => false,
781 }, function test_should_not_be_skipped() {
786 self
.writeManifest(["test_not_skip.js"])
787 self
.assertTestResult(True, verbose
=True)
788 self
.assertEqual(1, self
.x
.testCount
)
789 self
.assertEqual(1, self
.x
.passCount
)
790 self
.assertEqual(0, self
.x
.failCount
)
791 self
.assertEqual(0, self
.x
.todoCount
)
792 self
.assertInLog(TEST_PASS_STRING
)
793 self
.assertNotInLog("TEST-SKIP")
794 self
.assertNotInLog(TEST_FAIL_STRING
)
796 def testSkipForAddTask(self
):
798 Check that add_task is skipped if |skip_if| condition is true
805 }, function test_should_be_skipped() {
810 self
.writeManifest(["test_skip.js"])
811 self
.assertTestResult(True, verbose
=True)
812 self
.assertEqual(1, self
.x
.testCount
)
813 self
.assertEqual(1, self
.x
.passCount
)
814 self
.assertEqual(0, self
.x
.failCount
)
815 self
.assertEqual(0, self
.x
.todoCount
)
816 self
.assertInLog(TEST_PASS_STRING
)
817 self
.assertInLog("TEST-SKIP")
818 self
.assertNotInLog(TEST_FAIL_STRING
)
820 def testNotSkipForAddTest(self
):
822 Check that add_test is not skipped if |skip_if| condition is false
828 skip_if: () => false,
829 }, function test_should_not_be_skipped() {
835 self
.writeManifest(["test_not_skip.js"])
836 self
.assertTestResult(True, verbose
=True)
837 self
.assertEqual(1, self
.x
.testCount
)
838 self
.assertEqual(1, self
.x
.passCount
)
839 self
.assertEqual(0, self
.x
.failCount
)
840 self
.assertEqual(0, self
.x
.todoCount
)
841 self
.assertInLog(TEST_PASS_STRING
)
842 self
.assertNotInLog("TEST-SKIP")
843 self
.assertNotInLog(TEST_FAIL_STRING
)
845 def testSyntaxError(self
):
847 Check that running a test file containing a syntax error produces
848 a test failure and expected output.
850 self
.writeFile("test_syntax_error.js", '"')
851 self
.writeManifest(["test_syntax_error.js"])
853 self
.assertTestResult(False, verbose
=True)
854 self
.assertEqual(1, self
.x
.testCount
)
855 self
.assertEqual(0, self
.x
.passCount
)
856 self
.assertEqual(1, self
.x
.failCount
)
857 self
.assertEqual(0, self
.x
.todoCount
)
858 self
.assertInLog(TEST_FAIL_STRING
)
859 self
.assertNotInLog(TEST_PASS_STRING
)
861 def testUnicodeInAssertMethods(self
):
863 Check that passing unicode characters through an assertion method works.
865 self
.writeFile("test_unicode_assert.js", PASSING_TEST_UNICODE
, mode
="wb")
866 self
.writeManifest(["test_unicode_assert.js"])
868 self
.assertTestResult(True, verbose
=True)
871 "MOZ_AUTOMATION" in os
.environ
,
872 "Timeout code path occasionally times out (bug 1098121)",
874 def testHangingTimeout(self
):
876 Check that a test that never finishes results in the correct error log.
878 self
.writeFile("test_loop.js", SIMPLE_LOOPING_TEST
)
879 self
.writeManifest(["test_loop.js"])
881 old_timeout
= self
.x
.harness_timeout
882 self
.x
.harness_timeout
= 1
884 self
.assertTestResult(False)
885 self
.assertEqual(1, self
.x
.testCount
)
886 self
.assertEqual(1, self
.x
.failCount
)
887 self
.assertEqual(0, self
.x
.passCount
)
888 self
.assertEqual(0, self
.x
.todoCount
)
889 self
.assertInLog("TEST-UNEXPECTED-TIMEOUT")
891 self
.x
.harness_timeout
= old_timeout
893 def testPassFail(self
):
895 Check that running more than one test works.
897 self
.writeFile("test_pass.js", SIMPLE_PASSING_TEST
)
898 self
.writeFile("test_fail.js", SIMPLE_FAILING_TEST
)
899 self
.writeManifest(["test_pass.js", "test_fail.js"])
901 self
.assertTestResult(False)
902 self
.assertEqual(2, self
.x
.testCount
)
903 self
.assertEqual(1, self
.x
.passCount
)
904 self
.assertEqual(1, self
.x
.failCount
)
905 self
.assertEqual(0, self
.x
.todoCount
)
906 self
.assertInLog(TEST_PASS_STRING
)
907 self
.assertInLog(TEST_FAIL_STRING
)
911 Check that a simple failing test skipped in the manifest does
914 self
.writeFile("test_basic.js", SIMPLE_FAILING_TEST
)
915 self
.writeManifest([("test_basic.js", "skip-if = true")])
916 self
.assertTestResult(True)
917 self
.assertEqual(1, self
.x
.testCount
)
918 self
.assertEqual(0, self
.x
.passCount
)
919 self
.assertEqual(0, self
.x
.failCount
)
920 self
.assertEqual(0, self
.x
.todoCount
)
921 self
.assertNotInLog(TEST_FAIL_STRING
)
922 self
.assertNotInLog(TEST_PASS_STRING
)
924 def testKnownFail(self
):
926 Check that a simple failing test marked as known-fail in the manifest
927 does not cause failure.
929 self
.writeFile("test_basic.js", SIMPLE_FAILING_TEST
)
930 self
.writeManifest([("test_basic.js", "fail-if = true")])
931 self
.assertTestResult(True)
932 self
.assertEqual(1, self
.x
.testCount
)
933 self
.assertEqual(0, self
.x
.passCount
)
934 self
.assertEqual(0, self
.x
.failCount
)
935 self
.assertEqual(1, self
.x
.todoCount
)
936 self
.assertInLog("TEST-FAIL")
937 # This should be suppressed because the harness doesn't include
938 # the full log from the xpcshell run when things pass.
939 self
.assertNotInLog(TEST_FAIL_STRING
)
940 self
.assertNotInLog(TEST_PASS_STRING
)
942 def testUnexpectedPass(self
):
944 Check that a simple failing test marked as known-fail in the manifest
945 that passes causes an unexpected pass.
947 self
.writeFile("test_basic.js", SIMPLE_PASSING_TEST
)
948 self
.writeManifest([("test_basic.js", "fail-if = true")])
949 self
.assertTestResult(False)
950 self
.assertEqual(1, self
.x
.testCount
)
951 self
.assertEqual(0, self
.x
.passCount
)
952 self
.assertEqual(1, self
.x
.failCount
)
953 self
.assertEqual(0, self
.x
.todoCount
)
954 # From the outer (Python) harness
955 self
.assertInLog("TEST-UNEXPECTED-PASS")
956 self
.assertNotInLog("TEST-KNOWN-FAIL")
958 def testReturnNonzero(self
):
960 Check that a test where xpcshell returns nonzero fails.
962 self
.writeFile("test_error.js", "throw 'foo'")
963 self
.writeManifest(["test_error.js"])
965 self
.assertTestResult(False)
966 self
.assertEqual(1, self
.x
.testCount
)
967 self
.assertEqual(0, self
.x
.passCount
)
968 self
.assertEqual(1, self
.x
.failCount
)
969 self
.assertEqual(0, self
.x
.todoCount
)
970 self
.assertInLog(TEST_FAIL_STRING
)
971 self
.assertNotInLog(TEST_PASS_STRING
)
973 def testUncaughtRejection(self
):
975 Ensure a simple test with an uncaught rejection is reported.
978 "test_simple_uncaught_rejection.js", SIMPLE_UNCAUGHT_REJECTION_TEST
980 self
.writeManifest(["test_simple_uncaught_rejection.js"])
982 self
.assertTestResult(False)
983 self
.assertInLog(TEST_FAIL_STRING
)
984 self
.assertInLog("test_simple_uncaught_rejection.js:3:18")
985 self
.assertInLog("Test rejection.")
986 self
.assertEqual(1, self
.x
.testCount
)
987 self
.assertEqual(0, self
.x
.passCount
)
988 self
.assertEqual(1, self
.x
.failCount
)
990 def testAddTestSimple(self
):
992 Ensure simple add_test() works.
994 self
.writeFile("test_add_test_simple.js", ADD_TEST_SIMPLE
)
995 self
.writeManifest(["test_add_test_simple.js"])
997 self
.assertTestResult(True)
998 self
.assertEqual(1, self
.x
.testCount
)
999 self
.assertEqual(1, self
.x
.passCount
)
1000 self
.assertEqual(0, self
.x
.failCount
)
1002 def testCrashLogging(self
):
1004 Test that a crashing test process logs a failure.
1006 self
.writeFile("test_crashes.js", TEST_CRASHING
)
1007 self
.writeManifest(["test_crashes.js"])
1009 self
.assertTestResult(False)
1010 self
.assertEqual(1, self
.x
.testCount
)
1011 self
.assertEqual(0, self
.x
.passCount
)
1012 self
.assertEqual(1, self
.x
.failCount
)
1013 if mozinfo
.info
.get("crashreporter"):
1014 self
.assertInLog("\nPROCESS-CRASH")
1016 def testLogCorrectFileName(self
):
1018 Make sure a meaningful filename and line number is logged
1021 self
.writeFile("test_add_test_simple.js", ADD_TEST_SIMPLE
)
1022 self
.writeManifest(["test_add_test_simple.js"])
1024 self
.assertTestResult(True, verbose
=True)
1025 self
.assertInLog("true == true")
1026 self
.assertNotInLog("[Assert.ok :")
1027 self
.assertInLog("[test_simple : 5]")
1029 def testAddTestFailing(self
):
1031 Ensure add_test() with a failing test is reported.
1033 self
.writeFile("test_add_test_failing.js", ADD_TEST_FAILING
)
1034 self
.writeManifest(["test_add_test_failing.js"])
1036 self
.assertTestResult(False)
1037 self
.assertEqual(1, self
.x
.testCount
)
1038 self
.assertEqual(0, self
.x
.passCount
)
1039 self
.assertEqual(1, self
.x
.failCount
)
1041 def testAddTestUncaughtRejection(self
):
1043 Ensure add_test() with an uncaught rejection is reported.
1046 "test_add_test_uncaught_rejection.js", ADD_TEST_UNCAUGHT_REJECTION
1048 self
.writeManifest(["test_add_test_uncaught_rejection.js"])
1050 self
.assertTestResult(False)
1051 self
.assertEqual(1, self
.x
.testCount
)
1052 self
.assertEqual(0, self
.x
.passCount
)
1053 self
.assertEqual(1, self
.x
.failCount
)
1055 def testAddTaskTestSingle(self
):
1057 Ensure add_test_task() with a single passing test works.
1059 self
.writeFile("test_add_task_simple.js", ADD_TASK_SINGLE
)
1060 self
.writeManifest(["test_add_task_simple.js"])
1062 self
.assertTestResult(True)
1063 self
.assertEqual(1, self
.x
.testCount
)
1064 self
.assertEqual(1, self
.x
.passCount
)
1065 self
.assertEqual(0, self
.x
.failCount
)
1067 def testAddTaskTestMultiple(self
):
1069 Ensure multiple calls to add_test_task() work as expected.
1071 self
.writeFile("test_add_task_multiple.js", ADD_TASK_MULTIPLE
)
1072 self
.writeManifest(["test_add_task_multiple.js"])
1074 self
.assertTestResult(True)
1075 self
.assertEqual(1, self
.x
.testCount
)
1076 self
.assertEqual(1, self
.x
.passCount
)
1077 self
.assertEqual(0, self
.x
.failCount
)
1079 def testAddTaskTestRejected(self
):
1081 Ensure rejected task reports as failure.
1083 self
.writeFile("test_add_task_rejected.js", ADD_TASK_REJECTED
)
1084 self
.writeManifest(["test_add_task_rejected.js"])
1086 self
.assertTestResult(False)
1087 self
.assertEqual(1, self
.x
.testCount
)
1088 self
.assertEqual(0, self
.x
.passCount
)
1089 self
.assertEqual(1, self
.x
.failCount
)
1091 def testAddTaskTestRejectedUndefined(self
):
1093 Ensure rejected task with undefined reason reports as failure and does not hang.
1096 "test_add_task_rejected_undefined.js", ADD_TASK_REJECTED_UNDEFINED
1098 self
.writeManifest(["test_add_task_rejected_undefined.js"])
1100 self
.assertTestResult(False)
1101 self
.assertEqual(1, self
.x
.testCount
)
1102 self
.assertEqual(0, self
.x
.passCount
)
1103 self
.assertEqual(1, self
.x
.failCount
)
1104 self
.assertNotInLog("TEST-UNEXPECTED-TIMEOUT")
1106 def testAddTaskTestFailureInside(self
):
1108 Ensure tests inside task are reported as failures.
1110 self
.writeFile("test_add_task_failure_inside.js", ADD_TASK_FAILURE_INSIDE
)
1111 self
.writeManifest(["test_add_task_failure_inside.js"])
1113 self
.assertTestResult(False)
1114 self
.assertEqual(1, self
.x
.testCount
)
1115 self
.assertEqual(0, self
.x
.passCount
)
1116 self
.assertEqual(1, self
.x
.failCount
)
1118 def testAddTaskRunNextTest(self
):
1120 Calling run_next_test() from inside add_task() results in failure.
1122 self
.writeFile("test_add_task_run_next_test.js", ADD_TASK_RUN_NEXT_TEST
)
1123 self
.writeManifest(["test_add_task_run_next_test.js"])
1125 self
.assertTestResult(False)
1126 self
.assertEqual(1, self
.x
.testCount
)
1127 self
.assertEqual(0, self
.x
.passCount
)
1128 self
.assertEqual(1, self
.x
.failCount
)
1130 def testAddTaskStackTrace(self
):
1132 Ensuring that calling Assert.ok(false) from inside add_task()
1133 results in a human-readable stack trace.
1135 self
.writeFile("test_add_task_stack_trace.js", ADD_TASK_STACK_TRACE
)
1136 self
.writeManifest(["test_add_task_stack_trace.js"])
1138 self
.assertTestResult(False)
1139 self
.assertInLog("this_test_will_fail")
1140 self
.assertInLog("run_next_test")
1141 self
.assertInLog("run_test")
1143 def testAddTaskSkip(self
):
1144 self
.writeFile("test_tasks_skip.js", ADD_TASK_SKIP
)
1145 self
.writeManifest(["test_tasks_skip.js"])
1147 self
.assertTestResult(True)
1148 self
.assertEqual(1, self
.x
.testCount
)
1149 self
.assertEqual(1, self
.x
.passCount
)
1150 self
.assertEqual(0, self
.x
.failCount
)
1152 def testAddTaskSkipAll(self
):
1153 self
.writeFile("test_tasks_skipall.js", ADD_TASK_SKIPALL
)
1154 self
.writeManifest(["test_tasks_skipall.js"])
1156 self
.assertTestResult(True)
1157 self
.assertEqual(1, self
.x
.testCount
)
1158 self
.assertEqual(1, self
.x
.passCount
)
1159 self
.assertEqual(0, self
.x
.failCount
)
1161 def testMissingHeadFile(self
):
1163 Ensure that missing head file results in fatal failure.
1165 self
.writeFile("test_basic.js", SIMPLE_PASSING_TEST
)
1166 self
.writeManifest([("test_basic.js", 'head = "missing.js"')])
1171 # The actual return value is never checked because we raise.
1172 self
.assertTestResult(True)
1173 except Exception as ex
:
1175 self
.assertEqual(str(ex
)[0:9], "head file")
1177 self
.assertTrue(raised
)
1179 def testRandomExecution(self
):
1181 Check that random execution doesn't break.
1184 for i
in range(0, 10):
1185 filename
= "test_pass_%d.js" % i
1186 self
.writeFile(filename
, SIMPLE_PASSING_TEST
)
1187 manifest
.append(filename
)
1189 self
.writeManifest(manifest
)
1190 self
.assertTestResult(True, shuffle
=True)
1191 self
.assertEqual(10, self
.x
.testCount
)
1192 self
.assertEqual(10, self
.x
.passCount
)
1194 def testDoThrowString(self
):
1196 Check that do_throw produces reasonable messages when the
1197 input is a string instead of an object
1199 self
.writeFile("test_error.js", ADD_TEST_THROW_STRING
)
1200 self
.writeManifest(["test_error.js"])
1202 self
.assertTestResult(False)
1203 self
.assertInLog(TEST_FAIL_STRING
)
1204 self
.assertInLog("Passing a string to do_throw")
1205 self
.assertNotInLog(TEST_PASS_STRING
)
1207 def testDoThrowForeignObject(self
):
1209 Check that do_throw produces reasonable messages when the
1210 input is a generic object with 'filename', 'message' and 'stack' attributes
1211 but 'object instanceof Error' returns false
1213 self
.writeFile("test_error.js", ADD_TEST_THROW_OBJECT
)
1214 self
.writeManifest(["test_error.js"])
1216 self
.assertTestResult(False)
1217 self
.assertInLog(TEST_FAIL_STRING
)
1218 self
.assertInLog("failure.js")
1219 self
.assertInLog("Error object")
1220 self
.assertInLog("ERROR STACK")
1221 self
.assertNotInLog(TEST_PASS_STRING
)
1223 def testDoReportForeignObject(self
):
1225 Check that do_report_unexpected_exception produces reasonable messages when the
1226 input is a generic object with 'filename', 'message' and 'stack' attributes
1227 but 'object instanceof Error' returns false
1229 self
.writeFile("test_error.js", ADD_TEST_REPORT_OBJECT
)
1230 self
.writeManifest(["test_error.js"])
1232 self
.assertTestResult(False)
1233 self
.assertInLog(TEST_FAIL_STRING
)
1234 self
.assertInLog("failure.js")
1235 self
.assertInLog("Error object")
1236 self
.assertInLog("ERROR STACK")
1237 self
.assertNotInLog(TEST_PASS_STRING
)
1239 def testDoReportRefError(self
):
1241 Check that do_report_unexpected_exception produces reasonable messages when the
1242 input is a JS-generated Error
1244 self
.writeFile("test_error.js", ADD_TEST_REPORT_REF_ERROR
)
1245 self
.writeManifest(["test_error.js"])
1247 self
.assertTestResult(False)
1248 self
.assertInLog(TEST_FAIL_STRING
)
1249 self
.assertInLog("test_error.js")
1250 self
.assertInLog("obj.noSuchFunction is not a function")
1251 self
.assertInLog("run_test@")
1252 self
.assertNotInLog(TEST_PASS_STRING
)
1254 def testDoReportSyntaxError(self
):
1256 Check that attempting to load a test file containing a syntax error
1257 generates details of the error in the log
1259 self
.writeFile("test_error.js", LOAD_ERROR_SYNTAX_ERROR
)
1260 self
.writeManifest(["test_error.js"])
1262 self
.assertTestResult(False)
1263 self
.assertInLog(TEST_FAIL_STRING
)
1264 self
.assertInLog("test_error.js:3")
1265 self
.assertNotInLog(TEST_PASS_STRING
)
1267 def testDoReportNonSyntaxError(self
):
1269 Check that attempting to load a test file containing an error other
1270 than a syntax error generates details of the error in the log
1272 self
.writeFile("test_error.js", LOAD_ERROR_OTHER_ERROR
)
1273 self
.writeManifest(["test_error.js"])
1275 self
.assertTestResult(False)
1276 self
.assertInLog(TEST_FAIL_STRING
)
1277 self
.assertInLog("ReferenceError: assignment to undeclared variable")
1278 self
.assertInLog("test_error.js:3")
1279 self
.assertNotInLog(TEST_PASS_STRING
)
1281 def testDoPrintWhenVerboseNotExplicit(self
):
1283 Check that info() and similar calls that generate output do
1284 not have the output when not run verbosely.
1286 self
.writeFile("test_verbose.js", ADD_TEST_VERBOSE
)
1287 self
.writeManifest(["test_verbose.js"])
1289 self
.assertTestResult(True)
1290 self
.assertNotInLog("a message from info")
1292 def testDoPrintWhenVerboseExplicit(self
):
1294 Check that info() and similar calls that generate output have the
1295 output shown when run verbosely.
1297 self
.writeFile("test_verbose.js", ADD_TEST_VERBOSE
)
1298 self
.writeManifest(["test_verbose.js"])
1299 self
.assertTestResult(True, verbose
=True)
1300 self
.assertInLog("a message from info")
1302 def testDoPrintWhenVerboseInManifest(self
):
1304 Check that info() and similar calls that generate output have the
1305 output shown when 'verbose = true' is in the manifest, even when
1308 self
.writeFile("test_verbose.js", ADD_TEST_VERBOSE
)
1309 self
.writeManifest([("test_verbose.js", "verbose = true")])
1311 self
.assertTestResult(True)
1312 self
.assertInLog("a message from info")
1314 def testAsyncCleanup(self
):
1316 Check that registerCleanupFunction handles nicely async cleanup tasks
1318 self
.writeFile("test_asyncCleanup.js", ASYNC_CLEANUP
)
1319 self
.writeManifest(["test_asyncCleanup.js"])
1320 self
.assertTestResult(False)
1321 self
.assertInLog('"123456" == "123456"')
1322 self
.assertInLog("At this stage, the test has succeeded")
1323 self
.assertInLog("Throwing an error to force displaying the log")
1325 def testNoRunTestAddTest(self
):
1327 Check that add_test() works fine without run_test() in the test file.
1329 self
.writeFile("test_noRunTestAddTest.js", NO_RUN_TEST_ADD_TEST
)
1330 self
.writeManifest(["test_noRunTestAddTest.js"])
1332 self
.assertTestResult(True)
1333 self
.assertEqual(1, self
.x
.testCount
)
1334 self
.assertEqual(1, self
.x
.passCount
)
1335 self
.assertEqual(0, self
.x
.failCount
)
1336 self
.assertInLog(TEST_PASS_STRING
)
1337 self
.assertNotInLog(TEST_FAIL_STRING
)
1339 def testNoRunTestAddTask(self
):
1341 Check that add_task() works fine without run_test() in the test file.
1343 self
.writeFile("test_noRunTestAddTask.js", NO_RUN_TEST_ADD_TASK
)
1344 self
.writeManifest(["test_noRunTestAddTask.js"])
1346 self
.assertTestResult(True)
1347 self
.assertEqual(1, self
.x
.testCount
)
1348 self
.assertEqual(1, self
.x
.passCount
)
1349 self
.assertEqual(0, self
.x
.failCount
)
1350 self
.assertInLog(TEST_PASS_STRING
)
1351 self
.assertNotInLog(TEST_FAIL_STRING
)
1353 def testNoRunTestAddTestAddTask(self
):
1355 Check that both add_test() and add_task() work without run_test()
1358 self
.writeFile("test_noRunTestAddTestAddTask.js", NO_RUN_TEST_ADD_TEST_ADD_TASK
)
1359 self
.writeManifest(["test_noRunTestAddTestAddTask.js"])
1361 self
.assertTestResult(True)
1362 self
.assertEqual(1, self
.x
.testCount
)
1363 self
.assertEqual(1, self
.x
.passCount
)
1364 self
.assertEqual(0, self
.x
.failCount
)
1365 self
.assertInLog(TEST_PASS_STRING
)
1366 self
.assertNotInLog(TEST_FAIL_STRING
)
1368 def testNoRunTestEmptyTest(self
):
1370 Check that the test passes on an empty file that contains neither
1371 run_test() nor add_test(), add_task().
1373 self
.writeFile("test_noRunTestEmptyTest.js", NO_RUN_TEST_EMPTY_TEST
)
1374 self
.writeManifest(["test_noRunTestEmptyTest.js"])
1376 self
.assertTestResult(True)
1377 self
.assertEqual(1, self
.x
.testCount
)
1378 self
.assertEqual(1, self
.x
.passCount
)
1379 self
.assertEqual(0, self
.x
.failCount
)
1380 self
.assertInLog(TEST_PASS_STRING
)
1381 self
.assertNotInLog(TEST_FAIL_STRING
)
1383 def testNoRunTestAddTestFail(self
):
1385 Check that test fails on using add_test() without run_test().
1387 self
.writeFile("test_noRunTestAddTestFail.js", NO_RUN_TEST_ADD_TEST_FAIL
)
1388 self
.writeManifest(["test_noRunTestAddTestFail.js"])
1390 self
.assertTestResult(False)
1391 self
.assertEqual(1, self
.x
.testCount
)
1392 self
.assertEqual(0, self
.x
.passCount
)
1393 self
.assertEqual(1, self
.x
.failCount
)
1394 self
.assertInLog(TEST_FAIL_STRING
)
1395 self
.assertNotInLog(TEST_PASS_STRING
)
1397 def testNoRunTestAddTaskFail(self
):
1399 Check that test fails on using add_task() without run_test().
1401 self
.writeFile("test_noRunTestAddTaskFail.js", NO_RUN_TEST_ADD_TASK_FAIL
)
1402 self
.writeManifest(["test_noRunTestAddTaskFail.js"])
1404 self
.assertTestResult(False)
1405 self
.assertEqual(1, self
.x
.testCount
)
1406 self
.assertEqual(0, self
.x
.passCount
)
1407 self
.assertEqual(1, self
.x
.failCount
)
1408 self
.assertInLog(TEST_FAIL_STRING
)
1409 self
.assertNotInLog(TEST_PASS_STRING
)
1411 def testNoRunTestAddTaskMultiple(self
):
1413 Check that multple add_task() tests work without run_test().
1416 "test_noRunTestAddTaskMultiple.js", NO_RUN_TEST_ADD_TASK_MULTIPLE
1418 self
.writeManifest(["test_noRunTestAddTaskMultiple.js"])
1420 self
.assertTestResult(True)
1421 self
.assertEqual(1, self
.x
.testCount
)
1422 self
.assertEqual(1, self
.x
.passCount
)
1423 self
.assertEqual(0, self
.x
.failCount
)
1424 self
.assertInLog(TEST_PASS_STRING
)
1425 self
.assertNotInLog(TEST_FAIL_STRING
)
1427 def testMozinfo(self
):
1429 Check that mozinfo.json is loaded
1431 self
.writeFile("test_mozinfo.js", LOAD_MOZINFO
)
1432 self
.writeManifest(["test_mozinfo.js"])
1433 self
.assertTestResult(True)
1434 self
.assertEqual(1, self
.x
.testCount
)
1435 self
.assertEqual(1, self
.x
.passCount
)
1436 self
.assertEqual(0, self
.x
.failCount
)
1437 self
.assertEqual(0, self
.x
.todoCount
)
1438 self
.assertInLog(TEST_PASS_STRING
)
1439 self
.assertNotInLog(TEST_FAIL_STRING
)
1441 def testChildMozinfo(self
):
1443 Check that mozinfo.json is loaded in child process
1445 self
.writeFile("test_mozinfo.js", LOAD_MOZINFO
)
1446 self
.writeFile("test_child_mozinfo.js", CHILD_MOZINFO
)
1447 self
.writeManifest(["test_child_mozinfo.js"])
1448 self
.assertTestResult(True)
1449 self
.assertEqual(1, self
.x
.testCount
)
1450 self
.assertEqual(1, self
.x
.passCount
)
1451 self
.assertEqual(0, self
.x
.failCount
)
1452 self
.assertEqual(0, self
.x
.todoCount
)
1453 self
.assertInLog(TEST_PASS_STRING
)
1454 self
.assertNotInLog(TEST_FAIL_STRING
)
1456 def testNotHeadlessByDefault(self
):
1458 Check that the default is not headless.
1460 self
.writeFile("test_notHeadlessByDefault.js", HEADLESS_FALSE
)
1461 self
.writeManifest(["test_notHeadlessByDefault.js"])
1462 self
.assertTestResult(True)
1464 def testHeadlessWhenHeadlessExplicit(self
):
1466 Check that explicitly requesting headless works when the manifest doesn't override.
1468 self
.writeFile("test_headlessWhenExplicit.js", HEADLESS_TRUE
)
1469 self
.writeManifest(["test_headlessWhenExplicit.js"])
1470 self
.assertTestResult(True, headless
=True)
1472 def testHeadlessWhenHeadlessTrueInManifest(self
):
1474 Check that enabling headless in the manifest alone works.
1476 self
.writeFile("test_headlessWhenTrueInManifest.js", HEADLESS_TRUE
)
1477 self
.writeManifest([("test_headlessWhenTrueInManifest.js", "headless = true")])
1478 self
.assertTestResult(True)
1480 def testNotHeadlessWhenHeadlessFalseInManifest(self
):
1482 Check that the manifest entry overrides the explicit default.
1484 self
.writeFile("test_notHeadlessWhenFalseInManifest.js", HEADLESS_FALSE
)
1486 [("test_notHeadlessWhenFalseInManifest.js", "headless = false")]
1488 self
.assertTestResult(True, headless
=True)
1491 if __name__
== "__main__":
1494 mozinfo
.find_and_update_from_json()