Skip to content

Commit 10c6acd

Browse files
authored
Always build all tests as a "reactor" (#1448)
This commit switches the way tests are built such that all binaries produced are "reactors" or those without a `main` function. This ensures that all imports/exports are fully described with WIT in this repository as opposed to implicitly relying on `wasi:cli/run`. This additionally means that testing in this repository no longer relies on toolchain conventions for the `wasi:cli/run` world making testing a bit more self-contained here, especially in the context of async. This notably came up on #1447 which should make some of the tests there easier to write and more idiomatic.
1 parent ba933bd commit 10c6acd

File tree

202 files changed

+1570
-1037
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

202 files changed

+1570
-1037
lines changed

crates/test/src/c.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::config::StringList;
2-
use crate::{Compile, Kind, LanguageMethods, Runner, Verify};
2+
use crate::{Compile, LanguageMethods, Runner, Verify};
33
use anyhow::{Context, Result};
44
use clap::Parser;
55
use heck::ToSnakeCase;
@@ -144,12 +144,7 @@ fn compile(runner: &Runner<'_>, compile: &Compile<'_>, compiler: PathBuf) -> Res
144144
for flag in Vec::from(config.cflags) {
145145
cmd.arg(flag);
146146
}
147-
match compile.component.kind {
148-
Kind::Runner => {}
149-
Kind::Test => {
150-
cmd.arg("-mexec-model=reactor");
151-
}
152-
}
147+
cmd.arg("-mexec-model=reactor");
153148
if produces_component(runner) {
154149
cmd.arg("-Wl,--skip-wit-component");
155150
}

crates/test/src/cpp.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::config::StringList;
2-
use crate::{Kind, LanguageMethods, Runner};
2+
use crate::{LanguageMethods, Runner};
33
use anyhow::Context;
44
use heck::ToSnakeCase;
55
use serde::Deserialize;
@@ -174,12 +174,7 @@ impl LanguageMethods for Cpp {
174174
for flag in Vec::from(config.cflags) {
175175
cmd.arg(flag);
176176
}
177-
match compile.component.kind {
178-
Kind::Runner => {}
179-
Kind::Test => {
180-
cmd.arg("-mexec-model=reactor");
181-
}
182-
}
177+
cmd.arg("-mexec-model=reactor");
183178
runner.run_command(&mut cmd)?;
184179
Ok(())
185180
}

crates/test/src/csharp.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{Compile, Kind, LanguageMethods, Runner, Verify};
1+
use crate::{Compile, LanguageMethods, Runner, Verify};
22
use anyhow::Result;
33
use heck::*;
44
use std::env;
@@ -75,9 +75,6 @@ impl LanguageMethods for Csharp {
7575
let mut csproj =
7676
wit_bindgen_csharp::CSProject::new(test_dir.to_path_buf(), &assembly_name, world_name);
7777
csproj.aot();
78-
if let Kind::Runner = compile.component.kind {
79-
csproj.binary();
80-
}
8178
csproj.generate()?;
8279

8380
let mut cmd = dotnet();

crates/test/src/lib.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,14 +1030,8 @@ status: {}",
10301030
section.encode(&mut module);
10311031
}
10321032

1033-
let wasi_adapter = match compile.component.kind {
1034-
Kind::Runner => {
1035-
wasi_preview1_component_adapter_provider::WASI_SNAPSHOT_PREVIEW1_COMMAND_ADAPTER
1036-
}
1037-
Kind::Test => {
1038-
wasi_preview1_component_adapter_provider::WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER
1039-
}
1040-
};
1033+
let wasi_adapter =
1034+
wasi_preview1_component_adapter_provider::WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER;
10411035

10421036
let component = ComponentEncoder::default()
10431037
.module(module.as_slice())

crates/test/src/runner.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl TestRunner {
4545
for arg in self.args.iter() {
4646
ret.arg(arg);
4747
}
48+
ret.arg("--invoke=run()");
4849
ret
4950
}
5051
}

