Bug 509269: new harness for shell JSTests with multiprocessing and more control, r=bc,jorendorff
authorDavid Mandelin <dmandelin@mozilla.com>
Mon, 05 Oct 2009 12:07:26 -0700
changeset 35338 4b1f9afcedb1ff8543f35f523fc688cb1f695386
parent 35337 5b26aa0baceea96cd05bb822bc1624bf95d86f55
child 35339 6684f72a9c729cd9ecbc5706292d4e3d44d307d0
child 35340 9f3d4978017366fbbab7100f934a68d3fdbdc2f6
push idunknown
push userunknown
push dateunknown
reviewersbc, jorendorff
bugs509269
milestone1.9.3a1pre
Bug 509269: new harness for shell JSTests with multiprocessing and more control, r=bc,jorendorff
js/src/tests/e4x/Expressions/jstests.list
js/src/tests/e4x/GC/jstests.list
js/src/tests/e4x/Regress/jstests.list
js/src/tests/ecma/Date/jstests.list
js/src/tests/ecma/ExecutionContexts/jstests.list
js/src/tests/ecma/TypeConversion/9.3-1.js
js/src/tests/ecma_2/Statements/jstests.list
js/src/tests/js1_3/Script/jstests.list
js/src/tests/js1_3/regress/jstests.list
js/src/tests/js1_5/Array/jstests.list
js/src/tests/js1_5/GC/jstests.list
js/src/tests/js1_5/Regress/jstests.list
js/src/tests/js1_5/Regress/regress-3649-n.js
js/src/tests/js1_5/extensions/jstests.list
js/src/tests/js1_6/decompilation/jstests.list
js/src/tests/js1_6/extensions/jstests.list
js/src/tests/js1_7/extensions/jstests.list
js/src/tests/js1_7/iterable/jstests.list
js/src/tests/js1_8/extensions/jstests.list
js/src/tests/js1_8/genexps/jstests.list
js/src/tests/js1_8/regress/jstests.list
js/src/tests/js1_8_1/regress/jstests.list
js/src/tests/jstests.py
js/src/tests/manifest.py
js/src/tests/progressbar.py
js/src/tests/spidermonkey-n-1.9.3.tests
js/src/tests/tests.py
js/src/tests/workers.py
js/src/trace-test/trace-test.py
--- a/js/src/tests/e4x/Expressions/jstests.list
+++ b/js/src/tests/e4x/Expressions/jstests.list
@@ -1,16 +1,16 @@
 url-prefix ../../jsreftest.html?test=e4x/Expressions/
 script 11.1.1.js
 script 11.1.2.js
 script 11.1.3.js
 script 11.1.4-01.js
 script 11.1.4-02.js
 script 11.1.4-03.js
-fails script 11.1.4-04.js
+fails-if(!xulRuntime.shell) script 11.1.4-04.js # bug - Expected value 'NL    there ', Actual value 'there' 
 script 11.1.4-05.js
 script 11.1.4-06.js
 script 11.1.4-07.js
 fails script 11.1.4-08.js
 script 11.1.4.js
 script 11.1.5.js
 script 11.2.1.js
 script 11.2.2.js
--- a/js/src/tests/e4x/GC/jstests.list
+++ b/js/src/tests/e4x/GC/jstests.list
@@ -1,11 +1,11 @@
 url-prefix ../../jsreftest.html?test=e4x/GC/
 script regress-280844-1.js
 script regress-280844-2.js
-skip script regress-292455.js # does not always dismiss alert
+skip-if(!xulRuntime.shell) script regress-292455.js # does not always dismiss alert
 script regress-313952-01.js
 script regress-313952-02.js
 script regress-324117.js
 skip script regress-324278.js # slow
 script regress-339785.js
 script regress-357063-01.js
 script regress-357063-02.js
--- a/js/src/tests/e4x/Regress/jstests.list
+++ b/js/src/tests/e4x/Regress/jstests.list
@@ -13,17 +13,17 @@ script regress-277935.js
 skip script regress-278112.js # obsolete test
 script regress-283349.js
 script regress-290056.js
 script regress-290499.js
 script regress-301553.js
 script regress-301573.js
 script regress-301596.js
 script regress-301692.js
-skip-if(isDebugBuild) script regress-308111.js # slow
+skip-if(!xulRuntime.shell&&isDebugBuild) script regress-308111.js # slow
 script regress-309897.js
 script regress-311580.js
 script regress-313799.js
 script regress-318922.js
 skip script regress-319872.js # slow, Bug 514139
 script regress-321547.js
 script regress-322499.js
 script regress-323338-1.js
@@ -36,17 +36,17 @@ script regress-327697.js
 script regress-328249.js
 script regress-329257.js
 script regress-331558.js
 script regress-331664.js
 script regress-344455.js
 script regress-347155.js
 script regress-350206-1.js
 script regress-350206.js
-skip script regress-350238.js # slow
+skip-if(!xulRuntime.shell) script regress-350238.js # slow
 script regress-350629.js
 script regress-352097.js
 script regress-352103.js
 script regress-352223.js
 script regress-354145-01.js
 script regress-354145-02.js
 script regress-354145-03.js
 script regress-354145-04.js
--- a/js/src/tests/ecma/Date/jstests.list
+++ b/js/src/tests/ecma/Date/jstests.list
@@ -28,17 +28,17 @@ script 15.9.4.2-1.js
 script 15.9.4.2.js
 script 15.9.4.3.js
 script 15.9.5.1.js
 script 15.9.5.10-1.js
 script 15.9.5.10-10.js
 script 15.9.5.10-11.js
 script 15.9.5.10-12.js
 script 15.9.5.10-13.js
-skip script 15.9.5.10-2.js # bug xxx
+script 15.9.5.10-2.js
 script 15.9.5.10-3.js
 script 15.9.5.10-4.js
 script 15.9.5.10-5.js
 script 15.9.5.10-6.js
 script 15.9.5.10-7.js
 script 15.9.5.10-8.js
 script 15.9.5.10-9.js
 script 15.9.5.11-1.js
@@ -141,11 +141,11 @@ script 15.9.5.37-2.js
 script 15.9.5.37-3.js
 script 15.9.5.37-4.js
 script 15.9.5.37-5.js
 script 15.9.5.4-1.js
 script 15.9.5.4-2-n.js
 script 15.9.5.5.js
 script 15.9.5.6.js
 script 15.9.5.7.js
-skip-if(isDebugBuild) script 15.9.5.8.js # slow
+script 15.9.5.8.js
 script 15.9.5.9.js
 script 15.9.5.js
