1 use test_programs::sockets::supports_ipv6;
2 use test_programs::wasi::sockets::network::{
3     ErrorCode, IpAddress, IpAddressFamily, IpSocketAddress, Network,
4 };
5 use test_programs::wasi::sockets::tcp::{ShutdownType, TcpSocket};
6 
test_tcp_unbound_state_invariants(family: IpAddressFamily)7 fn test_tcp_unbound_state_invariants(family: IpAddressFamily) {
8     let sock = TcpSocket::new(family).unwrap();
9 
10     // Skipping: tcp::start_bind
11     assert!(matches!(sock.finish_bind(), Err(ErrorCode::NotInProgress)));
12     // Skipping: tcp::start_connect
13     assert!(matches!(
14         sock.finish_connect(),
15         Err(ErrorCode::NotInProgress)
16     ));
17     assert!(matches!(
18         sock.start_listen(),
19         Err(ErrorCode::InvalidState) // Unlike POSIX, trying to listen without an explicit bind should fail in WASI.
20     ));
21     assert!(matches!(
22         sock.finish_listen(),
23         Err(ErrorCode::NotInProgress)
24     ));
25     assert!(matches!(sock.accept(), Err(ErrorCode::InvalidState)));
26     assert!(matches!(
27         sock.shutdown(ShutdownType::Both),
28         Err(ErrorCode::InvalidState)
29     ));
30 
31     assert!(matches!(sock.local_address(), Err(ErrorCode::InvalidState)));
32     assert!(matches!(
33         sock.remote_address(),
34         Err(ErrorCode::InvalidState)
35     ));
36     assert_eq!(sock.is_listening(), false);
37     assert_eq!(sock.address_family(), family);
38 
39     assert!(matches!(sock.set_listen_backlog_size(32), Ok(_)));
40     assert!(matches!(sock.keep_alive_enabled(), Ok(_)));
41     assert!(matches!(sock.set_keep_alive_enabled(false), Ok(_)));
42     assert!(matches!(sock.keep_alive_idle_time(), Ok(_)));
43     assert!(matches!(sock.set_keep_alive_idle_time(1), Ok(_)));
44     assert!(matches!(sock.keep_alive_interval(), Ok(_)));
45     assert!(matches!(sock.set_keep_alive_interval(1), Ok(_)));
46     assert!(matches!(sock.keep_alive_count(), Ok(_)));
47     assert!(matches!(sock.set_keep_alive_count(1), Ok(_)));
48     assert!(matches!(sock.hop_limit(), Ok(_)));
49     assert!(matches!(sock.set_hop_limit(255), Ok(_)));
50     assert!(matches!(sock.receive_buffer_size(), Ok(_)));
51     assert!(matches!(sock.set_receive_buffer_size(16000), Ok(_)));
52     assert!(matches!(sock.send_buffer_size(), Ok(_)));
53     assert!(matches!(sock.set_send_buffer_size(16000), Ok(_)));
54 }
55 
test_tcp_bound_state_invariants(net: &Network, family: IpAddressFamily)56 fn test_tcp_bound_state_invariants(net: &Network, family: IpAddressFamily) {
57     let bind_address = IpSocketAddress::new(IpAddress::new_loopback(family), 0);
58     let sock = TcpSocket::new(family).unwrap();
59     sock.blocking_bind(net, bind_address).unwrap();
60 
61     assert!(matches!(
62         sock.start_bind(net, bind_address),
63         Err(ErrorCode::InvalidState)
64     ));
65     assert!(matches!(sock.finish_bind(), Err(ErrorCode::NotInProgress)));
66     // Skipping: tcp::start_connect
67     assert!(matches!(
68         sock.finish_connect(),
69         Err(ErrorCode::NotInProgress)
70     ));
71     // Skipping: tcp::start_listen
72     assert!(matches!(
73         sock.finish_listen(),
74         Err(ErrorCode::NotInProgress)
75     ));
76     assert!(matches!(sock.accept(), Err(ErrorCode::InvalidState)));
77     assert!(matches!(
78         sock.shutdown(ShutdownType::Both),
79         Err(ErrorCode::InvalidState)
80     ));
81 
82     assert!(matches!(sock.local_address(), Ok(_)));
83     assert!(matches!(
84         sock.remote_address(),
85         Err(ErrorCode::InvalidState)
86     ));
87     assert_eq!(sock.is_listening(), false);
88     assert_eq!(sock.address_family(), family);
89 
90     assert!(matches!(sock.set_listen_backlog_size(32), Ok(_)));
91     assert!(matches!(sock.keep_alive_enabled(), Ok(_)));
92     assert!(matches!(sock.set_keep_alive_enabled(false), Ok(_)));
93     assert!(matches!(sock.keep_alive_idle_time(), Ok(_)));
94     assert!(matches!(sock.set_keep_alive_idle_time(1), Ok(_)));
95     assert!(matches!(sock.keep_alive_interval(), Ok(_)));
96     assert!(matches!(sock.set_keep_alive_interval(1), Ok(_)));
97     assert!(matches!(sock.keep_alive_count(), Ok(_)));
98     assert!(matches!(sock.set_keep_alive_count(1), Ok(_)));
99     assert!(matches!(sock.hop_limit(), Ok(_)));
100     assert!(matches!(sock.set_hop_limit(255), Ok(_)));
101     assert!(matches!(sock.receive_buffer_size(), Ok(_)));
102     assert!(matches!(sock.set_receive_buffer_size(16000), Ok(_)));
103     assert!(matches!(sock.send_buffer_size(), Ok(_)));
104     assert!(matches!(sock.set_send_buffer_size(16000), Ok(_)));
105 }
106 
test_tcp_listening_state_invariants(net: &Network, family: IpAddressFamily)107 fn test_tcp_listening_state_invariants(net: &Network, family: IpAddressFamily) {
108     let bind_address = IpSocketAddress::new(IpAddress::new_loopback(family), 0);
109     let sock = TcpSocket::new(family).unwrap();
110     sock.blocking_bind(net, bind_address).unwrap();
111     sock.blocking_listen().unwrap();
112 
113     assert!(matches!(
114         sock.start_bind(net, bind_address),
115         Err(ErrorCode::InvalidState)
116     ));
117     assert!(matches!(sock.finish_bind(), Err(ErrorCode::NotInProgress)));
118     assert!(matches!(
119         sock.start_connect(net, bind_address), // Actual address shouldn't matter
120         Err(ErrorCode::InvalidState)
121     ));
122     assert!(matches!(
123         sock.finish_connect(),
124         Err(ErrorCode::NotInProgress)
125     ));
126     assert!(matches!(sock.start_listen(), Err(ErrorCode::InvalidState)));
127     assert!(matches!(
128         sock.finish_listen(),
129         Err(ErrorCode::NotInProgress)
130     ));
131     // Skipping: tcp::accept
132     assert!(matches!(
133         sock.shutdown(ShutdownType::Both),
134         Err(ErrorCode::InvalidState)
135     ));
136 
137     assert!(matches!(sock.local_address(), Ok(_)));
138     assert!(matches!(
139         sock.remote_address(),
140         Err(ErrorCode::InvalidState)
141     ));
142     assert_eq!(sock.is_listening(), true);
143     assert_eq!(sock.address_family(), family);
144 
145     assert!(matches!(
146         sock.set_listen_backlog_size(32),
147         Ok(_) | Err(ErrorCode::NotSupported)
148     ));
149     assert!(matches!(sock.keep_alive_enabled(), Ok(_)));
150     assert!(matches!(sock.set_keep_alive_enabled(false), Ok(_)));
151     assert!(matches!(sock.keep_alive_idle_time(), Ok(_)));
152     assert!(matches!(sock.set_keep_alive_idle_time(1), Ok(_)));
153     assert!(matches!(sock.keep_alive_interval(), Ok(_)));
154     assert!(matches!(sock.set_keep_alive_interval(1), Ok(_)));
155     assert!(matches!(sock.keep_alive_count(), Ok(_)));
156     assert!(matches!(sock.set_keep_alive_count(1), Ok(_)));
157     assert!(matches!(sock.hop_limit(), Ok(_)));
158     assert!(matches!(sock.set_hop_limit(255), Ok(_)));
159     assert!(matches!(sock.receive_buffer_size(), Ok(_)));
160     assert!(matches!(sock.set_receive_buffer_size(16000), Ok(_)));
161     assert!(matches!(sock.send_buffer_size(), Ok(_)));
162     assert!(matches!(sock.set_send_buffer_size(16000), Ok(_)));
163 }
164 
test_tcp_connected_state_invariants(net: &Network, family: IpAddressFamily)165 fn test_tcp_connected_state_invariants(net: &Network, family: IpAddressFamily) {
166     let bind_address = IpSocketAddress::new(IpAddress::new_loopback(family), 0);
167     let sock_listener = TcpSocket::new(family).unwrap();
168     sock_listener.blocking_bind(net, bind_address).unwrap();
169     sock_listener.blocking_listen().unwrap();
170     let addr_listener = sock_listener.local_address().unwrap();
171     let sock = TcpSocket::new(family).unwrap();
172     let (_input, _output) = sock.blocking_connect(net, addr_listener).unwrap();
173 
174     assert!(matches!(
175         sock.start_bind(net, bind_address),
176         Err(ErrorCode::InvalidState)
177     ));
178     assert!(matches!(sock.finish_bind(), Err(ErrorCode::NotInProgress)));
179     assert!(matches!(
180         sock.start_connect(net, addr_listener),
181         Err(ErrorCode::InvalidState)
182     ));
183     assert!(matches!(
184         sock.finish_connect(),
185         Err(ErrorCode::NotInProgress)
186     ));
187     assert!(matches!(sock.start_listen(), Err(ErrorCode::InvalidState)));
188     assert!(matches!(
189         sock.finish_listen(),
190         Err(ErrorCode::NotInProgress)
191     ));
192     assert!(matches!(sock.accept(), Err(ErrorCode::InvalidState)));
193     // Skipping: tcp::shutdown
194 
195     assert!(matches!(sock.local_address(), Ok(_)));
196     assert!(matches!(sock.remote_address(), Ok(_)));
197     assert_eq!(sock.is_listening(), false);
198     assert_eq!(sock.address_family(), family);
199 
200     assert!(matches!(sock.keep_alive_enabled(), Ok(_)));
201     assert!(matches!(sock.set_keep_alive_enabled(false), Ok(_)));
202     assert!(matches!(sock.keep_alive_idle_time(), Ok(_)));
203     assert!(matches!(sock.set_keep_alive_idle_time(1), Ok(_)));
204     assert!(matches!(sock.keep_alive_interval(), Ok(_)));
205     assert!(matches!(sock.set_keep_alive_interval(1), Ok(_)));
206     assert!(matches!(sock.keep_alive_count(), Ok(_)));
207     assert!(matches!(sock.set_keep_alive_count(1), Ok(_)));
208     assert!(matches!(sock.hop_limit(), Ok(_)));
209     assert!(matches!(sock.set_hop_limit(255), Ok(_)));
210     assert!(matches!(sock.receive_buffer_size(), Ok(_)));
211     assert!(matches!(sock.set_receive_buffer_size(16000), Ok(_)));
212     assert!(matches!(sock.send_buffer_size(), Ok(_)));
213     assert!(matches!(sock.set_send_buffer_size(16000), Ok(_)));
214 }
215 
main()216 fn main() {
217     let net = Network::default();
218 
219     test_tcp_unbound_state_invariants(IpAddressFamily::Ipv4);
220     test_tcp_bound_state_invariants(&net, IpAddressFamily::Ipv4);
221     test_tcp_listening_state_invariants(&net, IpAddressFamily::Ipv4);
222     test_tcp_connected_state_invariants(&net, IpAddressFamily::Ipv4);
223 
224     if supports_ipv6() {
225         test_tcp_unbound_state_invariants(IpAddressFamily::Ipv6);
226         test_tcp_bound_state_invariants(&net, IpAddressFamily::Ipv6);
227         test_tcp_listening_state_invariants(&net, IpAddressFamily::Ipv6);
228         test_tcp_connected_state_invariants(&net, IpAddressFamily::Ipv6);
229     }
230 }
231