1 use futures::join;
2 use test_programs::p3::wasi::sockets::types::{
3 ErrorCode, IpAddress, IpAddressFamily, IpSocketAddress, TcpSocket,
4 };
5 use test_programs::sockets::supports_ipv6;
6
7 struct Component;
8
9 test_programs::p3::export!(Component);
10
test_tcp_unbound_state_invariants(family: IpAddressFamily)11 fn test_tcp_unbound_state_invariants(family: IpAddressFamily) {
12 let sock = TcpSocket::create(family).unwrap();
13
14 // TODO: Test send and receive
15 //assert!(matches!(
16 // sock.shutdown(ShutdownType::Both),
17 // Err(ErrorCode::InvalidState)
18 //));
19 assert!(matches!(
20 sock.get_local_address(),
21 Err(ErrorCode::InvalidState)
22 ));
23 assert!(matches!(
24 sock.get_remote_address(),
25 Err(ErrorCode::InvalidState)
26 ));
27 assert!(!sock.get_is_listening());
28 assert_eq!(sock.get_address_family(), family);
29
30 sock.set_listen_backlog_size(32).unwrap();
31
32 assert!(sock.get_keep_alive_enabled().is_ok());
33 sock.set_keep_alive_enabled(false).unwrap();
34 assert_eq!(sock.get_keep_alive_enabled().unwrap(), false);
35
36 assert!(sock.get_keep_alive_idle_time().is_ok());
37 sock.set_keep_alive_idle_time(1).unwrap();
38
39 assert!(sock.get_keep_alive_interval().is_ok());
40 sock.set_keep_alive_interval(1).unwrap();
41
42 assert!(sock.get_keep_alive_count().is_ok());
43 sock.set_keep_alive_count(1).unwrap();
44
45 assert!(sock.get_hop_limit().is_ok());
46 sock.set_hop_limit(255).unwrap();
47 assert_eq!(sock.get_hop_limit().unwrap(), 255);
48
49 assert!(sock.get_receive_buffer_size().is_ok());
50 sock.set_receive_buffer_size(16000).unwrap();
51
52 assert!(sock.get_send_buffer_size().is_ok());
53 sock.set_send_buffer_size(16000).unwrap();
54 }
55
test_tcp_bound_state_invariants(family: IpAddressFamily)56 fn test_tcp_bound_state_invariants(family: IpAddressFamily) {
57 let bind_address = IpSocketAddress::new(IpAddress::new_loopback(family), 0);
58 let sock = TcpSocket::create(family).unwrap();
59 sock.bind(bind_address).unwrap();
60
61 assert!(matches!(
62 sock.bind(bind_address),
63 Err(ErrorCode::InvalidState)
64 ));
65 // TODO: Test send and receive
66 //assert!(matches!(
67 // sock.shutdown(ShutdownType::Both),
68 // Err(ErrorCode::InvalidState)
69 //));
70
71 assert!(sock.get_local_address().is_ok());
72 assert!(matches!(
73 sock.get_remote_address(),
74 Err(ErrorCode::InvalidState)
75 ));
76 assert!(!sock.get_is_listening());
77 assert_eq!(sock.get_address_family(), family);
78
79 sock.set_listen_backlog_size(32).unwrap();
80
81 assert!(sock.get_keep_alive_enabled().is_ok());
82 sock.set_keep_alive_enabled(false).unwrap();
83 assert_eq!(sock.get_keep_alive_enabled().unwrap(), false);
84
85 assert!(sock.get_keep_alive_idle_time().is_ok());
86 sock.set_keep_alive_idle_time(1).unwrap();
87
88 assert!(sock.get_keep_alive_interval().is_ok());
89 sock.set_keep_alive_interval(1).unwrap();
90
91 assert!(sock.get_keep_alive_count().is_ok());
92 sock.set_keep_alive_count(1).unwrap();
93
94 assert!(sock.get_hop_limit().is_ok());
95 sock.set_hop_limit(255).unwrap();
96 assert_eq!(sock.get_hop_limit().unwrap(), 255);
97
98 assert!(sock.get_receive_buffer_size().is_ok());
99 sock.set_receive_buffer_size(16000).unwrap();
100
101 assert!(sock.get_send_buffer_size().is_ok());
102 sock.set_send_buffer_size(16000).unwrap();
103 }
104
test_tcp_listening_state_invariants(family: IpAddressFamily)105 async fn test_tcp_listening_state_invariants(family: IpAddressFamily) {
106 let bind_address = IpSocketAddress::new(IpAddress::new_loopback(family), 0);
107 let sock = TcpSocket::create(family).unwrap();
108 sock.bind(bind_address).unwrap();
109 sock.listen().unwrap();
110
111 assert!(matches!(
112 sock.bind(bind_address),
113 Err(ErrorCode::InvalidState)
114 ));
115 assert!(matches!(
116 sock.connect(IpSocketAddress::new(IpAddress::new_loopback(family), 1))
117 .await,
118 Err(ErrorCode::InvalidState)
119 ));
120 assert!(matches!(sock.listen(), Err(ErrorCode::InvalidState)));
121 // Skipping: tcp::accept
122 // TODO: Test send and receive
123 //assert!(matches!(
124 // sock.shutdown(ShutdownType::Both),
125 // Err(ErrorCode::InvalidState)
126 //));
127
128 assert!(sock.get_local_address().is_ok());
129 assert!(matches!(
130 sock.get_remote_address(),
131 Err(ErrorCode::InvalidState)
132 ));
133 assert!(sock.get_is_listening());
134 assert_eq!(sock.get_address_family(), family);
135
136 assert!(matches!(
137 sock.set_listen_backlog_size(32),
138 Ok(_) | Err(ErrorCode::NotSupported)
139 ));
140
141 assert!(sock.get_keep_alive_enabled().is_ok());
142 sock.set_keep_alive_enabled(false).unwrap();
143 assert_eq!(sock.get_keep_alive_enabled().unwrap(), false);
144
145 assert!(sock.get_keep_alive_idle_time().is_ok());
146 sock.set_keep_alive_idle_time(1).unwrap();
147
148 assert!(sock.get_keep_alive_interval().is_ok());
149 sock.set_keep_alive_interval(1).unwrap();
150
151 assert!(sock.get_keep_alive_count().is_ok());
152 sock.set_keep_alive_count(1).unwrap();
153
154 assert!(sock.get_hop_limit().is_ok());
155 sock.set_hop_limit(255).unwrap();
156 assert_eq!(sock.get_hop_limit().unwrap(), 255);
157
158 assert!(sock.get_receive_buffer_size().is_ok());
159 sock.set_receive_buffer_size(16000).unwrap();
160
161 assert!(sock.get_send_buffer_size().is_ok());
162 sock.set_send_buffer_size(16000).unwrap();
163 }
164
test_tcp_connected_state_invariants(family: IpAddressFamily)165 async fn test_tcp_connected_state_invariants(family: IpAddressFamily) {
166 let bind_address = IpSocketAddress::new(IpAddress::new_loopback(family), 0);
167 let sock_listener = TcpSocket::create(family).unwrap();
168 sock_listener.bind(bind_address).unwrap();
169 let mut accept = sock_listener.listen().unwrap();
170 let addr_listener = sock_listener.get_local_address().unwrap();
171 let sock = TcpSocket::create(family).unwrap();
172 join!(
173 async {
174 sock.connect(addr_listener).await.unwrap();
175 },
176 async {
177 accept.next().await.unwrap();
178 }
179 );
180
181 assert!(matches!(
182 sock.bind(bind_address),
183 Err(ErrorCode::InvalidState)
184 ));
185 assert!(matches!(
186 sock.connect(addr_listener).await,
187 Err(ErrorCode::InvalidState)
188 ));
189 assert!(matches!(sock.listen(), Err(ErrorCode::InvalidState)));
190 // Skipping: tcp::shutdown
191
192 assert!(sock.get_local_address().is_ok());
193 assert!(sock.get_remote_address().is_ok());
194 assert!(!sock.get_is_listening());
195 assert_eq!(sock.get_address_family(), family);
196
197 assert!(sock.get_keep_alive_enabled().is_ok());
198 sock.set_keep_alive_enabled(false).unwrap();
199 assert_eq!(sock.get_keep_alive_enabled().unwrap(), false);
200
201 assert!(sock.get_keep_alive_idle_time().is_ok());
202 sock.set_keep_alive_idle_time(1).unwrap();
203
204 assert!(sock.get_keep_alive_interval().is_ok());
205 sock.set_keep_alive_interval(1).unwrap();
206
207 assert!(sock.get_keep_alive_count().is_ok());
208 sock.set_keep_alive_count(1).unwrap();
209
210 assert!(sock.get_hop_limit().is_ok());
211 sock.set_hop_limit(255).unwrap();
212 assert_eq!(sock.get_hop_limit().unwrap(), 255);
213
214 assert!(sock.get_receive_buffer_size().is_ok());
215 sock.set_receive_buffer_size(16000).unwrap();
216
217 assert!(sock.get_send_buffer_size().is_ok());
218 sock.set_send_buffer_size(16000).unwrap();
219 }
220
221 impl test_programs::p3::exports::wasi::cli::run::Guest for Component {
run() -> Result<(), ()>222 async fn run() -> Result<(), ()> {
223 test_tcp_unbound_state_invariants(IpAddressFamily::Ipv4);
224 test_tcp_bound_state_invariants(IpAddressFamily::Ipv4);
225 test_tcp_listening_state_invariants(IpAddressFamily::Ipv4).await;
226 test_tcp_connected_state_invariants(IpAddressFamily::Ipv4).await;
227
228 if supports_ipv6() {
229 test_tcp_unbound_state_invariants(IpAddressFamily::Ipv6);
230 test_tcp_bound_state_invariants(IpAddressFamily::Ipv6);
231 test_tcp_listening_state_invariants(IpAddressFamily::Ipv6).await;
232 test_tcp_connected_state_invariants(IpAddressFamily::Ipv6).await;
233 }
234
235 Ok(())
236 }
237 }
238
main()239 fn main() {}
240