LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/iscsi/param.c - param_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 209 212 98.6 %
Date: 2024-07-13 22:49:35 Functions: 6 12 50.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 66 140 47.1 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2016 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : 
       8                 :            : #include "spdk/scsi.h"
       9                 :            : 
      10                 :            : #include "spdk_internal/cunit.h"
      11                 :            : 
      12                 :            : #include "../common.c"
      13                 :            : #include "iscsi/param.c"
      14                 :            : 
      15                 :            : #include "spdk_internal/mock.h"
      16                 :            : 
      17                 :            : struct spdk_iscsi_globals g_iscsi;
      18                 :            : 
      19         [ #  # ]:          0 : DEFINE_STUB(iscsi_find_tgt_node, struct spdk_iscsi_tgt_node *,
      20                 :            :             (const char *target_name), NULL);
      21                 :            : 
      22   [ #  #  #  # ]:          0 : DEFINE_STUB(iscsi_tgt_node_access, bool,
      23                 :            :             (struct spdk_iscsi_conn *conn, struct spdk_iscsi_tgt_node *target,
      24                 :            :              const char *iqn, const char *addr),
      25                 :            :             false);
      26                 :            : 
      27         [ #  # ]:          0 : DEFINE_STUB(iscsi_send_tgts, int,
      28                 :            :             (struct spdk_iscsi_conn *conn, const char *iiqn, const char *iaddr,
      29                 :            :              const char *tiqn, uint8_t *data, int alloc_len, int data_len),
      30                 :            :             0);
      31                 :            : 
      32                 :            : static void
      33                 :         24 : burst_length_param_negotiation(int FirstBurstLength, int MaxBurstLength,
      34                 :            :                                int initialR2T)
      35                 :            : {
      36                 :         24 :         struct spdk_iscsi_sess sess;
      37                 :         24 :         struct spdk_iscsi_conn conn;
      38                 :         24 :         struct iscsi_param *params;
      39                 :            :         struct iscsi_param **params_p;
      40                 :         24 :         char data[8192];
      41                 :            :         int rc;
      42                 :            :         int total, len;
      43                 :            : 
      44                 :         24 :         total = 0;
      45                 :         24 :         params = NULL;
      46                 :         24 :         params_p = &params;
      47                 :            : 
      48         [ -  + ]:         24 :         memset(&sess, 0, sizeof(sess));
      49         [ -  + ]:         24 :         memset(&conn, 0, sizeof(conn));
      50         [ -  + ]:         24 :         memset(data, 0, 8192);
      51                 :            : 
      52                 :         24 :         sess.ExpCmdSN = 0;
      53                 :         24 :         sess.MaxCmdSN = 64;
      54                 :         24 :         sess.session_type = SESSION_TYPE_NORMAL;
      55                 :         24 :         sess.params = NULL;
      56                 :         24 :         sess.MaxBurstLength = 65536;
      57                 :         24 :         sess.InitialR2T = true;
      58                 :         24 :         sess.FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH;
      59                 :         24 :         sess.MaxOutstandingR2T = 1;
      60                 :            : 
      61                 :            :         /* set default params */
      62                 :         24 :         rc = iscsi_sess_params_init(&sess.params);
      63                 :         24 :         CU_ASSERT(rc == 0);
      64                 :            : 
      65                 :         24 :         rc = iscsi_param_set_int(sess.params, "FirstBurstLength",
      66                 :            :                                  sess.FirstBurstLength);
      67                 :         24 :         CU_ASSERT(rc == 0);
      68                 :            : 
      69                 :         24 :         rc = iscsi_param_set_int(sess.params, "MaxBurstLength",
      70                 :            :                                  sess.MaxBurstLength);
      71                 :         24 :         CU_ASSERT(rc == 0);
      72                 :            : 
      73                 :         24 :         rc = iscsi_param_set(sess.params, "InitialR2T",
      74   [ -  +  +  - ]:         24 :                              sess.InitialR2T ? "Yes" : "No");
      75                 :         24 :         CU_ASSERT(rc == 0);
      76                 :            : 
      77                 :         24 :         conn.full_feature = 1;
      78                 :         24 :         conn.sess = &sess;
      79                 :         24 :         conn.MaxRecvDataSegmentLength = 65536;
      80                 :            : 
      81                 :         24 :         rc = iscsi_conn_params_init(&conn.params);
      82                 :         24 :         CU_ASSERT(rc == 0);
      83                 :            : 
      84                 :            :         /* construct the data */
      85         [ -  + ]:         24 :         len = snprintf(data + total, 8192 - total, "%s=%d",
      86                 :            :                        "FirstBurstLength", FirstBurstLength);
      87                 :         24 :         total += len + 1;
      88                 :            : 
      89         [ -  + ]:         24 :         len = snprintf(data + total, 8192 - total, "%s=%d",
      90                 :            :                        "MaxBurstLength", MaxBurstLength);
      91                 :         24 :         total += len + 1;
      92                 :            : 
      93         [ -  + ]:         24 :         len = snprintf(data + total, 8192 - total, "%s=%d",
      94                 :            :                        "InitialR2T", initialR2T);
      95                 :         24 :         total += len + 1;
      96                 :            : 
      97                 :            :         /* add one extra NUL byte at the end to match real iSCSI params */
      98                 :         24 :         total++;
      99                 :            : 
     100                 :            :         /* store incoming parameters */
     101                 :         24 :         rc = iscsi_parse_params(params_p, data, total, false, NULL);
     102                 :         24 :         CU_ASSERT(rc == 0);
     103                 :            : 
     104                 :            :         /* negotiate parameters */
     105                 :         24 :         rc = iscsi_negotiate_params(&conn, params_p,
     106                 :            :                                     data, 8192, rc);
     107                 :         24 :         CU_ASSERT(rc > 0);
     108                 :            : 
     109                 :         24 :         rc = iscsi_copy_param2var(&conn);
     110                 :         24 :         CU_ASSERT(rc == 0);
     111                 :         24 :         CU_ASSERT(conn.sess->FirstBurstLength <= SPDK_ISCSI_FIRST_BURST_LENGTH);
     112                 :         24 :         CU_ASSERT(conn.sess->FirstBurstLength <= conn.sess->MaxBurstLength);
     113                 :         24 :         CU_ASSERT(conn.sess->MaxBurstLength <= SPDK_ISCSI_MAX_BURST_LENGTH);
     114                 :         24 :         CU_ASSERT(conn.sess->MaxOutstandingR2T == 1);
     115                 :            : 
     116                 :         24 :         iscsi_param_free(sess.params);
     117                 :         24 :         iscsi_param_free(conn.params);
     118                 :         24 :         iscsi_param_free(*params_p);
     119                 :         24 : }
     120                 :            : 
     121                 :            : static void
     122                 :          4 : param_negotiation_test(void)
     123                 :            : {
     124                 :          4 :         burst_length_param_negotiation(8192, 16384, 0);
     125                 :          4 :         burst_length_param_negotiation(8192, 16384, 1);
     126                 :          4 :         burst_length_param_negotiation(8192, 1024, 1);
     127                 :          4 :         burst_length_param_negotiation(8192, 1024, 0);
     128                 :          4 :         burst_length_param_negotiation(512, 1024, 1);
     129                 :          4 :         burst_length_param_negotiation(512, 1024, 0);
     130                 :          4 : }
     131                 :            : 
     132                 :            : static void
     133                 :          4 : list_negotiation_test(void)
     134                 :            : {
     135                 :          4 :         int add_param_value = 0;
     136                 :          4 :         struct iscsi_param param = {};
     137                 :            :         char *new_val;
     138                 :          4 :         char valid_list_buf[1024];
     139                 :          4 :         char in_val_buf[1024];
     140                 :            : 
     141                 :            : #define TEST_LIST(valid_list, in_val, expected_result) \
     142                 :            :         do { \
     143                 :            :                 snprintf(valid_list_buf, sizeof(valid_list_buf), "%s", valid_list); \
     144                 :            :                 snprintf(in_val_buf, sizeof(in_val_buf), "%s", in_val); \
     145                 :            :                 new_val = iscsi_negotiate_param_list(&add_param_value, &param, valid_list_buf, in_val_buf, NULL); \
     146                 :            :                 if (expected_result) { \
     147                 :            :                         SPDK_CU_ASSERT_FATAL(new_val != NULL); \
     148                 :            :                         CU_ASSERT_STRING_EQUAL(new_val, expected_result); \
     149                 :            :                 } \
     150                 :            :         } while (0)
     151                 :            : 
     152   [ -  +  -  + ]:          4 :         TEST_LIST("None", "None", "None");
     153   [ -  +  -  + ]:          4 :         TEST_LIST("CHAP,None", "None", "None");
     154   [ -  +  -  + ]:          4 :         TEST_LIST("CHAP,None", "CHAP", "CHAP");
     155   [ -  +  -  + ]:          4 :         TEST_LIST("KRB5,SRP,CHAP,None", "SRP,CHAP,None", "SRP");
     156   [ -  +  -  + ]:          4 :         TEST_LIST("KRB5,SRP,CHAP,None", "CHAP,SRP,None", "CHAP");
     157   [ -  +  -  + ]:          4 :         TEST_LIST("KRB5,SRP,CHAP,None", "SPKM1,SRP,CHAP,None", "SRP");
     158   [ -  +  -  + ]:          4 :         TEST_LIST("KRB5,SRP,None", "CHAP,None", "None");
     159                 :          4 : }
     160                 :            : 
     161                 :            : #define PARSE(strconst, partial_enabled, partial_text) \
     162                 :            :         data = strconst; \
     163                 :            :         len = sizeof(strconst) - 1; \
     164                 :            :         rc = iscsi_parse_params(&params, data, len, partial_enabled, partial_text)
     165                 :            : 
     166                 :            : #define EXPECT_VAL(key, expected_value) \
     167                 :            :         { \
     168                 :            :                 const char *val = iscsi_param_get_val(params, key); \
     169                 :            :                 CU_ASSERT(val != NULL); \
     170                 :            :                 if (val != NULL) { \
     171                 :            :                         CU_ASSERT(strcmp(val, expected_value) == 0); \
     172                 :            :                 } \
     173                 :            :         }
     174                 :            : 
     175                 :            : #define EXPECT_NULL(key) \
     176                 :            :         CU_ASSERT(iscsi_param_get_val(params, key) == NULL)
     177                 :            : 
     178                 :            : static void
     179                 :          4 : parse_valid_test(void)
     180                 :            : {
     181                 :          4 :         struct iscsi_param *params = NULL;
     182                 :            :         int rc;
     183                 :            :         char *data;
     184                 :            :         int len;
     185                 :          4 :         char *partial_parameter = NULL;
     186                 :            : 
     187                 :            :         /* simple test with a single key=value */
     188                 :          4 :         PARSE("Abc=def\0", false, NULL);
     189                 :          4 :         CU_ASSERT(rc == 0);
     190   [ +  -  -  + ]:          4 :         EXPECT_VAL("Abc", "def");
     191                 :            : 
     192                 :            :         /* multiple key=value pairs */
     193                 :          4 :         PARSE("Aaa=bbbbbb\0Xyz=test\0", false, NULL);
     194                 :          4 :         CU_ASSERT(rc == 0);
     195   [ +  -  -  + ]:          4 :         EXPECT_VAL("Aaa", "bbbbbb");
     196   [ +  -  -  + ]:          4 :         EXPECT_VAL("Xyz", "test");
     197                 :            : 
     198                 :            :         /* value with embedded '=' */
     199                 :          4 :         PARSE("A=b=c\0", false, NULL);
     200                 :          4 :         CU_ASSERT(rc == 0);
     201   [ +  -  -  + ]:          4 :         EXPECT_VAL("A", "b=c");
     202                 :            : 
     203                 :            :         /* CHAP_C=AAAA.... with value length 8192 */
     204                 :          4 :         len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1/* null terminators */;
     205                 :          4 :         data = malloc(len);
     206         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(data != NULL);
     207         [ -  + ]:          4 :         memset(data, 'A', len);
     208         [ -  + ]:          4 :         memcpy(data, "CHAP_C", 6);
     209                 :          4 :         data[6] = '=';
     210                 :          4 :         data[len - 1] = '\0';
     211                 :          4 :         rc = iscsi_parse_params(&params, data, len, false, NULL);
     212                 :          4 :         CU_ASSERT(rc == 0);
     213                 :          4 :         free(data);
     214                 :            : 
     215                 :            :         /* partial parameter: value is partial */
     216                 :          4 :         PARSE("C=AAA\0D=B", true, &partial_parameter);
     217         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(partial_parameter != NULL);
     218         [ -  + ]:          4 :         CU_ASSERT_STRING_EQUAL(partial_parameter, "D=B");
     219                 :          4 :         CU_ASSERT(rc == 0);
     220   [ +  -  -  + ]:          4 :         EXPECT_VAL("C", "AAA");
     221                 :          4 :         EXPECT_NULL("D");
     222                 :          4 :         PARSE("XXXX\0E=UUUU\0", false, &partial_parameter);
     223                 :          4 :         CU_ASSERT(rc == 0);
     224   [ +  -  -  + ]:          4 :         EXPECT_VAL("D", "BXXXX");
     225   [ +  -  -  + ]:          4 :         EXPECT_VAL("E", "UUUU");
     226                 :          4 :         CU_ASSERT_PTR_NULL(partial_parameter);
     227                 :            : 
     228                 :            :         /* partial parameter: key is partial */
     229                 :          4 :         PARSE("IAMAFAK", true, &partial_parameter);
     230         [ -  + ]:          4 :         CU_ASSERT_STRING_EQUAL(partial_parameter, "IAMAFAK");
     231                 :          4 :         CU_ASSERT(rc == 0);
     232                 :          4 :         EXPECT_NULL("IAMAFAK");
     233                 :          4 :         PARSE("EDKEY=TTTT\0F=IIII", false, &partial_parameter);
     234                 :          4 :         CU_ASSERT(rc == 0);
     235   [ +  -  -  + ]:          4 :         EXPECT_VAL("IAMAFAKEDKEY", "TTTT");
     236   [ +  -  -  + ]:          4 :         EXPECT_VAL("F", "IIII");
     237                 :          4 :         CU_ASSERT_PTR_NULL(partial_parameter);
     238                 :            : 
     239                 :            :         /* partial parameter: NULL data */
     240                 :            :         /* It is technically allowed to have a TEXT PDU with no data, yet
     241                 :            :          * CONTINUE bit is enabled - make sure we handle that case correctly.
     242                 :            :          */
     243                 :          4 :         rc = iscsi_parse_params(&params, NULL, 0, true, &partial_parameter);
     244                 :          4 :         CU_ASSERT(rc == 0);
     245                 :          4 :         CU_ASSERT_PTR_NULL(partial_parameter);
     246                 :            : 
     247                 :            :         /* Second partial parameter is the only parameter */
     248                 :          4 :         PARSE("OOOO", true, &partial_parameter);
     249         [ -  + ]:          4 :         CU_ASSERT_STRING_EQUAL(partial_parameter, "OOOO");
     250                 :          4 :         CU_ASSERT(rc == 0);
     251                 :          4 :         EXPECT_NULL("OOOO");
     252                 :          4 :         PARSE("LL=MMMM", false, &partial_parameter);
     253                 :          4 :         CU_ASSERT(rc == 0);
     254   [ +  -  -  + ]:          4 :         EXPECT_VAL("OOOOLL", "MMMM");
     255                 :          4 :         CU_ASSERT_PTR_NULL(partial_parameter);
     256                 :            : 
     257                 :          4 :         partial_parameter = NULL;
     258                 :          4 :         data = "PartialKey=";
     259                 :          4 :         len = 7;
     260                 :          4 :         rc = iscsi_parse_params(&params, data, len, true, &partial_parameter);
     261                 :          4 :         CU_ASSERT(rc == 0);
     262         [ -  + ]:          4 :         CU_ASSERT_STRING_EQUAL(partial_parameter, "Partial");
     263                 :          4 :         EXPECT_NULL("PartialKey");
     264                 :          4 :         PARSE("Key=Value", false, &partial_parameter);
     265                 :          4 :         CU_ASSERT(rc == 0);
     266   [ +  -  -  + ]:          4 :         EXPECT_VAL("PartialKey", "Value");
     267                 :          4 :         CU_ASSERT_PTR_NULL(partial_parameter);
     268                 :            : 
     269                 :          4 :         iscsi_param_free(params);
     270                 :          4 : }
     271                 :            : 
     272                 :            : static void
     273                 :          4 : parse_invalid_test(void)
     274                 :            : {
     275                 :          4 :         struct iscsi_param *params = NULL;
     276                 :            :         int rc;
     277                 :            :         char *data;
     278                 :            :         int len;
     279                 :            : 
     280                 :            :         /* key without '=' */
     281                 :          4 :         PARSE("Abc\0", false, NULL);
     282                 :          4 :         CU_ASSERT(rc != 0);
     283                 :          4 :         EXPECT_NULL("Abc");
     284                 :            : 
     285                 :            :         /* multiple key=value pairs, one missing '=' */
     286                 :          4 :         PARSE("Abc=def\0Xyz\0Www=test\0", false, NULL);
     287                 :          4 :         CU_ASSERT(rc != 0);
     288   [ +  -  -  + ]:          4 :         EXPECT_VAL("Abc", "def");
     289                 :          4 :         EXPECT_NULL("Xyz");
     290                 :          4 :         EXPECT_NULL("Www");
     291                 :            : 
     292                 :            :         /* empty key */
     293                 :          4 :         PARSE("=abcdef", false, NULL);
     294                 :          4 :         CU_ASSERT(rc != 0);
     295                 :          4 :         EXPECT_NULL("");
     296                 :            : 
     297                 :            :         /* CHAP_C=AAAA.... with value length 8192 + 1 */
     298                 :          4 :         len = strlen("CHAP_C=") + ISCSI_TEXT_MAX_VAL_LEN + 1 /* max value len + 1 */ +
     299                 :            :               1 /* null terminators */;
     300                 :          4 :         data = malloc(len);
     301         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(data != NULL);
     302         [ -  + ]:          4 :         memset(data, 'A', len);
     303         [ -  + ]:          4 :         memcpy(data, "CHAP_C", 6);
     304                 :          4 :         data[6] = '=';
     305                 :          4 :         data[len - 1] = '\0';
     306                 :          4 :         rc = iscsi_parse_params(&params, data, len, false, NULL);
     307                 :          4 :         free(data);
     308                 :          4 :         CU_ASSERT(rc != 0);
     309                 :          4 :         EXPECT_NULL("CHAP_C");
     310                 :            : 
     311                 :            :         /* Test simple value, length of value bigger than 255 */
     312                 :          4 :         len = strlen("A=") + ISCSI_TEXT_MAX_SIMPLE_VAL_LEN + 1 /* max simple value len + 1 */ +
     313                 :            :               1 /* null terminators */;
     314                 :          4 :         data = malloc(len);
     315         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(data != NULL);
     316         [ -  + ]:          4 :         memset(data, 'A', len);
     317                 :          4 :         data[1] = '=';
     318                 :          4 :         data[len - 1] = '\0';
     319                 :          4 :         rc = iscsi_parse_params(&params, data, len, false, NULL);
     320                 :          4 :         free(data);
     321                 :          4 :         CU_ASSERT(rc != 0);
     322                 :          4 :         EXPECT_NULL("A");
     323                 :            : 
     324                 :            :         /* key length bigger than 63 */
     325                 :          4 :         len = ISCSI_TEXT_MAX_KEY_LEN + 1 /* max key length + 1 */ + 1 /* = */ + 1 /* A */ +
     326                 :            :               1 /* null terminators */;
     327                 :          4 :         data = malloc(len);
     328         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(data != NULL);
     329         [ -  + ]:          4 :         memset(data, 'A', len);
     330                 :          4 :         data[64] = '=';
     331                 :          4 :         data[len - 1] = '\0';
     332                 :          4 :         rc = iscsi_parse_params(&params, data, len, false, NULL);
     333                 :          4 :         free(data);
     334                 :          4 :         CU_ASSERT(rc != 0);
     335                 :          4 :         EXPECT_NULL("A");
     336                 :            : 
     337                 :            :         /* duplicated key */
     338                 :          4 :         PARSE("B=BB", false, NULL);
     339                 :          4 :         CU_ASSERT(rc == 0);
     340                 :          4 :         PARSE("B=BBBB", false, NULL);
     341                 :          4 :         CU_ASSERT(rc != 0);
     342   [ +  -  -  + ]:          4 :         EXPECT_VAL("B", "BB");
     343                 :            : 
     344                 :            :         /* Test where data buffer has non-NULL characters past the end of
     345                 :            :          * the valid data region.  This can happen with SPDK iSCSI target,
     346                 :            :          * since data buffers are reused and we do not zero the data buffers
     347                 :            :          * after they are freed since it would be too expensive.  Added as
     348                 :            :          * part of fixing an intermittent Calsoft failure that triggered this
     349                 :            :          * bug.
     350                 :            :          */
     351                 :          4 :         data = "MaxRecvDataSegmentLength=81928";
     352         [ -  + ]:          4 :         len = strlen(data) - 1;
     353                 :          4 :         rc = iscsi_parse_params(&params, data, len, false, NULL);
     354   [ +  -  -  + ]:          4 :         EXPECT_VAL("MaxRecvDataSegmentLength", "8192");
     355                 :          4 :         CU_ASSERT(rc == 0);
     356                 :          4 :         iscsi_param_free(params);
     357                 :          4 : }
     358                 :            : 
     359                 :            : int
     360                 :          4 : main(int argc, char **argv)
     361                 :            : {
     362                 :          4 :         CU_pSuite       suite = NULL;
     363                 :            :         unsigned int    num_failures;
     364                 :            : 
     365                 :          4 :         CU_initialize_registry();
     366                 :            : 
     367                 :          4 :         suite = CU_add_suite("iscsi_suite", NULL, NULL);
     368                 :            : 
     369                 :          4 :         CU_ADD_TEST(suite, param_negotiation_test);
     370                 :          4 :         CU_ADD_TEST(suite, list_negotiation_test);
     371                 :          4 :         CU_ADD_TEST(suite, parse_valid_test);
     372                 :          4 :         CU_ADD_TEST(suite, parse_invalid_test);
     373                 :            : 
     374                 :          4 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     375                 :          4 :         CU_cleanup_registry();
     376                 :          4 :         return num_failures;
     377                 :            : }

Generated by: LCOV version 1.14