Skip to content

Commit a53a7a4

Browse files
authored
Refactor integration tests (#727)
* Refactor integration tests This commit refactors the integration tests to use the `javy-runner` crate. The main motivation for this change is to reduce duplication and make it easier to test more complex scenarios in the future e.g., the upcoming changes in #702 * Style changes * More style changes
1 parent 6fa604d commit a53a7a4

16 files changed

+529
-459
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cli/tests/common/mod.rs

-60
This file was deleted.

crates/cli/tests/dylib_test.rs

+30-136
Original file line numberDiff line numberDiff line change
@@ -1,169 +1,63 @@
11
use anyhow::Result;
2-
use std::boxed::Box;
2+
use javy_runner::{Runner, RunnerError};
3+
use std::path::{Path, PathBuf};
34
use std::str;
4-
use wasi_common::{pipe::WritePipe, sync::WasiCtxBuilder, WasiCtx, WasiFile};
5-
use wasmtime::{AsContextMut, Engine, Instance, Linker, Store};
65

7-
mod common;
6+
static ROOT: &str = env!("CARGO_MANIFEST_DIR");
87

98
#[test]
109
fn test_dylib() -> Result<()> {
1110
let js_src = "console.log(42);";
12-
let stderr = WritePipe::new_in_memory();
13-
run_js_src(js_src, &stderr)?;
11+
let mut runner = Runner::with_dylib(provider_module()?)?;
1412

15-
let output = stderr.try_into_inner().unwrap().into_inner();
16-
assert_eq!("42\n", str::from_utf8(&output)?);
13+
let (_, logs, _) = runner.exec_through_dylib(js_src, None)?;
14+
assert_eq!("42\n", str::from_utf8(&logs)?);
1715

1816
Ok(())
1917
}
2018

2119
#[test]
2220
fn test_dylib_with_error() -> Result<()> {
2321
let js_src = "function foo() { throw new Error('foo error'); } foo();";
24-
let stderr = WritePipe::new_in_memory();
25-
let result = run_js_src(js_src, &stderr);
2622

27-
assert!(result.is_err());
28-
let output = stderr.try_into_inner().unwrap().into_inner();
23+
let mut runner = Runner::with_dylib(provider_module()?)?;
2924

25+
let res = runner.exec_through_dylib(js_src, None);
26+
27+
assert!(res.is_err());
28+
29+
let e = res.err().unwrap();
3030
let expected_log_output = "Error:1:24 foo error\n at foo (function.mjs:1:24)\n at <anonymous> (function.mjs:1:50)\n\n";
31-
assert_eq!(expected_log_output, str::from_utf8(&output)?);
31+
assert_eq!(
32+
expected_log_output,
33+
String::from_utf8(e.downcast_ref::<RunnerError>().unwrap().stderr.clone())?
34+
);
3235

3336
Ok(())
3437
}
3538

3639
#[test]
3740
fn test_dylib_with_exported_func() -> Result<()> {
3841
let js_src = "export function foo() { console.log('In foo'); }; console.log('Toplevel');";
39-
let stderr = WritePipe::new_in_memory();
40-
run_invoke(js_src, "foo", &stderr)?;
4142

42-
let output = stderr.try_into_inner().unwrap().into_inner();
43-
assert_eq!("Toplevel\nIn foo\n", str::from_utf8(&output)?);
43+
let mut runner = Runner::with_dylib(provider_module()?)?;
4444

45-
Ok(())
46-
}
45+
let (_, logs, _) = runner.exec_through_dylib(js_src, Some("foo"))?;
46+
assert_eq!("Toplevel\nIn foo\n", str::from_utf8(&logs)?);
4747

48-
fn run_js_src<T: WasiFile + Clone + 'static>(js_src: &str, stderr: &T) -> Result<()> {
49-
let (instance, mut store) = create_wasm_env(stderr)?;
50-
51-
let eval_bytecode_func =
52-
instance.get_typed_func::<(u32, u32), ()>(store.as_context_mut(), "eval_bytecode")?;
53-
let (bytecode_ptr, bytecode_len) =
54-
compile_src(js_src.as_bytes(), &instance, store.as_context_mut())?;
55-
eval_bytecode_func.call(store.as_context_mut(), (bytecode_ptr, bytecode_len))?;
5648
Ok(())
5749
}
5850

