Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 #!/usr/bin/env python
2 #
3 # Any copyright is dedicated to the Public Domain.
4 # http://creativecommons.org/publicdomain/zero/1.0/
5 #
7 from __future__ import with_statement
8 import sys, os, unittest, tempfile, shutil
9 import mozinfo
11 from StringIO import StringIO
12 from xml.etree.ElementTree import ElementTree
14 from mozbuild.base import MozbuildObject
15 build_obj = MozbuildObject.from_environment()
17 from runxpcshelltests import XPCShellTests
19 mozinfo.find_and_update_from_json()
21 objdir = build_obj.topobjdir.encode("utf-8")
22 xpcshellBin = os.path.join(objdir, "dist", "bin", "xpcshell")
23 if sys.platform == "win32":
24 xpcshellBin += ".exe"
26 SIMPLE_PASSING_TEST = "function run_test() { do_check_true(true); }"
27 SIMPLE_FAILING_TEST = "function run_test() { do_check_true(false); }"
29 ADD_TEST_SIMPLE = '''
30 function run_test() { run_next_test(); }
32 add_test(function test_simple() {
33 do_check_true(true);
34 run_next_test();
35 });
36 '''
38 ADD_TEST_FAILING = '''
39 function run_test() { run_next_test(); }
41 add_test(function test_failing() {
42 do_check_true(false);
43 run_next_test();
44 });
45 '''
47 CHILD_TEST_PASSING = '''
48 function run_test () { run_next_test(); }
50 add_test(function test_child_simple () {
51 run_test_in_child("test_pass.js");
52 run_next_test();
53 });
54 '''
56 CHILD_TEST_FAILING = '''
57 function run_test () { run_next_test(); }
59 add_test(function test_child_simple () {
60 run_test_in_child("test_fail.js");
61 run_next_test();
62 });
63 '''
65 CHILD_TEST_HANG = '''
66 function run_test () { run_next_test(); }
68 add_test(function test_child_simple () {
69 do_test_pending("hang test");
70 do_load_child_test_harness();
71 sendCommand("_log('child_test_start', {_message: 'CHILD-TEST-STARTED'}); " +
72 + "const _TEST_FILE=['test_pass.js']; _execute_test(); ",
73 do_test_finished);
74 run_next_test();
75 });
76 '''
78 ADD_TASK_SINGLE = '''
79 Components.utils.import("resource://gre/modules/Promise.jsm");
81 function run_test() { run_next_test(); }
83 add_task(function test_task() {
84 yield Promise.resolve(true);
85 yield Promise.resolve(false);
86 });
87 '''
89 ADD_TASK_MULTIPLE = '''
90 Components.utils.import("resource://gre/modules/Promise.jsm");
92 function run_test() { run_next_test(); }
94 add_task(function test_task() {
95 yield Promise.resolve(true);
96 });
98 add_task(function test_2() {
99 yield Promise.resolve(true);
100 });
101 '''
103 ADD_TASK_REJECTED = '''
104 Components.utils.import("resource://gre/modules/Promise.jsm");
106 function run_test() { run_next_test(); }
108 add_task(function test_failing() {
109 yield Promise.reject(new Error("I fail."));
110 });
111 '''
113 ADD_TASK_FAILURE_INSIDE = '''
114 Components.utils.import("resource://gre/modules/Promise.jsm");
116 function run_test() { run_next_test(); }
118 add_task(function test() {
119 let result = yield Promise.resolve(false);
121 do_check_true(result);
122 });
123 '''
125 ADD_TASK_RUN_NEXT_TEST = '''
126 function run_test() { run_next_test(); }
128 add_task(function () {
129 Assert.ok(true);
131 run_next_test();
132 });
133 '''
135 ADD_TEST_THROW_STRING = '''
136 function run_test() {do_throw("Passing a string to do_throw")};
137 '''
139 ADD_TEST_THROW_OBJECT = '''
140 let error = {
141 message: "Error object",
142 fileName: "failure.js",
143 stack: "ERROR STACK",
144 toString: function() {return this.message;}
145 };
146 function run_test() {do_throw(error)};
147 '''
149 ADD_TEST_REPORT_OBJECT = '''
150 let error = {
151 message: "Error object",
152 fileName: "failure.js",
153 stack: "ERROR STACK",
154 toString: function() {return this.message;}
155 };
156 function run_test() {do_report_unexpected_exception(error)};
157 '''
159 # A test for genuine JS-generated Error objects
160 ADD_TEST_REPORT_REF_ERROR = '''
161 function run_test() {
162 let obj = {blah: 0};
163 try {
164 obj.noSuchFunction();
165 }
166 catch (error) {
167 do_report_unexpected_exception(error);
168 }
169 };
170 '''
172 # A test for failure to load a test due to a syntax error
173 LOAD_ERROR_SYNTAX_ERROR = '''
174 function run_test(
175 '''
177 # A test for failure to load a test due to an error other than a syntax error
178 LOAD_ERROR_OTHER_ERROR = '''
179 function run_test() {
180 yield "foo";
181 return "foo"; // can't use return in a generator!
182 };
183 '''
185 # A test for asynchronous cleanup functions
186 ASYNC_CLEANUP = '''
187 function run_test() {
188 Components.utils.import("resource://gre/modules/Promise.jsm", this);
190 // The list of checkpoints in the order we encounter them.
191 let checkpoints = [];
193 // Cleanup tasks, in reverse order
194 do_register_cleanup(function cleanup_checkout() {
195 do_check_eq(checkpoints.join(""), "1234");
196 do_print("At this stage, the test has succeeded");
197 do_throw("Throwing an error to force displaying the log");
198 });
200 do_register_cleanup(function sync_cleanup_2() {
201 checkpoints.push(4);
202 });
204 do_register_cleanup(function async_cleanup_2() {
205 let deferred = Promise.defer();
206 do_execute_soon(deferred.resolve);
207 return deferred.promise.then(function() {
208 checkpoints.push(3);
209 });
210 });
212 do_register_cleanup(function sync_cleanup() {
213 checkpoints.push(2);
214 });
216 do_register_cleanup(function async_cleanup() {
217 let deferred = Promise.defer();
218 do_execute_soon(deferred.resolve);
219 return deferred.promise.then(function() {
220 checkpoints.push(1);
221 });
222 });
224 }
225 '''
228 class XPCShellTestsTests(unittest.TestCase):
229 """
230 Yes, these are unit tests for a unit test harness.
231 """
232 def setUp(self):
233 self.log = StringIO()
234 self.tempdir = tempfile.mkdtemp()
235 self.x = XPCShellTests(log=self.log)
237 def tearDown(self):
238 shutil.rmtree(self.tempdir)
240 def writeFile(self, name, contents):
241 """
242 Write |contents| to a file named |name| in the temp directory,
243 and return the full path to the file.
244 """
245 fullpath = os.path.join(self.tempdir, name)
246 with open(fullpath, "w") as f:
247 f.write(contents)
248 return fullpath
250 def writeManifest(self, tests):
251 """
252 Write an xpcshell.ini in the temp directory and set
253 self.manifest to its pathname. |tests| is a list containing
254 either strings (for test names), or tuples with a test name
255 as the first element and manifest conditions as the following
256 elements.
257 """
258 testlines = []
259 for t in tests:
260 testlines.append("[%s]" % (t if isinstance(t, basestring)
261 else t[0]))
262 if isinstance(t, tuple):
263 testlines.extend(t[1:])
264 self.manifest = self.writeFile("xpcshell.ini", """
265 [DEFAULT]
266 head =
267 tail =
269 """ + "\n".join(testlines))
271 def assertTestResult(self, expected, shuffle=False, xunitFilename=None, verbose=False):
272 """
273 Assert that self.x.runTests with manifest=self.manifest
274 returns |expected|.
275 """
276 self.assertEquals(expected,
277 self.x.runTests(xpcshellBin,
278 manifest=self.manifest,
279 mozInfo=mozinfo.info,
280 shuffle=shuffle,
281 testsRootDir=self.tempdir,
282 verbose=verbose,
283 xunitFilename=xunitFilename,
284 sequential=True),
285 msg="""Tests should have %s, log:
286 ========
287 %s
288 ========
289 """ % ("passed" if expected else "failed", self.log.getvalue()))
291 def _assertLog(self, s, expected):
292 l = self.log.getvalue()
293 self.assertEqual(expected, s in l,
294 msg="""Value %s %s in log:
295 ========
296 %s
297 ========""" % (s, "expected" if expected else "not expected", l))
299 def assertInLog(self, s):
300 """
301 Assert that the string |s| is contained in self.log.
302 """
303 self._assertLog(s, True)
305 def assertNotInLog(self, s):
306 """
307 Assert that the string |s| is not contained in self.log.
308 """
309 self._assertLog(s, False)
311 def testPass(self):
312 """
313 Check that a simple test without any manifest conditions passes.
314 """
315 self.writeFile("test_basic.js", SIMPLE_PASSING_TEST)
316 self.writeManifest(["test_basic.js"])
318 self.assertTestResult(True)
319 self.assertEquals(1, self.x.testCount)
320 self.assertEquals(1, self.x.passCount)
321 self.assertEquals(0, self.x.failCount)
322 self.assertEquals(0, self.x.todoCount)
323 self.assertInLog("TEST-PASS")
324 self.assertNotInLog("TEST-UNEXPECTED-FAIL")
326 def testFail(self):
327 """
328 Check that a simple failing test without any manifest conditions fails.
329 """
330 self.writeFile("test_basic.js", SIMPLE_FAILING_TEST)
331 self.writeManifest(["test_basic.js"])
333 self.assertTestResult(False)
334 self.assertEquals(1, self.x.testCount)
335 self.assertEquals(0, self.x.passCount)
336 self.assertEquals(1, self.x.failCount)
337 self.assertEquals(0, self.x.todoCount)
338 self.assertInLog("TEST-UNEXPECTED-FAIL")
339 self.assertNotInLog("TEST-PASS")
341 @unittest.skipIf(build_obj.defines.get('MOZ_B2G'),
342 'selftests with child processes fail on b2g desktop builds')
343 def testChildPass(self):
344 """
345 Check that a simple test running in a child process passes.
346 """
347 self.writeFile("test_pass.js", SIMPLE_PASSING_TEST)
348 self.writeFile("test_child_pass.js", CHILD_TEST_PASSING)
349 self.writeManifest(["test_child_pass.js"])
351 self.assertTestResult(True, verbose=True)
352 self.assertEquals(1, self.x.testCount)
353 self.assertEquals(1, self.x.passCount)
354 self.assertEquals(0, self.x.failCount)
355 self.assertEquals(0, self.x.todoCount)
356 self.assertInLog("TEST-PASS")
357 self.assertInLog("CHILD-TEST-STARTED")
358 self.assertInLog("CHILD-TEST-COMPLETED")
359 self.assertNotInLog("TEST-UNEXPECTED-FAIL")
362 @unittest.skipIf(build_obj.defines.get('MOZ_B2G'),
363 'selftests with child processes fail on b2g desktop builds')
364 def testChildFail(self):
365 """
366 Check that a simple failing test running in a child process fails.
367 """
368 self.writeFile("test_fail.js", SIMPLE_FAILING_TEST)
369 self.writeFile("test_child_fail.js", CHILD_TEST_FAILING)
370 self.writeManifest(["test_child_fail.js"])
372 self.assertTestResult(False)
373 self.assertEquals(1, self.x.testCount)
374 self.assertEquals(0, self.x.passCount)
375 self.assertEquals(1, self.x.failCount)
376 self.assertEquals(0, self.x.todoCount)
377 self.assertInLog("TEST-UNEXPECTED-FAIL")
378 self.assertInLog("CHILD-TEST-STARTED")
379 self.assertInLog("CHILD-TEST-COMPLETED")
380 self.assertNotInLog("TEST-PASS")
382 @unittest.skipIf(build_obj.defines.get('MOZ_B2G'),
383 'selftests with child processes fail on b2g desktop builds')
384 def testChildHang(self):
385 """
386 Check that incomplete output from a child process results in a
387 test failure.
388 """
389 self.writeFile("test_pass.js", SIMPLE_PASSING_TEST)
390 self.writeFile("test_child_hang.js", CHILD_TEST_HANG)
391 self.writeManifest(["test_child_hang.js"])
393 self.assertTestResult(False)
394 self.assertEquals(1, self.x.testCount)
395 self.assertEquals(0, self.x.passCount)
396 self.assertEquals(1, self.x.failCount)
397 self.assertEquals(0, self.x.todoCount)
398 self.assertInLog("TEST-UNEXPECTED-FAIL")
399 self.assertInLog("CHILD-TEST-STARTED")
400 self.assertNotInLog("CHILD-TEST-COMPLETED")
401 self.assertNotInLog("TEST-PASS")
403 def testSyntaxError(self):
404 """
405 Check that running a test file containing a syntax error produces
406 a test failure and expected output.
407 """
408 self.writeFile("test_syntax_error.js", '"')
409 self.writeManifest(["test_syntax_error.js"])
411 self.assertTestResult(False, verbose=True)
412 self.assertEquals(1, self.x.testCount)
413 self.assertEquals(0, self.x.passCount)
414 self.assertEquals(1, self.x.failCount)
415 self.assertEquals(0, self.x.todoCount)
416 self.assertInLog("TEST-UNEXPECTED-FAIL")
417 self.assertNotInLog("TEST-PASS")
419 def testPassFail(self):
420 """
421 Check that running more than one test works.
422 """
423 self.writeFile("test_pass.js", SIMPLE_PASSING_TEST)
424 self.writeFile("test_fail.js", SIMPLE_FAILING_TEST)
425 self.writeManifest(["test_pass.js", "test_fail.js"])
427 self.assertTestResult(False)
428 self.assertEquals(2, self.x.testCount)
429 self.assertEquals(1, self.x.passCount)
430 self.assertEquals(1, self.x.failCount)
431 self.assertEquals(0, self.x.todoCount)
432 self.assertInLog("TEST-PASS")
433 self.assertInLog("TEST-UNEXPECTED-FAIL")
435 def testSkip(self):
436 """
437 Check that a simple failing test skipped in the manifest does
438 not cause failure.
439 """
440 self.writeFile("test_basic.js", SIMPLE_FAILING_TEST)
441 self.writeManifest([("test_basic.js", "skip-if = true")])
442 self.assertTestResult(True)
443 self.assertEquals(1, self.x.testCount)
444 self.assertEquals(0, self.x.passCount)
445 self.assertEquals(0, self.x.failCount)
446 self.assertEquals(0, self.x.todoCount)
447 self.assertNotInLog("TEST-UNEXPECTED-FAIL")
448 self.assertNotInLog("TEST-PASS")
450 def testKnownFail(self):
451 """
452 Check that a simple failing test marked as known-fail in the manifest
453 does not cause failure.
454 """
455 self.writeFile("test_basic.js", SIMPLE_FAILING_TEST)
456 self.writeManifest([("test_basic.js", "fail-if = true")])
457 self.assertTestResult(True)
458 self.assertEquals(1, self.x.testCount)
459 self.assertEquals(0, self.x.passCount)
460 self.assertEquals(0, self.x.failCount)
461 self.assertEquals(1, self.x.todoCount)
462 self.assertInLog("TEST-KNOWN-FAIL")
463 # This should be suppressed because the harness doesn't include
464 # the full log from the xpcshell run when things pass.
465 self.assertNotInLog("TEST-UNEXPECTED-FAIL")
466 self.assertNotInLog("TEST-PASS")
468 def testUnexpectedPass(self):
469 """
470 Check that a simple failing test marked as known-fail in the manifest
471 that passes causes an unexpected pass.
472 """
473 self.writeFile("test_basic.js", SIMPLE_PASSING_TEST)
474 self.writeManifest([("test_basic.js", "fail-if = true")])
475 self.assertTestResult(False)
476 self.assertEquals(1, self.x.testCount)
477 self.assertEquals(0, self.x.passCount)
478 self.assertEquals(1, self.x.failCount)
479 self.assertEquals(0, self.x.todoCount)
480 # From the outer (Python) harness
481 self.assertInLog("TEST-UNEXPECTED-PASS")
482 self.assertNotInLog("TEST-KNOWN-FAIL")
483 # From the inner (JS) harness
484 self.assertInLog("TEST-PASS")
486 def testReturnNonzero(self):
487 """
488 Check that a test where xpcshell returns nonzero fails.
489 """
490 self.writeFile("test_error.js", "throw 'foo'")
491 self.writeManifest(["test_error.js"])
493 self.assertTestResult(False)
494 self.assertEquals(1, self.x.testCount)
495 self.assertEquals(0, self.x.passCount)
496 self.assertEquals(1, self.x.failCount)
497 self.assertEquals(0, self.x.todoCount)
498 self.assertInLog("TEST-UNEXPECTED-FAIL")
499 self.assertNotInLog("TEST-PASS")
501 def testAddTestSimple(self):
502 """
503 Ensure simple add_test() works.
504 """
505 self.writeFile("test_add_test_simple.js", ADD_TEST_SIMPLE)
506 self.writeManifest(["test_add_test_simple.js"])
508 self.assertTestResult(True)
509 self.assertEquals(1, self.x.testCount)
510 self.assertEquals(1, self.x.passCount)
511 self.assertEquals(0, self.x.failCount)
513 def testAddTestFailing(self):
514 """
515 Ensure add_test() with a failing test is reported.
516 """
517 self.writeFile("test_add_test_failing.js", ADD_TEST_FAILING)
518 self.writeManifest(["test_add_test_failing.js"])
520 self.assertTestResult(False)
521 self.assertEquals(1, self.x.testCount)
522 self.assertEquals(0, self.x.passCount)
523 self.assertEquals(1, self.x.failCount)
525 def testAddTaskTestSingle(self):
526 """
527 Ensure add_test_task() with a single passing test works.
528 """
529 self.writeFile("test_add_task_simple.js", ADD_TASK_SINGLE)
530 self.writeManifest(["test_add_task_simple.js"])
532 self.assertTestResult(True)
533 self.assertEquals(1, self.x.testCount)
534 self.assertEquals(1, self.x.passCount)
535 self.assertEquals(0, self.x.failCount)
537 def testAddTaskTestMultiple(self):
538 """
539 Ensure multiple calls to add_test_task() work as expected.
540 """
541 self.writeFile("test_add_task_multiple.js",
542 ADD_TASK_MULTIPLE)
543 self.writeManifest(["test_add_task_multiple.js"])
545 self.assertTestResult(True)
546 self.assertEquals(1, self.x.testCount)
547 self.assertEquals(1, self.x.passCount)
548 self.assertEquals(0, self.x.failCount)
550 def testAddTaskTestRejected(self):
551 """
552 Ensure rejected task reports as failure.
553 """
554 self.writeFile("test_add_task_rejected.js",
555 ADD_TASK_REJECTED)
556 self.writeManifest(["test_add_task_rejected.js"])
558 self.assertTestResult(False)
559 self.assertEquals(1, self.x.testCount)
560 self.assertEquals(0, self.x.passCount)
561 self.assertEquals(1, self.x.failCount)
563 def testAddTaskTestFailureInside(self):
564 """
565 Ensure tests inside task are reported as failures.
566 """
567 self.writeFile("test_add_task_failure_inside.js",
568 ADD_TASK_FAILURE_INSIDE)
569 self.writeManifest(["test_add_task_failure_inside.js"])
571 self.assertTestResult(False)
572 self.assertEquals(1, self.x.testCount)
573 self.assertEquals(0, self.x.passCount)
574 self.assertEquals(1, self.x.failCount)
576 def testAddTaskRunNextTest(self):
577 """
578 Calling run_next_test() from inside add_task() results in failure.
579 """
580 self.writeFile("test_add_task_run_next_test.js",
581 ADD_TASK_RUN_NEXT_TEST)
582 self.writeManifest(["test_add_task_run_next_test.js"])
584 self.assertTestResult(False)
585 self.assertEquals(1, self.x.testCount)
586 self.assertEquals(0, self.x.passCount)
587 self.assertEquals(1, self.x.failCount)
589 def testMissingHeadFile(self):
590 """
591 Ensure that missing head file results in fatal error.
592 """
593 self.writeFile("test_basic.js", SIMPLE_PASSING_TEST)
594 self.writeManifest([("test_basic.js", "head = missing.js")])
596 raised = False
598 try:
599 # The actual return value is never checked because we raise.
600 self.assertTestResult(True)
601 except Exception, ex:
602 raised = True
603 self.assertEquals(ex.message[0:9], "head file")
605 self.assertTrue(raised)
607 def testMissingTailFile(self):
608 """
609 Ensure that missing tail file results in fatal error.
610 """
611 self.writeFile("test_basic.js", SIMPLE_PASSING_TEST)
612 self.writeManifest([("test_basic.js", "tail = missing.js")])
614 raised = False
616 try:
617 self.assertTestResult(True)
618 except Exception, ex:
619 raised = True
620 self.assertEquals(ex.message[0:9], "tail file")
622 self.assertTrue(raised)
624 def testRandomExecution(self):
625 """
626 Check that random execution doesn't break.
627 """
628 manifest = []
629 for i in range(0, 10):
630 filename = "test_pass_%d.js" % i
631 self.writeFile(filename, SIMPLE_PASSING_TEST)
632 manifest.append(filename)
634 self.writeManifest(manifest)
635 self.assertTestResult(True, shuffle=True)
636 self.assertEquals(10, self.x.testCount)
637 self.assertEquals(10, self.x.passCount)
639 def testXunitOutput(self):
640 """
641 Check that Xunit XML files are written.
642 """
643 self.writeFile("test_00.js", SIMPLE_PASSING_TEST)
644 self.writeFile("test_01.js", SIMPLE_FAILING_TEST)
645 self.writeFile("test_02.js", SIMPLE_PASSING_TEST)
647 manifest = [
648 "test_00.js",
649 "test_01.js",
650 ("test_02.js", "skip-if = true")
651 ]
653 self.writeManifest(manifest)
655 filename = os.path.join(self.tempdir, "xunit.xml")
657 self.assertTestResult(False, xunitFilename=filename)
659 self.assertTrue(os.path.exists(filename))
660 self.assertTrue(os.path.getsize(filename) > 0)
662 tree = ElementTree()
663 tree.parse(filename)
664 suite = tree.getroot()
666 self.assertTrue(suite is not None)
667 self.assertEqual(suite.get("tests"), "3")
668 self.assertEqual(suite.get("failures"), "1")
669 self.assertEqual(suite.get("skip"), "1")
671 testcases = suite.findall("testcase")
672 self.assertEqual(len(testcases), 3)
674 for testcase in testcases:
675 attributes = testcase.keys()
676 self.assertTrue("classname" in attributes)
677 self.assertTrue("name" in attributes)
678 self.assertTrue("time" in attributes)
680 self.assertTrue(testcases[1].find("failure") is not None)
681 self.assertTrue(testcases[2].find("skipped") is not None)
683 def testDoThrowString(self):
684 """
685 Check that do_throw produces reasonable messages when the
686 input is a string instead of an object
687 """
688 self.writeFile("test_error.js", ADD_TEST_THROW_STRING)
689 self.writeManifest(["test_error.js"])
691 self.assertTestResult(False)
692 self.assertInLog("TEST-UNEXPECTED-FAIL")
693 self.assertInLog("Passing a string to do_throw")
694 self.assertNotInLog("TEST-PASS")
696 def testDoThrowForeignObject(self):
697 """
698 Check that do_throw produces reasonable messages when the
699 input is a generic object with 'filename', 'message' and 'stack' attributes
700 but 'object instanceof Error' returns false
701 """
702 self.writeFile("test_error.js", ADD_TEST_THROW_OBJECT)
703 self.writeManifest(["test_error.js"])
705 self.assertTestResult(False)
706 self.assertInLog("TEST-UNEXPECTED-FAIL")
707 self.assertInLog("failure.js")
708 self.assertInLog("Error object")
709 self.assertInLog("ERROR STACK")
710 self.assertNotInLog("TEST-PASS")
712 def testDoReportForeignObject(self):
713 """
714 Check that do_report_unexpected_exception produces reasonable messages when the
715 input is a generic object with 'filename', 'message' and 'stack' attributes
716 but 'object instanceof Error' returns false
717 """
718 self.writeFile("test_error.js", ADD_TEST_REPORT_OBJECT)
719 self.writeManifest(["test_error.js"])
721 self.assertTestResult(False)
722 self.assertInLog("TEST-UNEXPECTED-FAIL")
723 self.assertInLog("failure.js")
724 self.assertInLog("Error object")
725 self.assertInLog("ERROR STACK")
726 self.assertNotInLog("TEST-PASS")
728 def testDoReportRefError(self):
729 """
730 Check that do_report_unexpected_exception produces reasonable messages when the
731 input is a JS-generated Error
732 """
733 self.writeFile("test_error.js", ADD_TEST_REPORT_REF_ERROR)
734 self.writeManifest(["test_error.js"])
736 self.assertTestResult(False)
737 self.assertInLog("TEST-UNEXPECTED-FAIL")
738 self.assertInLog("test_error.js")
739 self.assertInLog("obj.noSuchFunction is not a function")
740 self.assertInLog("run_test@")
741 self.assertNotInLog("TEST-PASS")
743 def testDoReportSyntaxError(self):
744 """
745 Check that attempting to load a test file containing a syntax error
746 generates details of the error in the log
747 """
748 self.writeFile("test_error.js", LOAD_ERROR_SYNTAX_ERROR)
749 self.writeManifest(["test_error.js"])
751 self.assertTestResult(False)
752 self.assertInLog("TEST-UNEXPECTED-FAIL")
753 self.assertInLog("test_error.js")
754 self.assertInLog("test_error.js contains SyntaxError")
755 self.assertInLog("Diagnostic: SyntaxError: missing formal parameter at")
756 self.assertInLog("test_error.js:3")
757 self.assertNotInLog("TEST-PASS")
759 def testDoReportNonSyntaxError(self):
760 """
761 Check that attempting to load a test file containing an error other
762 than a syntax error generates details of the error in the log
763 """
764 self.writeFile("test_error.js", LOAD_ERROR_OTHER_ERROR)
765 self.writeManifest(["test_error.js"])
767 self.assertTestResult(False)
768 self.assertInLog("TEST-UNEXPECTED-FAIL")
769 self.assertInLog("Diagnostic: TypeError: generator function run_test returns a value at")
770 self.assertInLog("test_error.js:4")
771 self.assertNotInLog("TEST-PASS")
773 def testAsyncCleanup(self):
774 """
775 Check that do_register_cleanup handles nicely cleanup tasks that
776 return a promise
777 """
778 self.writeFile("test_asyncCleanup.js", ASYNC_CLEANUP)
779 self.writeManifest(["test_asyncCleanup.js"])
780 self.assertTestResult(False)
781 self.assertInLog("\"1234\" == \"1234\"")
782 self.assertInLog("At this stage, the test has succeeded")
783 self.assertInLog("Throwing an error to force displaying the log")
785 if __name__ == "__main__":
786 unittest.main()