Skip to content

Commit 80a8edb

Browse files
committed
Add test262 test cases.
This currently only works on node, and only runs Promise-related test cases. It could be generalized to run a larger subset of the ES2015 test cases, and to not fail horribly when run in a browser.
1 parent 3d5bc93 commit 80a8edb

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@
8080
"mocha": "^2.3.4",
8181
"promises-aplus-tests": "^2.1.1",
8282
"promises-es6-tests": "^0.5.0",
83+
"test262": "git://github.com/cscott/test262.git#master",
84+
"test262-parser": "git://github.com/cscott/test262-parser.git#gh-11",
8385
"uglify-js": "^2.6.1",
8486
"evalmd": "^0.0.16"
8587
}

test/test262.js

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/* global describe, it, assert, require, __dirname */
2+
3+
var fs = require('fs');
4+
var path = require('path');
5+
var parser = require('test262-parser');
6+
var glob = require('glob');
7+
8+
var BASEDIR = path.resolve(__dirname, '../node_modules/test262/test');
9+
var TESTS = 'built-ins/Promise/**/*.js';
10+
11+
var BLACKLIST = [
12+
// These tests mutate the global state.
13+
'built-ins/Promise/all/does-not-invoke-array-setters.js',
14+
'built-ins/Promise/all/invoke-resolve.js',
15+
'built-ins/Promise/all/invoke-resolve-get-error.js',
16+
'built-ins/Promise/all/iter-close.js',
17+
'built-ins/Promise/race/invoke-resolve.js',
18+
'built-ins/Promise/race/invoke-resolve-get-error.js',
19+
// These tests reflect a v8 bug (anonymous functions shouldn't have
20+
// an 'own' name property).
21+
'built-ins/Promise/all/resolve-element-function-name.js',
22+
'built-ins/Promise/executor-function-name.js',
23+
'built-ins/Promise/reject-function-name.js',
24+
'built-ins/Promise/resolve-function-name.js',
25+
// These tests require unshimmable ES6 "construct" semantics.
26+
'built-ins/Promise/all/resolve-element-function-nonconstructor.js',
27+
'built-ins/Promise/executor-function-nonconstructor.js',
28+
'built-ins/Promise/reject-function-nonconstructor.js',
29+
'built-ins/Promise/resolve-function-nonconstructor.js',
30+
// The es6-shim package can't assign `catch` as a function name without
31+
// breaking compatibility with pre-ES5 code.
32+
'built-ins/Promise/prototype/catch/name.js'
33+
];
34+
// Node 0.10 doesn't set the descriptor correctly for 'name' and 'length'
35+
// properties of functions. There's not much we can do about it, other
36+
// than skip those tests.
37+
if (!Object.getOwnPropertyDescriptor(function f() {}, 'length').configurable) {
38+
BLACKLIST.push(
39+
'built-ins/Promise/all/length.js',
40+
'built-ins/Promise/all/name.js',
41+
'built-ins/Promise/all/resolve-element-function-length.js',
42+
'built-ins/Promise/executor-function-length.js',
43+
'built-ins/Promise/length.js',
44+
'built-ins/Promise/name.js',
45+
'built-ins/Promise/prototype/catch/length.js',
46+
'built-ins/Promise/prototype/catch/name.js',
47+
'built-ins/Promise/prototype/then/length.js',
48+
'built-ins/Promise/prototype/then/name.js',
49+
'built-ins/Promise/race/length.js',
50+
'built-ins/Promise/race/name.js',
51+
'built-ins/Promise/reject-function-length.js',
52+
'built-ins/Promise/reject/length.js',
53+
'built-ins/Promise/reject/name.js',
54+
'built-ins/Promise/resolve-function-length.js',
55+
'built-ins/Promise/resolve/length.js',
56+
'built-ins/Promise/resolve/name.js'
57+
);
58+
// There are similar bugs with Object.isExtensible
59+
BLACKLIST.push(
60+
'built-ins/Promise/all/resolve-element-function-extensible.js',
61+
'built-ins/Promise/executor-function-extensible.js',
62+
'built-ins/Promise/reject-function-extensible.js',
63+
'built-ins/Promise/resolve-function-extensible.js'
64+
);
65+
}
66+
67+
describe('test262', function (done) {
68+
/* jshint evil:true */ // It doesn't like the `eval`s here.
69+
'use strict';
70+
71+
var $ERROR = function (msg) { throw new Error(msg); };
72+
var test262assert = new Function(
73+
'$ERROR',
74+
fs.readFileSync(path.join(BASEDIR, '../harness/assert.js'), 'utf8') +
75+
'\n return assert;'
76+
)($ERROR);
77+
var setPrototypeOf = Object.setPrototypeOf || function (o, p) {
78+
/* jshint proto:true */
79+
o.__proto__ = p;
80+
};
81+
var Test262Error = function Test262Error(msg) {
82+
var self = new Error(msg);
83+
setPrototypeOf(self, Test262Error.prototype);
84+
return self;
85+
};
86+
setPrototypeOf(Test262Error, Error);
87+
Test262Error.prototype = Object.create(Error.prototype);
88+
Test262Error.prototype.constructor = Test262Error;
89+
90+
var eachFile = function (filename) {
91+
var shortName = path.relative(BASEDIR, filename);
92+
describe(shortName, function () {
93+
var file = parser.parseFile({
94+
file: filename,
95+
contents: fs.readFileSync(filename, 'utf8')
96+
});
97+
assert(file.copyright || file.isATest, file);
98+
var desc = file.attrs.description || '<no description>';
99+
var includes = file.attrs.includes || [];
100+
var features = file.attrs.features || [];
101+
var flags = file.attrs.flags || {};
102+
var prologue = flags.noStrict ? '' : "'use strict';\n";
103+
var itit = it;
104+
if (BLACKLIST.indexOf(shortName) >= 0) { itit = it.skip; }
105+
if (features.indexOf('class') >= 0) { itit = it.skip; }
106+
var usesSymbol = features.filter(function (f) {
107+
return /^Symbol/.test(f);
108+
}).length > 0;
109+
// Node 0.10 compatibility
110+
if (typeof Symbol === 'undefined' && usesSymbol) { itit = it.skip; }
111+
// Node doesn't yet have these symbols
112+
if (features.indexOf('Symbol.species') >= 0) { itit = it.skip; }
113+
if (features.indexOf('Symbol.toStringTag') >= 0) { itit = it.skip; }
114+
includes.forEach(function (f) {
115+
prologue +=
116+
fs.readFileSync(path.join(BASEDIR, '../harness', f), 'utf8');
117+
});
118+
119+
var runOne = function (done) {
120+
var body = new Function(
121+
'assert', '$ERROR', 'Test262Error', 'Promise', '$DONE',
122+
prologue + file.contents
123+
);
124+
var P = Promise;
125+
var res = Promise.resolve;
126+
var rej = Promise.reject;
127+
var check = function () {
128+
// Verify that this test case didn't stomp on the Promise object.
129+
assert(P === Promise);
130+
assert(res === Promise.resolve);
131+
assert(rej === Promise.reject);
132+
};
133+
var checkAsync = function (cb) {
134+
try { check(); } catch (e) { return cb(e); }
135+
cb();
136+
};
137+
if (done) {
138+
// Execute async test:
139+
body(test262assert, $ERROR, Test262Error, Promise, function (err) {
140+
if (err) { done(err); } else { checkAsync(done); }
141+
});
142+
} else {
143+
// Execute sync test:
144+
body(test262assert, $ERROR, Test262Error, Promise);
145+
check();
146+
}
147+
};
148+
// Mocha uses the # of declared args of the function to determine
149+
// whether or not to execute the test async.
150+
if (file.async) {
151+
itit(desc, function (done) { runOne(done); });
152+
} else {
153+
itit(desc, function () { runOne(); });
154+
}
155+
});
156+
};
157+
glob.sync(path.join(BASEDIR, TESTS)).forEach(eachFile);
158+
});

0 commit comments

Comments
 (0)