mirror of
https://github.com/fluencelabs/asmble
synced 2025-04-24 22:32:19 +00:00
Cleanup and ability to run all but a couple of the spec tests
This commit is contained in:
parent
9a1090c439
commit
b37bc44c50
@ -114,11 +114,17 @@ open class InsnReworker {
|
||||
}
|
||||
if (count == 0) return inject(stackManips.size)
|
||||
var countSoFar = 0
|
||||
var foundUnconditionalJump = false
|
||||
for ((amountChanged, insnIndex) in stackManips.asReversed()) {
|
||||
countSoFar += amountChanged
|
||||
if (!foundUnconditionalJump) foundUnconditionalJump = insns[insnIndex].let { insn ->
|
||||
insn is Node.Instr.Br || insn is Node.Instr.BrTable ||
|
||||
insn is Node.Instr.Unreachable || insn is Node.Instr.Return
|
||||
}
|
||||
if (countSoFar == count) return inject(insnIndex)
|
||||
}
|
||||
throw CompileErr.StackInjectionMismatch(count, insn)
|
||||
// Only consider it a failure if we didn't hit any unconditional jumps
|
||||
if (!foundUnconditionalJump) throw CompileErr.StackInjectionMismatch(count, insn)
|
||||
}
|
||||
|
||||
// Go over each insn, determining where to inject
|
||||
|
@ -17,6 +17,12 @@ class SpecTestUnit(val name: String, val wast: String, val expectedOutput: Strin
|
||||
|
||||
val shouldFail get() = name.endsWith(".fail")
|
||||
|
||||
val skipRunReason get() = when (name) {
|
||||
"br_table" -> "Table issues on jump"
|
||||
"switch" -> "Table issues on jumps (ref 'argument switch')"
|
||||
else -> null
|
||||
}
|
||||
|
||||
val defaultMaxMemPages get() = when (name) {
|
||||
"nop"-> 20
|
||||
"resizing" -> 830
|
||||
@ -24,6 +30,31 @@ class SpecTestUnit(val name: String, val wast: String, val expectedOutput: Strin
|
||||
else -> 1
|
||||
}
|
||||
|
||||
fun isWarningInsteadOfError(t: Throwable) = when (name) {
|
||||
// NaN bit patterns can be off
|
||||
"float_literals" -> isNanMismatch(t)
|
||||
"float_exprs" -> isNanMismatch(t)
|
||||
// We don't hold table capacity right now
|
||||
// TODO: Figure out how we want to store/retrieve table capacity. Right now
|
||||
// a table is an array, so there is only size not capacity. Since we want to
|
||||
// stay w/ the stdlib of the JVM, the best option may be to store the capacity
|
||||
// as a separate int value and query it or pass it around via import as
|
||||
// necessary. I guess I could use a vector, but it's not worth it just for
|
||||
// capacity since you lose speed.
|
||||
"imports" -> t is ScriptAssertionError && (t.assertion as? Script.Cmd.Assertion.Unlinkable).let {
|
||||
it != null && it.failure == "maximum size larger than declared" &&
|
||||
it.module.imports.singleOrNull()?.kind is Node.Import.Kind.Table
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun isNanMismatch(t: Throwable) = t is ScriptAssertionError && (
|
||||
t.assertion is Script.Cmd.Assertion.ReturnNan ||
|
||||
(t.assertion is Script.Cmd.Assertion.Return && (t.assertion as Script.Cmd.Assertion.Return).let {
|
||||
(it.action as? Script.Cmd.Action.Invoke)?.string?.contains("nan") ?: false
|
||||
})
|
||||
)
|
||||
|
||||
val parseResult: StrToSExpr.ParseResult.Success by lazy {
|
||||
StrToSExpr.parse(wast).let {
|
||||
when (it) {
|
||||
@ -37,150 +68,7 @@ class SpecTestUnit(val name: String, val wast: String, val expectedOutput: Strin
|
||||
|
||||
val script: Script by lazy { SExprToAst.toScript(SExpr.Multi(ast)) }
|
||||
|
||||
fun isWarningInsteadOfError(t: Throwable) = testsWithErrorToWarningPredicates[name]?.invoke(t) ?: false
|
||||
|
||||
companion object {
|
||||
|
||||
/*
|
||||
TODO: We are going down in order. One's we have not yet handled:
|
||||
- br_table.wast - Table issues on jumps
|
||||
- linking.wast - Not handling tables yet
|
||||
- return.wast - Not handling tables yet
|
||||
- switch.wast - Table issues on jumps (ref "argument switch")
|
||||
- typecheck.wast - Not handling tables yet
|
||||
- unreachable.wast - Not handling tables yet
|
||||
*/
|
||||
|
||||
val knownGoodTests = arrayOf(
|
||||
"address.wast",
|
||||
"address-offset-range.fail.wast",
|
||||
"binary.wast",
|
||||
"block.wast",
|
||||
"block-end-label-mismatch.fail.wast",
|
||||
"block-end-label-superfluous.wast",
|
||||
"br.wast",
|
||||
"br_if.wast",
|
||||
"break-drop.wast",
|
||||
"call.wast",
|
||||
"call_indirect.wast",
|
||||
"comments.wast",
|
||||
"conversions.wast",
|
||||
"custom_section.wast",
|
||||
"endianness.wast",
|
||||
"exports.wast",
|
||||
"f32.load32.fail.wast",
|
||||
"f32.load64.fail.wast",
|
||||
"f32.store32.fail.wast",
|
||||
"f32.store64.fail.wast",
|
||||
"f32.wast",
|
||||
"f32_cmp.wast",
|
||||
"f64.load32.fail.wast",
|
||||
"f64.load64.fail.wast",
|
||||
"f64.store32.fail.wast",
|
||||
"f64.store64.fail.wast",
|
||||
"f64.wast",
|
||||
"f64_cmp.wast",
|
||||
"fac.wast",
|
||||
"float_exprs.wast",
|
||||
"float_literals.wast",
|
||||
"float_memory.wast",
|
||||
"float_misc.wast",
|
||||
"forward.wast",
|
||||
"func_ptrs.wast",
|
||||
"func-local-after-body.fail.wast",
|
||||
"func-local-before-param.fail.wast",
|
||||
"func-local-before-result.fail.wast",
|
||||
"func-param-after-body.fail.wast",
|
||||
"func-result-after-body.fail.wast",
|
||||
"func-result-before-param.fail.wast",
|
||||
"func.wast",
|
||||
"get_local.wast",
|
||||
"globals.wast",
|
||||
"i32.load32_s.fail.wast",
|
||||
"i32.load32_u.fail.wast",
|
||||
"i32.load64_s.fail.wast",
|
||||
"i32.load64_u.fail.wast",
|
||||
"i32.store32.fail.wast",
|
||||
"i32.store64.fail.wast",
|
||||
"i32.wast",
|
||||
"i64.load64_s.fail.wast",
|
||||
"i64.load64_u.fail.wast",
|
||||
"i64.store64.fail.wast",
|
||||
"i64.wast",
|
||||
"if.wast",
|
||||
"if-else-end-label-mismatch.fail.wast",
|
||||
"if-else-end-label-superfluous.fail.wast",
|
||||
"if-else-label-mismatch.fail.wast",
|
||||
"if-else-label-superfluous.fail.wast",
|
||||
"if-end-label-mismatch.fail.wast",
|
||||
"if-end-label-superfluous.fail.wast",
|
||||
"import-after-func.fail.wast",
|
||||
"import-after-global.fail.wast",
|
||||
"import-after-memory.fail.wast",
|
||||
"import-after-table.fail.wast",
|
||||
"imports.wast",
|
||||
"int_exprs.wast",
|
||||
"int_literals.wast",
|
||||
"labels.wast",
|
||||
"left-to-right.wast",
|
||||
"linking.wast",
|
||||
"load-align-0.fail.wast",
|
||||
"load-align-odd.fail.wast",
|
||||
"loop.wast",
|
||||
"loop-end-label-mismatch.fail.wast",
|
||||
"loop-end-label-superfluous.fail.wast",
|
||||
"memory.wast",
|
||||
"memory_redundancy.wast",
|
||||
"memory_trap.wast",
|
||||
"names.wast",
|
||||
"nop.wast",
|
||||
"of_string-overflow-hex-u32.fail.wast",
|
||||
"of_string-overflow-hex-u64.fail.wast",
|
||||
"of_string-overflow-s32.fail.wast",
|
||||
"of_string-overflow-s64.fail.wast",
|
||||
"of_string-overflow-u32.fail.wast",
|
||||
"of_string-overflow-u64.fail.wast",
|
||||
"resizing.wast",
|
||||
"select.wast",
|
||||
"set_local.wast",
|
||||
"skip-stack-guard-page.wast",
|
||||
"stack.wast",
|
||||
"start.wast",
|
||||
"store-align-0.fail.wast",
|
||||
"store-align-odd.fail.wast",
|
||||
"store_retval.wast",
|
||||
"tee_local.wast",
|
||||
"traps.wast",
|
||||
"unreached-invalid.wast",
|
||||
"unwind.wast"
|
||||
)
|
||||
|
||||
val testsWithErrorToWarningPredicates: Map<String, (Throwable) -> Boolean> = mapOf(
|
||||
// NaN bit patterns can be off
|
||||
"float_literals" to this::isNanMismatch,
|
||||
"float_exprs" to this::isNanMismatch,
|
||||
// We don't hold table capacity right now
|
||||
// TODO: Figure out how we want to store/retrieve table capacity. Right now
|
||||
// a table is an array, so there is only size not capacity. Since we want to
|
||||
// stay w/ the stdlib of the JVM, the best option may be to store the capacity
|
||||
// as a separate int value and query it or pass it around via import as
|
||||
// necessary. I guess I could use a vector, but it's not worth it just for
|
||||
// capacity since you lose speed.
|
||||
"imports" to { t: Throwable ->
|
||||
t is ScriptAssertionError && (t.assertion as? Script.Cmd.Assertion.Unlinkable).let {
|
||||
it != null && it.failure == "maximum size larger than declared" &&
|
||||
it.module.imports.singleOrNull()?.kind is Node.Import.Kind.Table
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
fun isNanMismatch(t: Throwable) = t is ScriptAssertionError && (
|
||||
t.assertion is Script.Cmd.Assertion.ReturnNan ||
|
||||
(t.assertion is Script.Cmd.Assertion.Return && (t.assertion as Script.Cmd.Assertion.Return).let {
|
||||
(it.action as? Script.Cmd.Action.Invoke)?.string?.contains("nan") ?: false
|
||||
})
|
||||
)
|
||||
|
||||
val unitsPath = "/spec/test/core"
|
||||
|
||||
val allUnits by lazy { loadFromResourcePath("/local-spec") + loadFromResourcePath(unitsPath) }
|
||||
@ -193,9 +81,7 @@ class SpecTestUnit(val name: String, val wast: String, val expectedOutput: Strin
|
||||
fs.use { fs ->
|
||||
val path = fs?.getPath(basePath) ?: Paths.get(uri)
|
||||
val testWastFiles = Files.walk(path, 1).
|
||||
filter { it.toString().endsWith(".wast") }.
|
||||
// TODO: remove this when they all succeed
|
||||
filter { knownGoodTests.contains(it.fileName.toString()) }
|
||||
filter { it.toString().endsWith(".wast") }
|
||||
return testWastFiles.map {
|
||||
val name = it.fileName.toString().substringBeforeLast(".wast")
|
||||
SpecTestUnit(
|
||||
|
@ -4,6 +4,7 @@ import asmble.SpecTestUnit
|
||||
import asmble.io.AstToSExpr
|
||||
import asmble.io.SExprToStr
|
||||
import asmble.util.Logger
|
||||
import org.junit.Assume
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
@ -17,6 +18,8 @@ class RunTest(val unit: SpecTestUnit) : Logger by Logger.Print(Logger.Level.INFO
|
||||
|
||||
@Test
|
||||
fun testRun() {
|
||||
unit.skipRunReason?.let { Assume.assumeTrue("Skipping ${unit.name}, reason: $it", false) }
|
||||
|
||||
val ex = try { run(); null } catch (e: Throwable) { e }
|
||||
if (unit.shouldFail) {
|
||||
assertNotNull(ex, "Expected failure, but succeeded")
|
||||
|
@ -0,0 +1 @@
|
||||
;; TODO: test w/ emscripten compiled code
|
Loading…
x
Reference in New Issue
Block a user