mirror of
https://github.com/tc39/test262.git
synced 2025-05-04 15:00:42 +02:00
* [javascriptcore-test262-automation] changes from git@github.com:WebKit/webkit.git at sha 949e26452cfa153a7f4afe593da97e2fe9e1b706 on Tue Jul 03 2018 14:35:15 GMT-0400 (Eastern Daylight Time)
345 lines
9.4 KiB
JavaScript
345 lines
9.4 KiB
JavaScript
/*
|
|
* Copyright 2017 WebAssembly Community Group participants
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
let testNum = (function() {
|
|
let count = 1;
|
|
return function() {
|
|
return `#${count++} `;
|
|
}
|
|
})();
|
|
|
|
// WPT's assert_throw uses a list of predefined, hardcoded known errors. Since
|
|
// it is not aware of the WebAssembly error types (yet), implement our own
|
|
// version.
|
|
function assertThrows(func, err) {
|
|
let caught = false;
|
|
try {
|
|
func();
|
|
} catch(e) {
|
|
assert_true(e instanceof err, `expected ${err.name}, observed ${e.constructor.name}`);
|
|
caught = true;
|
|
}
|
|
assert_true(caught, testNum() + "assertThrows must catch any error.")
|
|
}
|
|
|
|
/******************************************************************************
|
|
***************************** WAST HARNESS ************************************
|
|
******************************************************************************/
|
|
|
|
// For assertions internal to our test harness.
|
|
function _assert(x) {
|
|
if (!x) {
|
|
throw new Error(`Assertion failure: ${x}`);
|
|
}
|
|
}
|
|
|
|
// A simple sum type that can either be a valid Value or an Error.
|
|
function Result(type, maybeValue) {
|
|
this.value = maybeValue;
|
|
this.type = type;
|
|
};
|
|
|
|
Result.VALUE = 'VALUE';
|
|
Result.ERROR = 'ERROR';
|
|
|
|
function ValueResult(val) { return new Result(Result.VALUE, val); }
|
|
function ErrorResult(err) { return new Result(Result.ERROR, err); }
|
|
|
|
Result.prototype.isError = function() { return this.type === Result.ERROR; }
|
|
|
|
const EXPECT_INVALID = false;
|
|
|
|
/* DATA **********************************************************************/
|
|
|
|
let soft_validate = true;
|
|
|
|
let $$;
|
|
|
|
// Default imports.
|
|
var registry = {};
|
|
|
|
// Resets the registry between two different WPT tests.
|
|
function reinitializeRegistry() {
|
|
if (typeof WebAssembly === 'undefined')
|
|
return;
|
|
|
|
registry = {
|
|
spectest: {
|
|
print: print,
|
|
global: 666,
|
|
table: new WebAssembly.Table({initial: 10, maximum: 20, element: 'anyfunc'}),
|
|
memory: new WebAssembly.Memory({initial: 1, maximum: 2})
|
|
}
|
|
};
|
|
}
|
|
|
|
reinitializeRegistry();
|
|
|
|
/* WAST POLYFILL *************************************************************/
|
|
|
|
function binary(bytes) {
|
|
let buffer = new ArrayBuffer(bytes.length);
|
|
let view = new Uint8Array(buffer);
|
|
for (let i = 0; i < bytes.length; ++i) {
|
|
view[i] = bytes.charCodeAt(i);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
/**
|
|
* Returns a compiled module, or throws if there was an error at compilation.
|
|
*/
|
|
function module(bytes, valid = true) {
|
|
let buffer = binary(bytes);
|
|
let validated;
|
|
|
|
try {
|
|
validated = WebAssembly.validate(buffer);
|
|
} catch (e) {
|
|
throw new Error(`WebAssembly.validate throws ${typeof e}: ${e}${e.stack}`);
|
|
}
|
|
|
|
if (validated !== valid) {
|
|
// Try to get a more precise error message from the WebAssembly.CompileError.
|
|
let err = '';
|
|
try {
|
|
new WebAssembly.Module(buffer);
|
|
} catch (e) {
|
|
if (e instanceof WebAssembly.CompileError)
|
|
throw new WebAssembly.CompileError(`WebAssembly.validate error: ${e.toString()}${e.stack}\n`);
|
|
else
|
|
throw new Error(`WebAssembly.validate throws ${typeof e}: ${e}${e.stack}`);
|
|
}
|
|
throw new Error(`WebAssembly.validate was expected to fail, but didn't`);
|
|
}
|
|
|
|
let module;
|
|
try {
|
|
module = new WebAssembly.Module(buffer);
|
|
} catch(e) {
|
|
if (valid)
|
|
throw new Error('WebAssembly.Module ctor unexpectedly throws ${typeof e}: ${e}${e.stack}');
|
|
throw e;
|
|
}
|
|
|
|
return module;
|
|
}
|
|
|
|
function uniqueTest(func, desc) {
|
|
test(func, testNum() + desc);
|
|
}
|
|
|
|
function assert_invalid(bytes) {
|
|
uniqueTest(() => {
|
|
try {
|
|
module(bytes, /* valid */ false);
|
|
throw new Error('did not fail');
|
|
} catch(e) {
|
|
assert_true(e instanceof WebAssembly.CompileError, "expected invalid failure:");
|
|
}
|
|
}, "A wast module that should be invalid or malformed.");
|
|
}
|
|
|
|
const assert_malformed = assert_invalid;
|
|
|
|
function assert_soft_invalid(bytes) {
|
|
uniqueTest(() => {
|
|
try {
|
|
module(bytes, /* valid */ soft_validate);
|
|
if (soft_validate)
|
|
throw new Error('did not fail');
|
|
} catch(e) {
|
|
if (soft_validate)
|
|
assert_true(e instanceof WebAssembly.CompileError, "expected soft invalid failure:");
|
|
}
|
|
}, "A wast module that *could* be invalid under certain engines.");
|
|
}
|
|
|
|
function instance(bytes, imports = registry, valid = true) {
|
|
if (imports instanceof Result) {
|
|
if (imports.isError())
|
|
return imports;
|
|
imports = imports.value;
|
|
}
|
|
|
|
let err = null;
|
|
|
|
let m, i;
|
|
try {
|
|
let m = module(bytes);
|
|
i = new WebAssembly.Instance(m, imports);
|
|
} catch(e) {
|
|
err = e;
|
|
}
|
|
|
|
if (valid) {
|
|
uniqueTest(() => {
|
|
let instantiated = err === null;
|
|
assert_true(instantiated, err);
|
|
}, "module successfully instantiated");
|
|
}
|
|
|
|
return err !== null ? ErrorResult(err) : ValueResult(i);
|
|
}
|
|
|
|
function register(name, instance) {
|
|
_assert(instance instanceof Result);
|
|
|
|
if (instance.isError())
|
|
return;
|
|
|
|
registry[name] = instance.value.exports;
|
|
}
|
|
|
|
function call(instance, name, args) {
|
|
_assert(instance instanceof Result);
|
|
|
|
if (instance.isError())
|
|
return instance;
|
|
|
|
let err = null;
|
|
let result;
|
|
try {
|
|
result = instance.value.exports[name](...args);
|
|
} catch(e) {
|
|
err = e;
|
|
}
|
|
|
|
return err !== null ? ErrorResult(err) : ValueResult(result);
|
|
};
|
|
|
|
function get(instance, name) {
|
|
_assert(instance instanceof Result);
|
|
|
|
if (instance.isError())
|
|
return instance;
|
|
|
|
return ValueResult(instance.value.exports[name]);
|
|
}
|
|
|
|
function exports(name, instance) {
|
|
_assert(instance instanceof Result);
|
|
|
|
if (instance.isError())
|
|
return instance;
|
|
|
|
return ValueResult({ [name]: instance.value.exports });
|
|
}
|
|
|
|
function run(action) {
|
|
let result = action();
|
|
|
|
_assert(result instanceof Result);
|
|
|
|
uniqueTest(() => {
|
|
if (result.isError())
|
|
throw result.value;
|
|
}, "A wast test that runs without any special assertion.");
|
|
}
|
|
|
|
function assert_unlinkable(bytes) {
|
|
let result = instance(bytes, registry, EXPECT_INVALID);
|
|
|
|
_assert(result instanceof Result);
|
|
|
|
uniqueTest(() => {
|
|
assert_true(result.isError(), 'expected error result');
|
|
if (result.isError()) {
|
|
let e = result.value;
|
|
assert_true(e instanceof WebAssembly.LinkError, `expected link error, observed ${e}:`);
|
|
}
|
|
}, "A wast module that is unlinkable.");
|
|
}
|
|
|
|
function assert_uninstantiable(bytes) {
|
|
let result = instance(bytes, registry, EXPECT_INVALID);
|
|
|
|
_assert(result instanceof Result);
|
|
|
|
uniqueTest(() => {
|
|
assert_true(result.isError(), 'expected error result');
|
|
if (result.isError()) {
|
|
let e = result.value;
|
|
assert_true(e instanceof WebAssembly.RuntimeError, `expected runtime error, observed ${e}:`);
|
|
}
|
|
}, "A wast module that is uninstantiable.");
|
|
}
|
|
|
|
function assert_trap(action) {
|
|
let result = action();
|
|
|
|
_assert(result instanceof Result);
|
|
|
|
uniqueTest(() => {
|
|
assert_true(result.isError(), 'expected error result');
|
|
if (result.isError()) {
|
|
let e = result.value;
|
|
assert_true(e instanceof WebAssembly.RuntimeError, `expected runtime error, observed ${e}:`);
|
|
}
|
|
}, "A wast module that must trap at runtime.");
|
|
}
|
|
|
|
let StackOverflow;
|
|
try { (function f() { 1 + f() })() } catch (e) { StackOverflow = e.constructor }
|
|
|
|
function assert_exhaustion(action) {
|
|
let result = action();
|
|
|
|
_assert(result instanceof Result);
|
|
|
|
uniqueTest(() => {
|
|
assert_true(result.isError(), 'expected error result');
|
|
if (result.isError()) {
|
|
let e = result.value;
|
|
assert_true(e instanceof StackOverflow, `expected stack overflow error, observed ${e}:`);
|
|
}
|
|
}, "A wast module that must exhaust the stack space.");
|
|
}
|
|
|
|
function assert_return(action, expected) {
|
|
if (expected instanceof Result) {
|
|
if (expected.isError())
|
|
return;
|
|
expected = expected.value;
|
|
}
|
|
|
|
let result = action();
|
|
|
|
_assert(result instanceof Result);
|
|
|
|
uniqueTest(() => {
|
|
assert_true(!result.isError(), `expected success result, got: ${result.value}.`);
|
|
if (!result.isError()) {
|
|
assert_equals(result.value, expected);
|
|
};
|
|
}, "A wast module that must return a particular value.");
|
|
};
|
|
|
|
function assert_return_nan(action) {
|
|
let result = action();
|
|
|
|
_assert(result instanceof Result);
|
|
|
|
uniqueTest(() => {
|
|
assert_true(!result.isError(), 'expected success result');
|
|
if (!result.isError()) {
|
|
assert_true(Number.isNaN(result.value), `expected NaN, observed ${result.value}.`);
|
|
};
|
|
}, "A wast module that must return NaN.");
|
|
}
|