summaryrefslogtreecommitdiffstats
path: root/third_party/rust/lucet-runtime-wasmsbx/tests
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/lucet-runtime-wasmsbx/tests')
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/c_api.c180
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/entrypoint.rs3
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/globals.rs3
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/guest_fault.rs3
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/guests/null.c3
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/guests/yield_resume.c8
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/guests/yield_resume_bindings.json5
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/host.rs3
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting.rs71
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/arithmetic_count.wat11
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/br_table_count.wat25
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/calls.wat22
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/count_after_br.wat21
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/empty_loop.wat9
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/empty_loop_2.wat11
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/if_count.wat21
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/if_not_taken_count.wat21
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/indirect_calls.wat68
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/loops.wat30
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/unreachable_call.wat17
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/memory.rs3
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/stack.rs3
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/start.rs3
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/strcmp.rs3
-rw-r--r--third_party/rust/lucet-runtime-wasmsbx/tests/val.rs61
25 files changed, 608 insertions, 0 deletions
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/c_api.c b/third_party/rust/lucet-runtime-wasmsbx/tests/c_api.c
new file mode 100644
index 0000000000..b799d186f0
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/c_api.c
@@ -0,0 +1,180 @@
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "lucet.h"
+
+bool lucet_runtime_test_expand_heap(struct lucet_dl_module *mod)
+{
+ struct lucet_region * region;
+ struct lucet_alloc_limits limits = {
+ .heap_memory_size = 4 * 1024 * 1024,
+ .heap_address_space_size = 8 * 1024 * 1024,
+ .stack_size = 64 * 1024,
+ .globals_size = 4096,
+ .signal_stack_size = 12 * 1024,
+ };
+
+ enum lucet_error err;
+
+ err = lucet_mmap_region_create(1, &limits, &region);
+ if (err != lucet_error_ok) {
+ fprintf(stderr, "failed to create region\n");
+ goto fail1;
+ }
+
+ struct lucet_instance *inst;
+ err = lucet_region_new_instance(region, mod, &inst);
+ if (err != lucet_error_ok) {
+ fprintf(stderr, "failed to create instance\n");
+ goto fail2;
+ }
+
+ uint32_t newpage_start;
+ err = lucet_instance_grow_heap(inst, 1, &newpage_start);
+ if (err != lucet_error_ok) {
+ fprintf(stderr, "failed to grow memory\n");
+ goto fail3;
+ }
+
+ lucet_instance_release(inst);
+ lucet_region_release(region);
+ lucet_dl_module_release(mod);
+
+ return true;
+
+fail3:
+ lucet_instance_release(inst);
+fail2:
+ lucet_region_release(region);
+fail1:
+ lucet_dl_module_release(mod);
+ return false;
+}
+
+enum yield_resume_tag {
+ yield_resume_tag_mult,
+ yield_resume_tag_result,
+};
+
+struct yield_resume_mult {
+ uint64_t x;
+ uint64_t y;
+};
+
+union yield_resume_val_inner {
+ struct yield_resume_mult mult;
+ uint64_t result;
+};
+
+struct yield_resume_val {
+ enum yield_resume_tag tag;
+ union yield_resume_val_inner val;
+};
+
+uint64_t lucet_runtime_test_hostcall_yield_resume(struct lucet_vmctx *vmctx, uint64_t n)
+{
+ if (n <= 1) {
+ struct yield_resume_val result_val = { .tag = yield_resume_tag_result,
+ .val = { .result = 1 } };
+ lucet_vmctx_yield(vmctx, &result_val);
+ return 1;
+ } else {
+ uint64_t n_rec = lucet_runtime_test_hostcall_yield_resume(vmctx, n - 1);
+ struct yield_resume_val mult_val = { .tag = yield_resume_tag_mult,
+ .val = { .mult = { .x = n, .y = n_rec } } };
+ uint64_t n = *(uint64_t *) lucet_vmctx_yield(vmctx, &mult_val);
+ struct yield_resume_val result_val = { .tag = yield_resume_tag_result,
+ .val = { .result = n } };
+ lucet_vmctx_yield(vmctx, &result_val);
+ return n;
+ }
+}
+
+bool lucet_runtime_test_yield_resume(struct lucet_dl_module *mod)
+{
+ struct lucet_region * region;
+ struct lucet_alloc_limits limits = {
+ .heap_memory_size = 4 * 1024 * 1024,
+ .heap_address_space_size = 8 * 1024 * 1024,
+ .stack_size = 64 * 1024,
+ .globals_size = 4096,
+ .signal_stack_size = 12 * 1024,
+ };
+
+ enum lucet_error err;
+
+ err = lucet_mmap_region_create(1, &limits, &region);
+ if (err != lucet_error_ok) {
+ fprintf(stderr, "failed to create region\n");
+ goto fail1;
+ }
+
+ struct lucet_instance *inst;
+ err = lucet_region_new_instance(region, mod, &inst);
+ if (err != lucet_error_ok) {
+ fprintf(stderr, "failed to create instance\n");
+ goto fail2;
+ }
+
+ uint64_t results[5] = { 0 };
+ size_t i = 0;
+
+ struct lucet_result res;
+ lucet_instance_run(inst, "f", 0, (const struct lucet_val[]){}, &res);
+ while (res.tag == lucet_result_tag_yielded) {
+ if (i >= 5) {
+ fprintf(stderr, "hostcall yielded too many results\n");
+ goto fail3;
+ }
+
+ struct yield_resume_val val = *(struct yield_resume_val *) res.val.yielded.val;
+
+ switch (val.tag) {
+ case yield_resume_tag_mult: {
+ uint64_t mult_result = val.val.mult.x * val.val.mult.y;
+ lucet_instance_resume(inst, &mult_result, &res);
+ continue;
+ }
+ case yield_resume_tag_result: {
+ results[i++] = val.val.result;
+ lucet_instance_resume(inst, NULL, &res);
+ continue;
+ }
+ default: {
+ fprintf(stderr, "unexpected yield_resume_tag\n");
+ goto fail3;
+ }
+ }
+ }
+ if (err != lucet_error_ok) {
+ fprintf(stderr, "instance finished with non-ok error: %s\n", lucet_error_name(err));
+ goto fail3;
+ }
+
+ if (res.tag != lucet_result_tag_returned) {
+ fprintf(stderr, "final instance result wasn't returned\n");
+ goto fail3;
+ }
+
+ uint64_t final_result = LUCET_UNTYPED_RETVAL_TO_U64(res.val.returned);
+
+ lucet_instance_release(inst);
+ lucet_region_release(region);
+ lucet_dl_module_release(mod);
+
+ uint64_t expected_results[5] = { 1, 2, 6, 24, 120 };
+ bool results_correct = final_result == 120;
+ for (i = 0; i < 5; i++) {
+ results_correct = results_correct && (results[i] == expected_results[i]);
+ }
+
+ return results_correct;
+
+fail3:
+ lucet_instance_release(inst);
+fail2:
+ lucet_region_release(region);
+fail1:
+ lucet_dl_module_release(mod);
+ return false;
+}
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/entrypoint.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/entrypoint.rs
new file mode 100644
index 0000000000..a4e849cf6f
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/entrypoint.rs
@@ -0,0 +1,3 @@
+use lucet_runtime_tests::entrypoint_tests;
+
+entrypoint_tests!(lucet_runtime::MmapRegion);
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/globals.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/globals.rs
new file mode 100644
index 0000000000..88f82089e6
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/globals.rs
@@ -0,0 +1,3 @@
+use lucet_runtime_tests::globals_tests;
+
+globals_tests!(lucet_runtime::MmapRegion);
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/guest_fault.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/guest_fault.rs
new file mode 100644
index 0000000000..945db4078e
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/guest_fault.rs
@@ -0,0 +1,3 @@
+use lucet_runtime_tests::guest_fault_tests;
+
+guest_fault_tests!(lucet_runtime::MmapRegion);
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/guests/null.c b/third_party/rust/lucet-runtime-wasmsbx/tests/guests/null.c
new file mode 100644
index 0000000000..dbec2355bc
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/guests/null.c
@@ -0,0 +1,3 @@
+void f() {
+ return;
+}
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/guests/yield_resume.c b/third_party/rust/lucet-runtime-wasmsbx/tests/guests/yield_resume.c
new file mode 100644
index 0000000000..22b68f37eb
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/guests/yield_resume.c
@@ -0,0 +1,8 @@
+#include <stdint.h>
+
+extern uint64_t lucet_runtime_test_hostcall_yield_resume(uint64_t n);
+
+uint64_t f()
+{
+ return lucet_runtime_test_hostcall_yield_resume(5);
+}
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/guests/yield_resume_bindings.json b/third_party/rust/lucet-runtime-wasmsbx/tests/guests/yield_resume_bindings.json
new file mode 100644
index 0000000000..fe9ffc6af7
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/guests/yield_resume_bindings.json
@@ -0,0 +1,5 @@
+{
+ "env": {
+ "lucet_runtime_test_hostcall_yield_resume": "lucet_runtime_test_hostcall_yield_resume"
+ }
+}
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/host.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/host.rs
new file mode 100644
index 0000000000..d42cb2bce0
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/host.rs
@@ -0,0 +1,3 @@
+use lucet_runtime_tests::host_tests;
+
+host_tests!(lucet_runtime::MmapRegion);
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting.rs
new file mode 100644
index 0000000000..fd1bf88629
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting.rs
@@ -0,0 +1,71 @@
+use lucet_runtime::{DlModule, Error, Limits, MmapRegion, Region, RunResult};
+use lucetc::{Lucetc, LucetcOpts};
+use rayon::prelude::*;
+use std::fs::DirEntry;
+use std::path::Path;
+use std::sync::Arc;
+use tempfile::TempDir;
+
+pub fn wasm_test<P: AsRef<Path>>(wasm_file: P) -> Result<Arc<DlModule>, Error> {
+ let workdir = TempDir::new().expect("create working directory");
+
+ let native_build = Lucetc::new(wasm_file).with_count_instructions(true);
+
+ let so_file = workdir.path().join("out.so");
+
+ native_build.shared_object_file(so_file.clone())?;
+
+ let dlmodule = DlModule::load(so_file)?;
+
+ Ok(dlmodule)
+}
+
+#[test]
+pub fn check_instruction_counts() {
+ let files: Vec<DirEntry> = std::fs::read_dir("./tests/instruction_counting")
+ .expect("can iterate test files")
+ .map(|ent| {
+ let ent = ent.expect("can get test files");
+ assert!(
+ ent.file_type().unwrap().is_file(),
+ "directories not supported in test/instruction_counting"
+ );
+ ent
+ })
+ .collect();
+
+ assert!(
+ files.len() > 0,
+ "there are no test cases in the `instruction_counting` directory"
+ );
+
+ files.par_iter().for_each(|ent| {
+ let wasm_path = ent.path();
+ let module = wasm_test(&wasm_path).expect("can load module");
+
+ let region = MmapRegion::create(1, &Limits::default()).expect("region can be created");
+
+ let mut inst = region
+ .new_instance(module)
+ .expect("instance can be created");
+
+ inst.run("test_function", &[]).expect("instance runs");
+
+ let instruction_count = inst.get_instruction_count();
+
+ assert_eq!(
+ instruction_count,
+ match inst
+ .run("instruction_count", &[])
+ .expect("instance still runs")
+ {
+ RunResult::Returned(value) => value.as_i64() as u64,
+ RunResult::Yielded(_) => {
+ panic!("instruction counting test runner doesn't support yielding");
+ }
+ },
+ "instruction count for test case {} is incorrect",
+ wasm_path.display()
+ );
+ });
+}
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/arithmetic_count.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/arithmetic_count.wat
new file mode 100644
index 0000000000..90891313a4
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/arithmetic_count.wat
@@ -0,0 +1,11 @@
+(module
+ (func $main (export "test_function")
+ i32.const 4
+ i32.const -5
+ i32.add
+ drop
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 3
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/br_table_count.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/br_table_count.wat
new file mode 100644
index 0000000000..29846f083d
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/br_table_count.wat
@@ -0,0 +1,25 @@
+(module
+ (func $main (export "test_function")
+ block $a
+ i64.const 1
+ drop
+
+ block $b
+ i64.const 2
+ drop
+
+ block $c
+ i64.const 3
+ drop
+
+ ;; 3 for above consts, one for i32.const below, 2 for br_table
+ ;; totalling to an expected count of 6
+ (br_table 0 1 2 3 (i32.const 4))
+ end
+ end
+ end
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 6
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/calls.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/calls.wat
new file mode 100644
index 0000000000..6fba4c4e6e
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/calls.wat
@@ -0,0 +1,22 @@
+(module
+ (func $mul2 (param $in i64) (result i64)
+ get_local $in
+ get_local $in
+ i64.mul
+ )
+ (func $main (export "test_function")
+ i64.const 1
+ call $mul2 ;; one from the call, three from the called function, one for the return
+ drop
+ i64.const 2
+ call $mul2 ;; and again
+ drop
+ i64.const 3
+ call $mul2 ;; and again
+ ;; for a total of 3 * 6 == 18 instructions
+ drop
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 18
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/count_after_br.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/count_after_br.wat
new file mode 100644
index 0000000000..52e180f6f1
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/count_after_br.wat
@@ -0,0 +1,21 @@
+(module
+ (func $main (export "test_function")
+ block $ops
+ i32.const 11
+ i32.const 10
+ i32.add
+
+ br 0 ;; branch to enclosing scope (end of this block)
+ ;; at this point we've counted four operations...
+ end
+
+ i32.const 14
+ i32.const 15
+ i32.add
+ ;; this puts us at 7 operations
+ drop
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 7
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/empty_loop.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/empty_loop.wat
new file mode 100644
index 0000000000..1817743134
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/empty_loop.wat
@@ -0,0 +1,9 @@
+(module
+ (func $main (export "test_function") (local $i i32)
+ loop $inner
+ end
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 0
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/empty_loop_2.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/empty_loop_2.wat
new file mode 100644
index 0000000000..302e0df8e4
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/empty_loop_2.wat
@@ -0,0 +1,11 @@
+(module
+ (func $main (export "test_function") (local $i i32)
+ block $a
+ loop $inner
+ end
+ end
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 0
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/if_count.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/if_count.wat
new file mode 100644
index 0000000000..e4bcb617ee
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/if_count.wat
@@ -0,0 +1,21 @@
+(module
+ (func $main (export "test_function")
+ i32.const 11
+ i32.const 10
+ i32.gt_s
+ ;; this counts up to 3
+ (if ;; this makes 4
+ (then
+ i64.const 5
+ i64.const 10
+ i64.mul
+ ;; and these were another 3
+ drop
+ ;; drop is ignored for a total of 7 operations
+ )
+ )
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 7
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/if_not_taken_count.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/if_not_taken_count.wat
new file mode 100644
index 0000000000..af5794d5a9
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/if_not_taken_count.wat
@@ -0,0 +1,21 @@
+(module
+ (func $main (export "test_function")
+ i32.const 10
+ i32.const 11
+ i32.gt_s
+ ;; this counts up to 3
+ (if ;; this makes 4
+ ;; but the `then` branch is not taken
+ (then
+ i64.const 5
+ i64.const 10
+ i64.mul
+ drop
+ )
+ )
+ ;; so we only execute 4 operations
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 4
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/indirect_calls.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/indirect_calls.wat
new file mode 100644
index 0000000000..e6a5bbf994
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/indirect_calls.wat
@@ -0,0 +1,68 @@
+(module
+ (type $mulfn (func (param i64) (result i64)))
+
+ ;; mul2 is 3 operations
+ (func $mul2 (param $in i64) (result i64)
+ get_local $in
+ get_local $in
+ i64.add
+ )
+ ;; mul4 is 2 * |mul2| + 2 call + 3 == 13
+ (func $mul4 (param $in i64) (result i64)
+ get_local $in
+ call $mul2
+ get_local $in
+ call $mul2
+ i64.add
+ )
+ ;; mul8 is 2 * |mul4| + 2 call + 3 == 33
+ (func $mul8 (param $in i64) (result i64)
+ get_local $in
+ call $mul4
+ get_local $in
+ call $mul4
+ i64.add
+ )
+ ;; mul16 is 2 * |mul8| + 2 call + 3 == 73
+ ;; by entire accident the number of instructions for
+ ;; subsequent similar functions for higher powers is given by
+ ;; mul(n^2) == 10 * (2 ^ (n - 1)) - 10 + 3
+ (func $mul16 (param $in i64) (result i64)
+ get_local $in
+ call $mul8
+ get_local $in
+ call $mul8
+ i64.add
+ )
+
+ (table anyfunc
+ (elem
+ $mul2 $mul4 $mul8 $mul16
+ )
+ )
+
+ (func $main (export "test_function")
+ ;; call_indirect here is 2, plus 1 for the const, one for the index, and
+ ;; 1 for return
+ ;; the called function (mul2) is 3 instructions, for 8 total.
+ (call_indirect (type $mulfn) (i64.const 0) (i32.const 0))
+ drop
+
+ ;; call_indirect here is 2, plus 1 for the const, one for the index, and
+ ;; 1 for return
+ ;; the called function (mul4) is 13 instructions, for 18 total.
+ (call_indirect (type $mulfn) (i64.const 1) (i32.const 1))
+ drop
+
+ ;; call_indirect here is 2, plus 1 for the const, one for the index, and
+ ;; 1 for return
+ ;; the called function (mul16) is 73 instructions, for 78 total.
+ (call_indirect (type $mulfn) (i64.const 2) (i32.const 3))
+ drop
+
+ ;; for a total of 8 + 18 + 78 == 104 instructions
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 104
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/loops.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/loops.wat
new file mode 100644
index 0000000000..3b68a0abd7
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/loops.wat
@@ -0,0 +1,30 @@
+(module
+ (func $main (export "test_function") (local $i i32)
+ i32.const 0
+ set_local $i
+ block $outer
+ loop $inner
+ ;; each loop iteration is:
+ ;; * 4 operations to increment i
+ ;; * 3 operations to test i == 10
+ ;; * 1 branch to break (untaken)
+ ;; * 1 branch to loop
+ get_local $i
+ i32.const 1
+ i32.add
+ set_local $i
+ get_local $i
+ i32.const 10
+ i32.eq
+ br_if $outer
+ br $inner
+ end
+ end
+ ;; iterating i = 0..9, that's 10 * 8 instructions from full executions,
+ ;; plus 9 instructions from the last round.
+ ;; add two for initializing i and that gives 80 + 9 + 2 = 91 instructions
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 91
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/unreachable_call.wat b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/unreachable_call.wat
new file mode 100644
index 0000000000..3caf474288
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/instruction_counting/unreachable_call.wat
@@ -0,0 +1,17 @@
+(module
+ (func $main (export "test_function") (result i64)
+ ;; counting the const
+ i64.const 1
+ ;; return is counted by the caller, so we count 1 so far
+ return
+
+ ;; we had a bug where calls in unreachable code would still add
+ ;; one to the instruction counter to track a matching return,
+ ;; but the call would never be made, so the return would never
+ ;; occur, and the count was in error.
+ call $main
+ )
+ (func $instruction_count (export "instruction_count") (result i64)
+ i64.const 1
+ )
+)
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/memory.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/memory.rs
new file mode 100644
index 0000000000..6778ab28d5
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/memory.rs
@@ -0,0 +1,3 @@
+use lucet_runtime_tests::memory_tests;
+
+memory_tests!(lucet_runtime::MmapRegion);
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/stack.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/stack.rs
new file mode 100644
index 0000000000..ab4ce5f626
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/stack.rs
@@ -0,0 +1,3 @@
+use lucet_runtime_tests::stack_tests;
+
+stack_tests!(lucet_runtime::MmapRegion);
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/start.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/start.rs
new file mode 100644
index 0000000000..6b1f2a26c4
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/start.rs
@@ -0,0 +1,3 @@
+use lucet_runtime_tests::start_tests;
+
+start_tests!(lucet_runtime::MmapRegion);
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/strcmp.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/strcmp.rs
new file mode 100644
index 0000000000..85547904c5
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/strcmp.rs
@@ -0,0 +1,3 @@
+use lucet_runtime_tests::strcmp_tests;
+
+strcmp_tests!(lucet_runtime::MmapRegion);
diff --git a/third_party/rust/lucet-runtime-wasmsbx/tests/val.rs b/third_party/rust/lucet-runtime-wasmsbx/tests/val.rs
new file mode 100644
index 0000000000..7fe78e3e22
--- /dev/null
+++ b/third_party/rust/lucet-runtime-wasmsbx/tests/val.rs
@@ -0,0 +1,61 @@
+use lucet_runtime_internals::val::UntypedRetVal;
+
+#[test]
+fn untyped_ret_val_from_f32() {
+ assert_eq!(1.2, f32::from(UntypedRetVal::from(1.2f32)));
+}
+
+#[test]
+fn untyped_ret_val_from_f64() {
+ assert_eq!(1.2, f64::from(UntypedRetVal::from(1.2f64)));
+}
+
+#[test]
+fn untyped_ret_val_from_u8() {
+ assert_eq!(5, u8::from(UntypedRetVal::from(5u8)));
+}
+
+#[test]
+fn untyped_ret_val_from_u16() {
+ assert_eq!(5, u16::from(UntypedRetVal::from(5u16)));
+}
+
+#[test]
+fn untyped_ret_val_from_u32() {
+ assert_eq!(5, u32::from(UntypedRetVal::from(5u32)));
+}
+
+#[test]
+fn untyped_ret_val_from_u64() {
+ assert_eq!(5, u64::from(UntypedRetVal::from(5u64)));
+}
+
+#[test]
+fn untyped_ret_val_from_i8() {
+ assert_eq!(5, i8::from(UntypedRetVal::from(5i8)));
+}
+
+#[test]
+fn untyped_ret_val_from_i16() {
+ assert_eq!(5, i16::from(UntypedRetVal::from(5i16)));
+}
+
+#[test]
+fn untyped_ret_val_from_i32() {
+ assert_eq!(5, i32::from(UntypedRetVal::from(5i32)));
+}
+
+#[test]
+fn untyped_ret_val_from_i64() {
+ assert_eq!(5, i64::from(UntypedRetVal::from(5i64)));
+}
+
+#[test]
+fn untyped_ret_val_from_bool_true() {
+ assert_eq!(true, bool::from(UntypedRetVal::from(true)));
+}
+
+#[test]
+fn untyped_ret_val_from_bool_false() {
+ assert_eq!(false, bool::from(UntypedRetVal::from(false)));
+}