Skip to content

Commit 25b3076

Browse files
authored
Merge pull request #208 from saulecabrera/sockets-send-receive-tests
sockets: Add tests for tcp/{connect, listen, send,receive}
2 parents 99ceffe + c546ee9 commit 25b3076

16 files changed

Lines changed: 717 additions & 12 deletions

tests/rust/wasm32-wasip3/src/bin/monotonic-clock.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
use test_wasm32_wasip3::cli::{export, exports::wasi::cli::run::Guest};
12
use test_wasm32_wasip3::clocks::{
2-
DAY, MILLISECOND, export,
3-
exports::wasi::cli::run::Guest,
3+
DAY, MILLISECOND,
44
wasi::clocks::monotonic_clock::{self, Duration, Mark},
55
};
66

tests/rust/wasm32-wasip3/src/bin/multi-clock-wait.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
use core::task::{Context, Poll, Waker};
22
use std::future::Future;
3-
use test_wasm32_wasip3::clocks::{
4-
export,
5-
exports::wasi::cli::run::Guest,
6-
wasi::clocks::monotonic_clock::{self, Mark},
7-
};
3+
use test_wasm32_wasip3::cli::{export, exports::wasi::cli::run::Guest};
4+
use test_wasm32_wasip3::clocks::wasi::clocks::monotonic_clock::{self, Mark};
85

