Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit f240483

Browse files
authored
Merge pull request #217 from bytecodealliance/dicej/more-miri-test-improvements
fix issues running `component-async-tests` under miri
2 parents 3b91e3b + 2d6312b commit f240483

File tree

28 files changed

+501
-334
lines changed

28 files changed

+501
-334
lines changed

crates/misc/component-async-tests/src/round_trip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub mod non_concurrent_export_bindings {
2525

2626
impl bindings::local::local::baz::HostConcurrent for Ctx {
2727
async fn foo<T>(_: &mut Accessor<T, Self>, s: String) -> wasmtime::Result<String> {
28-
tokio::time::sleep(Duration::from_millis(10)).await;
28+
crate::util::sleep(Duration::from_millis(10)).await;
2929
Ok(format!("{s} - entered host - exited host"))
3030
}
3131
}

crates/misc/component-async-tests/src/round_trip_direct.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub mod bindings {
1515

1616
impl bindings::RoundTripDirectImportsConcurrent for Ctx {
1717
async fn foo<T>(_: &mut Accessor<T, Self>, s: String) -> wasmtime::Result<String> {
18-
tokio::time::sleep(Duration::from_millis(10)).await;
18+
crate::util::sleep(Duration::from_millis(10)).await;
1919
Ok(format!("{s} - entered host - exited host"))
2020
}
2121
}

crates/misc/component-async-tests/src/round_trip_many.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl bindings::local::local::many::HostConcurrent for Ctx {
4747
Option<Stuff>,
4848
Result<Stuff, ()>,
4949
)> {
50-
tokio::time::sleep(Duration::from_millis(10)).await;
50+
crate::util::sleep(Duration::from_millis(10)).await;
5151
Ok((
5252
format!("{a} - entered host - exited host"),
5353
b,

crates/misc/component-async-tests/src/sleep.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ wasmtime::component::bindgen!({
1616

1717
impl local::local::sleep::HostConcurrent for Ctx {
1818
async fn sleep_millis<T>(_: &mut Accessor<T, Self>, time_in_millis: u64) {
19-
tokio::time::sleep(Duration::from_millis(time_in_millis)).await;
19+
crate::util::sleep(Duration::from_millis(time_in_millis)).await;
2020
}
2121
}
2222

crates/misc/component-async-tests/src/util.rs

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,60 @@ pub fn config() -> Config {
4242
config
4343
}
4444

45+
pub async fn sleep(duration: std::time::Duration) {
46+
if cfg!(miri) {
47+
// TODO: We should be able to use `tokio::time::sleep` here, but as of
48+
// this writing the miri-compatible version of `wasmtime-fiber` uses
49+
// threads behind the scenes, which means thread-local storage is not
50+
// preserved when we switch fibers, and that confuses Tokio. If we ever
51+
// fix that we can stop using our own, special version of `sleep` and
52+
// switch back to the Tokio version.
53+
54+
use std::{
55+
future,
56+
sync::{
57+
Arc, Mutex,
58+
atomic::{AtomicU32, Ordering::SeqCst},
59+
},
60+
task::Poll,
61+
thread,
62+
};
63+
64+
let state = Arc::new(AtomicU32::new(0));
65+
let waker = Arc::new(Mutex::new(None));
66+
let mut join_handle = None;
67+
future::poll_fn(move |cx| match state.load(SeqCst) {
68+
0 => {
69+
state.store(1, SeqCst);
70+
let state = state.clone();
71+
*waker.lock().unwrap() = Some(cx.waker().clone());
72+
let waker = waker.clone();
73+
join_handle = Some(thread::spawn(move || {
74+
thread::sleep(duration);
75+
state.store(2, SeqCst);
76+
let waker = waker.lock().unwrap().clone().unwrap();
77+
waker.wake();
78+
}));
79+
Poll::Pending
80+
}
81+
1 => {
82+
*waker.lock().unwrap() = Some(cx.waker().clone());
83+
Poll::Pending
84+
}
85+
2 => {
86+
if let Some(handle) = join_handle.take() {
87+
_ = handle.join();
88+
}
89+
Poll::Ready(())
90+
}
91+
_ => unreachable!(),
92+
})
93+
.await;
94+
} else {
95+
tokio::time::sleep(duration).await;
96+
}
97+
}
98+
4599
/// Compose two components
46100
///
47101
/// a is the "root" component, and b is composed into it
@@ -166,7 +220,11 @@ pub async fn test_run(components: &[&str]) -> Result<()> {
166220

167221
pub async fn test_run_with_count(components: &[&str], count: usize) -> Result<()> {
168222
let mut config = config();
169-
config.epoch_interruption(true);
223+
// As of this writing, miri/pulley/epochs is a problematic combination, so
224+
// we don't test it.
225+
if env::var_os("MIRI_TEST_CWASM_DIR").is_none() {
226+
config.epoch_interruption(true);
227+
}
170228

171229
let engine = Engine::new(&config)?;
172230

@@ -198,12 +256,15 @@ pub async fn test_run_with_count(components: &[&str], count: usize) -> Result<()
198256
wakers: Arc::new(std::sync::Mutex::new(None)),
199257
},
200258
);
201-
store.set_epoch_deadline(1);
202259

203-
std::thread::spawn(move || {
204-
std::thread::sleep(Duration::from_secs(10));
205-
engine.increment_epoch();
206-
});
260+
if env::var_os("MIRI_TEST_CWASM_DIR").is_none() {
261+
store.set_epoch_deadline(1);
262+
263+
std::thread::spawn(move || {
264+
std::thread::sleep(Duration::from_secs(10));
265+
engine.increment_epoch();
266+
});
267+
}
207268

208269
let instance = linker.instantiate_async(&mut store, &component).await?;
209270
let yield_host = super::yield_host::bindings::YieldHost::new(&mut store, &instance)?;

crates/misc/component-async-tests/tests/scenario/borrowing.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::env;
12
use std::sync::{Arc, Mutex};
23
use std::time::Duration;
34

@@ -65,7 +66,11 @@ pub async fn async_borrowing_callee() -> Result<()> {
6566

6667
pub async fn test_run_bool(components: &[&str], v: bool) -> Result<()> {
6768
let mut config = config();
68-
config.epoch_interruption(true);
69+
// As of this writing, miri/pulley/epochs is a problematic combination, so
70+
// we don't test it.
71+
if env::var_os("MIRI_TEST_CWASM_DIR").is_none() {
72+
config.epoch_interruption(true);
73+
}
6974

7075
let engine = Engine::new(&config)?;
7176

@@ -88,12 +93,15 @@ pub async fn test_run_bool(components: &[&str], v: bool) -> Result<()> {
8893
wakers: Arc::new(Mutex::new(None)),
8994
},
9095
);
91-
store.set_epoch_deadline(1);
9296

93-
std::thread::spawn(move || {
94-
std::thread::sleep(Duration::from_secs(10));
95-
engine.increment_epoch();
96-
});
97+
if env::var_os("MIRI_TEST_CWASM_DIR").is_none() {
98+
store.set_epoch_deadline(1);
99+
100+
std::thread::spawn(move || {
101+
std::thread::sleep(Duration::from_secs(10));
102+
engine.increment_epoch();
103+
});
104+
}
97105

98106
let instance = linker.instantiate_async(&mut store, &component).await?;
99107
let borrowing_host =

crates/misc/component-async-tests/tests/scenario/common.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ pub async fn compose(a: &[u8], b: &[u8]) -> Result<Vec<u8>> {
4949
#[allow(unused)]
5050
pub async fn test_run(component: &[u8]) -> Result<()> {
5151
let mut config = config();
52-
config.epoch_interruption(true);
52+
// As of this writing, miri/pulley/epochs is a problematic combination, so
53+
// we don't test it.
54+
if env::var_os("MIRI_TEST_CWASM_DIR").is_none() {
55+
config.epoch_interruption(true);
56+
}
5357

5458
let engine = Engine::new(&config)?;
5559

@@ -80,12 +84,15 @@ pub async fn test_run(component: &[u8]) -> Result<()> {
8084
wakers: Arc::new(Mutex::new(None)),
8185
},
8286
);
83-
store.set_epoch_deadline(1);
8487

85-
std::thread::spawn(move || {
86-
std::thread::sleep(Duration::from_secs(10));
87-
engine.increment_epoch();
88-
});
88+
if env::var_os("MIRI_TEST_CWASM_DIR").is_none() {
89+
store.set_epoch_deadline(1);
90+
91+
std::thread::spawn(move || {
92+
std::thread::sleep(Duration::from_secs(10));
93+
engine.increment_epoch();
94+
});
95+
}
8996

9097
let yield_host = component_async_tests::yield_host::bindings::YieldHost::instantiate_async(
9198
&mut store, &component, &linker,

crates/misc/component-async-tests/tests/scenario/error_context.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ pub async fn async_error_context() -> Result<()> {
77
test_run(&[test_programs_artifacts::ASYNC_ERROR_CONTEXT_COMPONENT]).await
88
}
99

10-
#[tokio::test]
11-
pub async fn async_error_context_callee() -> Result<()> {
12-
test_run(&[test_programs_artifacts::ASYNC_ERROR_CONTEXT_COMPONENT]).await
13-
}
10+
// No-op function; we only test this by composing it in `async_error_context_caller`
11+
#[allow(
12+
dead_code,
13+
reason = "here only to make the `assert_test_exists` macro happy"
14+
)]
15+
pub fn async_error_context_callee() {}
1416

1517
#[tokio::test]
1618
pub async fn async_error_context_caller() -> Result<()> {

0 commit comments

Comments
 (0)