Skip to content

Commit

Permalink
feat: new test runner WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
xtuc committed Sep 26, 2018
1 parent 4f15370 commit 16b8604
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -61,3 +61,5 @@ lib/
esm/

package-lock.json

wasm_test_dir
18 changes: 18 additions & 0 deletions packages/helper-testsuite-runner/package.json
@@ -0,0 +1,18 @@
{
"name": "@webassemblyjs/helper-testsuite-runner",
"version": "1.7.8",
"description": "",
"main": "lib/index.js",
"module": "esm/index.js",
"license": "MIT",
"devDependencies": {
"mamacro": "^0.0.3",
"webassemblyjs": "1.7.8"
},
"publishConfig": {
"access": "public"
},
"bin": {
"webassemblyjs-testsuite-runner": "lib/cli.js"
}
}
32 changes: 32 additions & 0 deletions packages/helper-testsuite-runner/src/asserts.js
@@ -0,0 +1,32 @@
// @flow

import { assert } from "mamacro";

// assert action has expected results
// ( assert_return <action> <expr>* )

// action:
// ( invoke <name>? <string> <expr>* ) ;; invoke function export
// ( get <name>? <string> ) ;; get global export

export function assert_return(
instance: Instance,
action: Object,
expected: Object
) {
const { type, field, args } = action;

assert(type === "invoke");

const fn = instance.exports[field];
assert(typeof fn === "function", `function ${field} not found`);

const res = fn(...args.map(x => x.value));

// check type
assert(res.type === expected[0].type);

console.log(res, expected[0].value);
// check value
assert(res.value.toString() === expected[0].value);
}
3 changes: 3 additions & 0 deletions packages/helper-testsuite-runner/src/cli.js
@@ -0,0 +1,3 @@
#!/usr/bin/env node

require("./index.js").default(process.argv[2]);
114 changes: 114 additions & 0 deletions packages/helper-testsuite-runner/src/index.js
@@ -0,0 +1,114 @@
// @flow

import { assert } from "mamacro";
import { execSync } from "child_process";
import { basename, join } from "path";
import { existsSync, mkdirSync, readFileSync } from "fs";
import { decode } from "@webassemblyjs/wasm-parser";
import { parse } from "@webassemblyjs/wast-parser";
import { createCompiledModule } from "webassemblyjs/lib/compiler/compile/module";
import { Instance } from "webassemblyjs/lib/interpreter";

import { assert_return } from "./asserts";

const WASM_TEST_DIR = "./wasm_test_dir";

function getModuleName(command: Command): string {
return command.name || "__default";
}

type Command = {
name?: string,
filename?: string,
type: string,
module_type: "text" | "binary",
action?: Object,
expected?: Object
};

type Manifest = {
source_filename: string,
commands: Array<Command>
};

export default function run(filename: string) {
assert(typeof filename === "string", "please specify a filename");

if (existsSync(WASM_TEST_DIR) === false) {
mkdirSync(WASM_TEST_DIR);
}

// generate wasm files

const out = basename(filename);
const manifestOut = join(WASM_TEST_DIR, out + ".json");

execSync(`wast2json ${filename} -o ${manifestOut}`);

// run tests

const manifest: Manifest = JSON.parse(readFileSync(manifestOut, "utf8"));

const instances = {};

manifest.commands.forEach(command => {
console.log(command);

switch (command.type) {
case "module": {
// $FlowIgnore
instances[getModuleName(command)] = loadModule(
"binary",
command.filename
);
break;
}

case "assert_return": {
assert(instances[getModuleName(command)] !== undefined);

assert_return(
instances[getModuleName(command)],
command.action,
command.expected
);
break;
}

default:
throw new Error("unknown command: " + command.type);
}
});
}

function loadModule(type: string, filename: string): Instance {
const internalInstanceOptions = {
checkForI64InSignature: false,
returnStackLocal: true
};

const importObject = {
_internalInstanceOptions: internalInstanceOptions
};

if (type === "text") {
const content = readFileSync(join(WASM_TEST_DIR, filename), "utf8");

// we need a module in order to be compiled
const ast = parse("(module " + content + ")");

// TODO(sven): pass fakeCompiler here?
const module = createCompiledModule(ast);

return new Instance(module, importObject);
} else if (type === "binary") {
// $FlowIgnore
const buff = readFileSync(join(WASM_TEST_DIR, filename), null);

const ast = decode(buff);
const module = createCompiledModule(ast);
return new Instance(module, importObject);
} else {
throw new Error("unsupported module type: " + type);
}
}

0 comments on commit 16b8604

Please sign in to comment.