react / wstein / node_modules / jest-cli / node_modules / istanbul / node_modules / esprima / test / runner.js
80684 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: null118};119120if (options.comment) {121options.attachComment = hasAttachedComment(syntax);122}123124if (typeof syntax.tokens !== 'undefined') {125if (syntax.tokens.length > 0) {126options.range = (typeof syntax.tokens[0].range !== 'undefined');127options.loc = (typeof syntax.tokens[0].loc !== 'undefined');128}129}130131if (typeof syntax.comments !== 'undefined') {132if (syntax.comments.length > 0) {133options.range = (typeof syntax.comments[0].range !== 'undefined');134options.loc = (typeof syntax.comments[0].loc !== 'undefined');135}136}137138if (options.loc) {139options.source = syntax.loc.source;140}141142syntax = sortedObject(syntax);143expected = JSON.stringify(syntax, null, 4);144try {145// Some variations of the options.146tree = esprima.parse(code, { tolerant: options.tolerant });147tree = esprima.parse(code, { tolerant: options.tolerant, range: true });148tree = esprima.parse(code, { tolerant: options.tolerant, loc: true });149150tree = esprima.parse(code, options);151152if (options.tolerant) {153for (i = 0, len = tree.errors.length; i < len; i += 1) {154tree.errors[i] = errorToObject(tree.errors[i]);155}156}157tree = sortedObject(tree);158actual = JSON.stringify(tree, null, 4);159160// Only to ensure that there is no error when using string object.161esprima.parse(new StringObject(code), options);162163} catch (e) {164throw new NotMatchingError(expected, e.toString());165}166if (expected !== actual) {167throw new NotMatchingError(expected, actual);168}169170function filter(key, value) {171return (key === 'loc' || key === 'range') ? undefined : value;172}173174if (options.tolerant) {175return;176}177178179// Check again without any location info.180options.range = false;181options.loc = false;182syntax = sortedObject(syntax);183expected = JSON.stringify(syntax, filter, 4);184try {185tree = esprima.parse(code, options);186187if (options.tolerant) {188for (i = 0, len = tree.errors.length; i < len; i += 1) {189tree.errors[i] = errorToObject(tree.errors[i]);190}191}192tree = sortedObject(tree);193actual = JSON.stringify(tree, filter, 4);194} catch (e) {195throw new NotMatchingError(expected, e.toString());196}197if (expected !== actual) {198throw new NotMatchingError(expected, actual);199}200}201202function testTokenize(esprima, code, tokens) {203'use strict';204var options, expected, actual, tree;205206options = {207comment: true,208tolerant: true,209loc: true,210range: true211};212213expected = JSON.stringify(tokens, null, 4);214215try {216tree = esprima.tokenize(code, options);217actual = JSON.stringify(tree, null, 4);218} catch (e) {219throw new NotMatchingError(expected, e.toString());220}221if (expected !== actual) {222throw new NotMatchingError(expected, actual);223}224}225226function testError(esprima, code, exception) {227'use strict';228var i, options, expected, actual, err, handleInvalidRegexFlag, tokenize;229230// Different parsing options should give the same error.231options = [232{},233{ comment: true },234{ raw: true },235{ raw: true, comment: true }236];237238// If handleInvalidRegexFlag is true, an invalid flag in a regular expression239// will throw an exception. In some old version of V8, this is not the case240// and hence handleInvalidRegexFlag is false.241handleInvalidRegexFlag = false;242try {243'test'.match(new RegExp('[a-z]', 'x'));244} catch (e) {245handleInvalidRegexFlag = true;246}247248exception.description = exception.message.replace(/Error: Line [0-9]+: /, '');249250if (exception.tokenize) {251tokenize = true;252exception.tokenize = undefined;253}254expected = JSON.stringify(exception);255256for (i = 0; i < options.length; i += 1) {257258try {259if (tokenize) {260esprima.tokenize(code, options[i]);261} else {262esprima.parse(code, options[i]);263}264} catch (e) {265err = errorToObject(e);266err.description = e.description;267actual = JSON.stringify(err);268}269270if (expected !== actual) {271272// Compensate for old V8 which does not handle invalid flag.273if (exception.message.indexOf('Invalid regular expression') > 0) {274if (typeof actual === 'undefined' && !handleInvalidRegexFlag) {275return;276}277}278279throw new NotMatchingError(expected, actual);280}281282}283}284285function testAPI(esprima, code, expected) {286var result;287// API test.288expected = JSON.stringify(expected, null, 4);289try {290result = eval(code);291result = JSON.stringify(result, null, 4);292} catch (e) {293throw new NotMatchingError(expected, e.toString());294}295if (expected !== result) {296throw new NotMatchingError(expected, result);297}298}299300function generateTestCase(esprima, testCase) {301var tree, fileName = testCase.key + ".tree.json";302try {303tree = esprima.parse(testCase.case, {loc: true, range: true});304tree = JSON.stringify(tree, null, 4);305} catch (e) {306if (typeof e.index === 'undefined') {307console.error("Failed to generate test result.");308throw e;309}310tree = errorToObject(e);311tree.description = e.description;312tree = JSON.stringify(tree);313fileName = testCase.key + ".failure.json";314}315require('fs').writeFileSync(fileName, tree);316console.error("Done.");317}318319if (typeof window === 'undefined') {320(function () {321'use strict';322323var esprima = require('../esprima'),324vm = require('vm'),325fs = require('fs'),326diff = require('json-diff').diffString,327total = 0,328result,329failures = [],330cases = {},331context = {source: '', result: null},332tick = new Date(),333expected,334testCase,335header;336337function enumerateFixtures(root) {338var dirs = fs.readdirSync(root), key, kind,339kinds = ['case', 'source', 'run', 'tree', 'tokens', 'failure', 'result'],340suffices = ['js', 'js', 'js', 'json', 'json', 'json', 'json'];341342dirs.forEach(function (item) {343var i;344if (fs.statSync(root + '/' + item).isDirectory()) {345enumerateFixtures(root + '/' + item);346} else {347kind = 'case';348key = item.slice(0, -3);349for (i = 1; i < kinds.length; i++) {350var suffix = '.' + kinds[i] + '.' + suffices[i];351if (item.slice(-suffix.length) === suffix) {352key = item.slice(0, -suffix.length);353kind = kinds[i];354}355}356key = root + '/' + key;357if (!cases[key]) {358total++;359cases[key] = { key: key };360}361cases[key][kind] = fs.readFileSync(root + '/' + item, 'utf-8');362}363});364}365366enumerateFixtures(__dirname + '/fixtures');367368for (var key in cases) {369if (cases.hasOwnProperty(key)) {370testCase = cases[key];371372if (testCase.hasOwnProperty('source')) {373testCase.case = eval(testCase.source + ';source');374}375376try {377if (testCase.hasOwnProperty('tree')) {378testParse(esprima, testCase.case, JSON.parse(testCase.tree));379} else if (testCase.hasOwnProperty('tokens')) {380testTokenize(esprima, testCase.case, JSON.parse(testCase.tokens));381} else if (testCase.hasOwnProperty('failure')) {382testError(esprima, testCase.case, JSON.parse(testCase.failure));383} else if (testCase.hasOwnProperty('result')) {384testAPI(esprima, testCase.run, JSON.parse(testCase.result));385} else {386console.error('Incomplete test case:' + testCase.key + '. Generating test result...');387generateTestCase(esprima, testCase);388}389} catch (e) {390if (!e.expected) {391throw e;392}393e.source = testCase.case || testCase.key;394failures.push(e);395}396}397}398399tick = (new Date()) - tick;400401header = total + ' tests. ' + failures.length + ' failures. ' +402tick + ' ms';403if (failures.length) {404console.error(header);405failures.forEach(function (failure) {406try {407var expectedObject = JSON.parse(failure.expected);408var actualObject = JSON.parse(failure.actual);409410console.error(failure.source + ': Expected\n ' +411failure.expected.split('\n').join('\n ') +412'\nto match\n ' + failure.actual + '\nDiff:\n' +413diff(expectedObject, actualObject));414} catch (ex) {415console.error(failure.source + ': Expected\n ' +416failure.expected.split('\n').join('\n ') +417'\nto match\n ' + failure.actual);418}419});420} else {421console.log(header);422}423process.exit(failures.length === 0 ? 0 : 1);424}());425}426427428