59-
fn run_invoke<T: WasiFile + Clone + 'static>(
60-
js_src: &str,
61-
fn_to_invoke: &str,
62-
stderr: &T,
63-
) -> Result<()> {
64-
let (instance, mut store) = create_wasm_env(stderr)?;
65-
66-
let invoke_func =
67-
instance.get_typed_func::<(u32, u32, u32, u32), ()>(store.as_context_mut(), "invoke")?;
68-
let (bytecode_ptr, bytecode_len) =
69-
compile_src(js_src.as_bytes(), &instance, store.as_context_mut())?;
70-
let (fn_name_ptr, fn_name_len) =
71-
copy_func_name(fn_to_invoke, &instance, store.as_context_mut())?;
72-
invoke_func.call(
73-
store.as_context_mut(),
74-
(bytecode_ptr, bytecode_len, fn_name_ptr, fn_name_len),
75-
)?;
76-
Ok(())
77-
}
78-
79-
fn create_wasm_env<T: WasiFile + Clone + 'static>(
80-
stderr: &T,
81-
) -> Result<(Instance, Store<WasiCtx>)> {
82-
let engine = Engine::default();
83-
let mut linker = Linker::new(&engine);
84-
wasi_common::sync::add_to_linker(&mut linker, |s| s)?;
85-
let wasi = WasiCtxBuilder::new()
86-
.stderr(Box::new(stderr.clone()))
87-
.build();
88-
let module = common::create_quickjs_provider_module(&engine)?;
89-
90-
let mut store = Store::new(&engine, wasi);
91-
let instance = linker.instantiate(store.as_context_mut(), &module)?;
92-
93-
Ok((instance, store))
94-
}
95-
96-
fn compile_src(
97-
js_src: &[u8],
98-
instance: &Instance,
99-
mut store: impl AsContextMut,
100-
) -> Result<(u32, u32)> {
101-
let memory = instance
102-
.get_memory(store.as_context_mut(), "memory")
103-
.unwrap();
104-
let compile_src_func =
105-
instance.get_typed_func::<(u32, u32), u32>(store.as_context_mut(), "compile_src")?;
106-
107-
let js_src_ptr = allocate_memory(
108-
instance,
109-
store.as_context_mut(),
110-
1,
111-
js_src.len().try_into()?,
112-
)?;
113-
memory.write(store.as_context_mut(), js_src_ptr.try_into()?, js_src)?;
114-
115-
let ret_ptr = compile_src_func.call(
116-
store.as_context_mut(),
117-
(js_src_ptr, js_src.len().try_into()?),
118-
)?;
119-
let mut ret_buffer = [0; 8];
120-
memory.read(store.as_context(), ret_ptr.try_into()?, &mut ret_buffer)?;
121-
let bytecode_ptr = u32::from_le_bytes(ret_buffer[0..4].try_into()?);
122-
let bytecode_len = u32::from_le_bytes(ret_buffer[4..8].try_into()?);
123-
124-
Ok((bytecode_ptr, bytecode_len))
125-
}
126-
127-
fn copy_func_name(
128-
fn_name: &str,
129-
instance: &Instance,
130-
mut store: impl AsContextMut,
131-
) -> Result<(u32, u32)> {
132-
let memory = instance
133-
.get_memory(store.as_context_mut(), "memory")
134-
.unwrap();
135-
let fn_name_bytes = fn_name.as_bytes();
136-
let fn_name_ptr = allocate_memory(
137-
instance,
138-
store.as_context_mut(),
139-
1,
140-
fn_name_bytes.len().try_into()?,
141-
)?;
142-
memory.write(
143-
store.as_context_mut(),
144-
fn_name_ptr.try_into()?,
145-
fn_name_bytes,
146-
)?;
147-
148-
Ok((fn_name_ptr, fn_name_bytes.len().try_into()?))
149-
}
51+
fn provider_module() -> Result<Vec<u8>> {
52+
let mut lib_path = PathBuf::from(ROOT);
53+
lib_path.pop();
54+
lib_path.pop();
55+
lib_path = lib_path.join(
56+
Path::new("target")
57+
.join("wasm32-wasi")
58+
.join("release")
59+
.join("javy_quickjs_provider_wizened.wasm"),
60+
);
15061

151-
fn allocate_memory(
152-
instance: &Instance,
153-
mut store: impl AsContextMut,
154-
alignment: u32,
155-
new_size: u32,
156-
) -> Result<u32> {
157-
let realloc_func = instance.get_typed_func::<(u32, u32, u32, u32), u32>(
158-
store.as_context_mut(),
159-
"canonical_abi_realloc",
160-
)?;
161-
let orig_ptr = 0;
162-
let orig_size = 0;
163-
realloc_func
164-
.call(
165-
store.as_context_mut(),
166-
(orig_ptr, orig_size, alignment, new_size),
167-
)
168-
.map_err(Into::into)
62+
std::fs::read(lib_path).map_err(Into::into)
16963
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log(42);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function foo() {
2+
throw "Error";
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package local:main
2+
3+
world foo-test {
4+
export foo: func()
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log(Javy.JSON.toStdout(Javy.JSON.fromStdin()));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default () => console.log(42)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package local:test
2+
3+
world exported-arrow {
4+
export default: func()
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function foo() {
2+
console.log('In foo');
3+
};
4+
5+
console.log('Toplevel');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function fooBar() {
2+
console.log('In foo');
3+
};
4+
5+
console.log('Toplevel');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package local:main
2+
3+
world foo-test {
4+
export foo-bar: func()
5+
}

0 commit comments

Comments
 (0)