aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMark Miller <erights@gmail.com>2011-09-09 14:48:37 -0700
committerMark Miller <erights@gmail.com>2011-09-09 14:48:37 -0700
commit274b5514fa83ded95fea7892c4cf037839abfcde (patch)
treeacf154c5a9a128a045f7ee56869b3f8ea6b22c99 /tools
parent5c054fa41258f844547d8ad4c1da2fb913ff3836 (diff)
As David Fugate requested, changed the conversion of ietestcenter
style to append runTestCase(funcName); rather than assertTrue(funcName.call(this)), giving the testing framework more control.
Diffstat (limited to 'tools')
-rw-r--r--tools/converter/convert.js102
-rw-r--r--tools/converter/utils.js118
-rw-r--r--tools/converter/v8PosixPlatform.js150
3 files changed, 245 insertions, 125 deletions
diff --git a/tools/converter/convert.js b/tools/converter/convert.js
index 8ebb03de5..6c99aac4a 100644
--- a/tools/converter/convert.js
+++ b/tools/converter/convert.js
@@ -6,13 +6,35 @@
"use strict";
var t262 = global.t262;
+
var platform = t262.platform;
- var regExp = platform.regExp;
var toRelPathStr = platform.toRelPathStr;
var toPathStr = platform.toPathStr;
var toRelPath = platform.toRelPath;
var toPath = platform.toPath;
+ var utils = t262.utils;
+ var forEach = utils.forEach;
+ var map = utils.map;
+ var filter = utils.filter;
+ var keys = utils.keys;
+ var trim = utils.trim;
+ var regExp = utils.regExp;
+
+ var CONTRIB_DIRS = [
+ ['test', 'suite', 'other'],
+ ['test', 'suite', 'sputnik', 'Conformance'],
+ ['test', 'suite', 'ietestcenter']
+ ];
+
+ var CONVERTED_DIR = ['test', 'suite', 'converted'];
+
+ var OUT_DIR = ['website', 'resources', 'scripts', 'testcases2'];
+
+ var CONVERT_PATH = platform.CONVERTER_DIR.concat('convert.js');
+
+/////////////////////////////////////////////////////////////////
+
var headerPattern = /(?:(?:\/\/.*)?\s*\n)*/;
var captureCommentPattern = /\/\*\*?((?:\s|\S)*?)\*\/\s*\n/;
var anyPattern = /(?:\s|\S)*/;
@@ -48,12 +70,14 @@
/return\s+true;?/, blanksPattern,
/\}$/);
+/////////////////////////////////////////////////////////////////
+
/**
* Strip the left margin "*"s that are found in the body of a
* multiline doc-comment like this one.
*/
function stripStars(text) {
- return text.replace(/\s*\n\s*\*\s?/g, '\n').trim();
+ return trim(text.replace(/\s*\n\s*\*\s?/g, '\n'));
}
/**
@@ -77,12 +101,12 @@
// Can't happen?
throw new Error('unrecognized: ' + name);
}
- envelope.header = envelopeMatch[1].trim();
+ envelope.header = trim(envelopeMatch[1]);
if (envelopeMatch[2]) {
var propTexts = envelopeMatch[2].split(/\s*\n\s*\*\s*@/);
envelope.comment = stripStars(propTexts.shift()), // notice side effect
- propTexts.forEach(function(propText) {
+ forEach(propTexts, function(propText) {
var propName = propText.match(/^\w+/)[0];
var propVal = propText.substring(propName.length);
// strip optional initial colon or final semicolon.
@@ -100,8 +124,8 @@
var registerMatch = registerPattern.exec(envelope.rest);
if (registerMatch) {
- envelope.rest = registerMatch[1].trim();
- envelope.registerExpr = registerMatch[2].trim();
+ envelope.rest = trim(registerMatch[1]);
+ envelope.registerExpr = trim(registerMatch[2]);
} else if (envelope.rest.indexOf('ES5Harness.registerTest') >= 0) {
print(' \n--header---\n|' + envelope.header +
'|\n--rest-----\n|' + envelope.rest +
@@ -122,9 +146,10 @@
* <p>Programs do not conveniently return any value, even their
* completion value, so Programs in canonical test262 style instead
* indicate success simply by completing normally, i.e., without
- * throwing anything. The convertion assumes a one argument
- * <code>assertTrue</code> function which throws an indication of
- * test failure iff given a falsy argument.
+ * throwing anything. The conversion assumes a one argument
+ * <code>runTestCase</code> function which calls it function
+ * argument and throws an indication of test failure iff that
+ * function returns a falsy argument.
*
* <p>Unless it specifies otherwise, the Program source may be
* executed strict and/or non-strict, and it may be exeuted within
@@ -137,25 +162,25 @@
if (!cfnbMatch) {
throw new Error('Could not recognize: "' + funcSrc + '"');
}
- var name = cfnbMatch[1].trim();
- var body = cfnbMatch[2].trim();
+ var name = trim(cfnbMatch[1]);
+ var body = trim(cfnbMatch[2]);
// Look for special cases
var cebMatch = captureExprBodyPattern.exec(body);
if (cebMatch) {
- return 'assertTrue(' + cebMatch[1].trim() + ');';
+ return 'assertTrue(' + trim(cebMatch[1]) + ');';
}
var cpMatch = capturePredicatePattern.exec(body);
if (cpMatch) {
- return 'assertTrue(' + cpMatch[1].trim() + ');';
+ return 'assertTrue(' + trim(cpMatch[1]) + ');';
}
// General case
return funcSrc + '\n' +
- 'assertTrue(' + name + '.call(this));';
+ 'runTestCase(' + name + ');';
}
/**
@@ -164,7 +189,7 @@
*/
function gatherOne(envelope, name) {
if (envelope.testRecord) {
- var propNames = Object.keys(envelope.testRecord);
+ var propNames = keys(envelope.testRecord);
if (propNames.length >= 1) {
// This need not be an error. It's just here so we notice the
// first time it happens. This would happen if an
@@ -254,7 +279,7 @@
var nextRelPath = relPath.concat([name]);
var nextPath = inBase.concat(nextRelPath);
- var src = platform.read(nextPath);
+ var src = platform.getText(nextPath);
var testRecord;
if (!src) {
throw new Error('no src: ' + toPathStr(nextPath));
@@ -313,8 +338,8 @@
result += ' * ' + testRecord.comment.replace(/\n/g, '\n * ') + '\n *\n';
}
delete testRecord.comment;
- KNOWN_PROPS.forEach(addProp);
- Object.keys(testRecord).forEach(addProp);
+ forEach(KNOWN_PROPS, addProp);
+ forEach(keys(testRecord), addProp);
result += ' */\n\n' + test;
return result;
}
@@ -334,18 +359,6 @@
}
t262.convertTest = convertTest;
- var SRC_DIRS = [
- ['test', 'suite', 'other'],
- ['test', 'suite', 'ietestcenter'],
- ['test', 'suite', 'sputnik', 'Conformance']
- ];
-
- var CONV_DIR = ['test', 'suite', 'converted'];
-
- var OUT_DIR = ['website', 'resources', 'scripts', 'testcases2'];
-
- var ME_PATH = platform.CONVERTER_PATH.concat('convert.js');
-
var writeSpawnFailures = [];
/**
@@ -357,7 +370,7 @@
var inPath = inBase.concat(relPath);
var outPath = outBase.concat(relPath);
platform.mkdir(outPath);
- platform.ls(inPath).forEach(function(name) {
+ forEach(platform.ls(inPath), function(name) {
var nextRelPath = relPath.concat([name]);
if (platform.isDirectory(inBase.concat(nextRelPath))) {
convertAll(inBase, outBase, nextRelPath);
@@ -365,8 +378,8 @@
var outFilePath = outPath.concat([name]);
try {
platform.writeSpawn(
- [ME_PATH],
- 'print(t262.convertTest("' + toPathStr(inBase) +
+ [CONVERT_PATH],
+ 't262.show(t262.convertTest("' + toPathStr(inBase) +
'", "' + toRelPathStr(nextRelPath) + '"));',
void 0,
outFilePath);
@@ -388,12 +401,12 @@
function convert(opt_relPathStr) {
var relPath = opt_relPathStr ? toRelPath(opt_relPathStr) : [];
writeSpawnFailures = [];
- SRC_DIRS.forEach(function(srcDir) {
- convertAll(srcDir, CONV_DIR, relPath);
+ forEach(CONTRIB_DIRS, function(srcDir) {
+ convertAll(srcDir, CONVERTED_DIR, relPath);
});
if (writeSpawnFailures.length >= 1) {
print('********* failures **********');
- writeSpawnFailures.forEach(function(failure) {
+ forEach(writeSpawnFailures, function(failure) {
print(failure.error + ': ' + toRelPathStr(failure.relPath));
});
throw writeSpawnFailures[0].error;
@@ -411,17 +424,17 @@
var path = toPath(pathStr);
if (!platform.isDirectory(path)) { throw new Error('not dir: ' + path); }
- var jsFiles = platform.ls(path).filter(function(name) {
+ var jsFiles = filter(platform.ls(path), function(name) {
return /\.js$/.test(name);
});
- var testRecords = jsFiles.map(function(name) {
+ var testRecords = map(jsFiles, function(name) {
var testRecord = parseTestRecord(path, name);
delete testRecord.header;
delete testRecord.comment;
return testRecord;
});
- testRecords = testRecords.filter(function(testRecord) {
+ testRecords = filter(testRecords, function(testRecord) {
return testRecord !== null;
});
return {
@@ -441,7 +454,7 @@
function buildAll(inBase, outBase, relPath) {
var inPath = inBase.concat(relPath);
var hasJS = false;
- platform.ls(inPath).forEach(function(name) {
+ forEach(platform.ls(inPath), function(name) {
var nextRelPath = relPath.concat([name]);
if (platform.isDirectory(inBase.concat(nextRelPath))) {
buildAll(inBase, outBase, nextRelPath);
@@ -454,9 +467,8 @@
var outFilePath = outBase.concat([name]);
try {
platform.writeSpawn(
- [ME_PATH],
- 'print(t262.asJSONTxt(t262.buildSection("' +
- toPathStr(inPath) + '")));',
+ [CONVERT_PATH],
+ 't262.showJSON(t262.buildSection("' + toPathStr(inPath) + '"));',
void 0,
outFilePath);
} catch (err) {
@@ -479,10 +491,10 @@
*/
function buildWebSite(opt_relPathStr) {
var relPath = opt_relPathStr ? toRelPath(opt_relPathStr) : [];
- SRC_DIRS.forEach(function(srcDir) {
+ forEach(CONTRIB_DIRS, function(srcDir) {
buildAll(srcDir, OUT_DIR, relPath);
});
-// buildAll(CONV_DIR, OUT_DIR, relPath);
+// buildAll(CONVERTED_DIR, OUT_DIR, relPath);
}
t262.buildWebSite = buildWebSite;
diff --git a/tools/converter/utils.js b/tools/converter/utils.js
new file mode 100644
index 000000000..ba96748ec
--- /dev/null
+++ b/tools/converter/utils.js
@@ -0,0 +1,118 @@
+// Copyright 2011 by Google, Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+
+/**
+ * General conveniences, including some functionality available in ES5
+ * but not ES3.
+ *
+ * <p>This file must be able to run in many browsers, and so should
+ * assume the platform may be anything from ES3+Reality forward,
+ * including somewhat non-conformant implementations. It must also be
+ * able to run in a non-browser environment, such as from the command
+ * line.
+ *
+ * <p>The conveniences that are analogs of similar ES5 features are
+ * not full emulations, but only emulations of the portion of their
+ * semantics we need.
+ */
+(function(global) {
+ "use strict";
+
+ global.t262 = global.t262 || {};
+
+ var utils = global.t262.utils = global.t262.utils || {};
+
+ ////////////////////////////////////////////////////////
+
+ /**
+ * Like ES5 call.bind([].forEach)(list, func), but supporting fewer
+ * optional arguments.
+ */
+ function forEach(list, func) {
+ for (var i = 0, len = list.length; i < len; i++) {
+ func(list[i], i);
+ }
+ }
+ utils.forEach = forEach;
+
+ /**
+ * Like ES5 call.bind([].map)(list, func), but supporting fewer
+ * optional arguments.
+ */
+ function map(list, func) {
+ var result = [];
+ for (var i = 0, len = list.length; i < len; i++) {
+ result.push(func(list[i], i));
+ }
+ return result;
+ }
+ utils.map = map;
+
+ /**
+ * Like ES5 call.bind([].filter)(list, pred), but supporting fewer
+ * optional arguments.
+ */
+ function filter(list, pred) {
+ var result = [];
+ for (var i = 0, len = list.length; i < len; i++) {
+ if (pred(list[i], i)) { result.push(list[i]); }
+ }
+ return result;
+ }
+ utils.filter = filter;
+
+ /**
+ * Like ES5 Object.keys(obj).
+ */
+ function keys(obj) {
+ var result = [];
+ var hop = {}.hasOwnProperty;
+ for (var k in obj) {
+ if (hop.call(obj, k)) { result.push(k); }
+ }
+ return result;
+ }
+ utils.keys = keys;
+
+ /**
+ * Like ES5 call.bind(''.trim)(string).
+ */
+ function trim(str) {
+ return str.replace(/^\s*/, '').replace(/\s*$/, '');
+ }
+ utils.trim = trim;
+
+ /**
+ * Appends a bunch of RegExps together into a single RegExp,
+ * solving both the RegExp-one-liner problem and the doubled
+ * backslash problem when composing literal strings.
+ *
+ * <p>The arguments can be any mixture of RegExps and strings. By
+ * expressing the portions that should be well formed regexps as
+ * regexps, we catch well-formedness errors within such a portion
+ * separately. The strings are added as is without escaping --
+ * BEWARE. By not escaping the strings, we can use them to
+ * represent the individually unbalanced fragments, like capturing
+ * parens, around other regexps. If arguments[0] is a RegExp, we
+ * use its flags on the resuting RegExp.
+ *
+ * <p>Not platform dependent, so does not really belong in this
+ * file.
+ */
+ function regExp(var_args) {
+ var args = [].slice.call(arguments, 0);
+ var reSrc = map(args, function(arg) {
+ return (typeof arg === 'string') ? arg : arg.source;
+ }).join('');
+ var flags = '';
+ if (typeof args[0] === 'object') {
+ var parts = (''+args[0]).split('/');
+ flags = parts[parts.length -1];
+ }
+ return new RegExp(reSrc, flags);
+ }
+ utils.regExp = regExp;
+
+
+ })(this); \ No newline at end of file
diff --git a/tools/converter/v8PosixPlatform.js b/tools/converter/v8PosixPlatform.js
index a98d412de..f2d9b6451 100644
--- a/tools/converter/v8PosixPlatform.js
+++ b/tools/converter/v8PosixPlatform.js
@@ -7,7 +7,9 @@
* engine peculiarities.
*
* <p>The implementation here is specific to the v8 shell running on a
- * Posix platform.
+ * Posix platform. Therefore, it may legitimately use ES5 features,
+ * although it generally avoids them for consistency with the rest of
+ * test262.
*/
(function (global) {
"use strict";
@@ -31,38 +33,11 @@
var platform = global.t262.platform = {};
- /**
- * Appends a bunch of RegExps together into a single RegExp,
- * solving both the RegExp-one-liner problem and the doubled
- * backslash problem when composing literal strings.
- *
- * <p>The arguments can be any mixture of RegExps and strings. By
- * expressing the portions that should be well formed regexps as
- * regexps, we catch well-formedness errors within such a portion
- * separately. The strings are added as is without escaping --
- * BEWARE. By not escaping the strings, we can use them to
- * represent the individually unbalanced fragments, like capturing
- * parens, around other regexps. If arguments[0] is a RegExp, we
- * use its flags on the resuting RegExp.
- *
- * <p>Not platform dependent, so does not really belong in this
- * file.
- */
- function regExp(var_args) {
- var args = [].slice.call(arguments, 0);
- var reSrc = args.map(function(arg) {
- return (typeof arg === 'string') ? arg : arg.source;
- }).join('');
- var flags = '';
- if (typeof args[0] === 'object') {
- var parts = (''+args[0]).split('/');
- flags = parts[parts.length -1];
- }
- return new RegExp(reSrc, flags);
- }
- platform.regExp = regExp;
-
- ////////////////// Needed for building and running //////////////
+ var utils = global.t262.utils;
+ var forEach = utils.forEach;
+ var map = utils.map;
+ var keys = utils.keys;
+ var trim = utils.trim;
try {
read('tools/converter/v8PosixPlatform.js');
@@ -70,23 +45,31 @@
throw new Error('Must run in a test262 source root');
}
- var ABS_ROOT = os.system('pwd', ['-P']).trim().split('/');
+ var ABS_ROOT = trim(os.system('pwd', ['-P'])).split('/');
var TEST262_ROOT = ABSOLUTE_PATHSTR ? ABS_ROOT : [];
var TEST262_ROOT_STR = TEST262_ROOT.join('/');
- var CONVERTER_PATH = ['tools', 'converter'];
- platform.CONVERTER_PATH = CONVERTER_PATH;
+ var HARNESS_DIR = ['test', 'harness'];
+ platform.HARNESS_DIR = HARNESS_DIR;
+
+ var CONVERTER_DIR = ['tools', 'converter'];
+ platform.CONVERTER_DIR = CONVERTER_DIR;
+
+ var PLATFORM_PATHS = [
+ CONVERTER_DIR.concat('utils.js'),
+ CONVERTER_DIR.concat('v8PosixPlatform.js')
+ ];
- var ME_PATH = CONVERTER_PATH.concat('v8PosixPlatform.js');
+ ////////////////// Needed for building and running test //////////////
/**
*
*/
function validatePath(path) {
var pathStr = path.join('/');
- path.forEach(function(segment) {
+ forEach(path, function(segment) {
if (segment === '') {
throw new Error('A path cannot have empty segments: ' + pathStr);
}
@@ -129,31 +112,34 @@
/**
* Returns the text found at path, with newlines normalized and
* any initial BOM (Unicode Byte Order Mark) removed.
- *
- * Note: Don't simply revise this (without renamings) to follow the
- * general pattern of also defining a local 'read' function, as it
- * will mask the v8 shell's read function, which we use.
*/
- platform.read = function(path) {
- var text = read(toPathStr(path)).
- replace(/\r\n/g, '\n').
- replace(/\r/g, '\n');
+ function getText(path) {
+ var text = read(toPathStr(path));
+ text = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
if (text.charCodeAt(0) === 0xfeff) { return text.substring(1); }
return text;
- };
+ }
+ platform.getText = getText;
/**
* How one JavaScript script possibly spawns another and possibly
* redirects its printed form to a chosen file (or resource).
*
* <p>For example, if !DRY_RUN, then<pre>
- * writeSpawn([], 'print(+arguments[0] + +arguments[1]);', ['3', '5'])
+ * platform.writeSpawn([],
+ * 't262.show(+arguments[0] + +arguments[1]);',
+ * ['3', '5'])
* </pre>
- * should return the string "8" if writeSpawn decides to spawn.
+ * should emit string "8" to stdout.
+ *
+ * <p>To spawn a platform distinct from the present one -- for
+ * example, as outer v8-based driver can drive a rhino-based child
+ * -- create a distinct object representing that other platform and
+ * invoke its writeSpawn method.
*
* @param scriptPaths An array of path arrays of JavaScript source
- * files to be loaded into the spawned JS engine (in addition to
- * the spawning platform file) if we are indeed spawning.
+ * files to be loaded into the spawned JS engine, after
+ * PLATFORM_PATHS, if we are indeed spawning.
* @param opt_src A Program to be evaluated in an environment in
* which "arguments" is bound to the list of strings provided by
* opt_args. If spawned, the result is whatever the program writes
@@ -187,14 +173,14 @@
return ''+(1,eval)(str).apply(void 0, opt_args || []);
}
- var cmd = 'v8 ' + toPathStr(ME_PATH) + ' ';
- cmd += scriptPaths.map(toPathStr).join(' ');
+ var allScriptPaths = PLATFORM_PATHS.concat(scriptPaths);
+ var cmd = 'v8 ' + map(allScriptPaths, toPathStr).join(' ');
if (opt_src) {
cmd += ' -e ' + JSON.stringify(opt_src);
}
if (opt_args) {
- cmd += ' -- ' + opt_args.map(JSON.stringify).join(' ');
+ cmd += ' -- ' + map(opt_args, JSON.stringify).join(' ');
}
if (opt_targetPath) {
cmd += ' > ' + toPathStr(opt_targetPath);
@@ -207,8 +193,7 @@
if (opt_targetPath) {
// The error we catch is almost certainly less interesting
// than the one unfortunately written to the target file.
- var message = 'failed: ' + cmd + '\n' +
- platform.read(opt_targetPath);
+ var message = 'failed: ' + cmd + '\n' + getText(opt_targetPath);
os.system('rm', [toPathStr(opt_targetPath)]);
throw new Error(message);
}
@@ -218,24 +203,23 @@
platform.writeSpawn = writeSpawn;
- ////////////////// Only needed for building /////////////////////
+ ////////////////// Only needed for building tests /////////////////////
/**
* Calls a non-strict indirect eval function on exprSrc.
*
- * On platforms (like SES) where this can be a safely confining
+ * <p>On platforms (like SES) where this can be a safely confining
* evaluation, it should be. The implementation here is not safe.
*/
function evalExprIn(exprSrc, env, opt_forceNonStrict) {
- var varNames = Object.getOwnPropertyNames(env);
+ var varNames = keys(env);
var str = '(function(' + varNames.join(',') + ') {';
if (opt_forceNonStrict !== 'forceNonStrict') {
str += '"use strict";';
}
str += ' return (' + exprSrc + '); })';
- return (1,eval)(str).apply(void 0, varNames.map(function(varName) {
- return env[varName];
- }));
+ var vals = map(varNames, function(varName) { return env[varName]; });
+ return (1,eval)(str).apply(void 0, vals);
}
platform.evalExprIn = evalExprIn;
@@ -270,11 +254,6 @@
* Does path name a directory?
*/
function isDirectory(path) {
-// var fileOut = os.system('file', [toPathStr(path)]);
-// var fileMatch = fileOut.match(/:\s*([^:]*)\s*$/);
-// if (!fileMatch) { return null; }
-// var fileType = fileMatch[1].trim();
-// return fileType === 'directory';
try {
os.system('test', ['-d', toPathStr(path)]);
return true;
@@ -293,7 +272,7 @@
if (!isDirectory(path)) { return []; }
var lines;
try {
- lines = os.system('ls', [pathStr]).trim();
+ lines = trim(os.system('ls', [pathStr]));
} catch (err) {
throw err;
}
@@ -303,18 +282,8 @@
platform.ls = ls;
/**
- * Emits the jsonRecord serialized as JSON, either compactly or
- * readably according to VERBOSE.
+ * If the directory does not yet exist, create it.
*/
- function asJSONTxt(jsonRecord) {
- if (VERBOSE) {
- return JSON.stringify(jsonRecord, void 0, ' ');
- } else {
- return JSON.stringify(jsonRecord);
- }
- }
- global.t262.asJSONTxt = platform.asJSONTxt = asJSONTxt;
-
function mkdir(path) {
var pathStr = toPathStr(path);
if (DRY_RUN) {
@@ -330,7 +299,28 @@
}
platform.mkdir = mkdir;
- ////////////////// Only needed for running //////////////////////
+ /**
+ * Emits the text itself followed by a newline.
+ *
+ * <p>On the v8 shell, this is identical to "print".
+ */
+ var show = global.t262.show = print;
+
+ /**
+ * Emits the jsonRecord serialized as JSON, either compactly or
+ * readably according to VERBOSE.
+ */
+ function showJSON(jsonRecord) {
+ if (VERBOSE) {
+ print(JSON.stringify(jsonRecord, void 0, ' '));
+ } else {
+ print(JSON.stringify(jsonRecord));
+ }
+ }
+ global.t262.showJSON = platform.showJSON = showJSON;
+
+
+ ////////////////// Only needed for running tests //////////////////////
})(this);