Skip to content

Commit 5c4f359

Browse files
committed
feat: implement wasip3
Signed-off-by: Roman Volosatovs <[email protected]>
1 parent d6e14f6 commit 5c4f359

Some content is hidden

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

62 files changed

+5436
-3
lines changed

ci/vendor-wit.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ make_vendor "wasi-config" "config@f4d699b"
6363

6464
make_vendor "wasi-keyvalue" "keyvalue@219ea36"
6565

66+
make_vendor "wasi/src/p3" "
67+
68+
69+
filesystem@[email protected]
70+
71+
72+
"
73+
6674
rm -rf $cache_dir
6775

6876
# Separately (for now), vendor the `wasi-nn` WIT files since their retrieval is

crates/test-programs/artifacts/build.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ fn build_and_generate_tests() {
6969
// Bucket, based on the name of the test, into a "kind" which generates
7070
// a `foreach_*` macro below.
7171
let kind = match target.as_str() {
72+
s if s.starts_with("cli_0_3") => "cli_0_3",
73+
s if s.starts_with("clocks_0_3") => "clocks_0_3",
74+
s if s.starts_with("filesystem_0_3") => "filesystem_0_3",
75+
s if s.starts_with("random_0_3") => "random_0_3",
76+
s if s.starts_with("sockets_0_3") => "sockets_0_3",
7277
s if s.starts_with("http_") => "http",
7378
s if s.starts_with("preview1_") => "preview1",
7479
s if s.starts_with("preview2_") => "preview2",
@@ -102,6 +107,11 @@ fn build_and_generate_tests() {
102107
}
103108
let adapter = match target.as_str() {
104109
"reactor" => &reactor_adapter,
110+
s if s.starts_with("cli_0_3") => &reactor_adapter,
111+
s if s.starts_with("clocks_0_3") => &reactor_adapter,
112+
s if s.starts_with("filesystem_0_3") => &reactor_adapter,
113+
s if s.starts_with("random_0_3") => &reactor_adapter,
114+
s if s.starts_with("sockets_0_3") => &reactor_adapter,
105115
s if s.starts_with("async_") => &reactor_adapter,
106116
s if s.starts_with("api_proxy") => &proxy_adapter,
107117
_ => &command_adapter,
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use core::future::Future as _;
2+
use core::pin::pin;
3+
use core::ptr;
4+
use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
5+
6+
use test_programs::p3::wasi::clocks::monotonic_clock;
7+
8+
struct Component;
9+
10+
test_programs::p3::export!(Component);
11+
12+
impl test_programs::p3::exports::wasi::cli::run::Guest for Component {
13+
async fn run() -> Result<(), ()> {
14+
sleep_10ms().await;
15+
sleep_0ms();
16+
sleep_backwards_in_time();
17+
Ok(())
18+
}
19+
}
20+
21+
// Adapted from https://github.com/rust-lang/rust/blob/cd805f09ffbfa3896c8f50a619de9b67e1d9f3c3/library/core/src/task/wake.rs#L63-L77
22+
// TODO: Replace by `Waker::noop` once MSRV is raised to 1.85
23+
const NOOP_RAW_WAKER: RawWaker = {
24+
const VTABLE: RawWakerVTable = RawWakerVTable::new(
25+
// Cloning just returns a new no-op raw waker
26+
|_| NOOP_RAW_WAKER,
27+
// `wake` does nothing
28+
|_| {},
29+
// `wake_by_ref` does nothing
30+
|_| {},
31+
// Dropping does nothing as we don't allocate anything
32+
|_| {},
33+
);
34+
RawWaker::new(ptr::null(), &VTABLE)
35+
};
36+
37+
const NOOP_WAKER: &'static Waker = &unsafe { Waker::from_raw(NOOP_RAW_WAKER) };
38+
39+
async fn sleep_10ms() {
40+
let dur = 10_000_000;
41+
monotonic_clock::wait_until(monotonic_clock::now() + dur).await;
42+
monotonic_clock::wait_for(dur).await;
43+
}
44+
45+
fn sleep_0ms() {
46+
let mut cx = Context::from_waker(NOOP_WAKER);
47+
48+
assert_eq!(
49+
pin!(monotonic_clock::wait_until(monotonic_clock::now())).poll(&mut cx),
50+
Poll::Ready(()),
51+
"waiting until now() is ready immediately",
52+
);
53+
assert_eq!(
54+
pin!(monotonic_clock::wait_for(0)).poll(&mut cx),
55+
Poll::Ready(()),
56+
"waiting for 0 is ready immediately",
57+
);
58+
}
59+
60+
fn sleep_backwards_in_time() {
61+
let mut cx = Context::from_waker(NOOP_WAKER);
62+
63+
assert_eq!(
64+
pin!(monotonic_clock::wait_until(monotonic_clock::now() - 1)).poll(&mut cx),
65+
Poll::Ready(()),
66+
"waiting until instant which has passed is ready immediately",
67+
);
68+
}
69+
70+
fn main() {}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use test_programs::p3::wasi::random;
2+
3+
struct Component;
4+
5+
test_programs::p3::export!(Component);
6+
7+
impl test_programs::p3::exports::wasi::cli::run::Guest for Component {
8+
async fn run() -> Result<(), ()> {
9+
let mut bytes = [0_u8; 256];
10+
getrandom::getrandom(&mut bytes).unwrap();
11+
12+
assert!(bytes.iter().any(|x| *x != 0));
13+
14+
// Acquired random bytes should be of the expected length.
15+
let array = random::random::get_random_bytes(100);
16+
assert_eq!(array.len(), 100);
17+
18+
// It shouldn't take 100+ tries to get a nonzero random integer.
19+
for i in 0.. {
20+
if random::random::get_random_u64() == 0 {
21+
continue;
22+
}
23+
assert!(i < 100);
24+
break;
25+
}
26+
27+
// The `insecure_seed` API should return the same result each time.
28+
let (a1, b1) = random::insecure_seed::insecure_seed();
29+
let (a2, b2) = random::insecure_seed::insecure_seed();
30+
assert_eq!(a1, a2);
31+
assert_eq!(b1, b2);
32+
33+
// Acquired random bytes should be of the expected length.
34+
let array = random::insecure::get_insecure_random_bytes(100);
35+
assert_eq!(array.len(), 100);
36+
37+
// It shouldn't take 100+ tries to get a nonzero random integer.
38+
for i in 0.. {
39+
if random::insecure::get_insecure_random_u64() == 0 {
40+
continue;
41+
}
42+
assert!(i < 100);
43+
break;
44+
}
45+
Ok(())
46+
}
47+
}
48+
49+
fn main() {}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use futures::try_join;
2+
use test_programs::p3::wasi::sockets::ip_name_lookup::{resolve_addresses, ErrorCode};
3+
use test_programs::p3::wasi::sockets::types::IpAddress;
4+
5+
struct Component;
6+
7+
test_programs::p3::export!(Component);
8+
9+
async fn resolve_one(name: &str) -> Result<IpAddress, ErrorCode> {
10+
Ok(resolve_addresses(name).await?.first().unwrap().to_owned())
11+
}
12+
13+
impl test_programs::p3::exports::wasi::cli::run::Guest for Component {
14+
async fn run() -> Result<(), ()> {
15+
// Valid domains
16+
try_join!(
17+
resolve_addresses("localhost"),
18+
resolve_addresses("example.com")
19+
)
20+
.unwrap();
21+
22+
// NB: this is an actual real resolution, so it might time out, might cause
23+
// issues, etc. This result is ignored to prevent flaky failures in CI.
24+
let _ = resolve_addresses("münchen.de").await;
25+
26+
// Valid IP addresses
27+
assert_eq!(
28+
resolve_one("0.0.0.0").await.unwrap(),
29+
IpAddress::IPV4_UNSPECIFIED
30+
);
31+
assert_eq!(
32+
resolve_one("127.0.0.1").await.unwrap(),
33+
IpAddress::IPV4_LOOPBACK
34+
);
35+
assert_eq!(
36+
resolve_one("192.0.2.0").await.unwrap(),
37+
IpAddress::Ipv4((192, 0, 2, 0))
38+
);
39+
assert_eq!(
40+
resolve_one("::").await.unwrap(),
41+
IpAddress::IPV6_UNSPECIFIED
42+
);
43+
assert_eq!(resolve_one("::1").await.unwrap(), IpAddress::IPV6_LOOPBACK);
44+
assert_eq!(
45+
resolve_one("[::]").await.unwrap(),
46+
IpAddress::IPV6_UNSPECIFIED
47+
);
48+
assert_eq!(
49+
resolve_one("2001:0db8:0:0:0:0:0:0").await.unwrap(),
50+
IpAddress::Ipv6((0x2001, 0x0db8, 0, 0, 0, 0, 0, 0))
51+
);
52+
assert_eq!(
53+
resolve_one("dead:beef::").await.unwrap(),
54+
IpAddress::Ipv6((0xdead, 0xbeef, 0, 0, 0, 0, 0, 0))
55+
);
56+
assert_eq!(
57+
resolve_one("dead:beef::0").await.unwrap(),
58+
IpAddress::Ipv6((0xdead, 0xbeef, 0, 0, 0, 0, 0, 0))
59+
);
60+
assert_eq!(
61+
resolve_one("DEAD:BEEF::0").await.unwrap(),
62+
IpAddress::Ipv6((0xdead, 0xbeef, 0, 0, 0, 0, 0, 0))
63+
);
64+
65+
// Invalid inputs
66+
assert_eq!(
67+
resolve_addresses("").await.unwrap_err(),
68+
ErrorCode::InvalidArgument
69+
);
70+
assert_eq!(
71+
resolve_addresses(" ").await.unwrap_err(),
72+
ErrorCode::InvalidArgument
73+
);
74+
assert_eq!(
75+
resolve_addresses("a.b<&>").await.unwrap_err(),
76+
ErrorCode::InvalidArgument
77+
);
78+
assert_eq!(
79+
resolve_addresses("127.0.0.1:80").await.unwrap_err(),
80+
ErrorCode::InvalidArgument
81+
);
82+
assert_eq!(
83+
resolve_addresses("[::]:80").await.unwrap_err(),
84+
ErrorCode::InvalidArgument
85+
);
86+
assert_eq!(
87+
resolve_addresses("http://example.com/").await.unwrap_err(),
88+
ErrorCode::InvalidArgument
89+
);
90+
Ok(())
91+
}
92+
}
93+
94+
fn main() {}

0 commit comments

Comments
 (0)