xref: /spdk/test/unit/lib/sock/sock.c/sock_ut.c (revision 1fc4165fe9bf8512483356ad8e6d27f793f2e3db)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 #include "spdk/util.h"
36 
37 #include "spdk_cunit.h"
38 
39 #include "sock/sock.c"
40 #include "sock/posix/posix.c"
41 
42 #define UT_IP	"test_ip"
43 #define UT_PORT	1234
44 
45 bool g_read_data_called;
46 ssize_t g_bytes_read;
47 char g_buf[256];
48 struct spdk_sock *g_server_sock_read;
49 int g_ut_accept_count;
50 struct spdk_ut_sock *g_ut_listen_sock;
51 struct spdk_ut_sock *g_ut_client_sock;
52 
53 struct spdk_ut_sock {
54 	struct spdk_sock	base;
55 	struct spdk_ut_sock	*peer;
56 	size_t			bytes_avail;
57 	char			buf[256];
58 };
59 
60 struct spdk_ut_sock_group_impl {
61 	struct spdk_sock_group_impl	base;
62 	struct spdk_ut_sock		*sock;
63 };
64 
65 #define __ut_sock(sock) (struct spdk_ut_sock *)sock
66 #define __ut_group(group) (struct spdk_ut_sock_group_impl *)group
67 
68 static int
69 spdk_ut_sock_getaddr(struct spdk_sock *_sock, char *saddr, int slen, uint16_t *sport,
70 		     char *caddr, int clen, uint16_t *cport)
71 {
72 	return 0;
73 }
74 
75 static struct spdk_sock *
76 spdk_ut_sock_listen(const char *ip, int port)
77 {
78 	struct spdk_ut_sock *sock;
79 
80 	if (strcmp(ip, UT_IP) || port != UT_PORT) {
81 		return NULL;
82 	}
83 
84 	CU_ASSERT(g_ut_listen_sock == NULL);
85 
86 	sock = calloc(1, sizeof(*sock));
87 	SPDK_CU_ASSERT_FATAL(sock != NULL);
88 	g_ut_listen_sock = sock;
89 
90 	return &sock->base;
91 }
92 
93 static struct spdk_sock *
94 spdk_ut_sock_connect(const char *ip, int port)
95 {
96 	struct spdk_ut_sock *sock;
97 
98 	if (strcmp(ip, UT_IP) || port != UT_PORT) {
99 		return NULL;
100 	}
101 
102 	sock = calloc(1, sizeof(*sock));
103 	SPDK_CU_ASSERT_FATAL(sock != NULL);
104 	g_ut_accept_count++;
105 	CU_ASSERT(g_ut_client_sock == NULL);
106 	g_ut_client_sock = sock;
107 
108 	return &sock->base;
109 }
110 
111 static struct spdk_sock *
112 spdk_ut_sock_accept(struct spdk_sock *_sock)
113 {
114 	struct spdk_ut_sock *sock = __ut_sock(_sock);
115 	struct spdk_ut_sock *new_sock;
116 
117 	CU_ASSERT(sock == g_ut_listen_sock);
118 
119 	if (g_ut_accept_count == 0) {
120 		errno = EAGAIN;
121 		return NULL;
122 	}
123 
124 	g_ut_accept_count--;
125 	new_sock = calloc(1, sizeof(*sock));
126 	if (new_sock == NULL) {
127 		SPDK_ERRLOG("sock allocation failed\n");
128 		return NULL;
129 	}
130 
131 	SPDK_CU_ASSERT_FATAL(g_ut_client_sock != NULL);
132 	g_ut_client_sock->peer = new_sock;
133 
134 	return &new_sock->base;
135 }
136 
137 static int
138 spdk_ut_sock_close(struct spdk_sock *_sock)
139 {
140 	struct spdk_ut_sock *sock = __ut_sock(_sock);
141 
142 	if (sock == g_ut_listen_sock) {
143 		g_ut_listen_sock = NULL;
144 	}
145 	if (sock == g_ut_client_sock) {
146 		g_ut_client_sock = NULL;
147 	}
148 	free(_sock);
149 
150 	return 0;
151 }
152 
153 static ssize_t
154 spdk_ut_sock_recv(struct spdk_sock *_sock, void *buf, size_t len)
155 {
156 	struct spdk_ut_sock *sock = __ut_sock(_sock);
157 	char tmp[256];
158 
159 	len = spdk_min(len, sock->bytes_avail);
160 
161 	if (len == 0) {
162 		errno = EAGAIN;
163 		return -1;
164 	}
165 
166 	memcpy(buf, sock->buf, len);
167 	memcpy(tmp, &sock->buf[len], sock->bytes_avail - len);
168 	memcpy(sock->buf, tmp, sock->bytes_avail - len);
169 	sock->bytes_avail -= len;
170 
171 	return len;
172 }
173 
174 static ssize_t
175 spdk_ut_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
176 {
177 	struct spdk_ut_sock *sock = __ut_sock(_sock);
178 	size_t len;
179 	char tmp[256];
180 
181 	/* Test implementation only supports single iov for now. */
182 	CU_ASSERT(iovcnt == 1);
183 
184 	len = spdk_min(iov[0].iov_len, sock->bytes_avail);
185 
186 	if (len == 0) {
187 		errno = EAGAIN;
188 		return -1;
189 	}
190 
191 	memcpy(iov[0].iov_base, sock->buf, len);
192 	memcpy(tmp, &sock->buf[len], sock->bytes_avail - len);
193 	memcpy(sock->buf, tmp, sock->bytes_avail - len);
194 	sock->bytes_avail -= len;
195 
196 	return len;
197 }
198 
199 static ssize_t
200 spdk_ut_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
201 {
202 	struct spdk_ut_sock *sock = __ut_sock(_sock);
203 	struct spdk_ut_sock *peer;
204 
205 	SPDK_CU_ASSERT_FATAL(sock->peer != NULL);
206 	peer = sock->peer;
207 
208 	/* Test implementation only supports single iov for now. */
209 	CU_ASSERT(iovcnt == 1);
210 
211 	memcpy(&peer->buf[peer->bytes_avail], iov[0].iov_base, iov[0].iov_len);
212 	peer->bytes_avail += iov[0].iov_len;
213 
214 	return iov[0].iov_len;
215 }
216 
217 static int
218 spdk_ut_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes)
219 {
220 	return 0;
221 }
222 
223 static int
224 spdk_ut_sock_set_recvbuf(struct spdk_sock *_sock, int sz)
225 {
226 	return 0;
227 }
228 
229 static int
230 spdk_ut_sock_set_sendbuf(struct spdk_sock *_sock, int sz)
231 {
232 	return 0;
233 }
234 
235 static bool
236 spdk_ut_sock_is_ipv6(struct spdk_sock *_sock)
237 {
238 	return false;
239 }
240 
241 static bool
242 spdk_ut_sock_is_ipv4(struct spdk_sock *_sock)
243 {
244 	return true;
245 }
246 
247 static struct spdk_sock_group_impl *
248 spdk_ut_sock_group_impl_create(void)
249 {
250 	struct spdk_ut_sock_group_impl *group_impl;
251 
252 	group_impl = calloc(1, sizeof(*group_impl));
253 	SPDK_CU_ASSERT_FATAL(group_impl != NULL);
254 
255 	return &group_impl->base;
256 }
257 
258 static int
259 spdk_ut_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
260 {
261 	struct spdk_ut_sock_group_impl *group = __ut_group(_group);
262 	struct spdk_ut_sock *sock = __ut_sock(_sock);
263 
264 	group->sock = sock;
265 
266 	return 0;
267 }
268 
269 static int
270 spdk_ut_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
271 {
272 	struct spdk_ut_sock_group_impl *group = __ut_group(_group);
273 	struct spdk_ut_sock *sock = __ut_sock(_sock);
274 
275 	CU_ASSERT(group->sock == sock);
276 	group->sock = NULL;
277 
278 	return 0;
279 }
280 
281 static int
282 spdk_ut_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events,
283 			     struct spdk_sock **socks)
284 {
285 	struct spdk_ut_sock_group_impl *group = __ut_group(_group);
286 
287 	if (group->sock != NULL && group->sock->bytes_avail > 0) {
288 		socks[0] = &group->sock->base;
289 		return 1;
290 	}
291 
292 	return 0;
293 }
294 
295 static int
296 spdk_ut_sock_group_impl_close(struct spdk_sock_group_impl *_group)
297 {
298 	struct spdk_ut_sock_group_impl *group = __ut_group(_group);
299 
300 	CU_ASSERT(group->sock == NULL);
301 
302 	return 0;
303 }
304 
305 static struct spdk_net_impl g_ut_net_impl = {
306 	.name		= "ut",
307 	.getaddr	= spdk_ut_sock_getaddr,
308 	.connect	= spdk_ut_sock_connect,
309 	.listen		= spdk_ut_sock_listen,
310 	.accept		= spdk_ut_sock_accept,
311 	.close		= spdk_ut_sock_close,
312 	.recv		= spdk_ut_sock_recv,
313 	.readv		= spdk_ut_sock_readv,
314 	.writev		= spdk_ut_sock_writev,
315 	.set_recvlowat	= spdk_ut_sock_set_recvlowat,
316 	.set_recvbuf	= spdk_ut_sock_set_recvbuf,
317 	.set_sendbuf	= spdk_ut_sock_set_sendbuf,
318 	.is_ipv6	= spdk_ut_sock_is_ipv6,
319 	.is_ipv4	= spdk_ut_sock_is_ipv4,
320 	.group_impl_create	= spdk_ut_sock_group_impl_create,
321 	.group_impl_add_sock	= spdk_ut_sock_group_impl_add_sock,
322 	.group_impl_remove_sock = spdk_ut_sock_group_impl_remove_sock,
323 	.group_impl_poll	= spdk_ut_sock_group_impl_poll,
324 	.group_impl_close	= spdk_ut_sock_group_impl_close,
325 };
326 
327 SPDK_NET_IMPL_REGISTER(ut, &g_ut_net_impl);
328 
329 static void
330 _sock(const char *ip, int port)
331 {
332 	struct spdk_sock *listen_sock;
333 	struct spdk_sock *server_sock;
334 	struct spdk_sock *client_sock;
335 	char *test_string = "abcdef";
336 	char buffer[64];
337 	ssize_t bytes_read, bytes_written;
338 	struct iovec iov;
339 	int rc;
340 
341 	listen_sock = spdk_sock_listen(ip, port);
342 	SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
343 
344 	server_sock = spdk_sock_accept(listen_sock);
345 	CU_ASSERT(server_sock == NULL);
346 	CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK);
347 
348 	client_sock = spdk_sock_connect(ip, port);
349 	SPDK_CU_ASSERT_FATAL(client_sock != NULL);
350 
351 	/*
352 	 * Delay a bit here before checking if server socket is
353 	 *  ready.
354 	 */
355 	usleep(1000);
356 
357 	server_sock = spdk_sock_accept(listen_sock);
358 	SPDK_CU_ASSERT_FATAL(server_sock != NULL);
359 
360 	/* Test spdk_sock_recv */
361 	iov.iov_base = test_string;
362 	iov.iov_len = 7;
363 	bytes_written = spdk_sock_writev(client_sock, &iov, 1);
364 	CU_ASSERT(bytes_written == 7);
365 
366 	usleep(1000);
367 
368 	bytes_read = spdk_sock_recv(server_sock, buffer, 2);
369 	CU_ASSERT(bytes_read == 2);
370 
371 	usleep(1000);
372 
373 	bytes_read += spdk_sock_recv(server_sock, buffer + 2, 5);
374 	CU_ASSERT(bytes_read == 7);
375 
376 	CU_ASSERT(strncmp(test_string, buffer, 7) == 0);
377 
378 	/* Test spdk_sock_readv */
379 	iov.iov_base = test_string;
380 	iov.iov_len = 7;
381 	bytes_written = spdk_sock_writev(client_sock, &iov, 1);
382 	CU_ASSERT(bytes_written == 7);
383 
384 	usleep(1000);
385 
386 	iov.iov_base = buffer;
387 	iov.iov_len = 2;
388 	bytes_read = spdk_sock_readv(server_sock, &iov, 1);
389 	CU_ASSERT(bytes_read == 2);
390 
391 	usleep(1000);
392 
393 	iov.iov_base = buffer + 2;
394 	iov.iov_len = 5;
395 	bytes_read += spdk_sock_readv(server_sock, &iov, 1);
396 	CU_ASSERT(bytes_read == 7);
397 
398 	usleep(1000);
399 
400 	CU_ASSERT(strncmp(test_string, buffer, 7) == 0);
401 
402 	rc = spdk_sock_close(&client_sock);
403 	CU_ASSERT(client_sock == NULL);
404 	CU_ASSERT(rc == 0);
405 
406 	rc = spdk_sock_close(&server_sock);
407 	CU_ASSERT(server_sock == NULL);
408 	CU_ASSERT(rc == 0);
409 
410 	rc = spdk_sock_close(&listen_sock);
411 	CU_ASSERT(listen_sock == NULL);
412 	CU_ASSERT(rc == 0);
413 }
414 
415 static void
416 posix_sock(void)
417 {
418 	_sock("127.0.0.1", UT_PORT);
419 }
420 
421 static void
422 ut_sock(void)
423 {
424 	_sock(UT_IP, UT_PORT);
425 }
426 
427 static void
428 read_data(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock)
429 {
430 	struct spdk_sock *server_sock = cb_arg;
431 
432 	CU_ASSERT(server_sock == sock);
433 
434 	g_read_data_called = true;
435 	g_bytes_read += spdk_sock_recv(server_sock, g_buf + g_bytes_read, sizeof(g_buf) - g_bytes_read);
436 }
437 
438 static void
439 _sock_group(const char *ip, int port)
440 {
441 	struct spdk_sock_group *group;
442 	struct spdk_sock *listen_sock;
443 	struct spdk_sock *server_sock;
444 	struct spdk_sock *client_sock;
445 	char *test_string = "abcdef";
446 	ssize_t bytes_written;
447 	struct iovec iov;
448 	int rc;
449 
450 	listen_sock = spdk_sock_listen(ip, port);
451 	SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
452 
453 	server_sock = spdk_sock_accept(listen_sock);
454 	CU_ASSERT(server_sock == NULL);
455 	CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK);
456 
457 	client_sock = spdk_sock_connect(ip, port);
458 	SPDK_CU_ASSERT_FATAL(client_sock != NULL);
459 
460 	usleep(1000);
461 
462 	server_sock = spdk_sock_accept(listen_sock);
463 	SPDK_CU_ASSERT_FATAL(server_sock != NULL);
464 
465 	group = spdk_sock_group_create();
466 	SPDK_CU_ASSERT_FATAL(group != NULL);
467 
468 	/* pass null cb_fn */
469 	rc = spdk_sock_group_add_sock(group, server_sock, NULL, NULL);
470 	CU_ASSERT(rc == -1);
471 	CU_ASSERT(errno == EINVAL);
472 
473 	rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
474 	CU_ASSERT(rc == 0);
475 
476 	/* try adding sock a second time */
477 	rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
478 	CU_ASSERT(rc == -1);
479 	CU_ASSERT(errno == EBUSY);
480 
481 	g_read_data_called = false;
482 	g_bytes_read = 0;
483 	rc = spdk_sock_group_poll(group);
484 
485 	CU_ASSERT(rc == 0);
486 	CU_ASSERT(g_read_data_called == false);
487 
488 	iov.iov_base = test_string;
489 	iov.iov_len = 7;
490 	bytes_written = spdk_sock_writev(client_sock, &iov, 1);
491 	CU_ASSERT(bytes_written == 7);
492 
493 	usleep(1000);
494 
495 	g_read_data_called = false;
496 	g_bytes_read = 0;
497 	rc = spdk_sock_group_poll(group);
498 
499 	CU_ASSERT(rc == 0);
500 	CU_ASSERT(g_read_data_called == true);
501 	CU_ASSERT(g_bytes_read == 7);
502 
503 	CU_ASSERT(strncmp(test_string, g_buf, 7) == 0);
504 
505 	rc = spdk_sock_close(&client_sock);
506 	CU_ASSERT(client_sock == NULL);
507 	CU_ASSERT(rc == 0);
508 
509 	/* Try to close sock_group while it still has sockets. */
510 	rc = spdk_sock_group_close(&group);
511 	CU_ASSERT(rc == -1);
512 	CU_ASSERT(errno == EBUSY);
513 
514 	/* Try to close sock while it is still part of a sock_group. */
515 	rc = spdk_sock_close(&server_sock);
516 	CU_ASSERT(rc == -1);
517 	CU_ASSERT(errno == EBUSY);
518 
519 	rc = spdk_sock_group_remove_sock(group, server_sock);
520 	CU_ASSERT(rc == 0);
521 
522 	rc = spdk_sock_group_close(&group);
523 	CU_ASSERT(group == NULL);
524 	CU_ASSERT(rc == 0);
525 
526 	rc = spdk_sock_close(&server_sock);
527 	CU_ASSERT(server_sock == NULL);
528 	CU_ASSERT(rc == 0);
529 
530 	rc = spdk_sock_close(&listen_sock);
531 	CU_ASSERT(listen_sock == NULL);
532 	CU_ASSERT(rc == 0);
533 }
534 
535 static void
536 posix_sock_group(void)
537 {
538 	_sock_group("127.0.0.1", UT_PORT);
539 }
540 
541 static void
542 ut_sock_group(void)
543 {
544 	_sock_group(UT_IP, UT_PORT);
545 }
546 
547 static void
548 read_data_fairness(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock)
549 {
550 	struct spdk_sock *server_sock = cb_arg;
551 	ssize_t bytes_read;
552 	char buf[1];
553 
554 	CU_ASSERT(g_server_sock_read == NULL);
555 	CU_ASSERT(server_sock == sock);
556 
557 	g_server_sock_read = server_sock;
558 	bytes_read = spdk_sock_recv(server_sock, buf, 1);
559 	CU_ASSERT(bytes_read == 1);
560 }
561 
562 static void
563 posix_sock_group_fairness(void)
564 {
565 	struct spdk_sock_group *group;
566 	struct spdk_sock *listen_sock;
567 	struct spdk_sock *server_sock[3];
568 	struct spdk_sock *client_sock[3];
569 	char test_char = 'a';
570 	ssize_t bytes_written;
571 	struct iovec iov;
572 	int i, rc;
573 
574 	listen_sock = spdk_sock_listen("127.0.0.1", UT_PORT);
575 	SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
576 
577 	group = spdk_sock_group_create();
578 	SPDK_CU_ASSERT_FATAL(group != NULL);
579 
580 	for (i = 0; i < 3; i++) {
581 		client_sock[i] = spdk_sock_connect("127.0.0.1", UT_PORT);
582 		SPDK_CU_ASSERT_FATAL(client_sock[i] != NULL);
583 
584 		usleep(1000);
585 
586 		server_sock[i] = spdk_sock_accept(listen_sock);
587 		SPDK_CU_ASSERT_FATAL(server_sock[i] != NULL);
588 
589 		rc = spdk_sock_group_add_sock(group, server_sock[i],
590 					      read_data_fairness, server_sock[i]);
591 		CU_ASSERT(rc == 0);
592 	}
593 
594 	iov.iov_base = &test_char;
595 	iov.iov_len = 1;
596 
597 	for (i = 0; i < 3; i++) {
598 		bytes_written = spdk_sock_writev(client_sock[i], &iov, 1);
599 		CU_ASSERT(bytes_written == 1);
600 	}
601 
602 	usleep(1000);
603 
604 	/*
605 	 * Poll for just one event - this should be server sock 0, since that
606 	 *  is the peer of the first client sock that we wrote to.
607 	 */
608 	g_server_sock_read = NULL;
609 	rc = spdk_sock_group_poll_count(group, 1);
610 	CU_ASSERT(rc == 0);
611 	CU_ASSERT(g_server_sock_read == server_sock[0]);
612 
613 	/*
614 	 * Now write another byte to client sock 0.  We want to ensure that
615 	 *  the sock group does not unfairly process the event for this sock
616 	 *  before the socks that were written to earlier.
617 	 */
618 	bytes_written = spdk_sock_writev(client_sock[0], &iov, 1);
619 	CU_ASSERT(bytes_written == 1);
620 
621 	usleep(1000);
622 
623 	g_server_sock_read = NULL;
624 	rc = spdk_sock_group_poll_count(group, 1);
625 	CU_ASSERT(rc == 0);
626 	CU_ASSERT(g_server_sock_read == server_sock[1]);
627 
628 	g_server_sock_read = NULL;
629 	rc = spdk_sock_group_poll_count(group, 1);
630 	CU_ASSERT(rc == 0);
631 	CU_ASSERT(g_server_sock_read == server_sock[2]);
632 
633 	g_server_sock_read = NULL;
634 	rc = spdk_sock_group_poll_count(group, 1);
635 	CU_ASSERT(rc == 0);
636 	CU_ASSERT(g_server_sock_read == server_sock[0]);
637 
638 	for (i = 0; i < 3; i++) {
639 		rc = spdk_sock_group_remove_sock(group, server_sock[i]);
640 		CU_ASSERT(rc == 0);
641 
642 		rc = spdk_sock_close(&client_sock[i]);
643 		CU_ASSERT(client_sock[i] == NULL);
644 		CU_ASSERT(rc == 0);
645 
646 		rc = spdk_sock_close(&server_sock[i]);
647 		CU_ASSERT(server_sock[i] == NULL);
648 		CU_ASSERT(rc == 0);
649 	}
650 
651 	rc = spdk_sock_group_close(&group);
652 	CU_ASSERT(group == NULL);
653 	CU_ASSERT(rc == 0);
654 
655 	rc = spdk_sock_close(&listen_sock);
656 	CU_ASSERT(listen_sock == NULL);
657 	CU_ASSERT(rc == 0);
658 }
659 
660 int
661 main(int argc, char **argv)
662 {
663 	CU_pSuite	suite = NULL;
664 	unsigned int	num_failures;
665 
666 	if (CU_initialize_registry() != CUE_SUCCESS) {
667 		return CU_get_error();
668 	}
669 
670 	suite = CU_add_suite("sock", NULL, NULL);
671 	if (suite == NULL) {
672 		CU_cleanup_registry();
673 		return CU_get_error();
674 	}
675 
676 	if (
677 		CU_add_test(suite, "posix_sock", posix_sock) == NULL ||
678 		CU_add_test(suite, "ut_sock", ut_sock) == NULL ||
679 		CU_add_test(suite, "posix_sock_group", posix_sock_group) == NULL ||
680 		CU_add_test(suite, "ut_sock_group", ut_sock_group) == NULL ||
681 		CU_add_test(suite, "posix_sock_group_fairness", posix_sock_group_fairness) == NULL) {
682 		CU_cleanup_registry();
683 		return CU_get_error();
684 	}
685 
686 	CU_basic_set_mode(CU_BRM_VERBOSE);
687 
688 	CU_basic_run_tests();
689 
690 	num_failures = CU_get_number_of_failures();
691 	CU_cleanup_registry();
692 
693 	return num_failures;
694 }
695