crates/test/src/rust.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::config::StringList;
2-
use crate::{Compile, Kind, LanguageMethods, Runner, Verify};
2+
use crate::{Compile, LanguageMethods, Runner, Verify};
33
use anyhow::{Context, Result};
44
use clap::Parser;
55
use heck::ToSnakeCase;
@@ -206,12 +206,7 @@ path = 'lib.rs'
206206
let arg = format!("--extern={name}={}", path.display());
207207
cmd.arg(arg);
208208
}
209-
match compile.component.kind {
210-
Kind::Runner => {}
211-
Kind::Test => {
212-
cmd.arg("--crate-type=cdylib");
213-
}
214-
}
209+
cmd.arg("--crate-type=cdylib");
215210
if runner.produces_component() {
216211
cmd.arg("-Clink-arg=--skip-wit-component");
217212
}

tests/runtime-async/async/cancel-import/runner.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
//@ args = '--rename my:test/i=test'
1+
//@ args = '--rename my:test/i=test --async=-run'
22

33
#include <assert.h>
44
#include <runner.h>
55

6-
int main() {
6+
void exports_runner_run() {
77
// Call an import and cancel it.
88
{
99
test_future_void_writer_t writer;

tests/runtime-async/async/cancel-import/runner.rs

Lines changed: 124 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -6,128 +6,134 @@ use std::future::Future;
66
use std::task::Context;
77
use wit_bindgen::yield_async;
88

9-
fn main() {
10-
println!("test cancelling an import in progress");
11-
wit_bindgen::block_on(async {
12-
let (tx, rx) = wit_future::new(|| unreachable!());
13-
let mut import = Box::pin(pending_import(rx));
14-
assert!(import
15-
.as_mut()
16-
.poll(&mut Context::from_waker(noop_waker_ref()))
17-
.is_pending());
18-
drop(import);
19-
tx.write(()).await.unwrap_err();
20-
});
21-
22-
println!("test cancelling an import before it starts");
23-
wit_bindgen::block_on(async {
24-
let (tx, rx) = wit_future::new(|| unreachable!());
25-
let import = Box::pin(pending_import(rx));
26-
drop(import);
27-
tx.write(()).await.unwrap_err();
28-
});
29-
30-
println!("test cancelling an import in the started state");
31-
wit_bindgen::block_on(async {
32-
let (tx1, rx1) = wit_future::new(|| unreachable!());
33-
let (tx2, rx2) = wit_future::new(|| unreachable!());
34-
35-
// create a task in the "started" state, but don't complete it yet
36-
let mut started_import = Box::pin(pending_import(rx1));
37-
assert!(started_import
38-
.as_mut()
39-
.poll(&mut Context::from_waker(noop_waker_ref()))
40-
.is_pending());
41-
42-
// request the other component sets its backpressure flag meaning we
43-
// won't be able to create new tasks in the "started" state.
44-
backpressure_set(true);
45-
let mut starting_import = Box::pin(pending_import(rx2));
46-
assert!(starting_import
47-
.as_mut()
48-
.poll(&mut Context::from_waker(noop_waker_ref()))
49-
.is_pending());
50-
51-
// Now cancel the "starting" import. This should notably drop handles in
52-
// arguments since they get re-acquired during cancellation
53-
drop(starting_import);
54-
55-
// cancel our in-progress export
56-
drop(started_import);
57-
58-
backpressure_set(false);
59-
60-
// both channels should be dropped
61-
tx1.write(()).await.unwrap_err();
62-
tx2.write(()).await.unwrap_err();
63-
});
64-
65-
// Race an import's cancellation with a status code saying it's done.
66-
println!("test cancellation with a status code saying it's done");
67-
wit_bindgen::block_on(async {
68-
// Start a subtask and get it into the "started" state
69-
let (tx, rx) = wit_future::new(|| unreachable!());
70-
let mut import = Box::pin(pending_import(rx));
71-
assert!(import
72-
.as_mut()
73-
.poll(&mut Context::from_waker(noop_waker_ref()))
74-
.is_pending());
75-
76-
// Complete the subtask, but don't see the completion in Rust yet.
77-
tx.write(()).await.unwrap();
78-
79-
// Let the subtask's completion notification make its way to our task
80-
// here.
81-
for _ in 0..5 {
82-
yield_async().await;
9+
struct Component;
10+
11+
export!(Component);
12+
13+
impl Guest for Component {
14+
async fn run() {
15+
println!("test cancelling an import in progress");
16+
{
17+
let (tx, rx) = wit_future::new(|| unreachable!());
18+
let mut import = Box::pin(pending_import(rx));
19+
assert!(import
20+
.as_mut()
21+
.poll(&mut Context::from_waker(noop_waker_ref()))
22+
.is_pending());
23+
drop(import);
24+
tx.write(()).await.unwrap_err();
8325
}
8426

85-
// Now cancel the import, despite it actually being done. This should
86-
// realize that the cancellation is racing completion.
87-
drop(import);
88-
});
89-
90-
// Race an import's cancellation with a pending status code indicating that
91-
// it's transitioning from started => returned.
92-
println!("race cancellation with pending status code");
93-
wit_bindgen::block_on(async {
94-
// Start a subtask and get it into the "started" state
95-
let (tx1, rx1) = wit_future::new(|| unreachable!());
96-
let mut started_import = Box::pin(pending_import(rx1));
97-
assert!(started_import
98-
.as_mut()
99-
.poll(&mut Context::from_waker(noop_waker_ref()))
100-
.is_pending());
101-
102-
// force the next subtask to start out in the "starting" state, not the
103-
// "started" state.
104-
backpressure_set(true);
105-
let (tx2, rx2) = wit_future::new(|| unreachable!());
106-
let mut starting_import = Box::pin(pending_import(rx2));
107-
assert!(starting_import
108-
.as_mut()
109-
.poll(&mut Context::from_waker(noop_waker_ref()))
110-
.is_pending());
111-
112-
// Disable backpressure in the other component which will let the
113-
// `starting_import`, previously in the "STARTING" state, get a queued up
114-
// notification that it's entered the "STARTED" state.
115-
backpressure_set(false);
116-
for _ in 0..5 {
117-
yield_async().await;
27+
println!("test cancelling an import before it starts");
28+
{
29+
let (tx, rx) = wit_future::new(|| unreachable!());
30+
let import = Box::pin(pending_import(rx));
31+
drop(import);
32+
tx.write(()).await.unwrap_err();
11833
}
11934

120-
// Now cancel the `starting_import`. This should correctly pick up the
121-
// STARTING => STARTED state transition and handle that correctly.
122-
drop(starting_import);
35+
println!("test cancelling an import in the started state");
36+
{
37+
let (tx1, rx1) = wit_future::new(|| unreachable!());
38+
let (tx2, rx2) = wit_future::new(|| unreachable!());
39+
40+
// create a task in the "started" state, but don't complete it yet
41+
let mut started_import = Box::pin(pending_import(rx1));
42+
assert!(started_import
43+
.as_mut()
44+
.poll(&mut Context::from_waker(noop_waker_ref()))
45+
.is_pending());
46+
47+
// request the other component sets its backpressure flag meaning we
48+
// won't be able to create new tasks in the "started" state.
49+
backpressure_set(true);
50+
let mut starting_import = Box::pin(pending_import(rx2));
51+
assert!(starting_import
52+
.as_mut()
53+
.poll(&mut Context::from_waker(noop_waker_ref()))
54+
.is_pending());
55+
56+
// Now cancel the "starting" import. This should notably drop handles in
57+
// arguments since they get re-acquired during cancellation
58+
drop(starting_import);
59+
60+
// cancel our in-progress export
61+
drop(started_import);
62+
63+
backpressure_set(false);
64+
65+
// both channels should be dropped
66+
tx1.write(()).await.unwrap_err();
67+
tx2.write(()).await.unwrap_err();
68+
}
12369

124-
// Our future to the import we cancelled shouldn't be able to complete
125-
// its write.
126-
tx2.write(()).await.unwrap_err();
70+
// Race an import's cancellation with a status code saying it's done.
71+
println!("test cancellation with a status code saying it's done");
72+
{
73+
// Start a subtask and get it into the "started" state
74+
let (tx, rx) = wit_future::new(|| unreachable!());
75+
let mut import = Box::pin(pending_import(rx));
76+
assert!(import
77+
.as_mut()
78+
.poll(&mut Context::from_waker(noop_waker_ref()))
79+
.is_pending());
80+
81+
// Complete the subtask, but don't see the completion in Rust yet.
82+
tx.write(()).await.unwrap();
83+
84+
// Let the subtask's completion notification make its way to our task
85+
// here.
86+
for _ in 0..5 {
87+
yield_async().await;
88+
}
89+
90+
// Now cancel the import, despite it actually being done. This should
91+
// realize that the cancellation is racing completion.
92+
drop(import);
93+
}
12794

128-
// Complete the other import normally just to assert that it's not
129-
// cancelled and able to proceed as usual.
130-
tx1.write(()).await.unwrap();
131-
started_import.await;
132-
});
95+
// Race an import's cancellation with a pending status code indicating that
96+
// it's transitioning from started => returned.
97+
println!("race cancellation with pending status code");
98+
{
99+
// Start a subtask and get it into the "started" state
100+
let (tx1, rx1) = wit_future::new(|| unreachable!());
101+
let mut started_import = Box::pin(pending_import(rx1));
102+
assert!(started_import
103+
.as_mut()
104+
.poll(&mut Context::from_waker(noop_waker_ref()))
105+
.is_pending());
106+
107+
// force the next subtask to start out in the "starting" state, not the
108+
// "started" state.
109+
backpressure_set(true);
110+
let (tx2, rx2) = wit_future::new(|| unreachable!());
111+
let mut starting_import = Box::pin(pending_import(rx2));
112+
assert!(starting_import
113+
.as_mut()
114+
.poll(&mut Context::from_waker(noop_waker_ref()))
115+
.is_pending());
116+
117+
// Disable backpressure in the other component which will let the
118+
// `starting_import`, previously in the "STARTING" state, get a queued up
119+
// notification that it's entered the "STARTED" state.
120+
backpressure_set(false);
121+
for _ in 0..5 {
122+
yield_async().await;
123+
}
124+
125+
// Now cancel the `starting_import`. This should correctly pick up the
126+
// STARTING => STARTED state transition and handle that correctly.
127+
drop(starting_import);
128+
129+
// Our future to the import we cancelled shouldn't be able to complete
130+
// its write.
131+
tx2.write(()).await.unwrap_err();
132+
133+
// Complete the other import normally just to assert that it's not
134+
// cancelled and able to proceed as usual.
135+
tx1.write(()).await.unwrap();
136+
started_import.await;
137+
}
138+
}
133139
}

tests/runtime-async/async/cancel-import/test.wit

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ world test {
1111

1212
world runner {
1313
import i;
14+
15+
export run: async func();
1416
}

tests/runtime-async/async/future-cancel-read/runner.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
//@ args = '--rename my:test/i=test'
1+
//@ args = '--rename my:test/i=test --async=-run'
22

33
#include <assert.h>
44
#include <runner.h>
55

6-
int main() {
6+
void exports_runner_run() {
77
{
88
test_future_u32_writer_t writer;
99
test_future_u32_t reader = test_future_u32_new(&writer);

0 commit comments

Comments
 (0)