diff options
author | Mark Miller <erights@gmail.com> | 2011-09-09 14:48:37 -0700 |
---|---|---|
committer | Mark Miller <erights@gmail.com> | 2011-09-09 14:48:37 -0700 |
commit | 274b5514fa83ded95fea7892c4cf037839abfcde (patch) | |
tree | acf154c5a9a128a045f7ee56869b3f8ea6b22c99 /tools | |
parent | 5c054fa41258f844547d8ad4c1da2fb913ff3836 (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.js | 102 | ||||
-rw-r--r-- | tools/converter/utils.js | 118 | ||||
-rw-r--r-- | tools/converter/v8PosixPlatform.js | 150 |
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); |