test262 console runner working!

This commit is contained in:
Mark Miller 2011-09-30 08:24:38 -04:00
parent aad373e620
commit 13b63c5486
7 changed files with 231 additions and 425 deletions

View File

@ -1,14 +1,14 @@
/// Copyright (c) 2011 Microsoft Corporation
///
/// Copyright (c) 2011 Microsoft Corporation
///
/// Redistribution and use in source and binary forms, with or without modification, are permitted provided
/// that the following conditions are met:
/// that the following conditions are met:
/// * Redistributions of source code must retain the above copyright notice, this list of conditions and
/// the following disclaimer.
/// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
/// the following disclaimer in the documentation and/or other materials provided with the distribution.
/// the following disclaimer.
/// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
/// the following disclaimer in the documentation and/or other materials provided with the distribution.
/// * Neither the name of Microsoft nor the names of its contributors may be used to
/// endorse or promote products derived from this software without specific prior written permission.
///
///
/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
/// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
/// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
@ -16,13 +16,13 @@
/// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
/// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
/// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
/// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//Error Detector
if (this.window!==undefined) { //for console support
window.onerror = function(errorMsg, url, lineNumber) {
window.iframeError = errorMsg;
}
this.window.onerror = function(errorMsg, url, lineNumber) {
this.window.iframeError = errorMsg;
};
}
//This doesn't work with early errors in current versions of Opera

View File

@ -1,4 +1,4 @@
/// Copyright (c) 2011 Microsoft Corporation
/// Copyright (c) 2011 Microsoft Corporation
///
/// Redistribution and use in source and binary forms, with or without modification, are permitted provided
/// that the following conditions are met:

View File

