blob: 44cd9737404ee8ae433c71290ace9a09711c903f [file] [log] [blame]
import * as assert from '../assert.js'
import Builder from '../Builder.js'
const verbose = false;
const numFunctions = 2;
const maxParams = 32;
// This test starts running with a few bytes of executable memory available. Try
// to create and instantiate modules which have way more imports than anything
// else. Hopefully they'll fail when trying to instantiate their entrypoints.
const type = () => {
const types = ["i32", "f32", "f64"];
return types[(Math.random() * types.length) | 0];
};
const params = () => {
let p = [];
let count = (Math.random() * maxParams) | 0;
while (count--)
p.push(type());
return p;
};
const randomProgram = () => {
let b = new Builder()
.Type().End()
.Import();
const ps = params();
for (let f = 0; f < numFunctions; ++f)
b = b.Function("imp", `${f}`, { params: ps });
b = b.End()
.Function().End()
.Export();
for (let f = 0; f < numFunctions; ++f)
b = b.Function(`call${f}`);
b = b.End()
.Code();
for (let f = 0; f < numFunctions; ++f) {
b = b.Function(`call${f}`, { params: ps });
for (let p = 0; p < ps.length; ++p)
b = b.GetLocal(p);
b = b.Call(f).End();
}
b = b.End();
return b.WebAssembly().get();
}
let failCount = 0;
let callCount = 0;
let instances = [];
let imports = [];
for (let f = 0; f < numFunctions; ++f)
imports.push((...args) => {
if (verbose)
print(`Invoked ${f} with: ${args}`);
++callCount;
});
const invoke = instance => {
let result = 0;
for (let f = 0; f < numFunctions; ++f) {
const name = `call${f}`;
if (verbose)
print(`Invoking ${name}`);
result += instance.exports[name]();
}
return result;
};
while (failCount === 0) {
if (verbose)
print(`Trying...`);
const buf = randomProgram();
let module;
try {
module = new WebAssembly.Module(buf);
} catch (e) {
if (e instanceof WebAssembly.CompileError) {
if (verbose)
print(`Caught: ${e}`);
++failCount;
}
else
throw new Error(`Expected a WebAssembly.CompileError, got ${e}`);
}
if (module !== undefined) {
if (verbose)
print(`Creating instance`);
let instance;
try {
instance = new WebAssembly.Instance(module, { imp: imports });
} catch (e) {
if (e instanceof WebAssembly.LinkError) {
if (verbose)
print(`Caught: ${e}`);
++failCount;
}
else
throw new Error(`Expected a WebAssembly.LinkError, got ${e}`);
}
if (instance !== undefined) {
instances.push(instance);
invoke(instance);
}
}
}
if (callCount === 0)
throw new Error(`Expected to be able to allocate a WebAssembly module, instantiate it, and call its exports at least once`);
// Make sure we can still call all the instances we create, even after going OOM.
if (verbose)
print(`Invoking all previously created instances`);
for (let instance of instances)
invoke(instance);