react / wstein / node_modules / jest-cli / node_modules / istanbul / node_modules / js-yaml / node_modules / esprima / test / runner.js
80713 views/*1Copyright (C) 2012 Ariya Hidayat <[email protected]>2Copyright (C) 2012 Joost-Wim Boekesteijn <[email protected]>3Copyright (C) 2012 Yusuke Suzuki <[email protected]>4Copyright (C) 2012 Arpad Borsos <[email protected]>5Copyright (C) 2011 Ariya Hidayat <[email protected]>6Copyright (C) 2011 Yusuke Suzuki <[email protected]>7Copyright (C) 2011 Arpad Borsos <[email protected]>89Redistribution and use in source and binary forms, with or without10modification, are permitted provided that the following conditions are met:1112* Redistributions of source code must retain the above copyright13notice, this list of conditions and the following disclaimer.14* Redistributions in binary form must reproduce the above copyright15notice, this list of conditions and the following disclaimer in the16documentation and/or other materials provided with the distribution.1718THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"19AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY22DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES23(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;24LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND25ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT26(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF27THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.28*/2930/*jslint browser:true node:true */31/*global esprima:true, testFixture:true */3233var runTests;3435function NotMatchingError(expected, actual) {36'use strict';37Error.call(this, 'Expected ');38this.expected = expected;39this.actual = actual;40}41NotMatchingError.prototype = new Error();4243function errorToObject(e) {44'use strict';45var msg = e.toString();4647// Opera 9.64 produces an non-standard string in toString().48if (msg.substr(0, 6) !== 'Error:') {49if (typeof e.message === 'string') {50msg = 'Error: ' + e.message;51}52}5354return {55index: e.index,56lineNumber: e.lineNumber,57column: e.column,58message: msg59};60}6162function sortedObject(o) {63if (o === null) {64return o;65}66if (Array.isArray(o)) {67return o.map(sortedObject);68}69if (typeof o !== 'object') {70return o;71}72if (o instanceof RegExp) {73return o;74}75var keys = Object.keys(o);76var result = {77range: undefined,78loc: undefined79};80keys.forEach(function (key) {81if (o.hasOwnProperty(key)){82result[key] = sortedObject(o[key]);83}84});85return result;86}8788function hasAttachedComment(syntax) {89var key;90for (key in syntax) {91if (key === 'leadingComments' || key === 'trailingComments') {92return true;93}94if (typeof syntax[key] === 'object' && syntax[key] !== null) {95if (hasAttachedComment(syntax[key])) {96return true;97}98}99}100return false;101}102103function testParse(esprima, code, syntax) {104'use strict';105var expected, tree, actual, options, StringObject, i, len;106107// alias, so that JSLint does not complain.108StringObject = String;109110options = {111comment: (typeof syntax.comments !== 'undefined'),112range: true,113loc: true,114tokens: (typeof syntax.tokens !== 'undefined'),115raw: true,116tolerant: (typeof syntax.errors !== 'undefined'),117source: null,118sourceType: syntax.sourceType119};120121if (options.comment) {122options.attachComment = hasAttachedComment(syntax);123}124125if (typeof syntax.tokens !== 'undefined') {126if (syntax.tokens.length > 0) {127options.range = (typeof syntax.tokens[0].range !== 'undefined');128options.loc = (typeof syntax.tokens[0].loc !== 'undefined');129}130}131132if (typeof syntax.comments !== 'undefined') {133if (syntax.comments.length > 0) {134options.range = (typeof syntax.comments[0].range !== 'undefined');135options.loc = (typeof syntax.comments[0].loc !== 'undefined');136}137}138139if (options.loc) {140options.source = syntax.loc.source;141}142143syntax = sortedObject(syntax);144expected = JSON.stringify(syntax, null, 4);145try {146// Some variations of the options.147tree = esprima.parse(code, { tolerant: options.tolerant, sourceType: options.sourceType });148tree = esprima.parse(code, { tolerant: options.tolerant, sourceType: options.sourceType, range: true });149tree = esprima.parse(code, { tolerant: options.tolerant, sourceType: options.sourceType, loc: true });150151tree = esprima.parse(code, options);152153if (options.tolerant) {154for (i = 0, len = tree.errors.length; i < len; i += 1) {155tree.errors[i] = errorToObject(tree.errors[i]);156}157}158tree = sortedObject(tree);159actual = JSON.stringify(tree, null, 4);160161// Only to ensure that there is no error when using string object.162esprima.parse(new StringObject(code), options);163164} catch (e) {165throw new NotMatchingError(expected, e.toString());166}167if (expected !== actual) {168throw new NotMatchingError(expected, actual);169}170171function filter(key, value) {172return (key === 'loc' || key === 'range') ? undefined : value;173}174175if (options.tolerant) {176return;177}178179180// Check again without any location info.181options.range = false;182options.loc = false;183syntax = sortedObject(syntax);184expected = JSON.stringify(syntax, filter, 4);185try {186tree = esprima.parse(code, options);187188if (options.tolerant) {189for (i = 0, len = tree.errors.length; i < len; i += 1) {190tree.errors[i] = errorToObject(tree.errors[i]);191}192}193tree = sortedObject(tree);194actual = JSON.stringify(tree, filter, 4);195} catch (e) {196throw new NotMatchingError(expected, e.toString());197}198if (expected !== actual) {199throw new NotMatchingError(expected, actual);200}201}202203function testTokenize(esprima, code, tokens) {204'use strict';205var options, expected, actual, tree;206207options = {208comment: true,209tolerant: true,210loc: true,211range: true212};213214expected = JSON.stringify(tokens, null, 4);215216try {217tree = esprima.tokenize(code, options);218actual = JSON.stringify(tree, null, 4);219} catch (e) {220throw new NotMatchingError(expected, e.toString());221}222if (expected !== actual) {223throw new NotMatchingError(expected, actual);224}225}226227228function testModule(esprima, code, exception) {229'use strict';230var i, options, expected, actual, err, handleInvalidRegexFlag, tokenize;231232// Different parsing options should give the same error.233options = [234{ sourceType: 'module' },235{ sourceType: 'module', comment: true },236{ sourceType: 'module', raw: true },237{ sourceType: 'module', raw: true, comment: true }238];239240if (!exception.message) {241exception.message = 'Error: Line 1: ' + exception.description;242}243exception.description = exception.message.replace(/Error: Line [0-9]+: /, '');244245expected = JSON.stringify(exception);246247for (i = 0; i < options.length; i += 1) {248249try {250esprima.parse(code, options[i]);251} catch (e) {252err = errorToObject(e);253err.description = e.description;254actual = JSON.stringify(err);255}256257if (expected !== actual) {258259// Compensate for old V8 which does not handle invalid flag.260if (exception.message.indexOf('Invalid regular expression') > 0) {261if (typeof actual === 'undefined' && !handleInvalidRegexFlag) {262return;263}264}265266throw new NotMatchingError(expected, actual);267}268269}270}271272function testError(esprima, code, exception) {273'use strict';274var i, options, expected, actual, err, handleInvalidRegexFlag, tokenize;275276// Different parsing options should give the same error.277options = [278{},279{ comment: true },280{ raw: true },281{ raw: true, comment: true }282];283284// If handleInvalidRegexFlag is true, an invalid flag in a regular expression285// will throw an exception. In some old version of V8, this is not the case286// and hence handleInvalidRegexFlag is false.287handleInvalidRegexFlag = false;288try {289'test'.match(new RegExp('[a-z]', 'x'));290} catch (e) {291handleInvalidRegexFlag = true;292}293294exception.description = exception.message.replace(/Error: Line [0-9]+: /, '');295296if (exception.tokenize) {297tokenize = true;298exception.tokenize = undefined;299}300expected = JSON.stringify(exception);301302for (i = 0; i < options.length; i += 1) {303304try {305if (tokenize) {306esprima.tokenize(code, options[i]);307} else {308esprima.parse(code, options[i]);309}310} catch (e) {311err = errorToObject(e);312err.description = e.description;313actual = JSON.stringify(err);314}315316if (expected !== actual) {317318// Compensate for old V8 which does not handle invalid flag.319if (exception.message.indexOf('Invalid regular expression') > 0) {320if (typeof actual === 'undefined' && !handleInvalidRegexFlag) {321return;322}323}324325throw new NotMatchingError(expected, actual);326}327328}329}330331function testAPI(esprima, code, expected) {332var result;333// API test.334expected = JSON.stringify(expected, null, 4);335try {336result = eval(code);337result = JSON.stringify(result, null, 4);338} catch (e) {339throw new NotMatchingError(expected, e.toString());340}341if (expected !== result) {342throw new NotMatchingError(expected, result);343}344}345346function generateTestCase(esprima, testCase) {347var tree, fileName = testCase.key + ".tree.json";348try {349tree = esprima.parse(testCase.case, {loc: true, range: true});350tree = JSON.stringify(tree, null, 4);351} catch (e) {352if (typeof e.index === 'undefined') {353console.error("Failed to generate test result.");354throw e;355}356tree = errorToObject(e);357tree.description = e.description;358tree = JSON.stringify(tree);359fileName = testCase.key + ".failure.json";360}361require('fs').writeFileSync(fileName, tree);362console.error("Done.");363}364365if (typeof window === 'undefined') {366(function () {367'use strict';368369var esprima = require('../esprima'),370vm = require('vm'),371fs = require('fs'),372diff = require('json-diff').diffString,373total = 0,374result,375failures = [],376cases = {},377context = {source: '', result: null},378tick = new Date(),379expected,380testCase,381header;382383function enumerateFixtures(root) {384var dirs = fs.readdirSync(root), key, kind,385kinds = ['case', 'source', 'module', 'run', 'tree', 'tokens', 'failure', 'result'],386suffices = ['js', 'js', 'json', 'js', 'json', 'json', 'json', 'json'];387388dirs.forEach(function (item) {389var i;390if (fs.statSync(root + '/' + item).isDirectory()) {391enumerateFixtures(root + '/' + item);392} else {393kind = 'case';394key = item.slice(0, -3);395for (i = 1; i < kinds.length; i++) {396var suffix = '.' + kinds[i] + '.' + suffices[i];397if (item.slice(-suffix.length) === suffix) {398key = item.slice(0, -suffix.length);399kind = kinds[i];400}401}402key = root + '/' + key;403if (!cases[key]) {404total++;405cases[key] = { key: key };406}407cases[key][kind] = fs.readFileSync(root + '/' + item, 'utf-8');408}409});410}411412enumerateFixtures(__dirname + '/fixtures');413414for (var key in cases) {415if (cases.hasOwnProperty(key)) {416testCase = cases[key];417418if (testCase.hasOwnProperty('source')) {419testCase.case = eval(testCase.source + ';source');420}421422try {423if (testCase.hasOwnProperty('module')) {424testModule(esprima, testCase.case, JSON.parse(testCase.module));425} else if (testCase.hasOwnProperty('tree')) {426testParse(esprima, testCase.case, JSON.parse(testCase.tree));427} else if (testCase.hasOwnProperty('tokens')) {428testTokenize(esprima, testCase.case, JSON.parse(testCase.tokens));429} else if (testCase.hasOwnProperty('failure')) {430testError(esprima, testCase.case, JSON.parse(testCase.failure));431} else if (testCase.hasOwnProperty('result')) {432testAPI(esprima, testCase.run, JSON.parse(testCase.result));433} else {434console.error('Incomplete test case:' + testCase.key + '. Generating test result...');435generateTestCase(esprima, testCase);436}437} catch (e) {438if (!e.expected) {439throw e;440}441e.source = testCase.case || testCase.key;442failures.push(e);443}444}445}446447tick = (new Date()) - tick;448449header = total + ' tests. ' + failures.length + ' failures. ' +450tick + ' ms';451if (failures.length) {452console.error(header);453failures.forEach(function (failure) {454try {455var expectedObject = JSON.parse(failure.expected);456var actualObject = JSON.parse(failure.actual);457458console.error(failure.source + ': Expected\n ' +459failure.expected.split('\n').join('\n ') +460'\nto match\n ' + failure.actual + '\nDiff:\n' +461diff(expectedObject, actualObject));462} catch (ex) {463console.error(failure.source + ': Expected\n ' +464failure.expected.split('\n').join('\n ') +465'\nto match\n ' + failure.actual);466}467});468} else {469console.log(header);470}471process.exit(failures.length === 0 ? 0 : 1);472473}());474}475476477