LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/nvme/nvme_poll_group.c - nvme_poll_group_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 340 385 88.3 %
Date: 2024-12-09 11:32:52 Functions: 18 28 64.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 177 290 61.0 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2020 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  *   Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "spdk_internal/cunit.h"
       8                 :            : 
       9                 :            : #include "nvme/nvme_poll_group.c"
      10                 :            : #include "common/lib/test_env.c"
      11                 :            : 
      12                 :          4 : SPDK_LOG_REGISTER_COMPONENT(nvme)
      13                 :            : 
      14                 :            : struct spdk_nvme_transport {
      15                 :            :         const char                              name[32];
      16                 :            :         TAILQ_ENTRY(spdk_nvme_transport)        link;
      17                 :            : };
      18                 :            : 
      19                 :            : struct spdk_nvme_transport t1 = {
      20                 :            :         .name = "transport1",
      21                 :            : };
      22                 :            : 
      23                 :            : struct spdk_nvme_transport t2 = {
      24                 :            :         .name = "transport2",
      25                 :            : };
      26                 :            : 
      27                 :            : struct spdk_nvme_transport t3 = {
      28                 :            :         .name = "transport3",
      29                 :            : };
      30                 :            : 
      31                 :            : struct spdk_nvme_transport t4 = {
      32                 :            :         .name = "transport4",
      33                 :            : };
      34                 :            : 
      35                 :            : struct spdk_nvme_ctrlr c1 = {
      36                 :            :         .opts.enable_interrupts = 0,
      37                 :            : };
      38                 :            : 
      39                 :            : struct spdk_nvme_ctrlr c2 = {
      40                 :            :         .opts.enable_interrupts = 1,
      41                 :            : };
      42                 :            : 
      43                 :            : int64_t g_process_completions_return_value = 0;
      44                 :            : int g_destroy_return_value = 0;
      45                 :            : 
      46                 :            : TAILQ_HEAD(nvme_transport_list, spdk_nvme_transport) g_spdk_nvme_transports =
      47                 :            :         TAILQ_HEAD_INITIALIZER(g_spdk_nvme_transports);
      48                 :            : 
      49   [ #  #  #  # ]:          0 : DEFINE_STUB(nvme_transport_qpair_get_optimal_poll_group,
      50                 :            :             struct spdk_nvme_transport_poll_group *,
      51                 :            :             (const struct spdk_nvme_transport *transport,
      52                 :            :              struct spdk_nvme_qpair *qpair),
      53                 :            :             NULL);
      54   [ -  +  #  # ]:         24 : DEFINE_STUB(nvme_transport_get_trtype,
      55                 :            :             enum spdk_nvme_transport_type,
      56                 :            :             (const struct spdk_nvme_transport *transport),
      57                 :            :             SPDK_NVME_TRANSPORT_PCIE);
      58                 :            : 
      59   [ #  #  #  # ]:          0 : DEFINE_STUB(spdk_nvme_qpair_get_fd, int, (struct spdk_nvme_qpair *qpair,
      60                 :            :                 struct spdk_event_handler_opts *opts), 0);
      61   [ #  #  #  # ]:          0 : DEFINE_STUB(spdk_nvme_ctrlr_get_transport_id,
      62                 :            :             const struct spdk_nvme_transport_id *,
      63                 :            :             (struct spdk_nvme_ctrlr *ctrlr), NULL);
      64                 :            : int
      65                 :         12 : nvme_transport_poll_group_get_stats(struct spdk_nvme_transport_poll_group *tgroup,
      66                 :            :                                     struct spdk_nvme_transport_poll_group_stat **stats)
      67                 :            : {
      68                 :         12 :         *stats = calloc(1, sizeof(**stats));
      69         [ +  + ]:         12 :         SPDK_CU_ASSERT_FATAL(*stats != NULL);
      70                 :         12 :         (*stats)->trtype = nvme_transport_get_trtype(NULL);
      71                 :            : 
      72                 :         12 :         return 0;
      73                 :            : }
      74                 :            : 
      75                 :            : void
      76                 :         12 : nvme_transport_poll_group_free_stats(struct spdk_nvme_transport_poll_group *tgroup,
      77                 :            :                                      struct spdk_nvme_transport_poll_group_stat *stats)
      78                 :            : {
      79                 :         12 :         free(stats);
      80                 :         12 : }
      81                 :            : 
      82                 :            : static void
      83                 :          0 : unit_test_disconnected_qpair_cb(struct spdk_nvme_qpair *qpair, void *poll_group_ctx)
      84                 :            : {
      85                 :            : 
      86                 :          0 : }
      87                 :            : 
      88                 :            : const struct spdk_nvme_transport *
      89                 :         32 : nvme_get_first_transport(void)
      90                 :            : {
      91                 :         32 :         return TAILQ_FIRST(&g_spdk_nvme_transports);
      92                 :            : }
      93                 :            : 
      94                 :            : const struct spdk_nvme_transport *
      95                 :         40 : nvme_get_next_transport(const struct spdk_nvme_transport *transport)
      96                 :            : {
      97                 :         40 :         return TAILQ_NEXT(transport, link);
      98                 :            : }
      99                 :            : 
     100                 :            : int
     101                 :          0 : nvme_transport_poll_group_disconnect_qpair(struct spdk_nvme_qpair *qpair)
     102                 :            : {
     103                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     104                 :            :         struct spdk_nvme_qpair *iter_qp, *tmp_iter_qp;
     105                 :            : 
     106                 :          0 :         tgroup = qpair->poll_group;
     107                 :            : 
     108   [ #  #  #  # ]:          0 :         STAILQ_FOREACH_SAFE(iter_qp, &tgroup->connected_qpairs, poll_group_stailq, tmp_iter_qp) {
     109         [ #  # ]:          0 :                 if (qpair == iter_qp) {
     110   [ #  #  #  #  :          0 :                         STAILQ_REMOVE(&tgroup->connected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
             #  #  #  # ]
     111                 :          0 :                         STAILQ_INSERT_TAIL(&tgroup->disconnected_qpairs, qpair, poll_group_stailq);
     112                 :          0 :                         return 0;
     113                 :            :                 }
     114                 :          0 :         }
     115                 :            : 
     116         [ #  # ]:          0 :         STAILQ_FOREACH(iter_qp, &tgroup->disconnected_qpairs, poll_group_stailq) {
     117         [ #  # ]:          0 :                 if (qpair == iter_qp) {
     118                 :          0 :                         return 0;
     119                 :            :                 }
     120                 :          0 :         }
     121                 :            : 
     122                 :          0 :         return -EINVAL;
     123                 :          0 : }
     124                 :            : 
     125                 :            : int
     126                 :          4 : nvme_transport_poll_group_connect_qpair(struct spdk_nvme_qpair *qpair)
     127                 :            : {
     128                 :            :         struct spdk_nvme_transport_poll_group *tgroup;
     129                 :            :         struct spdk_nvme_qpair *iter_qp, *tmp_iter_qp;
     130                 :            : 
     131                 :          4 :         tgroup = qpair->poll_group;
     132                 :            : 
     133   [ +  +  -  + ]:          4 :         STAILQ_FOREACH_SAFE(iter_qp, &tgroup->disconnected_qpairs, poll_group_stailq, tmp_iter_qp) {
     134         [ #  # ]:          0 :                 if (qpair == iter_qp) {
     135   [ #  #  #  #  :          0 :                         STAILQ_REMOVE(&tgroup->disconnected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
             #  #  #  # ]
     136                 :          0 :                         STAILQ_INSERT_TAIL(&tgroup->connected_qpairs, qpair, poll_group_stailq);
     137                 :          0 :                         return 0;
     138                 :            :                 }
     139                 :          0 :         }
     140                 :            : 
     141         [ +  - ]:          4 :         STAILQ_FOREACH(iter_qp, &tgroup->connected_qpairs, poll_group_stailq) {
     142         [ +  + ]:          4 :                 if (qpair == iter_qp) {
     143                 :          4 :                         return 0;
     144                 :            :                 }
     145                 :          0 :         }
     146                 :            : 
     147                 :          0 :         return -EINVAL;
     148                 :          1 : }
     149                 :            : 
     150                 :            : struct spdk_nvme_transport_poll_group *
     151                 :         24 : nvme_transport_poll_group_create(const struct spdk_nvme_transport *transport)
     152                 :            : {
     153                 :         24 :         struct spdk_nvme_transport_poll_group *group = NULL;
     154                 :            : 
     155                 :            :         /* TODO: separate this transport function table from the transport specific one. */
     156                 :         24 :         group = calloc(1, sizeof(*group));
     157         [ +  - ]:         24 :         if (group) {
     158                 :         24 :                 group->transport = transport;
     159                 :         24 :                 STAILQ_INIT(&group->connected_qpairs);
     160                 :         24 :                 STAILQ_INIT(&group->disconnected_qpairs);
     161                 :          6 :         }
     162                 :            : 
     163                 :         24 :         return group;
     164                 :            : }
     165                 :            : 
     166                 :            : int
     167                 :          8 : nvme_transport_poll_group_destroy(struct spdk_nvme_transport_poll_group *tgroup)
     168                 :            : {
     169                 :          8 :         return g_destroy_return_value;
     170                 :            : }
     171                 :            : 
     172                 :            : int
     173                 :         36 : nvme_transport_poll_group_add(struct spdk_nvme_transport_poll_group *tgroup,
     174                 :            :                               struct spdk_nvme_qpair *qpair)
     175                 :            : {
     176                 :         36 :         STAILQ_INSERT_TAIL(&tgroup->connected_qpairs, qpair, poll_group_stailq);
     177                 :         36 :         qpair->poll_group = tgroup;
     178                 :            : 
     179                 :         36 :         return 0;
     180                 :            : }
     181                 :            : 
     182                 :            : int
     183                 :         32 : nvme_transport_poll_group_remove(struct spdk_nvme_transport_poll_group *tgroup,
     184                 :            :                                  struct spdk_nvme_qpair *qpair)
     185                 :            : {
     186                 :            :         struct spdk_nvme_qpair *iter_qp, *tmp_iter_qp;
     187                 :            : 
     188   [ +  -  +  - ]:         32 :         STAILQ_FOREACH_SAFE(iter_qp, &tgroup->connected_qpairs, poll_group_stailq, tmp_iter_qp) {
     189         [ +  + ]:         32 :                 if (qpair == iter_qp) {
     190   [ +  +  +  +  :         32 :                         STAILQ_REMOVE(&tgroup->connected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
             -  -  -  - ]
     191                 :         32 :                         return 0;
     192                 :            :                 }
     193                 :          0 :         }
     194                 :            : 
     195   [ #  #  #  # ]:          0 :         STAILQ_FOREACH_SAFE(iter_qp, &tgroup->disconnected_qpairs, poll_group_stailq, tmp_iter_qp) {
     196         [ #  # ]:          0 :                 if (qpair == iter_qp) {
     197   [ #  #  #  #  :          0 :                         STAILQ_REMOVE(&tgroup->disconnected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
             #  #  #  # ]
     198                 :          0 :                         return 0;
     199                 :            :                 }
     200                 :          0 :         }
     201                 :            : 
     202                 :          0 :         return -ENODEV;
     203                 :          8 : }
     204                 :            : 
     205                 :            : int32_t
     206                 :          0 : spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
     207                 :            : {
     208                 :          0 :         return g_process_completions_return_value;
     209                 :            : }
     210                 :            : 
     211                 :            : int64_t
     212                 :          4 : nvme_transport_poll_group_process_completions(struct spdk_nvme_transport_poll_group *group,
     213                 :            :                 uint32_t completions_per_qpair, spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb)
     214                 :            : {
     215                 :          4 :         return g_process_completions_return_value;
     216                 :            : }
     217                 :            : 
     218                 :            : static void
     219                 :          4 : test_spdk_nvme_poll_group_create(void)
     220                 :            : {
     221                 :            :         struct spdk_nvme_poll_group *group;
     222                 :            : 
     223                 :            :         /* basic case - create a poll group with no internal transport poll groups. */
     224                 :          4 :         group = spdk_nvme_poll_group_create(NULL, NULL);
     225                 :            : 
     226         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     227                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&group->tgroups));
     228         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
     229                 :            : 
     230                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t1, link);
     231                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t2, link);
     232                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t3, link);
     233                 :            : 
     234                 :            :         /* advanced case - create a poll group with three internal poll groups. */
     235                 :          4 :         group = spdk_nvme_poll_group_create(NULL, NULL);
     236                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&group->tgroups));
     237         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
     238                 :            : 
     239                 :            :         /* Failing case - failed to allocate a poll group. */
     240                 :          4 :         MOCK_SET(calloc, NULL);
     241                 :          4 :         group = spdk_nvme_poll_group_create(NULL, NULL);
     242                 :          4 :         CU_ASSERT(group == NULL);
     243   [ -  +  -  + ]:          4 :         MOCK_CLEAR(calloc);
     244                 :            : 
     245         [ +  - ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t1, link);
     246         [ +  - ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t2, link);
     247         [ -  + ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t3, link);
     248                 :          4 : }
     249                 :            : 
     250                 :            : static void
     251                 :          4 : test_spdk_nvme_poll_group_add_remove(void)
     252                 :            : {
     253                 :            :         struct spdk_nvme_poll_group *group;
     254                 :          4 :         struct spdk_nvme_transport_poll_group *tgroup = NULL, *tmp_tgroup, *tgroup_1 = NULL,
     255                 :          4 :                                                        *tgroup_2 = NULL,
     256                 :          4 :                                                         *tgroup_4 = NULL;
     257                 :            :         struct spdk_nvme_qpair *qpair;
     258                 :          4 :         struct spdk_nvme_qpair qpair1_1 = {0};
     259                 :          4 :         struct spdk_nvme_qpair qpair1_2 = {0};
     260                 :          4 :         struct spdk_nvme_qpair qpair2_1 = {0};
     261                 :          4 :         struct spdk_nvme_qpair qpair2_2 = {0};
     262                 :          4 :         struct spdk_nvme_qpair qpair4_1 = {0};
     263                 :          4 :         struct spdk_nvme_qpair qpair4_2 = {0};
     264                 :          4 :         int i = 0;
     265                 :            : 
     266                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t1, link);
     267                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t2, link);
     268                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t3, link);
     269                 :            : 
     270                 :          4 :         group = spdk_nvme_poll_group_create(NULL, NULL);
     271         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     272         [ -  + ]:          4 :         CU_ASSERT(group->enable_interrupts_is_valid == false);
     273         [ -  + ]:          4 :         CU_ASSERT(group->enable_interrupts == false);
     274                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&group->tgroups));
     275                 :            : 
     276                 :            :         /* Add qpairs from different controllers. One with interrupts other without. */
     277                 :          4 :         qpair1_1.transport = &t1;
     278                 :          4 :         qpair1_1.ctrlr = &c1;
     279                 :          4 :         qpair1_1.state = NVME_QPAIR_DISCONNECTED;
     280                 :          4 :         qpair1_2.transport = &t1;
     281                 :          4 :         qpair1_2.ctrlr = &c2;
     282                 :          4 :         qpair1_2.state = NVME_QPAIR_DISCONNECTED;
     283                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_1) == 0);
     284                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_2) == -EINVAL);
     285         [ -  + ]:          4 :         CU_ASSERT(group->enable_interrupts_is_valid == true);
     286         [ -  + ]:          4 :         CU_ASSERT(group->enable_interrupts == false);
     287         [ +  + ]:          8 :         STAILQ_FOREACH(tmp_tgroup, &group->tgroups, link) {
     288         [ +  + ]:          4 :                 if (tmp_tgroup->transport == &t1) {
     289                 :          4 :                         tgroup = tmp_tgroup;
     290                 :          1 :                 } else {
     291                 :          0 :                         CU_ASSERT(STAILQ_EMPTY(&tmp_tgroup->connected_qpairs));
     292                 :            :                 }
     293                 :          4 :                 i++;
     294                 :          1 :         }
     295                 :          4 :         CU_ASSERT(i == 1);
     296         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(tgroup != NULL);
     297                 :          4 :         qpair = STAILQ_FIRST(&tgroup->connected_qpairs);
     298         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair1_1);
     299                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     300                 :          4 :         CU_ASSERT(qpair == NULL);
     301                 :            : 
     302                 :            :         /* Add second qpair from the same controller as the first. */
     303                 :          4 :         qpair1_2.ctrlr = &c1;
     304                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_2) == 0);
     305                 :          4 :         i = 0;
     306         [ +  + ]:          8 :         STAILQ_FOREACH(tmp_tgroup, &group->tgroups, link) {
     307         [ +  + ]:          4 :                 if (tmp_tgroup->transport == &t1) {
     308                 :          4 :                         tgroup = tmp_tgroup;
     309                 :          1 :                 } else {
     310                 :          0 :                         CU_ASSERT(STAILQ_EMPTY(&tmp_tgroup->connected_qpairs));
     311                 :            :                 }
     312                 :          4 :                 i++;
     313                 :          1 :         }
     314                 :          4 :         CU_ASSERT(i == 1);
     315                 :          4 :         qpair = STAILQ_FIRST(&tgroup->connected_qpairs);
     316         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair1_1);
     317                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     318         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair1_2);
     319                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     320                 :          4 :         CU_ASSERT(qpair == NULL);
     321                 :            : 
     322                 :          4 :         i = 0;
     323                 :            :         /* Remove both qpairs and delete the transport poll group. */
     324                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair1_1) == 0);
     325                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair1_2) == 0);
     326   [ +  +  +  + ]:          8 :         STAILQ_FOREACH_SAFE(tgroup, &group->tgroups, link, tmp_tgroup) {
     327                 :          4 :                 CU_ASSERT(STAILQ_EMPTY(&tgroup->connected_qpairs));
     328   [ +  +  +  +  :          4 :                 STAILQ_REMOVE(&group->tgroups, tgroup, spdk_nvme_transport_poll_group, link);
             -  -  -  - ]
     329                 :          4 :                 free(tgroup);
     330                 :          4 :                 i++;
     331                 :          1 :         }
     332                 :          4 :         CU_ASSERT(i == 1);
     333                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&group->tgroups));
     334         [ -  + ]:          4 :         CU_ASSERT(group->enable_interrupts == false);
     335         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
     336                 :            : 
     337                 :          4 :         group = spdk_nvme_poll_group_create(NULL, NULL);
     338         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     339         [ -  + ]:          4 :         CU_ASSERT(group->enable_interrupts_is_valid == false);
     340         [ -  + ]:          4 :         CU_ASSERT(group->enable_interrupts == false);
     341                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&group->tgroups));
     342                 :            : 
     343                 :            :         /* Add qpairs to a single transport. */
     344                 :          4 :         qpair1_1.transport = &t1;
     345                 :          4 :         qpair1_1.ctrlr = &c1;
     346                 :          4 :         qpair1_1.state = NVME_QPAIR_DISCONNECTED;
     347                 :          4 :         qpair1_2.transport = &t1;
     348                 :          4 :         qpair1_2.ctrlr = &c1;
     349                 :          4 :         qpair1_2.state = NVME_QPAIR_ENABLED;
     350                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_1) == 0);
     351                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_2) == -EINVAL);
     352         [ -  + ]:          4 :         CU_ASSERT(group->enable_interrupts_is_valid == true);
     353         [ -  + ]:          4 :         CU_ASSERT(group->enable_interrupts == false);
     354                 :          4 :         i = 0;
     355         [ +  + ]:          8 :         STAILQ_FOREACH(tmp_tgroup, &group->tgroups, link) {
     356         [ +  + ]:          4 :                 if (tmp_tgroup->transport == &t1) {
     357                 :          4 :                         tgroup = tmp_tgroup;
     358                 :          1 :                 } else {
     359                 :          0 :                         CU_ASSERT(STAILQ_EMPTY(&tmp_tgroup->connected_qpairs));
     360                 :            :                 }
     361                 :          4 :                 i++;
     362                 :          1 :         }
     363                 :          4 :         CU_ASSERT(i == 1);
     364         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(tgroup != NULL);
     365                 :          4 :         qpair = STAILQ_FIRST(&tgroup->connected_qpairs);
     366         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair1_1);
     367                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     368                 :          4 :         CU_ASSERT(qpair == NULL);
     369                 :            : 
     370                 :            :         /* Add qpairs to a second transport. */
     371                 :          4 :         qpair2_1.transport = &t2;
     372                 :          4 :         qpair2_1.ctrlr = &c1;
     373                 :          4 :         qpair2_2.transport = &t2;
     374                 :          4 :         qpair2_2.ctrlr = &c1;
     375                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair2_1) == 0);
     376                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair2_2) == 0);
     377                 :          4 :         qpair4_1.transport = &t4;
     378                 :          4 :         qpair4_2.transport = &t4;
     379                 :          4 :         qpair4_1.ctrlr = &c1;
     380                 :          4 :         qpair4_2.ctrlr = &c1;
     381                 :            :         /* Add qpairs for a transport that doesn't exist. */
     382                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair4_1) == -ENODEV);
     383                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair4_2) == -ENODEV);
     384                 :          4 :         i = 0;
     385         [ +  + ]:         12 :         STAILQ_FOREACH(tmp_tgroup, &group->tgroups, link) {
     386         [ +  + ]:          8 :                 if (tmp_tgroup->transport == &t1) {
     387                 :          4 :                         tgroup_1 = tmp_tgroup;
     388         [ +  + ]:          5 :                 } else if (tmp_tgroup->transport == &t2) {
     389                 :          4 :                         tgroup_2 = tmp_tgroup;
     390                 :          1 :                 } else {
     391                 :          0 :                         CU_ASSERT(STAILQ_EMPTY(&tmp_tgroup->connected_qpairs));
     392                 :            :                 }
     393                 :          8 :                 i++;
     394                 :          2 :         }
     395                 :          4 :         CU_ASSERT(i == 2);
     396         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(tgroup_1 != NULL);
     397                 :          4 :         qpair = STAILQ_FIRST(&tgroup_1->connected_qpairs);
     398         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair1_1);
     399                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     400                 :          4 :         CU_ASSERT(qpair == NULL);
     401         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(tgroup_2 != NULL);
     402                 :          4 :         qpair = STAILQ_FIRST(&tgroup_2->connected_qpairs);
     403         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair2_1);
     404                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     405         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair2_2);
     406                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     407                 :          4 :         CU_ASSERT(qpair == NULL);
     408                 :            : 
     409                 :            :         /* Try removing a qpair that belongs to a transport not in our poll group. */
     410                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair4_1) == -ENODEV);
     411                 :            : 
     412                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t4, link);
     413                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair4_1) == 0);
     414                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair4_2) == 0);
     415         [ +  + ]:         16 :         STAILQ_FOREACH(tmp_tgroup, &group->tgroups, link) {
     416         [ +  + ]:         12 :                 if (tmp_tgroup->transport == &t1) {
     417                 :          4 :                         tgroup_1 = tmp_tgroup;
     418         [ +  + ]:          9 :                 } else if (tmp_tgroup->transport == &t2) {
     419                 :          4 :                         tgroup_2 = tmp_tgroup;
     420         [ +  + ]:          5 :                 } else if (tmp_tgroup->transport == &t4) {
     421                 :          4 :                         tgroup_4 = tmp_tgroup;
     422                 :          1 :                 } else {
     423                 :          0 :                         CU_ASSERT(STAILQ_EMPTY(&tmp_tgroup->connected_qpairs));
     424                 :            :                 }
     425                 :          3 :         }
     426         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(tgroup_1 != NULL);
     427                 :          4 :         qpair = STAILQ_FIRST(&tgroup_1->connected_qpairs);
     428         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair1_1);
     429                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     430                 :          4 :         CU_ASSERT(qpair == NULL);
     431         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(tgroup_2 != NULL);
     432                 :          4 :         qpair = STAILQ_FIRST(&tgroup_2->connected_qpairs);
     433         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair2_1);
     434                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     435         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair2_2);
     436                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     437                 :          4 :         CU_ASSERT(qpair == NULL);
     438         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(tgroup_4 != NULL);
     439                 :          4 :         qpair = STAILQ_FIRST(&tgroup_4->connected_qpairs);
     440         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair4_1);
     441                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     442         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(qpair == &qpair4_2);
     443                 :          4 :         qpair = STAILQ_NEXT(qpair, poll_group_stailq);
     444                 :          4 :         CU_ASSERT(qpair == NULL);
     445                 :            : 
     446                 :            :         /* remove all qpairs */
     447                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair1_1) == 0);
     448                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair2_1) == 0);
     449                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair2_2) == 0);
     450                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair4_1) == 0);
     451                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair4_2) == 0);
     452                 :            :         /* Confirm the fourth transport group was created. */
     453                 :          4 :         i = 0;
     454   [ +  +  +  + ]:         16 :         STAILQ_FOREACH_SAFE(tgroup, &group->tgroups, link, tmp_tgroup) {
     455                 :         12 :                 CU_ASSERT(STAILQ_EMPTY(&tgroup->connected_qpairs));
     456   [ +  +  +  +  :         12 :                 STAILQ_REMOVE(&group->tgroups, tgroup, spdk_nvme_transport_poll_group, link);
             -  -  -  - ]
     457                 :         12 :                 free(tgroup);
     458                 :         12 :                 i++;
     459                 :          3 :         }
     460                 :          4 :         CU_ASSERT(i == 3);
     461         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
     462                 :            : 
     463         [ +  - ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t1, link);
     464         [ +  - ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t2, link);
     465         [ +  - ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t3, link);
     466         [ -  + ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t4, link);
     467                 :          4 : }
     468                 :            : 
     469                 :            : static void
     470                 :          4 : test_spdk_nvme_poll_group_process_completions(void)
     471                 :            : {
     472                 :            :         struct spdk_nvme_poll_group *group;
     473                 :            :         struct spdk_nvme_transport_poll_group *tgroup, *tmp_tgroup;
     474                 :          4 :         struct spdk_nvme_qpair qpair1_1 = {0};
     475                 :            : 
     476                 :          4 :         group = spdk_nvme_poll_group_create(NULL, NULL);
     477         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     478                 :            : 
     479                 :            :         /* If we don't have any transport poll groups, we shouldn't get any completions. */
     480                 :          4 :         g_process_completions_return_value = 32;
     481                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_process_completions(group, 128,
     482                 :            :                         unit_test_disconnected_qpair_cb) == 0);
     483         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
     484                 :            : 
     485                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t1, link);
     486                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t2, link);
     487                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t3, link);
     488                 :            : 
     489                 :            :         /* try it with three transport poll groups. */
     490                 :          4 :         group = spdk_nvme_poll_group_create(NULL, NULL);
     491         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     492                 :          4 :         qpair1_1.state = NVME_QPAIR_DISCONNECTED;
     493                 :          4 :         qpair1_1.transport = &t1;
     494                 :          4 :         qpair1_1.ctrlr = &c1;
     495                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_1) == 0);
     496                 :          4 :         qpair1_1.state = NVME_QPAIR_ENABLED;
     497                 :          4 :         CU_ASSERT(nvme_poll_group_connect_qpair(&qpair1_1) == 0);
     498                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_process_completions(group, 128,
     499                 :            :                         unit_test_disconnected_qpair_cb) == 32);
     500                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair1_1) == 0);
     501   [ +  +  +  + ]:          8 :         STAILQ_FOREACH_SAFE(tgroup, &group->tgroups, link, tmp_tgroup) {
     502                 :          4 :                 CU_ASSERT(STAILQ_EMPTY(&tgroup->connected_qpairs));
     503   [ +  +  +  +  :          4 :                 STAILQ_REMOVE(&group->tgroups, tgroup, spdk_nvme_transport_poll_group, link);
             -  -  -  - ]
     504                 :          4 :                 free(tgroup);
     505                 :          1 :         }
     506         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
     507                 :            : 
     508         [ +  - ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t1, link);
     509         [ +  - ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t2, link);
     510         [ -  + ]:          4 :         TAILQ_REMOVE(&g_spdk_nvme_transports, &t3, link);
     511                 :          4 : }
     512                 :            : 
     513                 :            : static void
     514                 :          4 : test_spdk_nvme_poll_group_destroy(void)
     515                 :            : {
     516                 :            :         struct spdk_nvme_poll_group *group;
     517                 :            :         struct spdk_nvme_transport_poll_group *tgroup, *tgroup_1, *tgroup_2;
     518                 :          4 :         struct spdk_nvme_qpair qpair1_1 = {0};
     519                 :          4 :         int num_tgroups = 0;
     520                 :            : 
     521                 :            :         /* Simple destruction of empty poll group. */
     522                 :          4 :         group = spdk_nvme_poll_group_create(NULL, NULL);
     523         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     524         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
     525                 :            : 
     526                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t1, link);
     527                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t2, link);
     528                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t3, link);
     529                 :          4 :         group = spdk_nvme_poll_group_create(NULL, NULL);
     530         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(group != NULL);
     531                 :            : 
     532                 :          4 :         qpair1_1.transport = &t1;
     533                 :          4 :         qpair1_1.ctrlr = &c1;
     534                 :          4 :         CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_1) == 0);
     535                 :            : 
     536                 :            :         /* Don't remove busy poll groups. */
     537                 :          4 :         g_destroy_return_value = -EBUSY;
     538         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == -EBUSY);
     539         [ +  + ]:          8 :         STAILQ_FOREACH(tgroup, &group->tgroups, link) {
     540                 :          4 :                 num_tgroups++;
     541                 :          1 :         }
     542                 :          4 :         CU_ASSERT(num_tgroups == 1);
     543                 :            : 
     544                 :            :         /* destroy poll group with internal poll groups. */
     545                 :          4 :         g_destroy_return_value = 0;
     546                 :          4 :         tgroup_1 = STAILQ_FIRST(&group->tgroups);
     547                 :          4 :         tgroup_2 = STAILQ_NEXT(tgroup_1, link);
     548                 :          4 :         CU_ASSERT(tgroup_2 == NULL)
     549         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
     550                 :          4 :         free(tgroup_1);
     551                 :          4 : }
     552                 :            : 
     553                 :            : static void
     554                 :          4 : test_spdk_nvme_poll_group_get_free_stats(void)
     555                 :            : {
     556                 :          4 :         struct spdk_nvme_poll_group group = {};
     557                 :          4 :         struct spdk_nvme_poll_group_stat *stats = NULL;
     558                 :          4 :         struct spdk_nvme_transport_poll_group tgroup[3] = {};
     559                 :            :         int rc, i;
     560                 :            : 
     561                 :            :         /* Multiple tgroups */
     562                 :          4 :         STAILQ_INIT(&group.tgroups);
     563         [ +  + ]:         16 :         for (i = 0; i < 3; i++) {
     564                 :         12 :                 STAILQ_INSERT_TAIL(&group.tgroups, &tgroup[i], link);
     565                 :          3 :         }
     566                 :            : 
     567                 :          4 :         rc = spdk_nvme_poll_group_get_stats(&group, &stats);
     568                 :          4 :         CU_ASSERT(rc == 0);
     569                 :          4 :         CU_ASSERT(stats->num_transports == 3);
     570                 :            : 
     571                 :          4 :         spdk_nvme_poll_group_free_stats(&group, stats);
     572         [ +  + ]:         16 :         for (i = 0; i < 3; i++) {
     573   [ +  +  +  +  :         12 :                 STAILQ_REMOVE(&group.tgroups, &tgroup[i], spdk_nvme_transport_poll_group, link);
             -  -  -  - ]
     574                 :          3 :         }
     575         [ +  + ]:          4 :         SPDK_CU_ASSERT_FATAL(STAILQ_EMPTY(&group.tgroups));
     576                 :            : 
     577                 :            :         /* No available tgroup */
     578                 :          4 :         rc = spdk_nvme_poll_group_get_stats(&group, &stats);
     579                 :          4 :         CU_ASSERT(rc == -ENOTSUP);
     580                 :          4 : }
     581                 :            : 
     582                 :            : int
     583                 :          4 : main(int argc, char **argv)
     584                 :            : {
     585                 :          4 :         CU_pSuite       suite = NULL;
     586                 :            :         unsigned int    num_failures;
     587                 :            : 
     588         [ -  + ]:          4 :         if (CU_initialize_registry() != CUE_SUCCESS) {
     589                 :          0 :                 return CU_get_error();
     590                 :            :         }
     591                 :            : 
     592                 :          4 :         suite = CU_add_suite("nvme_ns_cmd", NULL, NULL);
     593         [ +  + ]:          4 :         if (suite == NULL) {
     594                 :          0 :                 CU_cleanup_registry();
     595                 :          0 :                 return CU_get_error();
     596                 :            :         }
     597                 :            : 
     598         [ +  - ]:          3 :         if (
     599   [ +  -  +  - ]:          8 :                 CU_add_test(suite, "nvme_poll_group_create_test", test_spdk_nvme_poll_group_create) == NULL ||
     600                 :          4 :                 CU_add_test(suite, "nvme_poll_group_add_remove_test",
     601         [ +  - ]:          4 :                             test_spdk_nvme_poll_group_add_remove) == NULL ||
     602                 :          4 :                 CU_add_test(suite, "nvme_poll_group_process_completions",
     603         [ +  - ]:          4 :                             test_spdk_nvme_poll_group_process_completions) == NULL ||
     604         [ +  + ]:          7 :                 CU_add_test(suite, "nvme_poll_group_destroy_test", test_spdk_nvme_poll_group_destroy) == NULL ||
     605                 :          4 :                 CU_add_test(suite, "nvme_poll_group_get_free_stats",
     606                 :          1 :                             test_spdk_nvme_poll_group_get_free_stats) == NULL
     607                 :            :         ) {
     608                 :          0 :                 CU_cleanup_registry();
     609                 :          0 :                 return CU_get_error();
     610                 :            :         }
     611                 :            : 
     612                 :          4 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     613                 :          4 :         CU_cleanup_registry();
     614                 :          4 :         return num_failures;
     615                 :          1 : }

Generated by: LCOV version 1.14