Commit d8ac28e9 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Test more error messages

Extend the errors.js mjsunit test to also check for the message in the
generated errors. This will help catch bugs later, e.g. when
refactoring the way we output errors:
https://chromium-review.googlesource.com/c/565282

Drive-by 1: Fix a superfluous period in one error message.
Drive-by 2: Fix a weird exception catching construct in the test.

R=titzer@chromium.org

Change-Id: I1c2e92fb2c34a481cbf8802153f8502452d45348
Reviewed-on: https://chromium-review.googlesource.com/582960Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46858}
parent 7924985f
......@@ -639,13 +639,13 @@ class WasmFullDecoder : public WasmDecoder {
if (control_.size() > 1) {
error(control_.back().pc, "unterminated control structure");
} else {
error("function body must end with \"end\" opcode.");
error("function body must end with \"end\" opcode");
}
return TraceFailed();
}
if (!last_end_found_) {
error("function body must end with \"end\" opcode.");
error("function body must end with \"end\" opcode");
return false;
}
......
......@@ -486,9 +486,9 @@ var failWithMessage;
assertDoesNotThrow = function assertDoesNotThrow(code, name_opt) {
try {
if (typeof code === 'function') {
code();
return code();
} else {
eval(code);
return eval(code);
}
} catch (e) {
failWithMessage("threw an exception: " + (e.message || e));
......
......@@ -27,18 +27,8 @@ function instance(bytes, imports = {}) {
// instantiate should succeed but run should fail.
function instantiateAndFailAtRuntime(bytes, imports = {}) {
var instance = undefined;
try {
instance = new WebAssembly.Instance(module(bytes), imports);
} catch(e) {
// If we fail at startup.
if (e instanceof WebAssembly.RuntimeError) {
throw e;
}
// Swallow other instantiation errors because we expect instantiation
// to succeed but runtime to fail.
return;
}
var instance =
assertDoesNotThrow(new WebAssembly.Instance(module(bytes), imports));
instance.exports.run();
}
......@@ -46,59 +36,65 @@ function builder() {
return new WasmModuleBuilder;
}
function assertCompileError(bytes) {
assertThrows(() => module(bytes), WebAssembly.CompileError);
function assertCompileError(bytes, msg) {
assertThrows(() => module(bytes), WebAssembly.CompileError, msg);
}
// default imports to {} so we get LinkError by default, thus allowing us to
// distinguish the TypeError we want to catch
function assertTypeError(bytes, imports = {}) {
assertThrows(() => instance(bytes, imports), TypeError);
function assertTypeError(bytes, imports = {}, msg) {
assertThrows(() => instance(bytes, imports), TypeError, msg);
}
function assertLinkError(bytes, imports) {
assertThrows(() => instance(bytes, imports), WebAssembly.LinkError);
function assertLinkError(bytes, imports, msg) {
assertThrows(() => instance(bytes, imports), WebAssembly.LinkError, msg);
}
function assertRuntimeError(bytes, imports) {
assertThrows(() => instantiateAndFailAtRuntime(bytes, imports),
WebAssembly.RuntimeError);
function assertRuntimeError(bytes, imports, msg) {
assertThrows(
() => instantiateAndFailAtRuntime(bytes, imports),
WebAssembly.RuntimeError, msg);
}
function assertConversionError(bytes, imports) {
assertThrows(() => instantiateAndFailAtRuntime(bytes, imports), TypeError);
function assertConversionError(bytes, imports, msg) {
assertThrows(
() => instantiateAndFailAtRuntime(bytes, imports), TypeError, msg);
}
(function TestDecodingError() {
assertCompileError("");
assertCompileError("X");
assertCompileError("\0x00asm");
assertCompileError("", /is empty/);
assertCompileError("X", /expected 4 bytes, fell off end @\+0/);
assertCompileError(
"\0x00asm", /expected magic word 00 61 73 6d, found 00 78 30 30 @\+0/);
})();
(function TestValidationError() {
assertCompileError(builder().addFunction("f", kSig_i_v).end().toBuffer());
assertCompileError(
builder().addFunction("f", kSig_i_v).end().toBuffer(),
/function body must end with "end" opcode @/);
assertCompileError(builder().addFunction("f", kSig_i_v).addBody([
kExprReturn
]).end().toBuffer());
]).end().toBuffer(), /return found empty stack @/);
assertCompileError(builder().addFunction("f", kSig_v_v).addBody([
kExprGetLocal, 0
]).end().toBuffer());
assertCompileError(builder().addStart(0).toBuffer());
]).end().toBuffer(), /invalid local index: 0 @/);
assertCompileError(
builder().addStart(0).toBuffer(), /function index 0 out of bounds/);
})();
(function TestTypeError() {
let b;
b = builder();
b.addImport("foo", "bar", kSig_v_v);
assertTypeError(b.toBuffer(), {});
assertTypeError(b.toBuffer(), {}, /module is not an object or function/);
b = builder();
b.addImportedGlobal("foo", "bar", kWasmI32);
assertTypeError(b.toBuffer(), {});
assertTypeError(b.toBuffer(), {}, /module is not an object or function/);
b = builder();
b.addImportedMemory("foo", "bar");
assertTypeError(b.toBuffer(), {});
assertTypeError(b.toBuffer(), {}, /module is not an object or function/);
})();
(function TestLinkingError() {
......@@ -106,53 +102,60 @@ function assertConversionError(bytes, imports) {
b = builder();
b.addImport("foo", "bar", kSig_v_v);
assertLinkError(b.toBuffer(), {foo: {}});
assertLinkError(
b.toBuffer(), {foo: {}}, /function import requires a callable/);
b = builder();
b.addImport("foo", "bar", kSig_v_v);
assertLinkError(b.toBuffer(), {foo: {bar: 9}});
assertLinkError(
b.toBuffer(), {foo: {bar: 9}}, /function import requires a callable/);
b = builder();
b.addImportedGlobal("foo", "bar", kWasmI32);
assertLinkError(b.toBuffer(), {foo: {}});
assertLinkError(b.toBuffer(), {foo: {}}, /global import must be a number/);
b = builder();
b.addImportedGlobal("foo", "bar", kWasmI32);
assertLinkError(b.toBuffer(), {foo: {bar: ""}});
assertLinkError(
b.toBuffer(), {foo: {bar: ""}}, /global import must be a number/);
b = builder();
b.addImportedGlobal("foo", "bar", kWasmI32);
assertLinkError(b.toBuffer(), {foo: {bar: () => 9}});
assertLinkError(
b.toBuffer(), {foo: {bar: () => 9}}, /global import must be a number/);
b = builder();
b.addImportedMemory("foo", "bar");
assertLinkError(b.toBuffer(), {foo: {}});
assertLinkError(
b.toBuffer(), {foo: {}},
/memory import must be a WebAssembly\.Memory object/);
b = builder();
b.addImportedMemory("foo", "bar", 1);
assertLinkError(b.toBuffer(),
{foo: {bar: () => new WebAssembly.Memory({initial: 0})}});
assertLinkError(
b.toBuffer(), {foo: {bar: () => new WebAssembly.Memory({initial: 0})}},
/memory import must be a WebAssembly\.Memory object/);
b = builder();
b.addFunction("startup", kSig_v_v).addBody([
kExprUnreachable,
]).end().addStart(0);
assertRuntimeError(b.toBuffer());
assertRuntimeError(b.toBuffer(), {}, "unreachable");
})();
(function TestTrapError() {
assertRuntimeError(builder().addFunction("run", kSig_v_v).addBody([
kExprUnreachable
]).exportFunc().end().toBuffer());
]).exportFunc().end().toBuffer(), {}, "unreachable");
assertRuntimeError(builder().addFunction("run", kSig_v_v).addBody([
kExprI32Const, 1,
kExprI32Const, 0,
kExprI32DivS,
kExprDrop
]).exportFunc().end().toBuffer());
]).exportFunc().end().toBuffer(), {}, "divide by zero");
assertRuntimeError(builder().addFunction("run", kSig_v_v).addBody([
]).exportFunc().end().
addFunction("start", kSig_v_v).addBody([
kExprUnreachable
]).end().addStart(1).toBuffer());
assertRuntimeError(builder().
addFunction("run", kSig_v_v).addBody([]).exportFunc().end().
addFunction("start", kSig_v_v).addBody([kExprUnreachable]).end().
addStart(1).toBuffer(),
{}, "unreachable");
})();
(function TestConversionError() {
......@@ -160,10 +163,10 @@ function assertConversionError(bytes, imports) {
b.addImport("foo", "bar", kSig_v_l);
assertConversionError(b.addFunction("run", kSig_v_v).addBody([
kExprI64Const, 0, kExprCallFunction, 0
]).exportFunc().end().toBuffer(), {foo:{bar: (l)=>{}}});
]).exportFunc().end().toBuffer(), {foo:{bar: (l)=>{}}}, "invalid type");
b = builder()
assertConversionError(builder().addFunction("run", kSig_l_v).addBody([
kExprI64Const, 0
]).exportFunc().end().toBuffer());
]).exportFunc().end().toBuffer(), {}, "invalid type");
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment