source: mainline/uspace/srv/net/tcp/test/ucall.c@ 3f932a7e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3f932a7e was 3f932a7e, checked in by Jiri Svoboda <jiri@…>, 7 years ago

PCUT_INIT declaration also needs a terminating semicolon.

  • Property mode set to 100644
File size: 9.0 KB
Line 
1/*
2 * Copyright (c) 2017 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <errno.h>
30#include <inet/endpoint.h>
31#include <io/log.h>
32#include <pcut/pcut.h>
33
34#include "../conn.h"
35#include "../rqueue.h"
36#include "../ucall.h"
37
38PCUT_INIT;
39
40PCUT_TEST_SUITE(ucall);
41
42static void test_cstate_change(tcp_conn_t *, void *, tcp_cstate_t);
43static void test_conns_establish(tcp_conn_t **, tcp_conn_t **);
44static void test_conns_tear_down(tcp_conn_t *, tcp_conn_t *);
45
46static tcp_rqueue_cb_t test_rqueue_cb = {
47 .seg_received = tcp_as_segment_arrived
48};
49
50static tcp_cb_t test_conn_cb = {
51 .cstate_change = test_cstate_change
52};
53
54static tcp_conn_status_t cconn_status;
55static tcp_conn_status_t sconn_status;
56
57static FIBRIL_MUTEX_INITIALIZE(cst_lock);
58static FIBRIL_CONDVAR_INITIALIZE(cst_cv);
59
60PCUT_TEST_BEFORE
61{
62 errno_t rc;
63
64 /* We will be calling functions that perform logging */
65 rc = log_init("test-tcp");
66 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
67
68 rc = tcp_conns_init();
69 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
70
71 tcp_rqueue_init(&test_rqueue_cb);
72 tcp_rqueue_fibril_start();
73
74 /* Enable internal loopback */
75 tcp_conn_lb = tcp_lb_segment;
76}
77
78PCUT_TEST_AFTER
79{
80 tcp_rqueue_fini();
81 tcp_conns_fini();
82}
83
84/** Test creating a listening passive connection and then deleting it. */
85PCUT_TEST(listen_delete)
86{
87 tcp_conn_t *conn;
88 inet_ep2_t epp;
89 tcp_error_t trc;
90 tcp_conn_status_t cstatus;
91
92 inet_ep2_init(&epp);
93 inet_addr(&epp.local.addr, 127, 0, 0, 1);
94 epp.local.port = inet_port_user_lo;
95
96 conn = NULL;
97 trc = tcp_uc_open(&epp, ap_passive, tcp_open_nonblock, &conn);
98 PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
99 PCUT_ASSERT_NOT_NULL(conn);
100
101 tcp_uc_status(conn, &cstatus);
102 PCUT_ASSERT_INT_EQUALS(st_listen, cstatus.cstate);
103
104 trc = tcp_uc_close(conn);
105 PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
106 tcp_uc_delete(conn);
107}
108
109/** Test trying to connect to endpoint that sends RST back */
110PCUT_TEST(connect_rst)
111{
112 tcp_conn_t *conn;
113 inet_ep2_t epp;
114 tcp_error_t trc;
115
116 inet_ep2_init(&epp);
117 inet_addr(&epp.local.addr, 127, 0, 0, 1);
118 inet_addr(&epp.remote.addr, 127, 0, 0, 1);
119 epp.remote.port = inet_port_user_lo;
120
121 conn = NULL;
122 trc = tcp_uc_open(&epp, ap_active, 0, &conn);
123 PCUT_ASSERT_INT_EQUALS(TCP_ERESET, trc);
124 PCUT_ASSERT_NULL(conn);
125}
126
127/** Test establishing a connection */
128PCUT_TEST(conn_establish)
129{
130 tcp_conn_t *cconn, *sconn;
131
132 test_conns_establish(&cconn, &sconn);
133 test_conns_tear_down(cconn, sconn);
134}
135
136/** Test establishing and then closing down a connection first on one side,
137 * then on_the other. */
138PCUT_TEST(conn_est_close_seq)
139{
140 tcp_conn_t *cconn, *sconn;
141 tcp_error_t trc;
142
143 log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: establish");
144 /* Establish */
145 test_conns_establish(&cconn, &sconn);
146
147 log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: close cconn");
148 /* Close client side */
149 trc = tcp_uc_close(cconn);
150 PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
151
152 log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: wait cconn = fin-wait-2");
153 /* Wait for cconn to go to Fin-Wait-2 */
154 fibril_mutex_lock(&cst_lock);
155 tcp_uc_status(cconn, &cconn_status);
156 while (cconn_status.cstate != st_fin_wait_2)
157 fibril_condvar_wait(&cst_cv, &cst_lock);
158 fibril_mutex_unlock(&cst_lock);
159
160 log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: wait sconn = close-wait");
161 /* Wait for sconn to go to Close-Wait */
162 fibril_mutex_lock(&cst_lock);
163 tcp_uc_status(sconn, &sconn_status);
164 while (sconn_status.cstate != st_close_wait)
165 fibril_condvar_wait(&cst_cv, &cst_lock);
166 fibril_mutex_unlock(&cst_lock);
167
168 log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: close sconn");
169 /* Close server side */
170 trc = tcp_uc_close(sconn);
171 PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
172
173 log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: wait cconn = time-wait");
174 /* Wait for cconn to go to Time-Wait */
175 fibril_mutex_lock(&cst_lock);
176 tcp_uc_status(cconn, &cconn_status);
177 while (cconn_status.cstate != st_time_wait)
178 fibril_condvar_wait(&cst_cv, &cst_lock);
179 fibril_mutex_unlock(&cst_lock);
180
181 log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: wait sconn = closed");
182 /* Wait for sconn to go to Closed */
183 fibril_mutex_lock(&cst_lock);
184 tcp_uc_status(sconn, &sconn_status);
185 while (sconn_status.cstate != st_closed) {
186 log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: sconn.status == %d", sconn_status.cstate);
187 fibril_condvar_wait(&cst_cv, &cst_lock);
188 }
189 fibril_mutex_unlock(&cst_lock);
190
191 log_msg(LOG_DEFAULT, LVL_NOTE, "conn_est_close_seq: tear down");
192 /* Tear down */
193 test_conns_tear_down(cconn, sconn);
194}
195
196/** Test establishing and then simultaneously closing down a connection. */
197PCUT_TEST(conn_est_close_simult)
198{
199 tcp_conn_t *cconn, *sconn;
200 tcp_error_t trc;
201
202 /* Establish */
203 test_conns_establish(&cconn, &sconn);
204
205 /* Close both sides simultaneously */
206 trc = tcp_uc_close(cconn);
207 PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
208 trc = tcp_uc_close(sconn);
209 PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
210
211 /* Wait for cconn to go to Time-Wait */
212 fibril_mutex_lock(&cst_lock);
213 tcp_uc_status(cconn, &cconn_status);
214 while (cconn_status.cstate != st_time_wait)
215 fibril_condvar_wait(&cst_cv, &cst_lock);
216 fibril_mutex_unlock(&cst_lock);
217
218 /*
219 * Wait for sconn to go to Closed or Time-Wait. The connection
220 * goes to Closed if we managed to call tcp_uc_close() before
221 * sconn received FIN. Otherwise it goes to Time-Wait.
222 *
223 * XXX We may want to add delay to the loopback here to be
224 * absolutely sure that we go to Closing -> Time-Wait.
225 */
226 fibril_mutex_lock(&cst_lock);
227 tcp_uc_status(sconn, &sconn_status);
228 while (sconn_status.cstate != st_time_wait &&
229 sconn_status.cstate != st_closed)
230 fibril_condvar_wait(&cst_cv, &cst_lock);
231 fibril_mutex_unlock(&cst_lock);
232
233 /* Tear down */
234 test_conns_tear_down(cconn, sconn);
235}
236
237static void test_cstate_change(tcp_conn_t *conn, void *arg,
238 tcp_cstate_t old_state)
239{
240 tcp_conn_status_t *status = (tcp_conn_status_t *)arg;
241
242 fibril_mutex_lock(&cst_lock);
243 tcp_uc_status(conn, status);
244 fibril_mutex_unlock(&cst_lock);
245 fibril_condvar_broadcast(&cst_cv);
246}
247
248/** Establish client-server connection */
249static void test_conns_establish(tcp_conn_t **rcconn, tcp_conn_t **rsconn)
250{
251 tcp_conn_t *cconn, *sconn;
252 inet_ep2_t cepp, sepp;
253 tcp_conn_status_t cstatus;
254 tcp_error_t trc;
255
256 /* Client EPP */
257 inet_ep2_init(&cepp);
258 inet_addr(&cepp.local.addr, 127, 0, 0, 1);
259 inet_addr(&cepp.remote.addr, 127, 0, 0, 1);
260 cepp.remote.port = inet_port_user_lo;
261
262 /* Server EPP */
263 inet_ep2_init(&sepp);
264 inet_addr(&sepp.local.addr, 127, 0, 0, 1);
265 sepp.local.port = inet_port_user_lo;
266
267 /* Server side of the connection */
268 sconn = NULL;
269 trc = tcp_uc_open(&sepp, ap_passive, tcp_open_nonblock, &sconn);
270 PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
271 PCUT_ASSERT_NOT_NULL(sconn);
272
273 tcp_uc_set_cb(sconn, &test_conn_cb, &sconn_status);
274 PCUT_ASSERT_EQUALS(&sconn_status, tcp_uc_get_userptr(sconn));
275
276 tcp_uc_status(sconn, &cstatus);
277 PCUT_ASSERT_INT_EQUALS(st_listen, cstatus.cstate);
278
279 /* Client side of the connection */
280
281 cconn = NULL;
282 trc = tcp_uc_open(&cepp, ap_active, 0, &cconn);
283 PCUT_ASSERT_INT_EQUALS(TCP_EOK, trc);
284 PCUT_ASSERT_NOT_NULL(cconn);
285
286 tcp_uc_set_cb(cconn, &test_conn_cb, &cconn_status);
287 PCUT_ASSERT_EQUALS(&cconn_status, tcp_uc_get_userptr(cconn));
288
289 /* The client side of the connection should be established by now */
290
291 tcp_uc_status(cconn, &cstatus);
292 PCUT_ASSERT_INT_EQUALS(st_established, cstatus.cstate);
293
294 /* Need to wait for server side */
295
296 fibril_mutex_lock(&cst_lock);
297 tcp_uc_status(sconn, &sconn_status);
298 while (sconn_status.cstate != st_established)
299 fibril_condvar_wait(&cst_cv, &cst_lock);
300 fibril_mutex_unlock(&cst_lock);
301
302 *rcconn = cconn;
303 *rsconn = sconn;
304}
305
306/* Tear down client-server connection. */
307static void test_conns_tear_down(tcp_conn_t *cconn, tcp_conn_t *sconn)
308{
309 tcp_uc_abort(cconn);
310 tcp_uc_delete(cconn);
311
312 tcp_uc_abort(sconn);
313 tcp_uc_delete(sconn);
314}
315
316PCUT_EXPORT(ucall);
Note: See TracBrowser for help on using the repository browser.