LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/sock/sock.c - sock_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 699 713 98.0 %
Date: 2024-07-12 01:16:03 Functions: 40 42 95.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 81 142 57.0 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2018 Intel Corporation. All rights reserved.
       3                 :            :  *   Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
       4                 :            :  *   Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "spdk/stdinc.h"
       8                 :            : #include "spdk/util.h"
       9                 :            : 
      10                 :            : #include "spdk_internal/cunit.h"
      11                 :            : 
      12                 :            : #include "spdk_internal/sock.h"
      13                 :            : 
      14                 :            : #include "sock/sock.c"
      15                 :            : #include "sock/posix/posix.c"
      16                 :            : 
      17                 :            : #include "spdk_internal/mock.h"
      18                 :            : #include "common/lib/test_env.c"
      19                 :            : 
      20                 :            : #include "unit/lib/json_mock.c"
      21                 :            : 
      22                 :            : #define UT_IP   "test_ip"
      23                 :            : #define UT_PORT 1234
      24                 :            : 
      25                 :            : bool g_read_data_called;
      26                 :            : ssize_t g_bytes_read;
      27                 :            : char g_buf[256];
      28                 :            : struct spdk_sock *g_server_sock_read;
      29                 :            : int g_ut_accept_count;
      30                 :            : struct spdk_ut_sock *g_ut_listen_sock;
      31                 :            : struct spdk_ut_sock *g_ut_client_sock;
      32                 :            : 
      33                 :            : struct spdk_ut_sock {
      34                 :            :         struct spdk_sock        base;
      35                 :            :         struct spdk_ut_sock     *peer;
      36                 :            :         size_t                  bytes_avail;
      37                 :            :         char                    buf[256];
      38                 :            : };
      39                 :            : 
      40                 :            : struct spdk_ut_sock_group_impl {
      41                 :            :         struct spdk_sock_group_impl     base;
      42                 :            :         struct spdk_ut_sock             *sock;
      43                 :            : };
      44                 :            : 
      45                 :            : #define __ut_sock(sock) (struct spdk_ut_sock *)sock
      46                 :            : #define __ut_group(group) (struct spdk_ut_sock_group_impl *)group
      47                 :            : 
      48                 :            : static int
      49                 :          0 : spdk_ut_sock_getaddr(struct spdk_sock *_sock, char *saddr, int slen, uint16_t *sport,
      50                 :            :                      char *caddr, int clen, uint16_t *cport)
      51                 :            : {
      52                 :          0 :         return 0;
      53                 :            : }
      54                 :            : 
      55                 :            : static struct spdk_sock *
      56                 :         12 : spdk_ut_sock_listen(const char *ip, int port, struct spdk_sock_opts *opts)
      57                 :            : {
      58                 :            :         struct spdk_ut_sock *sock;
      59                 :            : 
      60   [ +  +  +  +  :         12 :         if (strcmp(ip, UT_IP) || port != UT_PORT) {
                   -  + ]
      61                 :          0 :                 return NULL;
      62                 :            :         }
      63                 :            : 
      64                 :         12 :         CU_ASSERT(g_ut_listen_sock == NULL);
      65                 :            : 
      66                 :         12 :         sock = calloc(1, sizeof(*sock));
      67         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(sock != NULL);
      68                 :         12 :         g_ut_listen_sock = sock;
      69                 :            : 
      70                 :         12 :         return &sock->base;
      71                 :            : }
      72                 :            : 
      73                 :            : static struct spdk_sock *
      74                 :         12 : spdk_ut_sock_connect(const char *ip, int port, struct spdk_sock_opts *opts)
      75                 :            : {
      76                 :            :         struct spdk_ut_sock *sock;
      77                 :            : 
      78   [ +  +  +  +  :         12 :         if (strcmp(ip, UT_IP) || port != UT_PORT) {
                   -  + ]
      79                 :          0 :                 return NULL;
      80                 :            :         }
      81                 :            : 
      82                 :         12 :         sock = calloc(1, sizeof(*sock));
      83         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(sock != NULL);
      84                 :         12 :         g_ut_accept_count++;
      85                 :         12 :         CU_ASSERT(g_ut_client_sock == NULL);
      86                 :         12 :         g_ut_client_sock = sock;
      87                 :            : 
      88                 :         12 :         return &sock->base;
      89                 :            : }
      90                 :            : 
      91                 :            : static struct spdk_sock *
      92                 :         24 : spdk_ut_sock_accept(struct spdk_sock *_sock)
      93                 :            : {
      94                 :         24 :         struct spdk_ut_sock *sock = __ut_sock(_sock);
      95                 :            :         struct spdk_ut_sock *new_sock;
      96                 :            : 
      97                 :         24 :         CU_ASSERT(sock == g_ut_listen_sock);
      98                 :            : 
      99         [ +  + ]:         24 :         if (g_ut_accept_count == 0) {
     100                 :         12 :                 errno = EAGAIN;
     101                 :         12 :                 return NULL;
     102                 :            :         }
     103                 :            : 
     104                 :         12 :         g_ut_accept_count--;
     105                 :         12 :         new_sock = calloc(1, sizeof(*sock));
     106         [ -  + ]:         12 :         if (new_sock == NULL) {
     107                 :          0 :                 SPDK_ERRLOG("sock allocation failed\n");
     108                 :          0 :                 return NULL;
     109                 :            :         }
     110                 :            : 
     111         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(g_ut_client_sock != NULL);
     112                 :         12 :         g_ut_client_sock->peer = new_sock;
     113                 :         12 :         new_sock->peer = g_ut_client_sock;
     114                 :            : 
     115                 :         12 :         return &new_sock->base;
     116                 :            : }
     117                 :            : 
     118                 :            : static int
     119                 :         36 : spdk_ut_sock_close(struct spdk_sock *_sock)
     120                 :            : {
     121                 :         36 :         struct spdk_ut_sock *sock = __ut_sock(_sock);
     122                 :            : 
     123         [ +  + ]:         36 :         if (sock == g_ut_listen_sock) {
     124                 :         12 :                 g_ut_listen_sock = NULL;
     125                 :            :         }
     126         [ +  + ]:         36 :         if (sock == g_ut_client_sock) {
     127                 :         12 :                 g_ut_client_sock = NULL;
     128                 :            :         }
     129                 :            : 
     130         [ +  + ]:         36 :         if (sock->peer != NULL) {
     131                 :         12 :                 sock->peer->peer = NULL;
     132                 :            :         }
     133                 :            : 
     134                 :         36 :         free(_sock);
     135                 :            : 
     136                 :         36 :         return 0;
     137                 :            : }
     138                 :            : 
     139                 :            : static ssize_t
     140                 :         18 : spdk_ut_sock_recv(struct spdk_sock *_sock, void *buf, size_t len)
     141                 :            : {
     142                 :         18 :         struct spdk_ut_sock *sock = __ut_sock(_sock);
     143                 :         15 :         char tmp[256];
     144                 :            : 
     145                 :         18 :         len = spdk_min(len, sock->bytes_avail);
     146                 :            : 
     147         [ -  + ]:         18 :         if (len == 0) {
     148                 :          0 :                 errno = EAGAIN;
     149                 :          0 :                 return -1;
     150                 :            :         }
     151                 :            : 
     152   [ -  +  -  + ]:         18 :         memcpy(buf, sock->buf, len);
     153         [ -  + ]:         18 :         memcpy(tmp, &sock->buf[len], sock->bytes_avail - len);
     154         [ -  + ]:         18 :         memcpy(sock->buf, tmp, sock->bytes_avail - len);
     155                 :         18 :         sock->bytes_avail -= len;
     156                 :            : 
     157                 :         18 :         return len;
     158                 :            : }
     159                 :            : 
     160                 :            : static ssize_t
     161                 :         12 : spdk_ut_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
     162                 :            : {
     163                 :         12 :         struct spdk_ut_sock *sock = __ut_sock(_sock);
     164                 :            :         size_t len;
     165                 :         10 :         char tmp[256];
     166                 :            : 
     167                 :            :         /* Test implementation only supports single iov for now. */
     168                 :         12 :         CU_ASSERT(iovcnt == 1);
     169                 :            : 
     170                 :         12 :         len = spdk_min(iov[0].iov_len, sock->bytes_avail);
     171                 :            : 
     172         [ -  + ]:         12 :         if (len == 0) {
     173                 :          0 :                 errno = EAGAIN;
     174                 :          0 :                 return -1;
     175                 :            :         }
     176                 :            : 
     177   [ -  +  -  + ]:         12 :         memcpy(iov[0].iov_base, sock->buf, len);
     178         [ -  + ]:         12 :         memcpy(tmp, &sock->buf[len], sock->bytes_avail - len);
     179         [ -  + ]:         12 :         memcpy(sock->buf, tmp, sock->bytes_avail - len);
     180                 :         12 :         sock->bytes_avail -= len;
     181                 :            : 
     182                 :         12 :         return len;
     183                 :            : }
     184                 :            : 
     185                 :            : static ssize_t
     186                 :         18 : spdk_ut_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
     187                 :            : {
     188                 :         18 :         struct spdk_ut_sock *sock = __ut_sock(_sock);
     189                 :            :         struct spdk_ut_sock *peer;
     190                 :            : 
     191         [ -  + ]:         18 :         SPDK_CU_ASSERT_FATAL(sock->peer != NULL);
     192                 :         18 :         peer = sock->peer;
     193                 :            : 
     194                 :            :         /* Test implementation only supports single iov for now. */
     195                 :         18 :         CU_ASSERT(iovcnt == 1);
     196                 :            : 
     197   [ -  +  -  + ]:         18 :         memcpy(&peer->buf[peer->bytes_avail], iov[0].iov_base, iov[0].iov_len);
     198                 :         18 :         peer->bytes_avail += iov[0].iov_len;
     199                 :            : 
     200                 :         18 :         return iov[0].iov_len;
     201                 :            : }
     202                 :            : 
     203                 :            : static int
     204                 :          0 : spdk_ut_sock_flush(struct spdk_sock *sock)
     205                 :            : {
     206                 :          0 :         return -1;
     207                 :            : }
     208                 :            : 
     209                 :            : static int
     210                 :          6 : spdk_ut_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes)
     211                 :            : {
     212                 :          6 :         return 0;
     213                 :            : }
     214                 :            : 
     215                 :            : static int
     216                 :          6 : spdk_ut_sock_set_recvbuf(struct spdk_sock *_sock, int sz)
     217                 :            : {
     218                 :          6 :         return 0;
     219                 :            : }
     220                 :            : 
     221                 :            : static int
     222                 :          6 : spdk_ut_sock_set_sendbuf(struct spdk_sock *_sock, int sz)
     223                 :            : {
     224                 :          6 :         return 0;
     225                 :            : }
     226                 :            : 
     227                 :            : static bool
     228                 :          6 : spdk_ut_sock_is_ipv6(struct spdk_sock *_sock)
     229                 :            : {
     230                 :          6 :         return false;
     231                 :            : }
     232                 :            : 
     233                 :            : static bool
     234                 :          6 : spdk_ut_sock_is_ipv4(struct spdk_sock *_sock)
     235                 :            : {
     236                 :          6 :         return true;
     237                 :            : }
     238                 :            : 
     239                 :            : static bool
     240                 :         18 : spdk_ut_sock_is_connected(struct spdk_sock *_sock)
     241                 :            : {
     242                 :         18 :         struct spdk_ut_sock *sock = __ut_sock(_sock);
     243                 :            : 
     244                 :         18 :         return (sock->peer != NULL);
     245                 :            : }
     246                 :            : 
     247                 :            : static struct spdk_sock_group_impl *
     248                 :          6 : spdk_ut_sock_group_impl_get_optimal(struct spdk_sock *_sock, struct spdk_sock_group_impl *hint)
     249                 :            : {
     250                 :          6 :         return NULL;
     251                 :            : }
     252                 :            : 
     253                 :            : static struct spdk_sock_group_impl *
     254                 :         48 : spdk_ut_sock_group_impl_create(void)
     255                 :            : {
     256                 :            :         struct spdk_ut_sock_group_impl *group_impl;
     257                 :            : 
     258                 :         48 :         group_impl = calloc(1, sizeof(*group_impl));
     259         [ -  + ]:         48 :         SPDK_CU_ASSERT_FATAL(group_impl != NULL);
     260                 :            : 
     261                 :         48 :         return &group_impl->base;
     262                 :            : }
     263                 :            : 
     264                 :            : static int
     265                 :          6 : spdk_ut_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
     266                 :            : {
     267                 :          6 :         struct spdk_ut_sock_group_impl *group = __ut_group(_group);
     268                 :          6 :         struct spdk_ut_sock *sock = __ut_sock(_sock);
     269                 :            : 
     270                 :          6 :         group->sock = sock;
     271                 :            : 
     272                 :          6 :         return 0;
     273                 :            : }
     274                 :            : 
     275                 :            : static int
     276                 :          6 : spdk_ut_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
     277                 :            : {
     278                 :          6 :         struct spdk_ut_sock_group_impl *group = __ut_group(_group);
     279                 :          6 :         struct spdk_ut_sock *sock = __ut_sock(_sock);
     280                 :            : 
     281                 :          6 :         CU_ASSERT(group->sock == sock);
     282                 :          6 :         group->sock = NULL;
     283                 :            : 
     284                 :          6 :         return 0;
     285                 :            : }
     286                 :            : 
     287                 :            : static int
     288                 :         12 : spdk_ut_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events,
     289                 :            :                              struct spdk_sock **socks)
     290                 :            : {
     291                 :         12 :         struct spdk_ut_sock_group_impl *group = __ut_group(_group);
     292                 :            : 
     293   [ +  -  +  + ]:         12 :         if (group->sock != NULL && group->sock->bytes_avail > 0) {
     294                 :          6 :                 socks[0] = &group->sock->base;
     295                 :          6 :                 return 1;
     296                 :            :         }
     297                 :            : 
     298                 :          6 :         return 0;
     299                 :            : }
     300                 :            : 
     301                 :            : static int
     302                 :         48 : spdk_ut_sock_group_impl_close(struct spdk_sock_group_impl *_group)
     303                 :            : {
     304                 :         48 :         struct spdk_ut_sock_group_impl *group = __ut_group(_group);
     305                 :            : 
     306                 :         48 :         CU_ASSERT(group->sock == NULL);
     307                 :         48 :         free(_group);
     308                 :            : 
     309                 :         48 :         return 0;
     310                 :            : }
     311                 :            : 
     312                 :            : static struct spdk_net_impl g_ut_net_impl = {
     313                 :            :         .name           = "ut",
     314                 :            :         .getaddr        = spdk_ut_sock_getaddr,
     315                 :            :         .connect        = spdk_ut_sock_connect,
     316                 :            :         .listen         = spdk_ut_sock_listen,
     317                 :            :         .accept         = spdk_ut_sock_accept,
     318                 :            :         .close          = spdk_ut_sock_close,
     319                 :            :         .recv           = spdk_ut_sock_recv,
     320                 :            :         .readv          = spdk_ut_sock_readv,
     321                 :            :         .writev         = spdk_ut_sock_writev,
     322                 :            :         .flush          = spdk_ut_sock_flush,
     323                 :            :         .set_recvlowat  = spdk_ut_sock_set_recvlowat,
     324                 :            :         .set_recvbuf    = spdk_ut_sock_set_recvbuf,
     325                 :            :         .set_sendbuf    = spdk_ut_sock_set_sendbuf,
     326                 :            :         .is_ipv6        = spdk_ut_sock_is_ipv6,
     327                 :            :         .is_ipv4        = spdk_ut_sock_is_ipv4,
     328                 :            :         .is_connected   = spdk_ut_sock_is_connected,
     329                 :            :         .group_impl_get_optimal = spdk_ut_sock_group_impl_get_optimal,
     330                 :            :         .group_impl_create      = spdk_ut_sock_group_impl_create,
     331                 :            :         .group_impl_add_sock    = spdk_ut_sock_group_impl_add_sock,
     332                 :            :         .group_impl_remove_sock = spdk_ut_sock_group_impl_remove_sock,
     333                 :            :         .group_impl_poll        = spdk_ut_sock_group_impl_poll,
     334                 :            :         .group_impl_close       = spdk_ut_sock_group_impl_close,
     335                 :            : };
     336                 :            : 
     337                 :          6 : SPDK_NET_IMPL_REGISTER(ut, &g_ut_net_impl);
     338                 :            : 
     339                 :            : static void
     340                 :         12 : _sock(const char *ip, int port, char *impl_name)
     341                 :            : {
     342                 :         10 :         struct spdk_sock *listen_sock;
     343                 :         10 :         struct spdk_sock *server_sock;
     344                 :         10 :         struct spdk_sock *client_sock;
     345                 :         12 :         char *test_string = "abcdef";
     346                 :         10 :         char buffer[64];
     347                 :            :         ssize_t bytes_read, bytes_written;
     348                 :         10 :         struct iovec iov;
     349                 :            :         int nbytes;
     350                 :            :         int rc;
     351                 :            : 
     352                 :         12 :         listen_sock = spdk_sock_listen(ip, port, impl_name);
     353         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
     354                 :            : 
     355                 :         12 :         server_sock = spdk_sock_accept(listen_sock);
     356                 :         12 :         CU_ASSERT(server_sock == NULL);
     357   [ -  +  -  - ]:         12 :         CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK);
     358                 :            : 
     359                 :         12 :         client_sock = spdk_sock_connect(ip, port, impl_name);
     360         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(client_sock != NULL);
     361                 :            : 
     362                 :            :         /*
     363                 :            :          * Delay a bit here before checking if server socket is
     364                 :            :          *  ready.
     365                 :            :          */
     366                 :         12 :         usleep(1000);
     367                 :            : 
     368                 :         12 :         server_sock = spdk_sock_accept(listen_sock);
     369         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(server_sock != NULL);
     370                 :         12 :         CU_ASSERT(spdk_sock_is_connected(client_sock) == true);
     371                 :         12 :         CU_ASSERT(spdk_sock_is_connected(server_sock) == true);
     372                 :            : 
     373                 :            :         /* Test spdk_sock_set_default_impl */
     374                 :         12 :         rc = spdk_sock_set_default_impl(impl_name);
     375                 :         12 :         CU_ASSERT(rc == 0);
     376                 :         12 :         CU_ASSERT(g_default_impl != NULL);
     377                 :            : 
     378                 :            :         /* Test spdk_sock_set_default_impl when name is NULL */
     379                 :         12 :         rc = spdk_sock_set_default_impl(NULL);
     380                 :         12 :         CU_ASSERT(rc == -1);
     381                 :         12 :         CU_ASSERT(errno == EINVAL);
     382                 :            : 
     383                 :            :         /* Test spdk_sock_is _ipv6 */
     384                 :         12 :         CU_ASSERT(!spdk_sock_is_ipv6(client_sock));
     385                 :            : 
     386                 :            :         /* Test spdk_sock_is _ipv4 */
     387                 :         12 :         CU_ASSERT(spdk_sock_is_ipv4(client_sock));
     388                 :            : 
     389                 :         12 :         nbytes = 2048;
     390                 :            : 
     391                 :            :         /* Test spdk_sock_set_recvlowat */
     392                 :         12 :         rc = spdk_sock_set_recvlowat(client_sock, nbytes);
     393                 :         12 :         CU_ASSERT(rc == 0);
     394                 :            : 
     395                 :            :         /* Test spdk_sock_set_recvbuf */
     396                 :         12 :         rc = spdk_sock_set_recvbuf(client_sock, nbytes);
     397                 :         12 :         CU_ASSERT(rc == 0);
     398                 :            : 
     399                 :            :         /* Test spdk_sock_set_sendbuf */
     400                 :         12 :         rc = spdk_sock_set_sendbuf(client_sock, nbytes);
     401                 :         12 :         CU_ASSERT(rc == 0);
     402                 :            : 
     403                 :            :         /* Test spdk_sock_recv */
     404                 :         12 :         iov.iov_base = test_string;
     405                 :         12 :         iov.iov_len = 7;
     406                 :         12 :         bytes_written = spdk_sock_writev(client_sock, &iov, 1);
     407                 :         12 :         CU_ASSERT(bytes_written == 7);
     408                 :            : 
     409                 :         12 :         usleep(1000);
     410                 :            : 
     411                 :         12 :         bytes_read = spdk_sock_recv(server_sock, buffer, 2);
     412                 :         12 :         CU_ASSERT(bytes_read == 2);
     413                 :            : 
     414                 :         12 :         usleep(1000);
     415                 :            : 
     416                 :         12 :         bytes_read += spdk_sock_recv(server_sock, buffer + 2, 5);
     417                 :         12 :         CU_ASSERT(bytes_read == 7);
     418                 :            : 
     419         [ -  + ]:         12 :         CU_ASSERT(strncmp(test_string, buffer, 7) == 0);
     420                 :            : 
     421                 :            :         /* Test spdk_sock_readv */
     422                 :         12 :         iov.iov_base = test_string;
     423                 :         12 :         iov.iov_len = 7;
     424                 :         12 :         bytes_written = spdk_sock_writev(client_sock, &iov, 1);
     425                 :         12 :         CU_ASSERT(bytes_written == 7);
     426                 :            : 
     427                 :         12 :         usleep(1000);
     428                 :            : 
     429                 :         12 :         iov.iov_base = buffer;
     430                 :         12 :         iov.iov_len = 2;
     431                 :         12 :         bytes_read = spdk_sock_readv(server_sock, &iov, 1);
     432                 :         12 :         CU_ASSERT(bytes_read == 2);
     433                 :            : 
     434                 :         12 :         usleep(1000);
     435                 :            : 
     436                 :         12 :         iov.iov_base = buffer + 2;
     437                 :         12 :         iov.iov_len = 5;
     438                 :         12 :         bytes_read += spdk_sock_readv(server_sock, &iov, 1);
     439                 :         12 :         CU_ASSERT(bytes_read == 7);
     440                 :            : 
     441                 :         12 :         usleep(1000);
     442                 :            : 
     443         [ -  + ]:         12 :         CU_ASSERT(strncmp(test_string, buffer, 7) == 0);
     444                 :            : 
     445                 :         12 :         rc = spdk_sock_close(&client_sock);
     446                 :         12 :         CU_ASSERT(client_sock == NULL);
     447                 :         12 :         CU_ASSERT(rc == 0);
     448                 :            : 
     449                 :            : #if defined(__FreeBSD__)
     450                 :            :         /* On FreeBSD, it takes a small amount of time for a close to propagate to the
     451                 :            :          * other side, even in loopback. Introduce a small sleep. */
     452                 :            :         sleep(1);
     453                 :            : #endif
     454                 :         12 :         CU_ASSERT(spdk_sock_is_connected(server_sock) == false);
     455                 :            : 
     456                 :         12 :         rc = spdk_sock_close(&server_sock);
     457                 :         12 :         CU_ASSERT(server_sock == NULL);
     458                 :         12 :         CU_ASSERT(rc == 0);
     459                 :            : 
     460                 :         12 :         rc = spdk_sock_close(&listen_sock);
     461                 :         12 :         CU_ASSERT(listen_sock == NULL);
     462                 :         12 :         CU_ASSERT(rc == 0);
     463                 :         12 : }
     464                 :            : 
     465                 :            : static void
     466                 :          6 : posix_sock(void)
     467                 :            : {
     468                 :          6 :         _sock("127.0.0.1", UT_PORT, "posix");
     469                 :          6 : }
     470                 :            : 
     471                 :            : static void
     472                 :          6 : ut_sock(void)
     473                 :            : {
     474                 :          6 :         _sock(UT_IP, UT_PORT, "ut");
     475                 :          6 : }
     476                 :            : 
     477                 :            : static void
     478                 :         12 : read_data(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock)
     479                 :            : {
     480                 :         12 :         struct spdk_sock *server_sock = cb_arg;
     481                 :            : 
     482                 :         12 :         CU_ASSERT(server_sock == sock);
     483                 :            : 
     484                 :         12 :         g_read_data_called = true;
     485                 :         12 :         g_bytes_read += spdk_sock_recv(server_sock, g_buf + g_bytes_read, sizeof(g_buf) - g_bytes_read);
     486                 :         12 : }
     487                 :            : 
     488                 :            : static void
     489                 :         12 : _sock_group(const char *ip, int port, char *impl_name)
     490                 :            : {
     491                 :         10 :         struct spdk_sock_group *group;
     492                 :         10 :         struct spdk_sock_group *hint;
     493                 :         10 :         struct spdk_sock *listen_sock;
     494                 :         10 :         struct spdk_sock *server_sock;
     495                 :         10 :         struct spdk_sock *client_sock;
     496                 :         12 :         char *test_string = "abcdef";
     497                 :            :         ssize_t bytes_written;
     498                 :         10 :         struct iovec iov;
     499                 :            :         int rc;
     500                 :            : 
     501                 :         12 :         listen_sock = spdk_sock_listen(ip, port, impl_name);
     502         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
     503                 :            : 
     504                 :         12 :         server_sock = spdk_sock_accept(listen_sock);
     505                 :         12 :         CU_ASSERT(server_sock == NULL);
     506   [ -  +  -  - ]:         12 :         CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK);
     507                 :            : 
     508                 :         12 :         client_sock = spdk_sock_connect(ip, port, impl_name);
     509         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(client_sock != NULL);
     510                 :            : 
     511                 :         12 :         usleep(1000);
     512                 :            : 
     513                 :         12 :         server_sock = spdk_sock_accept(listen_sock);
     514         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(server_sock != NULL);
     515                 :            : 
     516                 :         12 :         group = spdk_sock_group_create(NULL);
     517         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     518                 :            : 
     519                 :         12 :         hint = spdk_sock_group_create(NULL);
     520         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(hint != NULL);
     521                 :            : 
     522                 :            :         /* pass null cb_fn */
     523                 :         12 :         rc = spdk_sock_group_add_sock(group, server_sock, NULL, NULL);
     524                 :         12 :         CU_ASSERT(rc == -1);
     525                 :         12 :         CU_ASSERT(errno == EINVAL);
     526                 :            : 
     527                 :         12 :         rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
     528                 :         12 :         CU_ASSERT(rc == 0);
     529                 :            : 
     530                 :            :         /* try adding sock a second time */
     531                 :         12 :         rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
     532                 :         12 :         CU_ASSERT(rc == -1);
     533                 :         12 :         CU_ASSERT(errno == EINVAL);
     534                 :            : 
     535                 :         12 :         g_read_data_called = false;
     536                 :         12 :         g_bytes_read = 0;
     537                 :         12 :         rc = spdk_sock_group_poll(group);
     538                 :            : 
     539                 :         12 :         CU_ASSERT(rc == 0);
     540         [ -  + ]:         12 :         CU_ASSERT(g_read_data_called == false);
     541                 :            : 
     542                 :         12 :         iov.iov_base = test_string;
     543                 :         12 :         iov.iov_len = 7;
     544                 :         12 :         bytes_written = spdk_sock_writev(client_sock, &iov, 1);
     545                 :         12 :         CU_ASSERT(bytes_written == 7);
     546                 :            : 
     547                 :         12 :         usleep(1000);
     548                 :            : 
     549                 :         12 :         g_read_data_called = false;
     550                 :         12 :         g_bytes_read = 0;
     551                 :         12 :         rc = spdk_sock_group_poll(group);
     552                 :            : 
     553                 :         12 :         CU_ASSERT(rc == 1);
     554         [ -  + ]:         12 :         CU_ASSERT(g_read_data_called == true);
     555                 :         12 :         CU_ASSERT(g_bytes_read == 7);
     556                 :            : 
     557         [ -  + ]:         12 :         CU_ASSERT(strncmp(test_string, g_buf, 7) == 0);
     558                 :            : 
     559                 :         12 :         rc = spdk_sock_close(&client_sock);
     560                 :         12 :         CU_ASSERT(client_sock == NULL);
     561                 :         12 :         CU_ASSERT(rc == 0);
     562                 :            : 
     563                 :            :         /* Test get_optimal_sock_group */
     564                 :         12 :         rc = spdk_sock_get_optimal_sock_group(server_sock, &group, hint);
     565                 :         12 :         CU_ASSERT(rc == 0);
     566                 :            : 
     567                 :            :         /* Try to close sock_group while it still has sockets. */
     568                 :         12 :         rc = spdk_sock_group_close(&group);
     569                 :         12 :         CU_ASSERT(rc == -1);
     570                 :         12 :         CU_ASSERT(errno == EBUSY);
     571                 :            : 
     572                 :            :         /* Try to close sock while it is still part of a sock_group. */
     573                 :         12 :         rc = spdk_sock_close(&server_sock);
     574                 :         12 :         CU_ASSERT(rc == -1);
     575                 :         12 :         CU_ASSERT(errno == EBUSY);
     576                 :            : 
     577                 :         12 :         rc = spdk_sock_group_remove_sock(group, server_sock);
     578                 :         12 :         CU_ASSERT(rc == 0);
     579                 :            : 
     580                 :         12 :         rc = spdk_sock_group_close(&group);
     581                 :         12 :         CU_ASSERT(group == NULL);
     582                 :         12 :         CU_ASSERT(rc == 0);
     583                 :            : 
     584                 :         12 :         rc = spdk_sock_group_close(&hint);
     585                 :         12 :         CU_ASSERT(hint == NULL);
     586                 :         12 :         CU_ASSERT(rc == 0);
     587                 :            : 
     588                 :         12 :         rc = spdk_sock_close(&server_sock);
     589                 :         12 :         CU_ASSERT(server_sock == NULL);
     590                 :         12 :         CU_ASSERT(rc == 0);
     591                 :            : 
     592                 :         12 :         rc = spdk_sock_close(&listen_sock);
     593                 :         12 :         CU_ASSERT(listen_sock == NULL);
     594                 :         12 :         CU_ASSERT(rc == 0);
     595                 :         12 : }
     596                 :            : 
     597                 :            : static void
     598                 :          6 : posix_sock_group(void)
     599                 :            : {
     600                 :          6 :         _sock_group("127.0.0.1", UT_PORT, "posix");
     601                 :          6 : }
     602                 :            : 
     603                 :            : static void
     604                 :          6 : ut_sock_group(void)
     605                 :            : {
     606                 :          6 :         _sock_group(UT_IP, UT_PORT, "ut");
     607                 :          6 : }
     608                 :            : 
     609                 :            : static void
     610                 :         24 : read_data_fairness(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock)
     611                 :            : {
     612                 :         24 :         struct spdk_sock *server_sock = cb_arg;
     613                 :            :         ssize_t bytes_read;
     614                 :         20 :         char buf[1];
     615                 :            : 
     616                 :         24 :         CU_ASSERT(g_server_sock_read == NULL);
     617                 :         24 :         CU_ASSERT(server_sock == sock);
     618                 :            : 
     619                 :         24 :         g_server_sock_read = server_sock;
     620                 :         24 :         bytes_read = spdk_sock_recv(server_sock, buf, 1);
     621                 :         24 :         CU_ASSERT(bytes_read == 1);
     622                 :         24 : }
     623                 :            : 
     624                 :            : static void
     625                 :          6 : posix_sock_group_fairness(void)
     626                 :            : {
     627                 :          5 :         struct spdk_sock_group *group;
     628                 :          5 :         struct spdk_sock *listen_sock;
     629                 :          5 :         struct spdk_sock *server_sock[3];
     630                 :          5 :         struct spdk_sock *client_sock[3];
     631                 :          6 :         char test_char = 'a';
     632                 :            :         ssize_t bytes_written;
     633                 :          5 :         struct iovec iov;
     634                 :            :         int i, rc;
     635                 :            : 
     636                 :          6 :         listen_sock = spdk_sock_listen("127.0.0.1", UT_PORT, "posix");
     637         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
     638                 :            : 
     639                 :          6 :         group = spdk_sock_group_create(NULL);
     640         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     641                 :            : 
     642         [ +  + ]:         24 :         for (i = 0; i < 3; i++) {
     643                 :         18 :                 client_sock[i] = spdk_sock_connect("127.0.0.1", UT_PORT, "posix");
     644         [ -  + ]:         18 :                 SPDK_CU_ASSERT_FATAL(client_sock[i] != NULL);
     645                 :            : 
     646                 :         18 :                 usleep(1000);
     647                 :            : 
     648                 :         18 :                 server_sock[i] = spdk_sock_accept(listen_sock);
     649         [ -  + ]:         18 :                 SPDK_CU_ASSERT_FATAL(server_sock[i] != NULL);
     650                 :            : 
     651                 :         18 :                 rc = spdk_sock_group_add_sock(group, server_sock[i],
     652                 :         18 :                                               read_data_fairness, server_sock[i]);
     653                 :         18 :                 CU_ASSERT(rc == 0);
     654                 :            :         }
     655                 :            : 
     656                 :          6 :         iov.iov_base = &test_char;
     657                 :          6 :         iov.iov_len = 1;
     658                 :            : 
     659         [ +  + ]:         24 :         for (i = 0; i < 3; i++) {
     660                 :         18 :                 bytes_written = spdk_sock_writev(client_sock[i], &iov, 1);
     661                 :         18 :                 CU_ASSERT(bytes_written == 1);
     662                 :            :         }
     663                 :            : 
     664                 :          6 :         usleep(1000);
     665                 :            : 
     666                 :            :         /*
     667                 :            :          * Poll for just one event - this should be server sock 0, since that
     668                 :            :          *  is the peer of the first client sock that we wrote to.
     669                 :            :          */
     670                 :          6 :         g_server_sock_read = NULL;
     671                 :          6 :         rc = spdk_sock_group_poll_count(group, 1);
     672                 :          6 :         CU_ASSERT(rc == 1);
     673                 :          6 :         CU_ASSERT(g_server_sock_read == server_sock[0]);
     674                 :            : 
     675                 :            :         /*
     676                 :            :          * Now write another byte to client sock 0.  We want to ensure that
     677                 :            :          *  the sock group does not unfairly process the event for this sock
     678                 :            :          *  before the socks that were written to earlier.
     679                 :            :          */
     680                 :          6 :         bytes_written = spdk_sock_writev(client_sock[0], &iov, 1);
     681                 :          6 :         CU_ASSERT(bytes_written == 1);
     682                 :            : 
     683                 :          6 :         usleep(1000);
     684                 :            : 
     685                 :          6 :         g_server_sock_read = NULL;
     686                 :          6 :         rc = spdk_sock_group_poll_count(group, 1);
     687                 :          6 :         CU_ASSERT(rc == 1);
     688                 :          6 :         CU_ASSERT(g_server_sock_read == server_sock[1]);
     689                 :            : 
     690                 :          6 :         g_server_sock_read = NULL;
     691                 :          6 :         rc = spdk_sock_group_poll_count(group, 1);
     692                 :          6 :         CU_ASSERT(rc == 1);
     693                 :          6 :         CU_ASSERT(g_server_sock_read == server_sock[2]);
     694                 :            : 
     695                 :          6 :         g_server_sock_read = NULL;
     696                 :          6 :         rc = spdk_sock_group_poll_count(group, 1);
     697                 :          6 :         CU_ASSERT(rc == 1);
     698                 :          6 :         CU_ASSERT(g_server_sock_read == server_sock[0]);
     699                 :            : 
     700         [ +  + ]:         24 :         for (i = 0; i < 3; i++) {
     701                 :         18 :                 rc = spdk_sock_group_remove_sock(group, server_sock[i]);
     702                 :         18 :                 CU_ASSERT(rc == 0);
     703                 :            : 
     704                 :         18 :                 rc = spdk_sock_close(&client_sock[i]);
     705                 :         18 :                 CU_ASSERT(client_sock[i] == NULL);
     706                 :         18 :                 CU_ASSERT(rc == 0);
     707                 :            : 
     708                 :         18 :                 rc = spdk_sock_close(&server_sock[i]);
     709                 :         18 :                 CU_ASSERT(server_sock[i] == NULL);
     710                 :         18 :                 CU_ASSERT(rc == 0);
     711                 :            :         }
     712                 :            : 
     713                 :          6 :         rc = spdk_sock_group_close(&group);
     714                 :          6 :         CU_ASSERT(group == NULL);
     715                 :          6 :         CU_ASSERT(rc == 0);
     716                 :            : 
     717                 :          6 :         rc = spdk_sock_close(&listen_sock);
     718                 :          6 :         CU_ASSERT(listen_sock == NULL);
     719                 :          6 :         CU_ASSERT(rc == 0);
     720                 :          6 : }
     721                 :            : 
     722                 :            : struct close_ctx {
     723                 :            :         struct spdk_sock_group *group;
     724                 :            :         struct spdk_sock *sock;
     725                 :            :         bool called;
     726                 :            : };
     727                 :            : 
     728                 :            : static void
     729                 :          6 : _first_close_cb(void *cb_arg, int err)
     730                 :            : {
     731                 :          6 :         struct close_ctx *ctx = cb_arg;
     732                 :            :         int rc;
     733                 :            : 
     734                 :          6 :         ctx->called = true;
     735                 :            : 
     736                 :            :         /* Always close the socket here */
     737                 :          6 :         rc = spdk_sock_group_remove_sock(ctx->group, ctx->sock);
     738                 :          6 :         CU_ASSERT(rc == 0);
     739                 :          6 :         spdk_sock_close(&ctx->sock);
     740                 :            : 
     741                 :          6 :         CU_ASSERT(err == 0);
     742                 :          6 : }
     743                 :            : 
     744                 :            : static void
     745                 :          6 : _second_close_cb(void *cb_arg, int err)
     746                 :            : {
     747                 :          6 :         *(bool *)cb_arg = true;
     748                 :          6 :         CU_ASSERT(err == -ECANCELED);
     749                 :          6 : }
     750                 :            : 
     751                 :            : static void
     752                 :          6 : _sock_close(const char *ip, int port, char *impl_name)
     753                 :            : {
     754                 :          5 :         struct spdk_sock_group *group;
     755                 :          5 :         struct spdk_sock *listen_sock;
     756                 :            :         struct spdk_sock *server_sock;
     757                 :          5 :         struct spdk_sock *client_sock;
     758                 :          6 :         uint8_t data_buf[64] = {};
     759                 :            :         struct spdk_sock_request *req1, *req2;
     760                 :          6 :         struct close_ctx ctx = {};
     761                 :          6 :         bool cb_arg2 = false;
     762                 :            :         int rc;
     763                 :            : 
     764                 :          6 :         listen_sock = spdk_sock_listen(ip, port, impl_name);
     765         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
     766                 :            : 
     767                 :          6 :         client_sock = spdk_sock_connect(ip, port, impl_name);
     768         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(client_sock != NULL);
     769                 :            : 
     770                 :          6 :         usleep(1000);
     771                 :            : 
     772                 :          6 :         server_sock = spdk_sock_accept(listen_sock);
     773         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(server_sock != NULL);
     774                 :            : 
     775                 :          6 :         group = spdk_sock_group_create(NULL);
     776         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     777                 :            : 
     778                 :          6 :         rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
     779                 :          6 :         CU_ASSERT(rc == 0);
     780                 :            : 
     781                 :            :         /* Submit multiple async writevs on the server sock */
     782                 :            : 
     783                 :          6 :         req1 = calloc(1, sizeof(struct spdk_sock_request) + sizeof(struct iovec));
     784         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(req1 != NULL);
     785                 :          6 :         SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_base = data_buf;
     786                 :          6 :         SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_len = 64;
     787                 :          6 :         ctx.group = group;
     788                 :          6 :         ctx.sock = server_sock;
     789                 :          6 :         ctx.called = false;
     790                 :          6 :         req1->iovcnt = 1;
     791                 :          6 :         req1->cb_fn = _first_close_cb;
     792                 :          6 :         req1->cb_arg = &ctx;
     793                 :          6 :         spdk_sock_writev_async(server_sock, req1);
     794         [ -  + ]:          6 :         CU_ASSERT(ctx.called == false);
     795                 :            : 
     796                 :          6 :         req2 = calloc(1, sizeof(struct spdk_sock_request) + sizeof(struct iovec));
     797         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(req2 != NULL);
     798                 :          6 :         SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_base = data_buf;
     799                 :          6 :         SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_len = 64;
     800                 :          6 :         req2->iovcnt = 1;
     801                 :          6 :         req2->cb_fn = _second_close_cb;
     802                 :          6 :         req2->cb_arg = &cb_arg2;
     803                 :          6 :         spdk_sock_writev_async(server_sock, req2);
     804         [ -  + ]:          6 :         CU_ASSERT(cb_arg2 == false);
     805                 :            : 
     806                 :            :         /* Test spdk_sock_flush when sock is NULL */
     807                 :          6 :         rc = spdk_sock_flush(NULL);
     808                 :          6 :         CU_ASSERT(rc == -1);
     809                 :          6 :         CU_ASSERT(errno == EBADF);
     810                 :            : 
     811                 :            :         /* Test spdk_sock_flush when sock is not NULL */
     812                 :          6 :         rc = spdk_sock_flush(client_sock);
     813                 :          6 :         CU_ASSERT(rc == 0);
     814                 :            : 
     815                 :            :         /* Poll the socket so the writev_async's send. The first one's
     816                 :            :          * callback will close the socket. */
     817                 :          6 :         spdk_sock_group_poll(group);
     818   [ -  +  -  + ]:          6 :         if (ctx.called == false) {
     819                 :            :                 /* Sometimes the zerocopy completion isn't posted immediately. Delay slightly
     820                 :            :                 * and poll one more time. */
     821                 :          0 :                 usleep(1000);
     822                 :          0 :                 spdk_sock_group_poll(group);
     823                 :            :         }
     824         [ -  + ]:          6 :         CU_ASSERT(ctx.called == true);
     825         [ -  + ]:          6 :         CU_ASSERT(cb_arg2 == true);
     826                 :            : 
     827                 :          6 :         rc = spdk_sock_group_close(&group);
     828                 :          6 :         CU_ASSERT(group == NULL);
     829                 :          6 :         CU_ASSERT(rc == 0);
     830                 :            : 
     831                 :          6 :         rc = spdk_sock_close(&client_sock);
     832                 :          6 :         CU_ASSERT(client_sock == NULL);
     833                 :          6 :         CU_ASSERT(rc == 0);
     834                 :            : 
     835                 :          6 :         rc = spdk_sock_close(&listen_sock);
     836                 :          6 :         CU_ASSERT(listen_sock == NULL);
     837                 :          6 :         CU_ASSERT(rc == 0);
     838                 :            : 
     839                 :          6 :         free(req1);
     840                 :          6 :         free(req2);
     841                 :          6 : }
     842                 :            : 
     843                 :            : static void
     844                 :          6 : _posix_sock_close(void)
     845                 :            : {
     846                 :          6 :         _sock_close("127.0.0.1", UT_PORT, "posix");
     847                 :          6 : }
     848                 :            : 
     849                 :            : static void
     850                 :          6 : sock_get_default_opts(void)
     851                 :            : {
     852                 :          5 :         struct spdk_sock_opts opts;
     853                 :            : 
     854                 :            :         /* opts_size is 0 */
     855                 :          6 :         opts.opts_size = 0;
     856                 :          6 :         opts.priority = 3;
     857                 :          6 :         spdk_sock_get_default_opts(&opts);
     858                 :          6 :         CU_ASSERT(opts.priority == 3);
     859                 :          6 :         CU_ASSERT(opts.opts_size == 0);
     860                 :            : 
     861                 :            :         /* opts_size is less than sizeof(opts) */
     862                 :          6 :         opts.opts_size = 4;
     863                 :          6 :         opts.priority = 3;
     864                 :          6 :         spdk_sock_get_default_opts(&opts);
     865                 :          6 :         CU_ASSERT(opts.priority == 3);
     866                 :          6 :         CU_ASSERT(opts.opts_size == 4);
     867                 :            : 
     868                 :            :         /* opts_size is equal to sizeof(opts) */
     869                 :          6 :         opts.opts_size = sizeof(opts);
     870                 :          6 :         opts.priority = 3;
     871                 :          6 :         spdk_sock_get_default_opts(&opts);
     872                 :          6 :         CU_ASSERT(opts.priority == SPDK_SOCK_DEFAULT_PRIORITY);
     873                 :          6 :         CU_ASSERT(opts.opts_size == sizeof(opts));
     874                 :            : 
     875                 :            :         /* opts_size is larger then sizeof(opts) */
     876                 :          6 :         opts.opts_size = sizeof(opts) + 1;
     877                 :          6 :         opts.priority = 3;
     878                 :          6 :         spdk_sock_get_default_opts(&opts);
     879                 :          6 :         CU_ASSERT(opts.priority == SPDK_SOCK_DEFAULT_PRIORITY);
     880                 :          6 :         CU_ASSERT(opts.opts_size == (sizeof(opts) + 1));
     881                 :          6 : }
     882                 :            : 
     883                 :            : static void
     884                 :          6 : ut_sock_impl_get_set_opts(void)
     885                 :            : {
     886                 :            :         int rc;
     887                 :          6 :         size_t len = 0;
     888                 :            :         /* Use any pointer value for opts. It is never dereferenced in this test */
     889                 :          6 :         struct spdk_sock_impl_opts *opts = (struct spdk_sock_impl_opts *)0x123456789;
     890                 :            : 
     891                 :          6 :         rc = spdk_sock_impl_get_opts("ut", NULL, &len);
     892                 :          6 :         CU_ASSERT(rc == -1);
     893                 :          6 :         CU_ASSERT(errno == EINVAL);
     894                 :          6 :         rc = spdk_sock_impl_get_opts("ut", opts, NULL);
     895                 :          6 :         CU_ASSERT(rc == -1);
     896                 :          6 :         CU_ASSERT(errno == EINVAL);
     897                 :          6 :         rc = spdk_sock_impl_get_opts("ut", opts, &len);
     898                 :          6 :         CU_ASSERT(rc == -1);
     899                 :          6 :         CU_ASSERT(errno == ENOTSUP);
     900                 :            : 
     901                 :          6 :         rc = spdk_sock_impl_set_opts("ut", NULL, len);
     902                 :          6 :         CU_ASSERT(rc == -1);
     903                 :          6 :         CU_ASSERT(errno == EINVAL);
     904                 :          6 :         rc = spdk_sock_impl_set_opts("ut", opts, len);
     905                 :          6 :         CU_ASSERT(rc == -1);
     906                 :          6 :         CU_ASSERT(errno == ENOTSUP);
     907                 :          6 : }
     908                 :            : 
     909                 :            : static void
     910                 :          6 : posix_sock_impl_get_set_opts(void)
     911                 :            : {
     912                 :            :         int rc;
     913                 :          6 :         size_t len = 0;
     914                 :          6 :         struct spdk_sock_impl_opts opts = {};
     915                 :            : 
     916                 :          6 :         rc = spdk_sock_impl_get_opts("posix", NULL, &len);
     917                 :          6 :         CU_ASSERT(rc == -1);
     918                 :          6 :         CU_ASSERT(errno == EINVAL);
     919                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &opts, NULL);
     920                 :          6 :         CU_ASSERT(rc == -1);
     921                 :          6 :         CU_ASSERT(errno == EINVAL);
     922                 :            : 
     923                 :            :         /* Check default opts */
     924                 :          6 :         len = sizeof(opts);
     925                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &opts, &len);
     926                 :          6 :         CU_ASSERT(rc == 0);
     927                 :          6 :         CU_ASSERT(len == sizeof(opts));
     928                 :          6 :         CU_ASSERT(opts.recv_buf_size == DEFAULT_SO_RCVBUF_SIZE);
     929                 :          6 :         CU_ASSERT(opts.send_buf_size == DEFAULT_SO_SNDBUF_SIZE);
     930                 :            : 
     931                 :            :         /* Try to request zero opts */
     932                 :          6 :         len = 0;
     933                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &opts, &len);
     934                 :          6 :         CU_ASSERT(rc == 0);
     935                 :          6 :         CU_ASSERT(len == 0);
     936                 :            : 
     937                 :          6 :         rc = spdk_sock_impl_set_opts("posix", NULL, len);
     938                 :          6 :         CU_ASSERT(rc == -1);
     939                 :          6 :         CU_ASSERT(errno == EINVAL);
     940                 :            : 
     941                 :          6 :         opts.recv_buf_size = 16;
     942                 :          6 :         opts.send_buf_size = 4;
     943                 :          6 :         rc = spdk_sock_impl_set_opts("posix", &opts, sizeof(opts));
     944                 :          6 :         CU_ASSERT(rc == 0);
     945                 :          6 :         len = sizeof(opts);
     946                 :          6 :         memset(&opts, 0, sizeof(opts));
     947                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &opts, &len);
     948                 :          6 :         CU_ASSERT(rc == 0);
     949                 :          6 :         CU_ASSERT(opts.recv_buf_size == 16);
     950                 :          6 :         CU_ASSERT(opts.send_buf_size == 4);
     951                 :            : 
     952                 :            :         /* Try to set less opts. Opts in the end should be untouched */
     953                 :          6 :         opts.recv_buf_size = 5;
     954                 :          6 :         opts.send_buf_size = 10;
     955                 :          6 :         rc = spdk_sock_impl_set_opts("posix", &opts, sizeof(opts.recv_buf_size));
     956                 :          6 :         CU_ASSERT(rc == 0);
     957                 :          6 :         len = sizeof(opts);
     958                 :          6 :         memset(&opts, 0, sizeof(opts));
     959                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &opts, &len);
     960                 :          6 :         CU_ASSERT(rc == 0);
     961                 :          6 :         CU_ASSERT(opts.recv_buf_size == 5);
     962                 :          6 :         CU_ASSERT(opts.send_buf_size == 4);
     963                 :            : 
     964                 :            :         /* Try to set partial option. It should not be changed */
     965                 :          6 :         opts.recv_buf_size = 1000;
     966                 :          6 :         rc = spdk_sock_impl_set_opts("posix", &opts, 1);
     967                 :          6 :         CU_ASSERT(rc == 0);
     968                 :          6 :         len = sizeof(opts);
     969                 :          6 :         memset(&opts, 0, sizeof(opts));
     970                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &opts, &len);
     971                 :          6 :         CU_ASSERT(rc == 0);
     972                 :          6 :         CU_ASSERT(opts.recv_buf_size == 5);
     973                 :          6 : }
     974                 :            : 
     975                 :            : static void
     976                 :          6 : ut_sock_map(void)
     977                 :            : {
     978                 :          6 :         struct spdk_sock_map map = {
     979                 :            :                 .entries = STAILQ_HEAD_INITIALIZER(map.entries),
     980                 :            :                 .mtx = PTHREAD_MUTEX_INITIALIZER
     981                 :            :         };
     982                 :          5 :         struct spdk_sock_group_impl *group_1, *group_2, *test_group;
     983                 :            :         int rc;
     984                 :            :         int test_id;
     985                 :            : 
     986                 :          6 :         group_1 = spdk_ut_sock_group_impl_create();
     987                 :          6 :         group_2 = spdk_ut_sock_group_impl_create();
     988                 :            : 
     989                 :            :         /* Test 1
     990                 :            :          * Sanity check when sock_map is empty */
     991                 :          6 :         test_id = spdk_sock_map_find_free(&map);
     992                 :          6 :         CU_ASSERT(test_id == -1);
     993                 :            : 
     994                 :          6 :         test_group = NULL;
     995                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
     996                 :          6 :         CU_ASSERT(rc == -EINVAL);
     997                 :          6 :         CU_ASSERT(test_group == NULL);
     998                 :            : 
     999                 :            :         /* Test 2
    1000                 :            :          * Insert single entry */
    1001                 :          6 :         rc = spdk_sock_map_insert(&map, 1, group_1);
    1002                 :          6 :         CU_ASSERT(rc == 0);
    1003                 :            : 
    1004                 :          6 :         test_group = NULL;
    1005                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
    1006                 :          6 :         CU_ASSERT(rc == 0);
    1007                 :          6 :         CU_ASSERT(test_group == group_1);
    1008                 :            : 
    1009                 :            :         /* There is single entry allocated, but it is not free */
    1010                 :          6 :         test_id = spdk_sock_map_find_free(&map);
    1011                 :          6 :         CU_ASSERT(test_id == -1);
    1012                 :            : 
    1013                 :            :         /* Free the entry and verify */
    1014                 :          6 :         spdk_sock_map_release(&map, 1);
    1015                 :          6 :         test_id = spdk_sock_map_find_free(&map);
    1016                 :          6 :         CU_ASSERT(test_id == 1);
    1017                 :            : 
    1018                 :          6 :         spdk_sock_map_cleanup(&map);
    1019                 :            : 
    1020                 :            :         /* Test 3
    1021                 :            :          * Insert sock_group into placement_id multiple times */
    1022                 :          6 :         rc = spdk_sock_map_insert(&map, 1, group_1);
    1023                 :          6 :         CU_ASSERT(rc == 0);
    1024                 :          6 :         CU_ASSERT(STAILQ_FIRST(&map.entries)->ref == 1);
    1025                 :          6 :         rc = spdk_sock_map_insert(&map, 1, group_1);
    1026                 :          6 :         CU_ASSERT(rc == 0);
    1027                 :          6 :         CU_ASSERT(STAILQ_FIRST(&map.entries)->ref == 2);
    1028                 :            : 
    1029                 :            :         /* Release entry once and see that it still exists. */
    1030                 :          6 :         spdk_sock_map_release(&map, 1);
    1031                 :          6 :         test_group = NULL;
    1032                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
    1033                 :          6 :         CU_ASSERT(rc == 0);
    1034                 :          6 :         CU_ASSERT(test_group == group_1);
    1035                 :            : 
    1036                 :            :         /* Release entry second and final time. */
    1037                 :          6 :         spdk_sock_map_release(&map, 1);
    1038                 :          6 :         test_group = NULL;
    1039                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
    1040                 :          6 :         CU_ASSERT(rc == -EINVAL);
    1041                 :          6 :         CU_ASSERT(test_group == NULL);
    1042                 :            : 
    1043                 :          6 :         spdk_sock_map_cleanup(&map);
    1044                 :            : 
    1045                 :            :         /* Test 4
    1046                 :            :          * Test multiple entries */
    1047                 :          6 :         rc = spdk_sock_map_insert(&map, 1, group_1);
    1048                 :          6 :         CU_ASSERT(rc == 0);
    1049                 :            : 
    1050                 :          6 :         test_group = NULL;
    1051                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
    1052                 :          6 :         CU_ASSERT(rc == 0);
    1053                 :          6 :         CU_ASSERT(test_group == group_1);
    1054                 :            : 
    1055                 :          6 :         rc = spdk_sock_map_insert(&map, 2, group_2);
    1056                 :          6 :         CU_ASSERT(rc == 0);
    1057                 :            : 
    1058                 :          6 :         test_group = NULL;
    1059                 :          6 :         rc = spdk_sock_map_lookup(&map, 2, &test_group, NULL);
    1060                 :          6 :         CU_ASSERT(rc == 0);
    1061                 :          6 :         CU_ASSERT(test_group == group_2);
    1062                 :            : 
    1063                 :          6 :         spdk_sock_map_cleanup(&map);
    1064                 :            : 
    1065                 :            :         /* Test 5
    1066                 :            :          * Attempt inserting multiple entries into single placement_id */
    1067                 :          6 :         rc = spdk_sock_map_insert(&map, 1, group_1);
    1068                 :          6 :         CU_ASSERT(rc == 0);
    1069                 :            : 
    1070                 :          6 :         test_group = NULL;
    1071                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
    1072                 :          6 :         CU_ASSERT(rc == 0);
    1073                 :          6 :         CU_ASSERT(test_group == group_1);
    1074                 :            : 
    1075                 :          6 :         rc = spdk_sock_map_insert(&map, 1, group_2);
    1076                 :          6 :         CU_ASSERT(rc == -EINVAL);
    1077                 :            : 
    1078                 :          6 :         test_group = NULL;
    1079                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
    1080                 :          6 :         CU_ASSERT(rc == 0);
    1081                 :          6 :         CU_ASSERT(test_group == group_1);
    1082                 :            : 
    1083                 :          6 :         spdk_sock_map_cleanup(&map);
    1084                 :            : 
    1085                 :            :         /* Test 6
    1086                 :            :          * Insert single entry without a sock_group */
    1087                 :          6 :         rc = spdk_sock_map_insert(&map, 1, NULL);
    1088                 :          6 :         CU_ASSERT(rc == 0);
    1089                 :            : 
    1090                 :          6 :         test_group = NULL;
    1091                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
    1092                 :          6 :         CU_ASSERT(rc == -EINVAL);
    1093                 :          6 :         CU_ASSERT(test_group == NULL);
    1094                 :            : 
    1095                 :          6 :         test_id = spdk_sock_map_find_free(&map);
    1096                 :          6 :         CU_ASSERT(test_id == 1);
    1097                 :            : 
    1098                 :          6 :         rc = spdk_sock_map_insert(&map, test_id, group_1);
    1099                 :          6 :         CU_ASSERT(rc == 0);
    1100                 :            : 
    1101                 :          6 :         test_group = NULL;
    1102                 :          6 :         rc = spdk_sock_map_lookup(&map, test_id, &test_group, NULL);
    1103                 :          6 :         CU_ASSERT(rc == 0);
    1104                 :          6 :         CU_ASSERT(test_group == group_1);
    1105                 :            : 
    1106                 :          6 :         spdk_sock_map_cleanup(&map);
    1107                 :            : 
    1108                 :            :         /* Test 6
    1109                 :            :          * Use hint sock_group for for placement_id */
    1110                 :          6 :         test_group = NULL;
    1111                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, group_1);
    1112                 :          6 :         CU_ASSERT(rc == 0);
    1113                 :          6 :         CU_ASSERT(test_group == NULL);
    1114                 :            : 
    1115                 :          6 :         test_group = NULL;
    1116                 :          6 :         rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
    1117                 :          6 :         CU_ASSERT(rc == 0);
    1118                 :          6 :         CU_ASSERT(test_group == group_1);
    1119                 :            : 
    1120                 :          6 :         test_id = spdk_sock_map_find_free(&map);
    1121                 :          6 :         CU_ASSERT(test_id == -1);
    1122                 :            : 
    1123                 :          6 :         rc = spdk_sock_map_insert(&map, 1, group_2);
    1124                 :          6 :         CU_ASSERT(rc == -EINVAL);
    1125                 :            : 
    1126                 :          6 :         rc = spdk_sock_map_insert(&map, 1, group_1);
    1127                 :          6 :         CU_ASSERT(rc == 0);
    1128                 :            : 
    1129                 :          6 :         spdk_sock_map_cleanup(&map);
    1130                 :            : 
    1131                 :          6 :         spdk_ut_sock_group_impl_close(group_2);
    1132                 :          6 :         spdk_ut_sock_group_impl_close(group_1);
    1133                 :          6 : }
    1134                 :            : 
    1135                 :            : static void
    1136                 :          6 : override_impl_opts(void)
    1137                 :            : {
    1138                 :          5 :         struct spdk_sock *lsock, *csock, *asock;
    1139                 :          5 :         struct spdk_sock_opts opts;
    1140                 :          5 :         struct spdk_sock_impl_opts impl_opts;
    1141                 :            :         uint32_t send_buf_size;
    1142                 :          5 :         size_t opts_size;
    1143                 :            :         int rc;
    1144                 :            : 
    1145                 :          6 :         opts_size = sizeof(impl_opts);
    1146                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size);
    1147                 :          6 :         CU_ASSERT_EQUAL(rc, 0);
    1148                 :          6 :         opts.opts_size = sizeof(opts);
    1149                 :          6 :         spdk_sock_get_default_opts(&opts);
    1150                 :          6 :         opts.impl_opts = &impl_opts;
    1151                 :          6 :         opts.impl_opts_size = sizeof(impl_opts);
    1152                 :            : 
    1153                 :            :         /* Use send_buf_size to verify that impl_opts get overridden */
    1154                 :          6 :         send_buf_size = impl_opts.send_buf_size;
    1155                 :          6 :         impl_opts.send_buf_size = send_buf_size + 1;
    1156                 :            : 
    1157                 :          6 :         lsock = spdk_sock_listen_ext("127.0.0.1", UT_PORT, "posix", &opts);
    1158         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(lsock != NULL);
    1159                 :          6 :         CU_ASSERT_EQUAL(lsock->impl_opts.send_buf_size, send_buf_size + 1);
    1160                 :            : 
    1161                 :            :         /* Check the same for connect() */
    1162                 :          6 :         opts_size = sizeof(impl_opts);
    1163                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size);
    1164                 :          6 :         CU_ASSERT_EQUAL(rc, 0);
    1165                 :          6 :         opts.opts_size = sizeof(opts);
    1166                 :          6 :         spdk_sock_get_default_opts(&opts);
    1167                 :          6 :         opts.impl_opts = &impl_opts;
    1168                 :          6 :         opts.impl_opts_size = sizeof(impl_opts);
    1169                 :            : 
    1170                 :          6 :         impl_opts.send_buf_size = send_buf_size + 2;
    1171                 :            : 
    1172                 :          6 :         csock = spdk_sock_connect_ext("127.0.0.1", UT_PORT, "posix", &opts);
    1173         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(csock != NULL);
    1174                 :          6 :         CU_ASSERT_EQUAL(csock->impl_opts.send_buf_size, send_buf_size + 2);
    1175                 :            : 
    1176                 :            :         /* Check that accept() inherits impl_opts from listen socket */
    1177                 :          6 :         asock = spdk_sock_accept(lsock);
    1178         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(asock != NULL);
    1179                 :          6 :         CU_ASSERT_EQUAL(asock->impl_opts.send_buf_size, send_buf_size + 1);
    1180                 :            : 
    1181                 :          6 :         spdk_sock_close(&asock);
    1182                 :          6 :         spdk_sock_close(&csock);
    1183                 :          6 :         spdk_sock_close(&lsock);
    1184                 :            : 
    1185                 :            :         /* Check that impl_opts_size is verified by setting it to the offset of send_buf_size  */
    1186                 :          6 :         opts_size = sizeof(impl_opts);
    1187                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size);
    1188                 :          6 :         CU_ASSERT_EQUAL(rc, 0);
    1189                 :          6 :         opts.opts_size = sizeof(opts);
    1190                 :          6 :         spdk_sock_get_default_opts(&opts);
    1191                 :          6 :         opts.impl_opts = &impl_opts;
    1192                 :          6 :         opts.impl_opts_size = offsetof(struct spdk_sock_impl_opts, send_buf_size);
    1193                 :            : 
    1194                 :          6 :         send_buf_size = impl_opts.send_buf_size;
    1195                 :          6 :         impl_opts.send_buf_size = send_buf_size + 1;
    1196                 :            : 
    1197                 :          6 :         lsock = spdk_sock_listen_ext("127.0.0.1", UT_PORT, "posix", &opts);
    1198         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(lsock != NULL);
    1199                 :          6 :         CU_ASSERT_EQUAL(lsock->impl_opts.send_buf_size, send_buf_size);
    1200                 :            : 
    1201                 :            :         /* Check the same for connect() */
    1202                 :          6 :         opts_size = sizeof(impl_opts);
    1203                 :          6 :         rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size);
    1204                 :          6 :         CU_ASSERT_EQUAL(rc, 0);
    1205                 :          6 :         opts.opts_size = sizeof(opts);
    1206                 :          6 :         spdk_sock_get_default_opts(&opts);
    1207                 :          6 :         opts.impl_opts = &impl_opts;
    1208                 :          6 :         opts.impl_opts_size = offsetof(struct spdk_sock_impl_opts, send_buf_size);
    1209                 :            : 
    1210                 :          6 :         impl_opts.send_buf_size = send_buf_size + 2;
    1211                 :            : 
    1212                 :          6 :         csock = spdk_sock_connect_ext("127.0.0.1", UT_PORT, "posix", &opts);
    1213         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(csock != NULL);
    1214                 :          6 :         CU_ASSERT_EQUAL(csock->impl_opts.send_buf_size, send_buf_size);
    1215                 :            : 
    1216                 :          6 :         spdk_sock_close(&lsock);
    1217                 :          6 :         spdk_sock_close(&csock);
    1218                 :          6 : }
    1219                 :            : 
    1220                 :            : static void
    1221                 :          6 : ut_sock_group_get_ctx(void)
    1222                 :            : {
    1223                 :          6 :         void *test_ctx = (void *)0xff0000000;
    1224                 :          6 :         void *test_ctx1 = (void *)0xfff000000;
    1225                 :          6 :         void *test_ctx2 = (void *)0xffff00000;
    1226                 :          5 :         struct spdk_sock_group group;
    1227                 :            : 
    1228                 :            :         /* The return should be NULL */
    1229                 :          6 :         test_ctx = spdk_sock_group_get_ctx(NULL);
    1230                 :          6 :         CU_ASSERT(test_ctx == NULL);
    1231                 :            : 
    1232                 :            :         /* The group.ctx should be changed */
    1233                 :          6 :         group.ctx = test_ctx1;
    1234                 :          6 :         test_ctx2 = spdk_sock_group_get_ctx(&group);
    1235                 :            : 
    1236                 :          6 :         CU_ASSERT(test_ctx1 == test_ctx2);
    1237                 :          6 : }
    1238                 :            : 
    1239                 :            : int
    1240                 :          6 : main(int argc, char **argv)
    1241                 :            : {
    1242                 :          6 :         CU_pSuite       suite = NULL;
    1243                 :            :         unsigned int    num_failures;
    1244                 :            : 
    1245                 :          6 :         CU_initialize_registry();
    1246                 :            : 
    1247                 :          6 :         suite = CU_add_suite("sock", NULL, NULL);
    1248                 :            : 
    1249                 :          6 :         CU_ADD_TEST(suite, posix_sock);
    1250                 :          6 :         CU_ADD_TEST(suite, ut_sock);
    1251                 :          6 :         CU_ADD_TEST(suite, posix_sock_group);
    1252                 :          6 :         CU_ADD_TEST(suite, ut_sock_group);
    1253                 :          6 :         CU_ADD_TEST(suite, posix_sock_group_fairness);
    1254                 :          6 :         CU_ADD_TEST(suite, _posix_sock_close);
    1255                 :          6 :         CU_ADD_TEST(suite, sock_get_default_opts);
    1256                 :          6 :         CU_ADD_TEST(suite, ut_sock_impl_get_set_opts);
    1257                 :          6 :         CU_ADD_TEST(suite, posix_sock_impl_get_set_opts);
    1258                 :          6 :         CU_ADD_TEST(suite, ut_sock_map);
    1259                 :          6 :         CU_ADD_TEST(suite, override_impl_opts);
    1260                 :          6 :         CU_ADD_TEST(suite, ut_sock_group_get_ctx);
    1261                 :            : 
    1262                 :            : 
    1263                 :          6 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
    1264                 :            : 
    1265                 :          6 :         CU_cleanup_registry();
    1266                 :            : 
    1267                 :          6 :         return num_failures;
    1268                 :            : }

Generated by: LCOV version 1.14