diff --git a/testing/xpcshell/Makefile.in b/testing/xpcshell/Makefile.in index 7797afb147b6..ead4483db2b4 100644 --- a/testing/xpcshell/Makefile.in +++ b/testing/xpcshell/Makefile.in @@ -10,6 +10,11 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk +# Run selftests +PYTHON_UNIT_TESTS := \ + selftest.py + $(NULL) + include $(topsrcdir)/config/rules.mk # Harness files from the srcdir @@ -54,11 +59,6 @@ libs:: $(INSTALL) $(srcdir)/xpcshell_android.ini $(DEPTH)/_tests/xpcshell cp $(DEPTH)/_tests/xpcshell/xpcshell.ini $(DEPTH)/_tests/xpcshell/all-test-dirs.list -# Run selftests -check:: - OBJDIR=$(DEPTH) $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(DEPTH)/build -I$(topsrcdir)/build -I$(topsrcdir)/testing/mozbase/mozinfo/mozinfo $(srcdir)/selftest.py - stage-package: $(NSINSTALL) -D $(PKG_STAGE)/xpcshell/tests @(cd $(topsrcdir)/testing/mozbase/mozinfo/mozinfo && tar $(TAR_CREATE_FLAGS) - $(MOZINFO_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -) diff --git a/testing/xpcshell/selftest.py b/testing/xpcshell/selftest.py index 5d91af860cd1..afefd01b0fdb 100644 --- a/testing/xpcshell/selftest.py +++ b/testing/xpcshell/selftest.py @@ -9,9 +9,12 @@ import sys, os, unittest, tempfile, shutil from StringIO import StringIO from xml.etree.ElementTree import ElementTree +from mozbuild.base import MozbuildObject +build_obj = MozbuildObject.from_environment() + from runxpcshelltests import XPCShellTests -objdir = os.path.abspath(os.environ["OBJDIR"]) +objdir = build_obj.topobjdir.encode("utf-8") xpcshellBin = os.path.join(objdir, "dist", "bin", "xpcshell") if sys.platform == "win32": xpcshellBin += ".exe" @@ -37,6 +40,37 @@ add_test(function test_failing() { }); ''' +CHILD_TEST_PASSING = ''' +function run_test () { run_next_test(); } + +add_test(function test_child_simple () { + run_test_in_child("test_pass.js"); + run_next_test(); +}); +''' + +CHILD_TEST_FAILING = ''' +function run_test () { run_next_test(); } + +add_test(function test_child_simple () { + run_test_in_child("test_fail.js"); + run_next_test(); +}); +''' + +CHILD_TEST_HANG = ''' +function run_test () { run_next_test(); } + +add_test(function test_child_simple () { + do_test_pending("hang test"); + do_load_child_test_harness(); + sendCommand("_dump('CHILD-TEST-STARTED'); " + + + "const _TEST_FILE=['test_pass.js']; _execute_test(); ", + do_test_finished); + run_next_test(); +}); +''' + ADD_TASK_SINGLE = ''' Components.utils.import("resource://gre/modules/commonjs/sdk/core/promise.js"); @@ -164,7 +198,7 @@ tail = """ + "\n".join(testlines)) - def assertTestResult(self, expected, shuffle=False, xunitFilename=None): + def assertTestResult(self, expected, shuffle=False, xunitFilename=None, verbose=False): """ Assert that self.x.runTests with manifest=self.manifest returns |expected|. @@ -175,6 +209,7 @@ tail = mozInfo={}, shuffle=shuffle, testsRootDir=self.tempdir, + verbose=verbose, xunitFilename=xunitFilename, sequential=True), msg="""Tests should have %s, log: @@ -233,6 +268,84 @@ tail = self.assertInLog("TEST-UNEXPECTED-FAIL") self.assertNotInLog("TEST-PASS") + @unittest.skipIf(build_obj.defines.get('MOZ_B2G'), + 'selftests with child processes fail on b2g desktop builds') + def testChildPass(self): + """ + Check that a simple test running in a child process passes. + """ + self.writeFile("test_pass.js", SIMPLE_PASSING_TEST) + self.writeFile("test_child_pass.js", CHILD_TEST_PASSING) + self.writeManifest(["test_child_pass.js"]) + + self.assertTestResult(True, verbose=True) + self.assertEquals(1, self.x.testCount) + self.assertEquals(1, self.x.passCount) + self.assertEquals(0, self.x.failCount) + self.assertEquals(0, self.x.todoCount) + self.assertInLog("TEST-PASS") + self.assertInLog("CHILD-TEST-STARTED") + self.assertInLog("CHILD-TEST-COMPLETED") + self.assertNotInLog("TEST-UNEXPECTED-FAIL") + + + @unittest.skipIf(build_obj.defines.get('MOZ_B2G'), + 'selftests with child processes fail on b2g desktop builds') + def testChildFail(self): + """ + Check that a simple failing test running in a child process fails. + """ + self.writeFile("test_fail.js", SIMPLE_FAILING_TEST) + self.writeFile("test_child_fail.js", CHILD_TEST_FAILING) + self.writeManifest(["test_child_fail.js"]) + + self.assertTestResult(False) + self.assertEquals(1, self.x.testCount) + self.assertEquals(0, self.x.passCount) + self.assertEquals(1, self.x.failCount) + self.assertEquals(0, self.x.todoCount) + self.assertInLog("TEST-UNEXPECTED-FAIL") + self.assertInLog("CHILD-TEST-STARTED") + self.assertInLog("CHILD-TEST-COMPLETED") + self.assertNotInLog("TEST-PASS") + + @unittest.skipIf(build_obj.defines.get('MOZ_B2G'), + 'selftests with child processes fail on b2g desktop builds') + def testChildHang(self): + """ + Check that incomplete output from a child process results in a + test failure. + """ + self.writeFile("test_pass.js", SIMPLE_PASSING_TEST) + self.writeFile("test_child_hang.js", CHILD_TEST_HANG) + self.writeManifest(["test_child_hang.js"]) + + self.assertTestResult(False) + self.assertEquals(1, self.x.testCount) + self.assertEquals(0, self.x.passCount) + self.assertEquals(1, self.x.failCount) + self.assertEquals(0, self.x.todoCount) + self.assertInLog("TEST-UNEXPECTED-FAIL") + self.assertInLog("CHILD-TEST-STARTED") + self.assertNotInLog("CHILD-TEST-COMPLETED") + self.assertNotInLog("TEST-PASS") + + def testSyntaxError(self): + """ + Check that running a test file containing a syntax error produces + a test failure and expected output. + """ + self.writeFile("test_syntax_error.js", '"') + self.writeManifest(["test_syntax_error.js"]) + + self.assertTestResult(False, verbose=True) + self.assertEquals(1, self.x.testCount) + self.assertEquals(0, self.x.passCount) + self.assertEquals(1, self.x.failCount) + self.assertEquals(0, self.x.todoCount) + self.assertInLog("TEST-UNEXPECTED-FAIL") + self.assertNotInLog("TEST-PASS") + def testPassFail(self): """ Check that running more than one test works.