@ -1,4 +1,4 @@
/// Copyright (c) 2009 Microsoft Corporation
/// Copyright (c) 2009 Microsoft Corporation
///
/// Redistribution and use in source and binary forms, with or without modification, are permitted provided
/// that the following conditions are met:
@ -335,8 +335,8 @@ function getPrecision(num) {
//TODO: Create a table of prec's,
// because using Math for testing Math isn't that correct.
log2num = Math.log(Math.abs(num)) / Math.LN2;
pernum = Math.ceil(log2num);
var log2num = Math.log(Math.abs(num)) / Math.LN2;
var pernum = Math.ceil(log2num);
return (2 * Math.pow(2, -52 + pernum));
//return(0);
}
@ -364,7 +364,7 @@ function isEqual(num1, num2) {
// This code is governed by the BSD license found in the LICENSE file.
function ToInteger(p) {
x = Number(p);
var x = Number(p);
if (isNaN(x)) {
return +0;
@ -437,7 +437,7 @@ var $LocalTZ,
current = new Date(current.getTime() + 1);
}
return current;
}
};
var juneDate = new Date(2000, 5, 20, 0, 0, 0, 0);
var decemberDate = new Date(2000, 11, 20, 0, 0, 0, 0);
@ -446,7 +446,7 @@ var $LocalTZ,
var isSouthernHemisphere = (juneOffset > decemberOffset);
var winterTime = isSouthernHemisphere ? juneDate : decemberDate;
var summerTime = isSouthernHemisphere ? decemberDate : juneDate;
var dstStart = findNearestDateBefore(winterTime, function (date) {
return date.getTimezoneOffset() == summerTime.getTimezoneOffset();
});
@ -454,7 +454,7 @@ var $LocalTZ,
$DST_start_sunday = dstStart.getDate() > 15 ? '"last"' : '"first"';
$DST_start_hour = dstStart.getHours();
$DST_start_minutes = dstStart.getMinutes();
var dstEnd = findNearestDateBefore(summerTime, function (date) {
return date.getTimezoneOffset() == winterTime.getTimezoneOffset();
});
@ -462,7 +462,7 @@ var $LocalTZ,
$DST_end_sunday = dstEnd.getDate() > 15 ? '"last"' : '"first"';
$DST_end_hour = dstEnd.getHours();
$DST_end_minutes = dstEnd.getMinutes();
return;
})();
@ -503,10 +503,10 @@ function YearFromTime(t) {
t = Number(t);
var sign = ( t < 0 ) ? -1 : 1;
var year = ( sign < 0 ) ? 1969 : 1970;
for(var time = 0;;year += sign){
time = TimeFromYear(year);
if(sign > 0 && time > t){
year -= sign;
break;
@ -517,11 +517,11 @@ function YearFromTime(t) {
};
return year;
}
function InLeapYear(t){
if(DaysInYear(YearFromTime(t)) == 365)
return 0;
if(DaysInYear(YearFromTime(t)) == 366)
return 1;
}
@ -584,7 +584,7 @@ var LocalTZA = $LocalTZ*msPerHour;
function DaysInMonth(m, leap) {
m = m%12;
//April, June, Sept, Nov
if(m == 3 || m == 5 || m == 8 || m == 10 ) {
return 30;
@ -601,13 +601,14 @@ function DaysInMonth(m, leap) {
function GetSundayInMonth(t, m, count){
var year = YearFromTime(t);
var tempDate;
if (count==='"first"') {
for (var d=1; d <= DaysInMonth(m, InLeapYear(t)); d++) {
tempDate = new Date(year, m, d);
if (tempDate.getDay()===0) {
return tempDate.valueOf();
}
}
}
} else if(count==='"last"') {
for (var d=DaysInMonth(m, InLeapYear(t)); d>0; d--) {
@ -624,7 +625,7 @@ function GetSundayInMonth(t, m, count){
var year = YearFromTime(t);
var leap = InLeapYear(t);
var day = 0;
if(m >= 1) day += DaysInMonth(0, leap);
if(m >= 2) day += DaysInMonth(1, leap);
if(m >= 3) day += DaysInMonth(2, leap);
@ -636,25 +637,25 @@ function GetSundayInMonth(t, m, count){
if(m >= 9) day += DaysInMonth(8, leap);
if(m >= 10) day += DaysInMonth(9, leap);
if(m >= 11) day += DaysInMonth(10, leap);
var month_start = TimeFromYear(year)+day*msPerDay;
var sunday = 0;
if(count === "last"){
for(var last_sunday = month_start+DaysInMonth(m, leap)*msPerDay;
for(var last_sunday = month_start+DaysInMonth(m, leap)*msPerDay;
WeekDay(last_sunday)>0;
last_sunday -= msPerDay
){};
sunday = last_sunday;
}
else {
for(var first_sunday = month_start;
for(var first_sunday = month_start;
WeekDay(first_sunday)>0;
first_sunday += msPerDay
){};
sunday = first_sunday+7*msPerDay*(count-1);
}
return sunday;
}*/
@ -662,11 +663,11 @@ function DaylightSavingTA(t) {
// t = t-LocalTZA;
var DST_start = GetSundayInMonth(t, $DST_start_month, $DST_start_sunday) +
$DST_start_hour*msPerHour +
$DST_start_hour*msPerHour +
$DST_start_minutes*msPerMinute;
var k = new Date(DST_start);
var DST_end = GetSundayInMonth(t, $DST_end_month, $DST_end_sunday) +
$DST_end_hour*msPerHour +
$DST_end_minutes*msPerMinute;
@ -770,7 +771,7 @@ function MakeDate( day, time ) {
if(!isFinite(day) || !isFinite(time)) {
return Number.NaN;
}
return day*msPerDay+time;
}
@ -803,20 +804,20 @@ function ConstructDate(year, month, date, hours, minutes, seconds, ms){
var r1 = Number(year);
var r2 = Number(month);
var r3 = ((date && arguments.length > 2) ? Number(date) : 1);
var r4 = ((hours && arguments.length > 3) ? Number(hours) : 0);
var r5 = ((minutes && arguments.length > 4) ? Number(minutes) : 0);
var r6 = ((seconds && arguments.length > 5) ? Number(seconds) : 0);
var r4 = ((hours && arguments.length > 3) ? Number(hours) : 0);
var r5 = ((minutes && arguments.length > 4) ? Number(minutes) : 0);
var r6 = ((seconds && arguments.length > 5) ? Number(seconds) : 0);
var r7 = ((ms && arguments.length > 6) ? Number(ms) : 0);
var r8 = r1;
if(!isNaN(r1) && (0 <= ToInteger(r1)) && (ToInteger(r1) <= 99))
r8 = 1900+r1;
var r9 = MakeDay(r8, r2, r3);
var r10 = MakeTime(r4, r5, r6, r7);
var r11 = MakeDate(r9, r10);
return TimeClip(UTC(r11));
}
@ -905,6 +906,6 @@ return attribs
//--Test case registration-----------------------------------------------------
function runTestCase(testcase) {
if (testcase() !== true) {
$ERROR("Test case returned non-true value!")
$ERROR("Test case returned non-true value!");
}
}

View File

@ -43,21 +43,21 @@ function BrowserRunner() {
globalScopeContents,
harnessDir = "harness/";
$.ajax({async: false,
dataType: "text",
success: function(data){errorDetectorFileContents = data;},
$.ajax({async: false,
dataType: "text",
success: function(data){errorDetectorFileContents = data;},
url:harnessDir+"ed.js"});
$.ajax({async: false,
dataType: "text",
success: function(data){simpleTestAPIContents = data;},
$.ajax({async: false,
dataType: "text",
success: function(data){simpleTestAPIContents = data;},
url:harnessDir+"sta.js"});
$.ajax({async: false,
dataType: "text",
success: function(data){globalScopeContents = data;},
$.ajax({async: false,
dataType: "text",
success: function(data){globalScopeContents = data;},
url:harnessDir+"gs.js"});
/* Called by the child window to notify that the test has
* finished. This function call is put in a separate script block
* at the end of the page so errors in the test script block
@ -180,8 +180,8 @@ function BrowserRunner() {
idoc.writeln(globalScopeContents);
idoc.writeln("</script>");
idoc.close();
}
};
//--Helper functions-------------------------------------------------------
this.convertForEval = function(txt) {
txt = txt.replace(/\\/g,"\\\\");
@ -190,7 +190,7 @@ function BrowserRunner() {
txt = txt.replace(/\r/g,"\\r");
txt = txt.replace(/\n/g,"\\n");
return txt;
}
};
}
/* Loads tests from the sections specified in testcases.json.
@ -264,7 +264,7 @@ function TestLoader() {
function getIdFromPath (path) {
//path is of the form "a/b/c.js"
var id = path.split("/");
//id is now of the form ["a", "b", "c.js"];
@ -307,9 +307,9 @@ function TestLoader() {
currentTestIndex = 0;
testGroupIndex = 0;
};
}
/* Controls test generation and running, and sends results to the presenter. */
@ -326,8 +326,8 @@ function Controller() {
this.implementerHook = {
//Adds a test result
addTestResult: function (test) { },
//Called whenever all tests have finished running. Provided with the
//Called whenever all tests have finished running. Provided with the
//elapsed time in milliseconds.
finished: function(elapsed) { }
};
@ -337,7 +337,7 @@ function Controller() {
try {
controller.implementerHook.addTestResult(test);
} catch(e) { /*no-op*/}
if(state === 'running')
setTimeout(loader.getNextTest, 10);
};
@ -366,7 +366,7 @@ function Controller() {
try {
controller.implementerHook.finished(elapsed);
} catch(e) { /*no-op*/}
}
};
this.start = function() {
state = 'running';

View File

@ -1,174 +0,0 @@
#!/usr/bin/env python
# Copyright 2011 by Google, Inc. All rights reserved.
# This code is governed by the BSD license found in the LICENSE file.
# Follows convert.js as closely as possible. So to minimize
# divergence, see convert.js for doc-comments that are missing here.
import logging
import optparse
import os
from os import path
import platform
import re
import subprocess
import sys
import tempfile
import time
# from TestCasePackagerConfig import *
headerPattern = r"(?:(?:\/\/.*)?\s*\n)*"
captureCommentPattern = r"\/\*\*?((?:\s|\S)*?)\*\/\s*\n"
anyPattern = r"(?:\s|\S)*"
blanksPattern = r"(?:\s|\n)*"
# only until we've done our last conversion from current sputnik
# format to canonical test262 format
captureStrictPattern = r"\s*('use strict'|\"use strict\");"
# Should match anything
testEnvelopePattern = r"^(" + headerPattern +
r")(?:" + captureCommentPattern +
r")?(?:" + captureStrictPattern +
r")?(" + anyPattern +
r")$"
registerPattern = r"^(" + anyPattern + r"?)(" +
r"ES5Harness\.registerTest\s*\(\s*\{" + anyPattern +
r"\}\s*\)" + r")" +
r"\s*;?(?:\s|\n)*$"
Matches a named function. Captures both the name and the body.
captureFuncNameBodyPattern = r"^function\s+(\w*)\(\s*\)\s*\{" +
r"(" + anyPattern + r")" +
r";?" + blanksPattern +
r"\}$"
# captureExprBodyPattern = r"^return\s+" +
# r"(" + anyPattern + r"?)" +
# r";$"
# capturePredicatePattern = r"^if\s+\((.*?)\)\s*\{" + blanksPattern +
# r"return\s+true;?" + blanksPattern +
# r"\}$"
stars = r"\s*\n\s*\*\s?"
atattrs = r"\s*\n\s*\*\s*@"
def stripStars(text):
return re.sub(stars, '\n', text).strip()
def parseTestEnvelope(src, name):
envelope = { 'testRecord': {} }
envelopeMatch = re.match(testEnvelopePattern, src)
if (envelopeMatch == None):
raise Exception('unrecognized: ' + name)
envelope['header'] = envelopeMatch.group(1).strip()
if (envelopeMatch.group(2)):
propTexts = re.split(atattrs, envelopeMatch.group(2))
envelope['commentary'] = stripStars(propTexts[0])
del propTexts[0]
for propText in propTexts:
# TODO: error check for mismatch
propName = re.match(r"^\w+", propText).group(0)
propVal = propText[len(propName):]
# Just till last one-time conversion
# strip optional initial colon or final semicolon.
# The initial colon is only stripped if it comes immediately
# after the identifier with no intervening whitespace.
propVal = re.sub(r"^:\s*", '', propVal, 1)
propVal = re.sub(r";\s*$", '', propVal, 1)
propVal = stripStars(propVal)
if (propName in envelope['testRecord']):
raise Exception('duplicate: ' + propName)
envelope['testRecord'][propName] = propVal;
if (envelopeMatch.group(3)):
envelope['testRecord']['strict_only'] = '';
envelope['rest'] = envelopeMatch.group(4) # do not trim
# Just till last one time conversion
registerMatch = re.match(registerPattern, envelope['rest'])
if (registerMatch):
envelope['rest'] = registerMatch.group(1).strip()
envelope['registerExpr'] = registerMatch.group(2).strip()
else if ('ES5Harness.registerTest' in envelope['rest']):
raise Exception('Malformed harness? ' + name)
return envelope
def functionSrcToProgramSrc(funcSrc):
cfnbMatch = re.match(captureFuncNameBodyPattern, funcSrc)
if (not cfnbMatch):
raise Exception('Could not recognize: "' + funcSrc + '"')
name = cfnbMatch.group(1).strip()
body = cfnbMatch.group(2).strip()
# Look for special cases
cebMatch = re.match(captureExprBodyPattern, body)
if (cebMatch):
return 'assertTruthy(' + cebMatch.group(1).strip() + ');'
cpMatch = re.match(capturePredicatePattern, body)
if (cpMatch):
return 'assertTruthy(' + cpMatch.group(1).strip() + ');'
# General case
return (funcSrc + '\n' +
'runTestCase(' + name + ');')
def gatherOne(envelope, name):
# TODO(erights): implement by pattern match rather than evaluation
raise Exception('gatherOne not implemented yet')
def transferProp(record, fromName, toName):
if (((toName not in testRecord) or
(testRecord[toName] == '')) and
(fromName in testRecord)):
testRecord[toName] = testRecord[fromName]
del testRecord[fromName]
# TODO: new midcap names
# don't mask collisions -- give errors
# if unrecognized names remain, give errors
def normalizeProps(testRecord):
if (('strict_only' not in testRecord) and
('strict' in testRecord) and
(testRecord['strict'] == 1)):
testRecord['strict_only'] = ''
if (testRecord['strict'] == 1):
del testRecord['strict']
if ('strict_mode_negative' in testRecord):
if ('strict_only' not in testRecord):
testRecord['strict_only'] = ''
transferProp(testRecord, 'strict_mode_negative', 'negative')
transferProp(testRecord, 'errortype', 'negative')
transferProp(testRecord, 'assertion', 'description')
transferProp(testRecord, 'assertion', 'commentary')
def getGlobalScopeRecord(relPath):
# TODO(erights): implement
raise Exception('getGlobalScopeRecord not implemented yet')
def parseTestRecord(inBase, relPath, name):
nextRelPath = relPath + [name]
nextPath = inBase + [name]

View File

@ -0,0 +1,65 @@
#!/usr/bin/env python
# Copyright 2011 by Google, Inc. All rights reserved.
# This code is governed by the BSD license found in the LICENSE file.
# TODO: resolve differences with common.py and unify into one file.
import logging
import optparse
import os
from os import path
import platform
import re
import subprocess
import sys
import tempfile
import time
# from TestCasePackagerConfig import *
headerPatternStr = r"(?:(?:\s*\/\/.*)?\s*\n)*"
captureCommentPatternStr = r"\/\*\*?((?:\s|\S)*?)\*\/\s*\n"
anyPatternStr = r"(?:\s|\S)*"
headerPattern = re.compile("^" + headerPatternStr)
# Should match anything
testRecordPattern = re.compile(r"^(" + headerPatternStr +
r")(?:" + captureCommentPatternStr +
r")?(" + anyPatternStr +
r")$")
stars = re.compile(r"\s*\n\s*\*\s?")
atattrs = re.compile(r"\s*\n\s*\*\s*@")
def stripStars(text):
return stars.sub('\n', text).strip()
def stripHeader(src):
header = headerPattern.match(src).group(0)
return src[len(header):]
def parseTestRecord(src, name):
testRecord = {}
match = testRecordPattern.match(src)
if match == None:
raise Exception('unrecognized: ' + name)
testRecord['header'] = match.group(1).strip()
testRecord['test'] = match.group(3) # do not trim
if match.group(2):
propTexts = atattrs.split(match.group(2))
testRecord['commentary'] = stripStars(propTexts[0])
del propTexts[0]
for propText in propTexts:
propMatch = re.match(r"^\w+", propText)
if propMatch == None:
raise Exception('Malformed "@" attribute: ' + name)
propName = propMatch.group(0)
propVal = stripStars(propText[len(propName):])
if propName in testRecord:
raise Exception('duplicate: ' + propName)
testRecord[propName] = propVal;
return testRecord

280
tools/test262.py → tools/packaging/test262.py Normal file → Executable file
View File

@ -2,6 +2,11 @@
# Copyright 2009 the Sputnik authors. All rights reserved.
# This code is governed by the BSD license found in the LICENSE file.
# This is derived from sputnik.py, the Sputnik console test runner,
# with elements from packager.py, which is separately
# copyrighted. TODO: Refactor so there is less duplication between
# test262.py and packager.py.
import logging
import optparse
@ -13,25 +18,42 @@ import subprocess
import sys
import tempfile
import time
import xml.dom.minidom
import datetime
import shutil
import json
import stat
from parseTestRecord import parseTestRecord, stripHeader
from packagerConfig import *
class Test262Error(Exception):
def __init__(self, message):
self.message = message
def ReportError(s):
raise Test262Error(s)
if not os.path.exists(EXCLUDED_FILENAME):
print "Cannot generate (JSON) test262 tests without a file," + \
" %s, showing which tests have been disabled!" % EXCLUDED_FILENAME
sys.exit(1)
EXCLUDE_LIST = xml.dom.minidom.parse(EXCLUDED_FILENAME)
EXCLUDE_LIST = EXCLUDE_LIST.getElementsByTagName("test")
EXCLUDE_LIST = [x.getAttribute("id") for x in EXCLUDE_LIST]
def BuildOptions():
result = optparse.OptionParser()
result.add_option("--command", default=None, help="The command-line to run")
result.add_option("--tests", default=path.abspath('.'),
help="Path to the tests")
result.add_option("--cat", default=False, action="store_true",
help="Print test source code")
help="Print packaged test code that would be run")
result.add_option("--summary", default=False, action="store_true",
help="Print summary after running tests")
result.add_option("--full-summary", default=False, action="store_true",
@ -40,7 +62,10 @@ def BuildOptions():
help="Test only strict mode")
result.add_option("--non_strict_only", default=False, action="store_true",
help="Test only non-strict mode")
# TODO: Once enough tests are made strict compat, change the default
# to "both"
result.add_option("--unmarked_default", default="non_strict",
help="default mode for tests of unspecified strictness")
return result
@ -51,16 +76,7 @@ def ValidateOptions(options):
ReportError("Couldn't find test path '%s'" % options.tests)
_PLACEHOLDER_PATTERN = re.compile(r"\{\{(\w+)\}\}")
_INCLUDE_PATTERN = re.compile(r"\$INCLUDE\(\"(.*)\"\);")
_SPECIAL_CALL_PATTERN = re.compile(r"\$([A-Z]+)(?=\()")
_SPECIAL_CALLS = {
'ERROR': 'testFailed',
'FAIL': 'testFailed',
'PRINT': 'testPrint'
}
placeHolderPattern = re.compile(r"\{\{(\w+)\}\}")
def IsWindows():
@ -68,12 +84,6 @@ def IsWindows():
return (p == 'Windows') or (p == 'Microsoft')
def StripHeader(str):
while str.startswith('//') and "\n" in str:
str = str[str.index("\n")+1:]
return str.lstrip()
class TempFile(object):
def __init__(self, suffix="", prefix="tmp", text=False):
@ -89,8 +99,7 @@ class TempFile(object):
(self.fd, self.name) = tempfile.mkstemp(
suffix = self.suffix,
prefix = self.prefix,
text = self.text
)
text = self.text)
def Write(self, str):
os.write(self.fd, str)
@ -127,7 +136,7 @@ class TestResult(object):
mode = self.case.GetMode()
if self.HasUnexpectedOutcome():
if self.case.IsNegative():
print "%s was expected to fail in %s, but didn't" % (name, mode)
print "=== %s was expected to fail in %s, but didn't ===" % (name, mode)
else:
if long_format:
print "=== %s failed in %s ===" % (name, mode)
@ -164,11 +173,17 @@ class TestCase(object):
self.suite = suite
self.name = name
self.full_path = full_path
self.contents = None
self.is_negative = None
self.strict_mode = strict_mode
self.is_strict_only = None
self.is_non_strict_only = None
f = open(self.full_path)
self.contents = f.read()
f.close()
testRecord = parseTestRecord(self.contents, name)
self.test = testRecord["test"]
del testRecord["test"]
del testRecord["header"]
del testRecord["commentary"]
self.testRecord = testRecord;
def GetName(self):
return path.join(*self.name)
@ -182,60 +197,33 @@ class TestCase(object):
def GetPath(self):
return self.name
def GetRawContents(self):
if self.contents is None:
f = open(self.full_path)
self.contents = f.read()
f.close()
return self.contents
def IsNegative(self):
if self.is_negative is None:
self.is_negative = ("@negative" in self.GetRawContents())
return self.is_negative
return 'negative' in self.testRecord
def IsStrictOnly(self):
if self.is_strict_only is None:
self.is_strict_only = ("@strict_only" in self.GetRawContents())
return self.is_strict_only
def IsOnlyStrict(self):
return 'onlyStrict' in self.testRecord
def IsNonStrictOnly(self):
if self.is_non_strict_only is None:
self.is_non_strict_only = ("@non_strict_only" in self.GetRawContents())
return self.is_non_strict_only
def IsNoStrict(self):
return 'noStrict' in self.testRecord
def GetSource(self):
source = self.suite.GetInclude("framework.js", False) + \
self.suite.GetInclude("sta.js", False)
source += StripHeader(self.GetRawContents())
def IncludeFile(match):
return self.suite.GetInclude(match.group(1))
source = _INCLUDE_PATTERN.sub(IncludeFile, source)
def SpecialCall(match):
key = match.group(1)
return _SPECIAL_CALLS.get(key, match.group(0))
# "var testDescrip = " + str(self.testRecord) + ';\n\n' + \
source = self.suite.GetInclude("cth.js") + \
self.suite.GetInclude("sta.js") + \
self.suite.GetInclude("ed.js") + \
self.test + '\n'
if self.strict_mode:
source = '"use strict";\nvar strict_mode = true;\n' + \
_SPECIAL_CALL_PATTERN.sub(SpecialCall, source)
source = '"use strict";\nvar strict_mode = true;\n' + source
else:
source = "var strict_mode = false; \n" + \
_SPECIAL_CALL_PATTERN.sub(SpecialCall, source)
source = "var strict_mode = false; \n" + source
return source
def InstantiateTemplate(self, template, params):
def GetParameter(match):
key = match.group(1)
return params.get(key, match.group(0))
return _PLACEHOLDER_PATTERN.sub(GetParameter, template)
def RunTestIn(self, command_template, tmp):
tmp.Write(self.GetSource())
tmp.Close()
command = self.InstantiateTemplate(command_template, {
'path': tmp.name
})
(code, out, err) = self.Execute(command)
return TestResult(code, out, err, self)
return placeHolderPattern.sub(GetParameter, template)
def Execute(self, command):
if IsWindows():
@ -260,6 +248,15 @@ class TestCase(object):
stderr.Dispose()
return (code, out, err)
def RunTestIn(self, command_template, tmp):
tmp.Write(self.GetSource())
tmp.Close()
command = self.InstantiateTemplate(command_template, {
'path': tmp.name
})
(code, out, err) = self.Execute(command)
return TestResult(code, out, err, self)
def Run(self, command_template):
tmp = TempFile(suffix=".js", prefix="test262-", text=True)
try:
@ -298,11 +295,13 @@ def MakePlural(n):
class TestSuite(object):
def __init__(self, root, strict_only, non_strict_only):
self.test_root = path.join(root, 'test', 'suite', 'converted')
def __init__(self, root, strict_only, non_strict_only, unmarked_default):
# TODO: derive from packagerConfig.py
self.test_root = path.join(root, 'test', 'suite')
self.lib_root = path.join(root, 'test', 'harness')
self.strict_only = strict_only
self.non_strict_only = non_strict_only
self.unmarked_default = unmarked_default
self.include_cache = { }
def Validate(self):
@ -325,41 +324,18 @@ class TestSuite(object):
return True
return False
def GetTimeZoneInfoInclude(self):
dst_attribs = GetDaylightSavingsAttribs()
if not dst_attribs:
return None
lines = []
for key in sorted(dst_attribs.keys()):
lines.append('var $DST_%s = %s;' % (key, str(dst_attribs[key])))
localtz = time.timezone / -3600
lines.append('var $LocalTZ = %i;' % localtz)
return "\n".join(lines)
def GetSpecialInclude(self, name):
if name == "environment.js":
return self.GetTimeZoneInfoInclude()
else:
return None
def GetInclude(self, name, strip_header=True):
key = (name, strip_header)
if not key in self.include_cache:
value = self.GetSpecialInclude(name)
if value:
self.include_cache[key] = value
def GetInclude(self, name):
if not name in self.include_cache:
static = path.join(self.lib_root, name)
if path.exists(static):
f = open(static)
contents = stripHeader(f.read())
contents = re.sub(r'\r\n', '\n', contents)
self.include_cache[name] = contents + "\n"
f.close()
else:
static = path.join(self.lib_root, name)
if path.exists(static):
f = open(static)
contents = f.read()
if strip_header:
contents = StripHeader(contents)
self.include_cache[key] = contents + "\n"
f.close()
else:
self.include_cache[key] = ""
return self.include_cache[key]
ReportError("Can't find: " + static)
return self.include_cache[name]
def EnumerateTests(self, tests):
logging.info("Listing tests in %s", self.test_root)
@ -379,14 +355,21 @@ class TestSuite(object):
if self.ShouldRun(rel_path, tests):
basename = path.basename(full_path)[:-3]
name = rel_path.split(path.sep)[:-1] + [basename]
if not self.non_strict_only:
strict_case = TestCase(self, name, full_path, True)
if not strict_case.IsNonStrictOnly():
cases.append(strict_case)
if not self.strict_only:
non_strict_case = TestCase(self, name, full_path, False)
if not non_strict_case.IsStrictOnly():
cases.append(non_strict_case)
if EXCLUDE_LIST.count(basename) >= 1:
print 'Excluded: ' + basename
else:
if not self.non_strict_only:
strict_case = TestCase(self, name, full_path, True)
if not strict_case.IsNoStrict():
if strict_case.IsOnlyStrict() or \
self.unmarked_default in ['both', 'strict']:
cases.append(strict_case)
if not self.strict_only:
non_strict_case = TestCase(self, name, full_path, False)
if not non_strict_case.IsOnlyStrict():
if non_strict_case.IsNoStrict() or \
self.unmarked_default in ['both', 'non_strict']:
cases.append(non_strict_case)
logging.info("Done listing tests")
return cases
@ -447,83 +430,14 @@ class TestSuite(object):
cases[0].Print()
def GetDaylightSavingsTimes():
# Is the given floating-point time in DST?
def IsDst(t):
return time.localtime(t)[-1]
# Binary search to find an interval between the two times no greater than
# delta where DST switches, returning the midpoint.
def FindBetween(start, end, delta):
while end - start > delta:
middle = (end + start) / 2
if IsDst(middle) == IsDst(start):
start = middle
else:
end = middle
return (start + end) / 2
now = time.time()
one_month = (30 * 24 * 60 * 60)
# First find a date with different daylight savings. To avoid corner cases
# we try four months before and after today.
after = now + 4 * one_month
before = now - 4 * one_month
if IsDst(now) == IsDst(before) and IsDst(now) == IsDst(after):
logging.warning("Was unable to determine DST info.")
return None
# Determine when the change occurs between now and the date we just found
# in a different DST.
if IsDst(now) != IsDst(before):
first = FindBetween(before, now, 1)
else:
first = FindBetween(now, after, 1)
# Determine when the change occurs between three and nine months from the
# first.
second = FindBetween(first + 3 * one_month, first + 9 * one_month, 1)
# Find out which switch is into and which if out of DST
if IsDst(first - 1) and not IsDst(first + 1):
start = second
end = first
else:
start = first
end = second
return (start, end)
def GetDaylightSavingsAttribs():
times = GetDaylightSavingsTimes()
if not times:
return None
(start, end) = times
def DstMonth(t):
return time.localtime(t)[1] - 1
def DstHour(t):
return time.localtime(t - 1)[3] + 1
def DstSunday(t):
if time.localtime(t)[2] > 15:
return "'last'"
else:
return "'first'"
def DstMinutes(t):
return (time.localtime(t - 1)[4] + 1) % 60
attribs = { }
attribs['start_month'] = DstMonth(start)
attribs['end_month'] = DstMonth(end)
attribs['start_sunday'] = DstSunday(start)
attribs['end_sunday'] = DstSunday(end)
attribs['start_hour'] = DstHour(start)
attribs['end_hour'] = DstHour(end)
attribs['start_minutes'] = DstMinutes(start)
attribs['end_minutes'] = DstMinutes(end)
return attribs
def Main():
parser = BuildOptions()
(options, args) = parser.parse_args()
ValidateOptions(options)
test_suite = TestSuite(options.tests,
options.strict_only,
options.non_strict_only)
options.non_strict_only,
options.unmarked_default)
test_suite.Validate()
if options.cat:
test_suite.Print(args)