96
// Offsets relative to "now" at which to wait_until(), in nanoseconds.
107
// These are 20 values chosen uniformly randomly over the range [-5
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"proposals": [
3+
"sockets"
4+
],
5+
"operations": [
6+
{
7+
"type": "run"
8+
},
9+
{
10+
"type": "wait"
11+
}
12+
]
13+
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
use test_wasm32_wasip3::cli::{export, exports::wasi::cli::run::Guest};
2+
use test_wasm32_wasip3::sockets::wasi::sockets::types::{
3+
ErrorCode, IpAddress, IpAddressFamily, IpSocketAddress, TcpSocket,
4+
};
5+
6+
const PORT: u16 = 42;
7+
8+
struct Component;
9+
10+
export!(Component);
11+
12+
async fn test_invalid_address_family(family: IpAddressFamily) {
13+
let sock = TcpSocket::create(family).unwrap();
14+
15+
let addr = match family {
16+
IpAddressFamily::Ipv4 => IpSocketAddress::localhost(IpAddressFamily::Ipv6, PORT),
17+
IpAddressFamily::Ipv6 => IpSocketAddress::localhost(IpAddressFamily::Ipv4, PORT),
18+
};
19+
20+
let result = sock.connect(addr).await;
21+
assert!(matches!(result, Err(ErrorCode::InvalidArgument)));
22+
}
23+
24+
async fn test_non_unicast(family: IpAddressFamily) {
25+
let mut non_unicast_addresses = Vec::new();
26+
27+
match family {
28+
IpAddressFamily::Ipv4 => {
29+
// Multicast
30+
for nibble in 224..=239 {
31+
non_unicast_addresses.push(IpAddress::Ipv4((nibble, 0, 0, 1)));
32+
}
33+
// Limited broadcast
34+
non_unicast_addresses.push(IpAddress::Ipv4((255, 255, 255, 255)));
35+
}
36+
IpAddressFamily::Ipv6 => {
37+
// Multicast
38+
for b in 0xff00..=0xffff {
39+
non_unicast_addresses.push(IpAddress::Ipv6((b, 0, 0, 0, 0, 0, 0, 1)));
40+
}
41+
}
42+
};
43+
44+
for addr in non_unicast_addresses {
45+
let sock = TcpSocket::create(family).unwrap();
46+
let socket_addr = IpSocketAddress::new(addr, PORT);
47+
let result = sock.connect(socket_addr).await;
48+
49+
assert!(matches!(result, Err(ErrorCode::InvalidArgument)));
50+
}
51+
}
52+
53+
async fn test_reject_dual_stack() {
54+
let sock = TcpSocket::create(IpAddressFamily::Ipv6).unwrap();
55+
let addr = IpSocketAddress::ipv4_mapped_ipv6_localhost(PORT);
56+
let result = sock.connect(addr).await;
57+
58+
assert!(matches!(result, Err(ErrorCode::InvalidArgument)));
59+
}
60+
61+
async fn test_unspecified_remote_addr(family: IpAddressFamily) {
62+
let sock = TcpSocket::create(family).unwrap();
63+
let addr = IpSocketAddress::unspecified(family, PORT);
64+
let result = sock.connect(addr).await;
65+
66+
assert!(matches!(result, Err(ErrorCode::InvalidArgument)));
67+
}
68+
69+
async fn test_connect_0_port(family: IpAddressFamily) {
70+
let sock = TcpSocket::create(family).unwrap();
71+
let addr = IpSocketAddress::localhost(family, 0);
72+
let result = sock.connect(addr).await;
73+
74+
assert!(matches!(result, Err(ErrorCode::InvalidArgument)));
75+
}
76+
77+
async fn test_connected_state(family: IpAddressFamily) {
78+
let listener = TcpSocket::create(family).unwrap();
79+
listener
80+
.bind(IpSocketAddress::localhost(family, 0))
81+
.unwrap();
82+
let server_addr = listener.get_local_address().unwrap();
83+
listener.listen().unwrap();
84+
85+
let sock = TcpSocket::create(family).unwrap();
86+
let result = sock.connect(server_addr).await;
87+
assert!(result.is_ok());
88+
89+
let result = sock.connect(server_addr).await;
90+
assert!(matches!(result, Err(ErrorCode::InvalidState)));
91+
}
92+
93+
async fn test_listening_state(family: IpAddressFamily) {
94+
let listener = TcpSocket::create(family).unwrap();
95+
listener
96+
.bind(IpSocketAddress::localhost(family, 0))
97+
.unwrap();
98+
listener.listen().unwrap();
99+
100+
let result = listener
101+
.connect(IpSocketAddress::localhost(family, PORT))
102+
.await;
103+
assert!(matches!(result, Err(ErrorCode::InvalidState)));
104+
}
105+
106+
async fn test_connection_refused(family: IpAddressFamily) {
107+
let sock = TcpSocket::create(family).unwrap();
108+
sock.bind(IpSocketAddress::localhost(family, 0)).unwrap();
109+
let addr = sock.get_local_address().unwrap();
110+
drop(sock);
111+
112+
let sock2 = TcpSocket::create(family).unwrap();
113+
let result = sock2.connect(addr).await;
114+
115+
assert!(matches!(result, Err(ErrorCode::ConnectionRefused)));
116+
}
117+
118+
async fn test_explicit_bind(family: IpAddressFamily) {
119+
let (listener, mut accept) = {
120+
let bind_address = IpSocketAddress::localhost(family, 0);
121+
let listener = TcpSocket::create(family).unwrap();
122+
listener.bind(bind_address).unwrap();
123+
let accept = listener.listen().unwrap();
124+
(listener, accept)
125+
};
126+
127+
let listener_address = listener.get_local_address().unwrap();
128+
let client = TcpSocket::create(family).unwrap();
129+
130+
client.bind(IpSocketAddress::localhost(family, 0)).unwrap();
131+
132+
futures::join!(
133+
async {
134+
client.connect(listener_address).await.unwrap();
135+
},
136+
async {
137+
accept.next().await.unwrap();
138+
}
139+
);
140+
}
141+
142+
async fn test_explicit_bind_addrinuse(family: IpAddressFamily) {
143+
let listener = {
144+
let bind_address = IpSocketAddress::localhost(family, 0);
145+
let listener = TcpSocket::create(family).unwrap();
146+
listener.bind(bind_address).unwrap();
147+
listener
148+
};
149+
150+
let listener_address = listener.get_local_address().unwrap();
151+
let client = TcpSocket::create(family).unwrap();
152+
153+
let result = client.bind(listener_address);
154+
assert!(matches!(result, Err(ErrorCode::AddressInUse)));
155+
}
156+
157+
impl Guest for Component {
158+
async fn run() -> Result<(), ()> {
159+
test_invalid_address_family(IpAddressFamily::Ipv4).await;
160+
test_invalid_address_family(IpAddressFamily::Ipv6).await;
161+
test_non_unicast(IpAddressFamily::Ipv4).await;
162+
test_non_unicast(IpAddressFamily::Ipv6).await;
163+
test_reject_dual_stack().await;
164+
test_unspecified_remote_addr(IpAddressFamily::Ipv4).await;
165+
test_unspecified_remote_addr(IpAddressFamily::Ipv6).await;
166+
test_connect_0_port(IpAddressFamily::Ipv4).await;
167+
test_connect_0_port(IpAddressFamily::Ipv6).await;
168+
test_connection_refused(IpAddressFamily::Ipv4).await;
169+
test_connection_refused(IpAddressFamily::Ipv6).await;
170+
test_connected_state(IpAddressFamily::Ipv4).await;
171+
test_connected_state(IpAddressFamily::Ipv6).await;
172+
test_listening_state(IpAddressFamily::Ipv4).await;
173+
test_listening_state(IpAddressFamily::Ipv6).await;
174+
test_explicit_bind(IpAddressFamily::Ipv4).await;
175+
test_explicit_bind(IpAddressFamily::Ipv6).await;
176+
test_explicit_bind_addrinuse(IpAddressFamily::Ipv4).await;
177+
test_explicit_bind_addrinuse(IpAddressFamily::Ipv6).await;
178+
Ok(())
179+
}
180+
}
181+
182+
fn main() {
183+
unreachable!()
184+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"proposals": [
3+
"sockets"
4+
],
5+
"operations": [
6+
{
7+
"type": "run"
8+
},
9+
{
10+
"type": "wait"
11+
}
12+
]
13+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use test_wasm32_wasip3::cli::{export, exports::wasi::cli::run::Guest};
2+
use test_wasm32_wasip3::sockets::wasi::sockets::types::{
3+
ErrorCode, IpAddressFamily, IpSocketAddress, TcpSocket,
4+
};
5+
6+
struct Component;
7+
8+
export!(Component);
9+
10+
fn test_with_bind(family: IpAddressFamily) {
11+
let addr = IpSocketAddress::localhost(family, 0);
12+
let sock = TcpSocket::create(family).unwrap();
13+
sock.bind(addr).unwrap();
14+
assert!(sock.listen().is_ok());
15+
}
16+
17+
fn test_without_bind(family: IpAddressFamily) {
18+
// Without an explicit bind, `listen` will assign an ephemeral
19+
// port.
20+
let sock = TcpSocket::create(family).unwrap();
21+
assert!(sock.get_local_address().is_err());
22+
assert!(sock.listen().is_ok());
23+
assert!(sock.get_local_address().is_ok());
24+
}
25+
26+
async fn test_inherited_properties(family: IpAddressFamily) {
27+
let addr = IpSocketAddress::localhost(family, 0);
28+
let sock = TcpSocket::create(family).unwrap();
29+
sock.bind(addr).unwrap();
30+
let client = TcpSocket::create(family).unwrap();
31+
let local_addr = sock.get_local_address().unwrap();
32+
33+
let mut accept = sock.listen().unwrap();
34+
futures::join!(
35+
async {
36+
let next = accept.next().await.unwrap();
37+
assert_eq!(next.get_address_family(), sock.get_address_family());
38+
assert_eq!(next.get_keep_alive_enabled(), sock.get_keep_alive_enabled());
39+
assert_eq!(
40+
next.get_keep_alive_idle_time(),
41+
sock.get_keep_alive_idle_time()
42+
);
43+
assert_eq!(
44+
next.get_keep_alive_interval(),
45+
sock.get_keep_alive_interval()
46+
);
47+
assert_eq!(next.get_keep_alive_count(), sock.get_keep_alive_count());
48+
assert_eq!(next.get_hop_limit(), sock.get_hop_limit());
49+
assert_eq!(
50+
next.get_receive_buffer_size(),
51+
sock.get_receive_buffer_size()
52+
);
53+
assert_eq!(next.get_send_buffer_size(), sock.get_send_buffer_size());
54+
},
55+
async {
56+
client.connect(local_addr).await.unwrap();
57+
}
58+
);
59+
}
60+
61+
fn test_listening(fam: IpAddressFamily) {
62+
let addr = IpSocketAddress::localhost(fam, 0);
63+
let sock = TcpSocket::create(fam).unwrap();
64+
sock.bind(addr).unwrap();
65+
sock.listen().unwrap();
66+
let result = sock.listen();
67+
assert!(matches!(result, Err(ErrorCode::InvalidState)));
68+
}
69+
70+
impl Guest for Component {
71+
async fn run() -> Result<(), ()> {
72+
test_with_bind(IpAddressFamily::Ipv4);
73+
test_with_bind(IpAddressFamily::Ipv6);
74+
test_without_bind(IpAddressFamily::Ipv4);
75+
test_without_bind(IpAddressFamily::Ipv6);
76+
test_inherited_properties(IpAddressFamily::Ipv4).await;
77+
test_inherited_properties(IpAddressFamily::Ipv6).await;
78+
test_listening(IpAddressFamily::Ipv4);
79+
test_listening(IpAddressFamily::Ipv6);
80+
Ok(())
81+
}
82+
}
83+
84+
fn main() {
85+
unreachable!()
86+
}

0 commit comments

Comments
 (0)