--- a/js/src/tests/ecma/ExecutionContexts/jstests.list
+++ b/js/src/tests/ecma/ExecutionContexts/jstests.list
@@ -13,12 +13,12 @@ script 10.1.4-7.js
 script 10.1.4-8.js
 script 10.1.5-1.js
 script 10.1.5-2.js
 script 10.1.5-3.js
 script 10.1.5-4.js
 script 10.1.8-2.js
 script 10.1.8-3.js
 script 10.2.1.js
-fails script 10.2.2-1.js
-fails script 10.2.2-2.js
+skip-if(!xulRuntime.shell) script 10.2.2-1.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR Line 91
+skip-if(!xulRuntime.shell) script 10.2.2-2.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR Line 177
 script 10.2.3-1.js
 script 10.2.3-2.js
--- a/js/src/tests/ecma/TypeConversion/9.3-1.js
+++ b/js/src/tests/ecma/TypeConversion/9.3-1.js
@@ -93,8 +93,9 @@ new TestCase( SECTION, "typeof Number(ne
 
 new TestCase( SECTION, "Number(new Boolean(false))", 0, Number(new Boolean(false)) );
 new TestCase( SECTION, "typeof Number(new Boolean(false))", "number", typeof Number(new Boolean(false)) );
 
 // object is array
 new TestCase( SECTION, "Number(new Array(2,4,8,16,32))", Number.NaN, Number(new Array(2,4,8,16,32)) );
 new TestCase( SECTION, "typeof Number(new Array(2,4,8,16,32))", "number", typeof Number(new Array(2,4,8,16,32)) );
 
+test();
--- a/js/src/tests/ecma_2/Statements/jstests.list
+++ b/js/src/tests/ecma_2/Statements/jstests.list
@@ -2,17 +2,17 @@ url-prefix ../../jsreftest.html?test=ecm
 script dowhile-001.js
 script dowhile-002.js
 script dowhile-003.js
 script dowhile-004.js
 script dowhile-005.js
 script dowhile-006.js
 script dowhile-007.js
 script forin-001.js
-fails script forin-002.js
+fails-if(!xulRuntime.shell) script forin-002.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 112
 script if-001.js
 script label-001.js
 script label-002.js
 script switch-001.js
 script switch-002.js
 script switch-003.js
 script switch-004.js
 script try-001.js
--- a/js/src/tests/js1_3/Script/jstests.list
+++ b/js/src/tests/js1_3/Script/jstests.list
@@ -1,7 +1,7 @@
 url-prefix ../../jsreftest.html?test=js1_3/Script/
-skip script delete-001.js # obsolete test
+script delete-001.js
 skip script function-001-n.js # obsolete test
 script function-002.js
 script in-001.js
 script new-001.js
 script switch-001.js
--- a/js/src/tests/js1_3/regress/jstests.list
+++ b/js/src/tests/js1_3/regress/jstests.list
@@ -1,7 +1,7 @@
 url-prefix ../../jsreftest.html?test=js1_3/regress/
-skip script delete-001.js # obsolete test
+script delete-001.js
 skip script function-001-n.js # obsolete test
 script function-002.js
 script in-001.js
 script new-001.js
 script switch-001.js
--- a/js/src/tests/js1_5/Array/jstests.list
+++ b/js/src/tests/js1_5/Array/jstests.list
@@ -1,14 +1,14 @@
 url-prefix ../../jsreftest.html?test=js1_5/Array/
 script 11.1.4.js
 script array-001.js
 script regress-101964.js
 script regress-107138.js
-fails script regress-108440.js
+fails-if(!xulRuntime.shell) script regress-108440.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 74
 script regress-154338.js
 skip-if(xulRuntime.OS=="Linux"&&xulRuntime.XPCOMABI.match(/x86_64/)) script regress-157652.js # No test results
 script regress-178722.js
 script regress-255555.js
 script regress-299644.js
 script regress-300858.js
 script regress-310351.js
 script regress-311515.js
--- a/js/src/tests/js1_5/GC/jstests.list
+++ b/js/src/tests/js1_5/GC/jstests.list
@@ -1,22 +1,22 @@
 url-prefix ../../jsreftest.html?test=js1_5/GC/
 script regress-104584.js
-skip-if(xulRuntime.OS=="Darwin") script regress-203278-2.js # slow
+skip-if(!xulRuntime.shell&&xulRuntime.OS=="Darwin") script regress-203278-2.js # slow
 script regress-203278-3.js
 script regress-278725.js
 script regress-306788.js
 script regress-311497.js
 script regress-313276.js
 script regress-313479.js
 script regress-316885-01.js
 script regress-316885-02.js
 script regress-316885-03.js
-skip script regress-319980-01.js # slow, sometimes out of memory fatal exception.
-script regress-324278.js
+skip-if(!xulRuntime.shell&&xulRuntime.OS=="Linux") script regress-319980-01.js # slow
+skip-if(!xulRuntime.shell&&!isDebugBuild) script regress-324278.js # slow
 script regress-331719.js
 skip script regress-338653.js # slow, killed on x86_64
 script regress-341877-01.js
 script regress-341877-02.js
 skip script regress-346794.js # slow, killed
 script regress-348532.js
 script regress-352606.js
 script regress-383269-01.js
--- a/js/src/tests/js1_5/Regress/jstests.list
+++ b/js/src/tests/js1_5/Regress/jstests.list
@@ -36,17 +36,17 @@ skip script regress-173067.js # obsolete
 script regress-174709.js
 script regress-176125.js
 script regress-179524.js
 script regress-185165.js
 script regress-191633.js
 script regress-191668.js
 script regress-192414.js
 script regress-193418.js
-skip-if(xulRuntime.OS=="Darwin") script regress-203278-1.js # slow
+skip-if(!xulRuntime.shell&&xulRuntime.OS=="Darwin"||xulRuntime.shell&&xulRuntime.OS=="Linux"&&xulRuntime.XPCOMABI.match(/x86_64/)) script regress-203278-1.js # slow
 script regress-203402.js
 script regress-203841.js
 script regress-204210.js
 script regress-210682.js
 script regress-211590.js
 script regress-213482.js
 script regress-214761.js
 script regress-216320.js
@@ -76,17 +76,17 @@ script regress-248444.js
 skip script regress-249211.js # obsolete test
 script regress-252892.js
 script regress-253150.js
 script regress-254296.js
 script regress-254974.js
 script regress-256501.js
 script regress-256617.js
 script regress-256798.js
-script regress-259935.js
+skip-if(xulRuntime.shell) script regress-259935.js # browser only
 script regress-260541.js
 script regress-261886.js
 script regress-261887.js
 skip script regress-271716-n.js # never terminates
 script regress-274035.js
 script regress-274888.js
 script regress-275378.js
 script regress-276103.js
@@ -200,17 +200,17 @@ script regress-355829-02.js
 script regress-355829-03.js
 script regress-356250.js
 script regress-356693.js
 script regress-360969-01.js
 script regress-360969-02.js
 script regress-360969-03.js
 script regress-360969-04.js
 script regress-360969-05.js
-skip-if(isDebugBuild) script regress-360969-06.js # slow
+script regress-360969-06.js
 script regress-361467.js
 script regress-361617.js
 skip script regress-362583.js # obsolete test
 fails-if(xulRuntime.OS=="WINNT") random-if(xulRuntime.OS=="Linux"&&!xulRuntime.XPCOMABI.match(/x86_64/)) skip-if(xulRuntime.OS=="Linux"&&xulRuntime.XPCOMABI.match(/x86_64/)) script regress-3649-n.js # No test results on windows, sometimes no test results on 32 bit linux, hangs os/consumes ram/swap on 64bit linux.
 script regress-366122.js
 script regress-366468.js
 script regress-366601.js
 script regress-367561-01.js
@@ -320,17 +320,17 @@ script regress-465347.js
 script regress-465366.js
 script regress-466262.js
 script regress-466747.js
 script regress-469044.js
 script regress-470061.js
 script regress-470187-01.js
 script regress-470187-02.js
 script regress-470758-01.js
-skip script regress-470758-02.js
+script regress-470758-02.js
 script regress-475645-01.js
 script regress-475645-02.js
 script regress-476049.js
 script regress-476192.js
 script regress-477733.js
 script regress-477758.js
 script regress-478314.js
 script regress-479353.js
--- a/js/src/tests/js1_5/Regress/regress-3649-n.js
+++ b/js/src/tests/js1_5/Regress/regress-3649-n.js
@@ -46,16 +46,17 @@ var expect = 'error';
 
 DESCRIPTION = summary;
 EXPECTED = expect;
 
 printBugNumber(BUGNUMBER);
 printStatus (summary);
  
 expectExitCode(0);
+expectExitCode(3);
 expectExitCode(5);
 
 var s = "";
 s = "abcd";
 for (i = 0; i < 100000; i++)  {
   s += s;
 }
 
--- a/js/src/tests/js1_5/extensions/jstests.list
+++ b/js/src/tests/js1_5/extensions/jstests.list
@@ -41,22 +41,22 @@ script regress-313938.js
 script regress-314874.js
 script regress-315509-02.js
 script regress-319683.js
 fails script regress-322957.js
 script regress-325269.js
 script regress-327608.js
 script regress-328443.js
 script regress-328556.js
-skip script regress-330569.js # slow
+script regress-330569.js
 script regress-333541.js
 skip script regress-335700.js # bug xxx - reftest hang, BigO
-skip script regress-336409-1.js # no results reported.
+skip-if(!xulRuntime.shell) script regress-336409-1.js # no results reported.
 script regress-336409-2.js
-skip script regress-336410-1.js # slow
+skip-if(!xulRuntime.shell) script regress-336410-1.js # slow
 script regress-336410-2.js
 script regress-338804-01.js
 script regress-338804-02.js
 script regress-338804-03.js
 script regress-339685.js
 script regress-340199.js
 script regress-341956-01.js
 script regress-341956-02.js
@@ -111,20 +111,20 @@ script regress-358594-05.js
 script regress-358594-06.js
 script regress-359024.js
 script regress-361346.js
 script regress-361360.js
 script regress-361552.js
 script regress-361558.js
 script regress-361571.js
 script regress-361856.js
-skip script regress-361964.js # slow
+skip-if(!xulRuntime.shell) script regress-361964.js # alert is not dismissed.
 random-if(xulRuntime.OS=="WINNT") script regress-363258.js # bug 524788
 script regress-363988.js
-skip-if(isDebugBuild) script regress-365527.js # slow
+script regress-365527.js
 script regress-365692.js
 script regress-365869.js
 script regress-366288.js
 script regress-366292.js
 script regress-366396.js
 script regress-367118-01.js
 script regress-367118-02.js
 script regress-367119-01.js
@@ -165,17 +165,17 @@ script regress-385134.js
 script regress-385393-02.js
 script regress-385393-09.js
 script regress-390597.js
 script regress-394967.js
 script regress-396326.js
 script regress-406572.js
 script regress-407019.js
 script regress-407501.js
-skip script regress-407720.js # slow
+skip-if(!xulRuntime.shell) script regress-407720.js # slow
 script regress-412926.js
 script regress-414755.js
 script regress-416354.js
 script regress-416460.js
 script regress-416834.js
 skip script regress-418730.js # obsolete test
 script regress-420612.js
 script regress-420869-01.js
@@ -197,17 +197,17 @@ script regress-435497-01.js
 script regress-435497-02.js
 script regress-435497-03.js
 script regress-436741.js
 skip script regress-437288-01.js # obsolete test
 script regress-44009.js
 script regress-443569.js
 script regress-446386.js
 script regress-449657.js
-skip-if(isDebugBuild) script regress-452168.js
+script regress-452168.js
 script regress-452178.js
 script regress-452329.js
 script regress-452338.js
 script regress-452372.js
 script regress-452565.js
 script regress-453249.js
 script regress-454040.js
 script regress-454142.js
--- a/js/src/tests/js1_6/decompilation/jstests.list
+++ b/js/src/tests/js1_6/decompilation/jstests.list
@@ -1,4 +1,4 @@
 url-prefix ../../jsreftest.html?test=js1_6/decompilation/
 script regress-352084.js
 script regress-352613-01.js
-skip-if(isDebugBuild) script regress-352613-02.js # bug xxx - hang reftests.
+script regress-352613-02.js
--- a/js/src/tests/js1_6/extensions/jstests.list
+++ b/js/src/tests/js1_6/extensions/jstests.list
@@ -1,15 +1,15 @@
 url-prefix ../../jsreftest.html?test=js1_6/extensions/
 script regress-312385-01.js
 script regress-352392.js
 script regress-385393-08.js
 script regress-414098.js
-fails script regress-455464-01.js
-fails script regress-455464-02.js
-fails script regress-455464-03.js
+fails-if(!xulRuntime.shell) script regress-455464-01.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 1
+fails-if(!xulRuntime.shell) script regress-455464-02.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 49
+fails-if(!xulRuntime.shell) script regress-455464-03.js # bug - NS_ERROR_DOM_NOT_SUPPORTED_ERR line 1
 fails-if(!xulRuntime.shell&&!isDebugBuild) skip-if(!xulRuntime.shell&&isDebugBuild) script regress-455464-04.js # bug xxx - hangs reftests in debug, ### bug xxx - NS_ERROR_DOM_NOT_SUPPORTED_ERR in opt
-skip script regress-456826.js # slow
+fails-if(xulRuntime.shell) skip-if(!xulRuntime.shell) script regress-456826.js # bug 504632
 script regress-457521.js
 script regress-465443.js
 script regress-470310.js
 script regress-472508.js
 fails-if(!xulRuntime.shell) script regress-475144.js # NS_ERROR_DOM_NOT_SUPPORTED_ERR
--- a/js/src/tests/js1_7/extensions/jstests.list
+++ b/js/src/tests/js1_7/extensions/jstests.list
@@ -50,16 +50,16 @@ script regress-381303.js
 script regress-387955-01.js
 script regress-387955-02.js
 script regress-392308.js
 script regress-396326.js
 script regress-429266.js
 script regress-453955.js
 fails-if(!xulRuntime.shell) script regress-455982-01.js # NS_ERROR_DOM_NOT_SUPPORTED_ERR
 fails-if(!xulRuntime.shell) script regress-455982-02.js # NS_ERROR_DOM_NOT_SUPPORTED_ERR
-skip script regress-458679.js # slow
+skip-if(!xulRuntime.shell||xulRuntime.shell&&xulRuntime.XPCOMABI.match(/x86_64/)) script regress-458679.js # slow
 script regress-469234.js
 script regress-470176.js
 script regress-470300-01.js
 script regress-470300-02.js
 script regress-474771-01.js
 script regress-474771-02.js
 script regress-477048.js
--- a/js/src/tests/js1_7/iterable/jstests.list
+++ b/js/src/tests/js1_7/iterable/jstests.list
@@ -1,15 +1,15 @@
 url-prefix ../../jsreftest.html?test=js1_7/iterable/
 script regress-340526-01.js
 skip script regress-340526-02.js # obsolete test
 script regress-341496.js
 script regress-341499.js
 script regress-341510.js
-skip script regress-341815.js # bug xxx - fails to dismiss alert
-skip script regress-341821.js # bug xxx - fails to dismiss alert
+skip-if(!xulRuntime.shell) script regress-341815.js # bug xxx - fails to dismiss alert
+skip-if(!xulRuntime.shell) script regress-341821.js # bug xxx - fails to dismiss alert
 script regress-354750-01.js
 script regress-355025.js
 script regress-355075-01.js
 script regress-355075-02.js
 script regress-355090.js
 script regress-412467.js
 script regress-415922.js
--- a/js/src/tests/js1_8/extensions/jstests.list
+++ b/js/src/tests/js1_8/extensions/jstests.list
@@ -25,17 +25,17 @@ script regress-455973.js
 script regress-465337.js
 script regress-465453.js
 script regress-469625.js
 script regress-471197.js
 script regress-472450-03.js
 script regress-472450-04.js
 script regress-473040.js
 script regress-475971.js
-skip script regress-476414-01.js # slow
-skip script regress-476414-02.js # slow
+skip-if(!xulRuntime.shell) script regress-476414-01.js # slow
+skip-if(!xulRuntime.shell) script regress-476414-02.js # slow
 fails-if(!xulRuntime.shell) script regress-476427.js # NS_ERROR_DOM_NOT_SUPPORTED_ERR
 script regress-476869.js
 script regress-479252.js
 script regress-479381.js
 script regress-481989.js
 script regress-482263.js
 script simple-tree.js
--- a/js/src/tests/js1_8/genexps/jstests.list
+++ b/js/src/tests/js1_8/genexps/jstests.list
@@ -1,10 +1,10 @@
 url-prefix ../../jsreftest.html?test=js1_8/genexps/
 script regress-347739.js
 script regress-349012-01.js
 script regress-349326.js
 script regress-349331.js
 script regress-380237-01.js
 script regress-380237-02.js
-skip script regress-380237-03.js # obsolete test
-skip script regress-380237-04.js # obsolete test
+script regress-380237-03.js
+skip script regress-380237-04.js # obsolete test, need to remove minor failures to reenable.
 script regress-384991.js
--- a/js/src/tests/js1_8/regress/jstests.list
+++ b/js/src/tests/js1_8/regress/jstests.list
@@ -21,17 +21,17 @@ script regress-459389.js
 script regress-461930.js
 script regress-461932.js
 script regress-463334-01.js
 script regress-463334-02.js
 script regress-463783.js
 script regress-464092-01.js
 script regress-464092-02.js
 script regress-464096.js
-skip-if(isDebugBuild) script regress-464418.js # slow
+script regress-464418.js
 script regress-464978.js
 script regress-465220.js
 script regress-465234.js
 script regress-465239.js
 script regress-465241.js
 script regress-465249.js
 script regress-465261.js
 script regress-465308.js
@@ -69,15 +69,15 @@ script regress-472450-01.js
 script regress-472450-02.js
 script regress-472528-01.js
 script regress-472528-02.js
 script regress-472703.js
 script regress-474769.js
 script regress-474771.js
 script regress-474935.js
 script regress-476655.js
-skip-if(isDebugBuild) script regress-477234.js # slow
+script regress-477234.js
 script regress-477581.js
 script regress-478205.js
 script regress-479353.js
 script regress-479740.js
 script regress-481800.js
 script regress-483749.js
--- a/js/src/tests/js1_8_1/regress/jstests.list
+++ b/js/src/tests/js1_8_1/regress/jstests.list
@@ -76,9 +76,10 @@ script regress-479430-05.js
 script regress-495773.js
 script regress-495907.js
 script regress-496922.js
 script regress-507053.js
 script regress-507295.js
 script regress-507424.js
 script regress-515885.js
 skip-if(isDebugBuild&&!xulRuntime.shell)  script regress-524743.js # hang
+script regress-522123.js
 script regress-524264.js
new file mode 100644
--- /dev/null
+++ b/js/src/tests/jstests.py
@@ -0,0 +1,316 @@
+# Test harness for JSTests, controlled by manifest files.
+
+import datetime, os, sys
+from subprocess import *
+
+from tests import TestResult, NullTestOutput
+from workers import Source
+from progressbar import ProgressBar
+
+def exclude_tests(test_list, exclude_files):
+    exclude_paths = []
+    for filename in exclude_files:
+        for line in open(filename):
+            if line.startswith('#'): continue
+            line = line.strip('\n')
+            if not line: continue
+            exclude_paths.append(line)
+    return [ _ for _ in test_list if _.path not in exclude_paths ]
+
+def check_manifest(test_list):
+    test_set = set([ _.path for _ in test_list ])
+
+    missing = []
+
+    for dirpath, dirnames, filenames in os.walk('.'):
+        for filename in filenames:
+            if dirpath == '.': continue
+            if not filename.endswith('.js'): continue
+            if filename in ('browser.js', 'shell.js', 'jsref.js', 'template.js'): continue
+
+            path = os.path.join(dirpath, filename)
+            if path.startswith('./'):
+                path = path[2:]
+            if path not in test_set:
+                missing.append(path)
+
+    if missing:
+        print "Test files not contained in any manifest:"
+        for path in missing:
+            print path
+    else:
+        print 'All test files are listed in manifests'
+
+class TestTask:
+    js_cmd_prefix = None
+
+    def __init__(self, test):
+        self.test = test
+
+    def __call__(self):
+        if self.test.enable or OPTIONS.run_skipped:
+            return self.test.run(self.js_cmd_prefix, OPTIONS.timeout)
+        else:
+            return NullTestOutput(self.test)
+
+    def __str__(self):
+        return str(self.test)
+
+    @classmethod
+    def set_js_cmd_prefix(self, js_path, js_args, debugger_prefix):
+        parts = []
+        if debugger_prefix:
+            parts += debugger_prefix
+        parts.append(js_path)
+        if js_args:
+            parts.append(js_args)
+        self.js_cmd_prefix = parts
+
+class ResultsSink:
+    output_file = None
+
+    def __init__(self):
+        self.groups = {}
+        self.counts = [ 0, 0, 0 ]
+        self.n = 0
+
+        self.finished = False
+        self.pb = None
+
+    def push(self, output):
+        if isinstance(output, NullTestOutput):
+            if OPTIONS.tinderbox:
+                print '%s | %s (SKIP)' % ('TEST-KNOWN-FAIL', output.test.path)
+            self.counts[2] += 1
+            self.n += 1
+        else:
+            if OPTIONS.show_cmd:
+                print >> self.output_file, output.cmd
+
+            if OPTIONS.show_output:
+                print >> self.output_file, '    rc = %d, run time = %f' % (output.rc, output.dt)
+                self.output_file.write(output.out)
+                self.output_file.write(output.err)
+
+            result = TestResult.from_output(output)
+            tup = (result.result, result.test.expect, result.test.random)
+            dev_label = self.LABELS[tup][1]
+            self.groups.setdefault(dev_label, []).append(result.test.path)
+
+            self.n += 1
+
+            if result.result == TestResult.PASS and not result.test.random:
+                self.counts[0] += 1
+            elif result.test.expect and not result.test.random:
+                self.counts[1] += 1
+            else:
+                self.counts[2] += 1
+
+            if OPTIONS.tinderbox:
+                if len(result.results) > 1:
+                    for sub_ok, msg in result.results:
+                        label = self.LABELS[(sub_ok, result.test.expect, result.test.random)][0]
+                        if label == 'TEST-UNEXPECTED-PASS':
+                            label = 'TEST-PASS (EXPECTED RANDOM)'
+                        print '%s | %s | %s' % (label, result.test.path, msg)
+                print '%s | %s' % (self.LABELS[(result.result, 
+                                              result.test.expect, result.test.random)][0],
+                                 result.test.path)
+           
+        if self.pb:
+            self.pb.label = '[%4d|%4d|%4d]'%tuple(self.counts)
+            self.pb.update(self.n)
+
+    # Conceptually, this maps (test result x test expection) to text labels.
+    #      key   is (result, expect, random)
+    #      value is (tinderbox label, dev test category)
+    LABELS = {
+        (TestResult.CRASH, False, False): ('TEST-KNOWN-FAIL',                    ''),
+        (TestResult.CRASH, False, True):  ('TEST-KNOWN-FAIL (EXPECTED RANDOM)',  ''),
+        (TestResult.CRASH, True,  False): ('TEST-UNEXPECTED-FAIL',               'REGRESSIONS'),
+        (TestResult.CRASH, True,  True):  ('TEST-KNOWN-FAIL (EXPECTED RANDOM)',  ''),
+
+        (TestResult.FAIL,  False, False): ('TEST-KNOWN-FAIL',                    ''),
+        (TestResult.FAIL,  False, True):  ('TEST-KNOWN-FAIL (EXPECTED RANDOM)',  ''),
+        (TestResult.FAIL,  True,  False): ('TEST-UNEXPECTED-FAIL',               'REGRESSIONS'),
+        (TestResult.FAIL,  True,  True):  ('TEST-KNOWN-FAIL (EXPECTED RANDOM)',  ''),
+
+        (TestResult.PASS,  False, False): ('TEST-UNEXPECTED-PASS',               'FIXES'),
+        (TestResult.PASS,  False, True):  ('TEST-PASS (EXPECTED RANDOM)',        ''),
+        (TestResult.PASS,  True,  False): ('TEST-PASS',                          ''),
+        (TestResult.PASS,  True,  True):  ('TEST-PASS (EXPECTED RANDOM)',        ''),
+        }
+
+    def list(self):
+        for label, paths in sorted(self.groups.items()):
+            if label == '': continue
+
+            print label
+            for path in paths:
+                print '    %s'%path
+
+        suffix = '' if self.finished else ' (partial run -- interrupted by user)'
+        if self.all_passed():
+            print 'PASS' + suffix
+        else:
+            print 'FAIL' + suffix
+
+    def all_passed(self):
+        return not self.groups.get((False, True, False))
+
+def run_tests(tests, results):
+    """Run the given tests, sending raw results to the given results accumulator."""
+    pb = None
+    if not OPTIONS.hide_progress:
+        try:
+            from progressbar import ProgressBar
+            pb = ProgressBar('', len(tests), 16)
+        except ImportError:
+            pass
+    results.pb = pb
+
+    test_list = [ TestTask(test) for test in tests ]
+    pipeline = Source(test_list, results, False)
+    results.finished = pipeline.start(OPTIONS.worker_count)
+
+    if pb: 
+        pb.finish()
+
+    if not OPTIONS.tinderbox:
+        results.list()
+
+if __name__ == '__main__':        
+    from optparse import OptionParser
+    op = OptionParser(usage='%prog JS_SHELL [TEST-SPECS]')
+    op.add_option('-s', '--show-cmd', dest='show_cmd', action='store_true',
+                  help='show js shell command run')
+    op.add_option('-o', '--show-output', dest='show_output', action='store_true',
+                  help='show output from js shell')
+    op.add_option('-O', '--output-file', dest='output_file',
+                  help='write command output to the given file')
+    op.add_option('-f', '--file', dest='test_file', action='append',
+                  help='get tests from the given file')
+    op.add_option('-x', '--exclude-file', dest='exclude_file', action='append',
+                  help='exclude tests from the given file')
+    op.add_option('--no-progress', dest='hide_progress', action='store_true',
+                  help='hide progress bar')
+    op.add_option('-j', '--worker-count', dest='worker_count', type=int, default=2,
+                  help='number of worker threads to run tests on (default 2)')
+    op.add_option('-m', '--manifest', dest='manifest', default='jstests.list',
+                  help='select manifest file')
+    op.add_option('-t', '--timeout', dest='timeout', type=float, default=60.0,
+                  help='set test timeout in seconds')
+    op.add_option('-d', '--exclude-random', dest='random', action='store_false',
+                  help='exclude tests marked random')
+    op.add_option('--run-skipped', dest='run_skipped', action='store_true',
+                  help='run skipped tests')
+    op.add_option('--run-only-skipped', dest='run_only_skipped', action='store_true',
+                  help='run only skipped tests')
+    op.add_option('--tinderbox', dest='tinderbox', action='store_true',
+                  help='Tinderbox-parseable output format')
+    op.add_option('--args', dest='shell_args',
+                  help='extra args to pass to the JS shell')
+    op.add_option('-g', '--debug', dest='debug', action='store_true',
+                  help='run test in debugger')
+    op.add_option('--valgrind', dest='valgrind', action='store_true',
+                  help='run tests in valgrind')
+    op.add_option('--valgrind-args', dest='valgrind_args',
+                  help='extra args to pass to valgrind')
+    op.add_option('-c', '--check-manifest', dest='check_manifest', action='store_true',
+                  help='check for test files not listed in the manifest')
+    (OPTIONS, args) = op.parse_args()
+    if len(args) < 1:
+        if not OPTIONS.check_manifest:
+            op.error('missing JS_SHELL argument')
+        JS, args = None, []
+    else:
+        JS, args = args[0], args[1:]
+
+    if OPTIONS.debug:
+        if OPTIONS.valgrind:
+            print >> sys.stderr, "--debug and --valgrind options are mutually exclusive"
+            sys.exit(2)
+        debugger_prefix = [ 'gdb', '-q', '--args' ]
+    elif OPTIONS.valgrind:
+        debugger_prefix = [ 'valgrind' ]
+        if os.uname()[0] == 'Darwin':
+            debugger_prefix += ['--dsymutil=yes']
+        if OPTIONS.valgrind_args:
+            debugger_prefix += [ valgrind_args ]
+        # Running under valgrind is not very useful if we don't show results.
+        OPTIONS.show_output = True 
+    else:
+        debugger_prefix = []
+    
+    TestTask.set_js_cmd_prefix(JS, OPTIONS.shell_args, debugger_prefix)
+
+    output_file = sys.stdout
+    if OPTIONS.output_file and (OPTIONS.show_cmd or OPTIONS.show_output):
+        output_file = open(OPTIONS.output_file, 'w')
+    ResultsSink.output_file = output_file
+
+    if ((OPTIONS.show_cmd or OPTIONS.show_output) and 
+        output_file == sys.stdout or OPTIONS.tinderbox):
+        OPTIONS.hide_progress = True
+
+    import manifest
+    if JS is None:
+        xul_tester = manifest.NullXULInfoTester()
+    else:
+        xul_info = manifest.XULInfo.create(JS)
+        xul_tester = manifest.XULInfoTester(xul_info, JS)
+    test_list = manifest.parse(OPTIONS.manifest, xul_tester)
+
+    if OPTIONS.check_manifest:
+        check_manifest(test_list)
+        if JS is None:
+            sys.exit()
+
+    if OPTIONS.test_file:
+        paths = set()
+        for test_file in OPTIONS.test_file:
+            paths |= set([ line.strip() for line in open(test_file).readlines()])
+        test_list = [ _ for _ in test_list if _.path in paths ]
+
+    if args:
+        def p(path):
+            for arg in args:
+                if path.find(arg) != -1:
+                    return True
+            return False
+        test_list = [ _ for _ in test_list if p(_.path) ]
+
+    if OPTIONS.exclude_file:
+        test_list = exclude_tests(test_list, OPTIONS.exclude_file)
+
+    if not OPTIONS.random:
+        test_list = [ _ for _ in test_list if not _.random ]
+
+    if OPTIONS.run_only_skipped:
+        OPTIONS.run_skipped = True
+        test_list = [ _ for _ in test_list if not _.enable ]
+
+    if OPTIONS.debug and test_list:
+        if len(test_list) > 1:
+            print('Multiple tests match command line arguments, debugger can only run one')
+            for tc in test_list:
+                print('    %s'%tc.path)
+            sys.exit(2)
+
+        cmd = test_list[0].get_command(TestTask.js_cmd_prefix)
+        if OPTIONS.show_cmd:
+            print ' '.join(cmd)
+        call(cmd)
+        sys.exit()
+
+    if not test_list:
+        print 'no tests selected'
+    else:
+        results = ResultsSink()
+        run_tests(test_list, results)
+
+    if output_file != sys.stdout:
+        output_file.close()
+
+    if not results.all_passed():
+        sys.exit(1)
new file mode 100644
--- /dev/null
+++ b/js/src/tests/manifest.py
@@ -0,0 +1,148 @@
+# Library for JSTest manifests.
+#
+# This includes classes for representing and parsing JS manifests.
+
+import os, re, sys
+from subprocess import *
+
+from tests import TestCase
+
+class XULInfo:
+    def __init__(self, abi, os, isdebug):
+        self.abi = abi
+        self.os = os
+        self.isdebug = isdebug
+
+    def as_js(self):
+        """Return JS that when executed sets up variables so that JS expression
+        predicates on XUL build info evaluate properly."""
+
+        return 'var xulRuntime = { OS: "%s", XPCOMABI: "%s", shell: true }; var isDebugBuild=%s;' % (
+            self.os,
+            self.abi,
+            str(self.isdebug).lower())
+
+    @classmethod
+    def create(cls, jsdir):
+        """Create a XULInfo based on the current platform's characteristics."""
+
+        # Our strategy is to find the autoconf.mk generated for the build and
+        # read the values from there.
+        
+        # Find config/autoconf.mk.
+        dir = jsdir
+        while True:
+            if os.path.basename(dir) == 'src':
+                path = None
+                break
+            path = os.path.join(dir, 'config/autoconf.mk')
+            if os.path.isfile(path):
+                break
+            dir = os.path.dirname(dir)
+
+        # Read the values.
+        val_re = re.compile(r'(TARGET_XPCOM_ABI|OS_TARGET|MOZ_DEBUG)\s*=\s*(.*)')
+        kw = {}
+        for line in open(path):
+            m = val_re.match(line)
+            if m:
+                key, val = m.groups()
+                val = val.rstrip()
+                if key == 'TARGET_XPCOM_ABI':
+                    kw['abi'] = val
+                if key == 'OS_TARGET':
+                    kw['os'] = val
+                if key == 'MOZ_DEBUG':
+                    kw['isdebug'] = (val == '1')
+        return cls(**kw)
+
+class XULInfoTester:
+    def __init__(self, xulinfo, js_bin):
+        self.js_prolog = xulinfo.as_js()
+        self.js_bin = js_bin
+        # Maps JS expr to evaluation result.
+        self.cache = {}
+
+    def test(self, cond):
+        """Test a XUL predicate condition against this local info."""
+        ans = self.cache.get(cond, None)
+        if ans is None:
+            cmd = [ self.js_bin, '-e', self.js_prolog, '-e', 'print(%s)'%cond ]
+            p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
+            out, err = p.communicate()
+            if out == 'true\n':
+                ans = True
+            elif out in ('false\n', 'null\n'):
+                ans = False
+            else:
+                raise Exception("Failed to test XUL condition '%s'"%cond)
+            self.cache[cond] = ans
+        return ans
+
+class NullXULInfoTester:
+    """Can be used to parse manifests without a JS shell."""
+    def test(self, cond):
+        return False
+
+def parse(filename, xul_tester):
+    ans = []
+    comment_re = re.compile(r'#.*')
+    dir = os.path.dirname(filename)
+
+    try:
+        f = open(filename)
+    except IOError:
+        print "warning: include file not found: '%s'"%filename
+        return ans
+
+    for line in f:
+        sline = comment_re.sub('', line)
+        parts = sline.split()
+        if parts[0] == 'include':
+            ans += parse(os.path.join(dir, parts[1]), xul_tester)
+        elif parts[0] == 'url-prefix':
+            # Doesn't apply to shell tests
+            pass
+        else:
+            script = None
+            enable = True
+            expect = True
+            random = False
+
+            pos = 0
+            while pos < len(parts):
+                if parts[pos] == 'fails':
+                    expect = False
+                    pos += 1
+                elif parts[pos] == 'skip':
+                    expect = enable = False
+                    pos += 1
+                elif parts[pos] == 'random':
+                    random = True
+                    pos += 1
+                elif parts[pos].startswith('fails-if'):
+                    cond = parts[pos][len('fails-if('):-1]
+                    if xul_tester.test(cond):
+                        expect = False
+                    pos += 1
+                elif parts[pos].startswith('skip-if'):
+                    cond = parts[pos][len('skip-if('):-1]
+                    if xul_tester.test(cond):
+                        expect = enable = False
+                    pos += 1
+                elif parts[pos].startswith('random-if'):
+                    cond = parts[pos][len('random-if('):-1]
+                    if xul_tester.test(cond):
+                        random = True
+                    pos += 1
+                elif parts[pos] == 'script':
+                    script = parts[pos+1]
+                    pos += 2
+                else:
+                    print 'warning: invalid manifest line element "%s"'%parts[pos]
+                    pos += 1
+
+            assert script is not None
+            ans.append(TestCase(os.path.join(dir, script), 
+                                enable, expect, random))
+    return ans
new file mode 100644
--- /dev/null
+++ b/js/src/tests/progressbar.py
@@ -0,0 +1,35 @@
+# Text progress bar library, like curl or scp.
+
+import sys, datetime
+
+class ProgressBar:
+    def __init__(self, label, limit, label_width=12):
+        self.label = label
+        self.limit = limit
+        self.label_width = label_width
+        self.cur = 0
+        self.t0 = datetime.datetime.now()
+
+        self.barlen = 64 - self.label_width
+        self.fmt = '\r%-' + str(label_width) + 's %3d%% %-' + str(self.barlen) + 's| %6.1fs'
+
+    def update(self, value):
+        self.cur = value
+        pct = int(100.0 * self.cur / self.limit)
+        barlen = int(1.0 * self.barlen * self.cur / self.limit) - 1
+        bar = '='*barlen + '>'
+        dt = datetime.datetime.now() - self.t0
+        dt = dt.seconds + dt.microseconds * 1e-6
+        sys.stdout.write(self.fmt % (self.label[:self.label_width], pct, bar, dt))
+        sys.stdout.flush()
+
+    def finish(self):
+        self.update(self.limit)
+        sys.stdout.write('\n')
+
+if __name__ == '__main__':
+    pb = ProgressBar('test', 12)
+    for i in range(12):
+        pb.update(i)
+        time.sleep(0.5)
+    pb.finish()
--- a/js/src/tests/spidermonkey-n-1.9.3.tests
+++ b/js/src/tests/spidermonkey-n-1.9.3.tests
@@ -120,17 +120,16 @@ js1_5/decompilation/regress-351626.js
 js1_5/decompilation/regress-354878.js
 js1_5/decompilation/regress-373678.js
 js1_5/extensions/regress-352281.js
 js1_7/decompilation/regress-346642-01.js
 js1_7/decompilation/regress-349605.js
 # decompilation change in spidermonkey 1.8.1
 js1_7/decompilation/regress-351070-01.js
 js1_8/decompilation/regress-443074.js
-js1_8/genexps/regress-380237-03.js
 js1_8/genexps/regress-380237-04.js
 # decompilation change in spidermonkey 1.8.1 (bug 460501)
 js1_7/decompilation/regress-352026.js
 # https://bugzilla.mozilla.org/show_bug.cgi?id=458851#c7
 js1_5/extensions/regress-437288-01.js
 js1_5/decompilation/regress-437288-02.js
 # more decompilation changes, bug 461233
 js1_7/block/regress-352609.js
new file mode 100644
--- /dev/null
+++ b/js/src/tests/tests.py
@@ -0,0 +1,158 @@
+# Library for JSTest tests.
+#
+# This contains classes that represent an individual test, including
+# metadata, and know how to run the tests and determine failures.
+
+import datetime, os, re, sys, time
+from subprocess import *
+from threading import *
+
+def do_run_cmd(cmd):
+    l = [ None, None ]
+    th_run_cmd(cmd, l)
+    return l[1]
+
+def th_run_cmd(cmd, l):
+    t0 = datetime.datetime.now()
+    p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+    l[0] = p
+    out, err = p.communicate()
+    t1 = datetime.datetime.now()
+    dd = t1-t0
+    dt = dd.seconds + 1e-6 * dd.microseconds
+    l[1] = (out, err, p.returncode, dt)
+
+def run_cmd(cmd, timeout=60.0):
+    if timeout is None:
+        return do_run_cmd(cmd)
+
+    l = [ None, None ]
+    th = Thread(target=th_run_cmd, args=(cmd, l))
+    th.start()
+    th.join(timeout)
+    while th.isAlive():
+        if l[0] is not None:
+            try:
+                # In Python 3, we could just do l[0].kill().
+                import signal
+                if sys.platform != 'win32':
+                    os.kill(l[0].pid, signal.SIGKILL)
+                time.sleep(.1)
+            except OSError:
+                # Expecting a "No such process" error
+                pass
+    th.join()
+    return l[1]
+
+class Test(object):
+    """A runnable test."""
+    def __init__(self, path):
+        self.path = path         # str:  path of JS file relative to tests root dir
+
+    @staticmethod
+    def prefix_command(path):
+        """Return the '-f shell.js' options needed to run a test with the given path."""
+        if path == '':
+            return [ '-f', 'shell.js' ]
+        head, base = os.path.split(path)
+        return Test.prefix_command(head) + [ '-f', os.path.join(path, 'shell.js') ]
+
+    def get_command(self, js_cmd_prefix):
+        dir, filename = os.path.split(self.path)
+        # There is a test that requires the path to start with './'.
+        return js_cmd_prefix + Test.prefix_command(dir) + [ '-f', './' + self.path ]
+
+    def run(self, js_cmd_prefix, timeout=30.0):
+        cmd = self.get_command(js_cmd_prefix)
+        out, err, rc, dt = run_cmd(cmd, timeout)
+        return TestOutput(self, cmd, out, err, rc, dt);
+
+class TestCase(Test):
+    """A test case consisting of a test and an expected result."""
+
+    def __init__(self, path, enable, expect, random):
+        Test.__init__(self, path)
+        self.enable = enable     # bool: True => run test, False => don't run
+        self.expect = expect     # bool: expected result, True => pass
+        self.random = random     # bool: True => ignore output as 'random'
+
+    def __str__(self):
+        ans = self.path
+        if not self.enable:
+            ans += ', skip'
+        if not self.expect:
+            ans += ', fails'
+        if self.random:
+            ans += ', random'
+        return ans
+
+class TestOutput:
+    """Output from a test run."""
+    def __init__(self, test, cmd, out, err, rc, dt):
+        self.test = test   # Test
+        self.cmd = cmd     # str:   command line of test
+        self.out = out     # str:   stdout
+        self.err = err     # str:   stderr
+        self.rc = rc       # int:   return code
+        self.dt = dt       # float: run time
+
+class NullTestOutput:
+    """Variant of TestOutput that indicates a test was not run."""
+    def __init__(self, test):
+        self.test = test
+        self.cmd = ''
+        self.out = ''
+        self.err = ''
+        self.rc = 0
+        self.dt = 0.0
+
+class TestResult:
+    PASS = 'PASS'
+    FAIL = 'FAIL'
+    CRASH = 'CRASH'
+
+    """Classified result from a test run."""
+    def __init__(self, test, result, results):
+        self.test = test
+        self.result = result
+        self.results = results
+
+    @classmethod
+    def from_output(cls, output):
+        test = output.test
+        result = None          # str:      overall result, see class-level variables
+        results = []           # (str,str) list: subtest results (pass/fail, message)
+
+        out, rc = output.out, output.rc
+
+        failures = 0
+        passes = 0
+
+        expected_rcs = []
+
+        for line in out.split('\n'):
+            if line.startswith(' FAILED!'):
+                failures += 1
+                msg = line[len(' FAILED! '):]
+                results.append((cls.FAIL, msg))
+            elif line.startswith(' PASSED!'):
+                passes += 1
+                msg = line[len(' PASSED! '):]
+                results.append((cls.PASS, msg))
+            else:
+                m = re.match('--- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE ((?:-|\\d)+) ---', line)
+                if m:
+                    expected_rcs.append(int(m.group(1)))
+
+        if rc:
+            if (test.path.endswith('-n.js') and rc == 3) or rc in expected_rcs:
+                result = cls.PASS
+            else:
+                result = cls.CRASH
+        else:
+            if passes > 0 and failures == 0:
+                result = cls.PASS
+            else:
+                result = cls.FAIL
+
+        return cls(test, result, results)
new file mode 100644
--- /dev/null
+++ b/js/src/tests/workers.py
@@ -0,0 +1,91 @@
+# Multiprocess activities with a push-driven divide-process-collect model.
+
+import os, sys, time
+from threading import Thread, Lock
+from Queue import Queue, Empty
+from datetime import datetime
+
+class Source:
+    def __init__(self, task_list, results, verbose = False):
+        self.tasks = Queue()
+        for task in task_list:
+            self.tasks.put_nowait(task)
+
+        self.results = results
+        self.verbose = verbose
+    
+    def start(self, worker_count):
+        t0 = datetime.now()
+
+        sink = Sink(self.results)
+        self.workers = [ Worker(_+1, self.tasks, sink, self.verbose) for _ in range(worker_count) ]
+        if self.verbose: print '[P] Starting workers.'
+        for w in self.workers:
+            w.t0 = t0
+            w.start()
+        ans = self.join_workers()
+        if self.verbose: print '[P] Finished.'
+
+        t1 = datetime.now()
+        dt = t1-t0
+
+        return ans
+
+    def join_workers(self):
+        try:
+            for w in self.workers:
+                w.thread.join(20000)
+            return True
+        except KeyboardInterrupt:
+            for w in self.workers:
+                w.stop = True
+            return False
+
+class Sink:
+    def __init__(self, results):
+        self.results = results
+        self.lock = Lock()
+
+    def push(self, result):
+        self.lock.acquire()
+        try:
+            self.results.push(result)
+        finally:
+            self.lock.release()
+
+class Worker(object):
+    def __init__(self, id, tasks, sink, verbose):
+        self.id = id
+        self.tasks = tasks
+        self.sink = sink
+        self.verbose = verbose
+
+        self.thread = None
+        self.stop = False
+
+    def log(self, msg):
+        dd = datetime.now() - self.t0
+        dt = dd.seconds + 1e-6 * dd.microseconds
+        
+        if self.verbose:
+            print '[W%d %.3f] %s' % (self.id, dt, msg)
+
+    def start(self):
+        self.thread = Thread(target=self.run)
+        self.thread.setDaemon(True)
+        self.thread.start()
+
+    def run(self):
+        try:
+            while True:
+                if self.stop:
+                    break
+                self.log('Get next task.')
+                task = self.tasks.get(False)
+                self.log('Start task %s.'%str(task))
+                result = task()
+                self.log('Finished task.')
+                self.sink.push(result)
+                self.log('Pushed result.')
+        except Empty:
+            pass
--- a/js/src/trace-test/trace-test.py
+++ b/js/src/trace-test/trace-test.py
@@ -1,15 +1,25 @@
 # trace-test.py -- Python harness for JavaScript trace tests.
 
 import datetime, os, re, sys, traceback
 import subprocess
 from subprocess import *
 
-JS = None
+DEBUGGER_INFO = {
+  "gdb": {
+    "interactive": True,
+    "args": "-q --args"
+  },
+
+  "valgrind": {
+    "interactive": False,
+    "args": "--leak-check=full"
+  }
+}
 
 # Backported from Python 3.1 posixpath.py
 def _relpath(path, start=None):
     """Return a relative version of a path"""
 
     if not path:
         raise ValueError("no path specified")