LCOV - code coverage report
Current view: top level - plugins/unittest - string_test.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 490 705 69.5 %
Date: 2023-07-05 22:20:52 Functions: 24 24 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : #include <vlib/vlib.h>
      16             : #include <vppinfra/string.h>
      17             : 
      18             : static int
      19           1 : test_memset_s (vlib_main_t * vm, unformat_input_t * input)
      20             : {
      21             :   u8 dst[64];
      22             :   int i;
      23             :   errno_t err;
      24             : 
      25           1 :   vlib_cli_output (vm, "Test memset_s...");
      26             : 
      27           1 :   err = memset_s (dst, ARRAY_LEN (dst), 0xfe, ARRAY_LEN (dst));
      28             : 
      29           1 :   if (err != EOK)
      30           0 :     return -1;
      31             : 
      32          65 :   for (i = 0; i < ARRAY_LEN (dst); i++)
      33          64 :     if (dst[i] != 0xFE)
      34           0 :       return -1;
      35             : 
      36           1 :   err = memset_s (dst, ARRAY_LEN (dst), 0xfa, ARRAY_LEN (dst) + 1);
      37             : 
      38           1 :   if (err == EOK)
      39           0 :     return -1;
      40             : 
      41           1 :   return 0;
      42             : }
      43             : 
      44             : static int
      45           1 : test_clib_memset (vlib_main_t * vm, unformat_input_t * input)
      46             : {
      47             :   u8 dst[64];
      48             :   int i;
      49             :   errno_t err;
      50             : 
      51           1 :   vlib_cli_output (vm, "Test clib_memset...");
      52             : 
      53           1 :   err = clib_memset (dst, 0xfe, ARRAY_LEN (dst));
      54             : 
      55           1 :   if (err != EOK)
      56           0 :     return -1;
      57             : 
      58          65 :   for (i = 0; i < ARRAY_LEN (dst); i++)
      59          64 :     if (dst[i] != 0xFE)
      60           0 :       return -1;
      61             : 
      62           1 :   return 0;
      63             : }
      64             : 
      65             : static int
      66           2 : test_memcpy_s (vlib_main_t * vm, unformat_input_t * input)
      67             : {
      68             :   char src[64], dst[64];
      69             :   int i;
      70             :   errno_t err;
      71             : 
      72           2 :   vlib_cli_output (vm, "Test memcpy_s...");
      73             : 
      74         130 :   for (i = 0; i < ARRAY_LEN (src); i++)
      75         128 :     src[i] = i + 1;
      76             : 
      77             :   /* Typical case */
      78           2 :   err = memcpy_s (dst, sizeof (dst), src, sizeof (src));
      79             : 
      80           2 :   if (err != EOK)
      81           0 :     return -1;
      82             : 
      83             :   /* This better not fail but check anyhow */
      84         130 :   for (i = 0; i < ARRAY_LEN (dst); i++)
      85         128 :     if (src[i] != dst[i])
      86           0 :       return -1;
      87             : 
      88             :   /*
      89             :    * Size test: sizeof (src) > sizeof (dst)
      90             :    * Skip this test when __builtin_constant_p (sizeof (src)) is true.
      91             :    * This is because memcpy_s_inline skips all the errors checking when the
      92             :    * the above buildin function returns true which may cause overrun problem
      93             :    * for dst buffer if this test is executed.
      94             :    */
      95             :   if (__builtin_constant_p (sizeof (src)) == 0)
      96             :     {
      97             :       err = memcpy_s (dst + 1, sizeof (dst) - 1, src, sizeof (src));
      98             : 
      99             :       if (err == EOK)
     100             :         return -1;
     101             :     }
     102             : 
     103             :   /* overlap fail */
     104           2 :   err = memcpy_s (dst, sizeof (dst), dst + 1, sizeof (dst) - 1);
     105             : 
     106           2 :   if (err == EOK)
     107           0 :     return -1;
     108             : 
     109             :   /* Zero length copy */
     110           2 :   err = memcpy_s (0, sizeof (dst), src, 0);
     111             : 
     112           2 :   if (err != EOK)
     113           0 :     return -1;
     114             : 
     115             :   /* OK, seems to work */
     116           2 :   return 0;
     117             : }
     118             : 
     119             : static int
     120           1 : test_clib_memcpy (vlib_main_t * vm, unformat_input_t * input)
     121             : {
     122             :   char src[64], dst[64];
     123             :   int i;
     124             :   errno_t err;
     125             : 
     126           1 :   vlib_cli_output (vm, "Test clib_memcpy...");
     127             : 
     128          65 :   for (i = 0; i < ARRAY_LEN (src); i++)
     129          64 :     src[i] = i + 1;
     130             : 
     131             :   /* Typical case */
     132           1 :   err = clib_memcpy (dst, src, sizeof (src));
     133             : 
     134           1 :   if (err != EOK)
     135           0 :     return -1;
     136             : 
     137             :   /* This better not fail but check anyhow */
     138          65 :   for (i = 0; i < ARRAY_LEN (dst); i++)
     139          64 :     if (src[i] != dst[i])
     140           0 :       return -1;
     141             :   /* verify it against memcpy */
     142           1 :   memcpy (dst, src, sizeof (src));
     143             : 
     144             :   /* This better not fail but check anyhow */
     145          65 :   for (i = 0; i < ARRAY_LEN (dst); i++)
     146          64 :     if (src[i] != dst[i])
     147           0 :       return -1;
     148             : 
     149             :   /* Zero length copy */
     150           1 :   err = clib_memcpy (0, src, 0);
     151             : 
     152           1 :   if (err != EOK)
     153           0 :     return -1;
     154             : 
     155             :   /* OK, seems to work */
     156           1 :   return 0;
     157             : }
     158             : 
     159             : static int
     160           1 : test_memcmp_s (vlib_main_t * vm, unformat_input_t * input)
     161             : {
     162             :   char src[64], dst[64];
     163             :   errno_t err;
     164           1 :   int diff = 0;
     165             : 
     166           1 :   vlib_cli_output (vm, "Test memcmp_s...");
     167             : 
     168             :   /* Fill array with different values */
     169           1 :   err = clib_memset (src, 0x1, ARRAY_LEN (src));
     170           1 :   if (err != EOK)
     171           0 :     return -1;
     172           1 :   err = clib_memset (dst, 0x3, ARRAY_LEN (dst));
     173           1 :   if (err != EOK)
     174           0 :     return -1;
     175             : 
     176             :   /* s1 > s2, > 0 is expected in diff */
     177           1 :   err = memcmp_s (dst, ARRAY_LEN (dst), src, ARRAY_LEN (src), &diff);
     178           1 :   if (err != EOK)
     179           0 :     return -1;
     180           1 :   if (!(diff > 0))
     181           0 :     return -1;
     182             : 
     183             :   /* s1 < s2, < 0 is expected in diff */
     184           1 :   err = memcmp_s (src, ARRAY_LEN (src), dst, ARRAY_LEN (dst), &diff);
     185           1 :   if (err != EOK)
     186           0 :     return -1;
     187           1 :   if (!(diff < 0))
     188           0 :     return -1;
     189             : 
     190           1 :   err = clib_memset (dst, 0x1, ARRAY_LEN (dst));
     191           1 :   if (err != EOK)
     192           0 :     return -1;
     193             : 
     194             :   /* s1 == s2, 0 is expected in diff */
     195           1 :   err = memcmp_s (src, ARRAY_LEN (src), dst, ARRAY_LEN (dst), &diff);
     196           1 :   if (err != EOK)
     197           0 :     return -1;
     198           1 :   if (diff != 0)
     199           0 :     return -1;
     200             : 
     201             :   /* Try negative tests */
     202           1 :   err = memcmp_s (0, 0, 0, 0, 0);
     203           1 :   if (err != EINVAL)
     204           0 :     return -1;
     205             : 
     206             :   /* Try s2max > s1max */
     207           1 :   err = memcmp_s (src, ARRAY_LEN (src) - 1, dst, ARRAY_LEN (dst), &diff);
     208           1 :   if (err != EINVAL)
     209           0 :     return -1;
     210             : 
     211             :   /* OK, seems to work */
     212           1 :   return 0;
     213             : }
     214             : 
     215             : static int
     216           1 : test_clib_memcmp (vlib_main_t * vm, unformat_input_t * input)
     217             : {
     218             :   char src[64], dst[64];
     219             :   errno_t err;
     220             :   char *s;
     221             : 
     222           1 :   vlib_cli_output (vm, "Test clib_memcmp...");
     223             : 
     224             :   /* Fill array with different values */
     225           1 :   err = clib_memset (src, 0x1, ARRAY_LEN (src));
     226           1 :   if (err != EOK)
     227           0 :     return -1;
     228           1 :   err = clib_memset (dst, 0x3, ARRAY_LEN (dst));
     229           1 :   if (err != EOK)
     230           0 :     return -1;
     231             : 
     232             :   /* s1 > s2, > 0 is expected in diff */
     233           1 :   if (!(clib_memcmp (dst, src, ARRAY_LEN (src)) > 0))
     234           0 :     return -1;
     235             :   /* verify it against memcmp */
     236           1 :   if (!(memcmp (dst, src, ARRAY_LEN (src)) > 0))
     237           0 :     return -1;
     238             : 
     239             :   /* s1 < s2, < 0 is expected in diff */
     240           1 :   if (!(clib_memcmp (src, dst, ARRAY_LEN (dst)) < 0))
     241           0 :     return -1;
     242             :   /* verify it against memcmp */
     243           1 :   if (!(memcmp (src, dst, ARRAY_LEN (dst)) < 0))
     244           0 :     return -1;
     245             : 
     246           1 :   err = clib_memset (dst, 0x1, ARRAY_LEN (dst));
     247           1 :   if (err != EOK)
     248           0 :     return -1;
     249             : 
     250             :   /* s1 == s2, 0 is expected in diff */
     251           1 :   if (clib_memcmp (src, dst, ARRAY_LEN (dst)) != 0)
     252           0 :     return -1;
     253             :   /* verify it against memcmp */
     254           1 :   if (memcmp (src, dst, ARRAY_LEN (dst)) != 0)
     255           0 :     return -1;
     256             : 
     257             :   /* Try negative tests */
     258           1 :   s = 0;
     259           1 :   if (clib_memcmp (s, s, 0) != 0)
     260           0 :     return -1;
     261             :   /* verify it against memcmp */
     262             :   if (memcmp (s, s, 0) != 0)
     263             :     return -1;
     264             : 
     265             :   /* OK, seems to work */
     266           1 :   return 0;
     267             : }
     268             : 
     269             : static int
     270           1 : test_strcmp_s (vlib_main_t * vm, unformat_input_t * input)
     271             : {
     272           1 :   char s1[] = "Simplicity is the ultimate sophistication";
     273           1 :   uword s1len = sizeof (s1) - 1;        // excluding null
     274             :   errno_t err;
     275           1 :   int indicator = 0;
     276             : 
     277           1 :   vlib_cli_output (vm, "Test strcmp_s...");
     278             : 
     279             :   /* s1 == s2, 0 is expected */
     280           1 :   err = strcmp_s (s1, s1len, "Simplicity is the ultimate sophistication",
     281             :                   &indicator);
     282           1 :   if (err != EOK)
     283           0 :     return -1;
     284           1 :   if (indicator != 0)
     285           0 :     return -1;
     286             : 
     287             :   /* s1 > s2, > 0 is expected */
     288           1 :   err = strcmp_s (s1, s1len, "Simplicity is the ultimate", &indicator);
     289           1 :   if (err != EOK)
     290           0 :     return -1;
     291           1 :   if (!(indicator > 0))
     292           0 :     return -1;
     293             : 
     294             :   /* s1 < s2, < 0 is expected */
     295           1 :   err = strcmp_s (s1, s1len, "Simplicity is the ultimate sophistication!",
     296             :                   &indicator);
     297           1 :   if (err != EOK)
     298           0 :     return -1;
     299           1 :   if (!(indicator < 0))
     300           0 :     return -1;
     301             : 
     302             :   /* Try some negative tests */
     303             : 
     304             :   /* Null pointers test */
     305           1 :   err = strcmp_s (0, 0, 0, 0);
     306           1 :   if (err != EINVAL)
     307           0 :     return -1;
     308             : 
     309             :   /* non-null terminated s1 */
     310           1 :   s1[s1len] = 0x1;
     311           1 :   err = strcmp_s (s1, s1len, "Simplicity is the ultimate sophistication",
     312             :                   &indicator);
     313           1 :   if (err != EINVAL)
     314           0 :     return -1;
     315             : 
     316             :   /* OK, seems to work */
     317           1 :   return 0;
     318             : }
     319             : 
     320             : static int
     321           1 : test_clib_strcmp (vlib_main_t * vm, unformat_input_t * input)
     322             : {
     323           1 :   char s1[] = "Simplicity is the ultimate sophistication";
     324             :   int indicator;
     325             :   char *s;
     326             : 
     327           1 :   vlib_cli_output (vm, "Test clib_strcmp...");
     328             : 
     329             :   /* s1 == s2, 0 is expected */
     330           1 :   indicator = clib_strcmp (s1, "Simplicity is the ultimate sophistication");
     331           1 :   if (indicator != 0)
     332           0 :     return -1;
     333             :   /* verify it against strcmp */
     334           1 :   indicator = strcmp (s1, "Simplicity is the ultimate sophistication");
     335           1 :   if (indicator != 0)
     336           0 :     return -1;
     337             : 
     338             :   /* s1 > s2, > 0 is expected */
     339           1 :   indicator = clib_strcmp (s1, "Simplicity is the ultimate");
     340           1 :   if (!(indicator > 0))
     341           0 :     return -1;
     342             :   /* verify it against strcmp */
     343           1 :   indicator = strcmp (s1, "Simplicity is the ultimate");
     344           1 :   if (!(indicator > 0))
     345           0 :     return -1;
     346             : 
     347             :   /* s1 < s2, < 0 is expected */
     348           1 :   indicator = clib_strcmp (s1, "Simplicity is the ultimate sophistication!");
     349           1 :   if (!(indicator < 0))
     350           0 :     return -1;
     351             :   /* verify it against strcmp */
     352           1 :   indicator = strcmp (s1, "Simplicity is the ultimate sophistication!");
     353           1 :   if (!(indicator < 0))
     354           0 :     return -1;
     355             : 
     356             :   /* Try some negative tests */
     357             : 
     358             :   /* Null pointers comparison */
     359           1 :   s = 0;
     360           1 :   indicator = clib_strcmp (s, s);
     361           1 :   if (indicator != 0)
     362           0 :     return -1;
     363             : 
     364             :   /* OK, seems to work */
     365           1 :   return 0;
     366             : }
     367             : 
     368             : static int
     369           1 : test_strncmp_s (vlib_main_t * vm, unformat_input_t * input)
     370             : {
     371           1 :   char s1[] = "Every moment is a fresh beginning";
     372           1 :   uword s1len = sizeof (s1) - 1;        // excluding null
     373             :   errno_t err;
     374           1 :   int indicator = 0;
     375             : 
     376           1 :   vlib_cli_output (vm, "Test strncmp_s...");
     377             : 
     378             :   /* s1 == s2, 0 is expected */
     379           1 :   err = strncmp_s (s1, s1len, "Every moment is a fresh beginning", s1len,
     380             :                    &indicator);
     381           1 :   if (err != EOK)
     382           0 :     return -1;
     383           1 :   if (indicator != 0)
     384           0 :     return -1;
     385             : 
     386             :   /* s1 > s2, 0 is expected since comparison is no more than n character */
     387           1 :   err = strncmp_s (s1, s1len, "Every moment is a fresh begin",
     388             :                    sizeof ("Every moment is a fresh begin") - 1, &indicator);
     389           1 :   if (err != EOK)
     390           0 :     return -1;
     391           1 :   if (indicator != 0)
     392           0 :     return -1;
     393             : 
     394             :   /* s1 < s2, < 0 is expected */
     395           1 :   err = strncmp_s (s1, s1len, "Every moment is fresh beginning",
     396             :                    sizeof ("Every moment is fresh beginning") - 1,
     397             :                    &indicator);
     398           1 :   if (err != EOK)
     399           0 :     return -1;
     400           1 :   if (!(indicator < 0))
     401           0 :     return -1;
     402             : 
     403             :   /* s1 > s2, > 0 is expected */
     404           1 :   err = strncmp_s ("Every moment is fresh beginning. ",
     405             :                    sizeof ("Every moment is fresh beginning. ") - 1, s1,
     406             :                    s1len, &indicator);
     407           1 :   if (err != EOK)
     408           0 :     return -1;
     409           1 :   if (!(indicator > 0))
     410           0 :     return -1;
     411             : 
     412             :   /* Try some negative tests */
     413             : 
     414             :   /* Null pointers */
     415           1 :   err = strncmp_s (0, 0, 0, 0, 0);
     416           1 :   if (err != EINVAL)
     417           0 :     return -1;
     418             : 
     419             :   /* n > s1max */
     420           1 :   err = strncmp_s (s1, s1len, "Every moment is a fresh beginning", s1len + 1,
     421             :                    &indicator);
     422           1 :   if (err != EINVAL)
     423           0 :     return -1;
     424             : 
     425             :   /* unterminated s1 */
     426           1 :   s1[s1len] = 0x1;
     427           1 :   err = strncmp_s (s1, s1len, "Every moment is a fresh beginning",
     428             :                    sizeof ("Every moment is a fresh beginning") - 1,
     429             :                    &indicator);
     430           1 :   if (err != EINVAL)
     431           0 :     return -1;
     432             : 
     433             :   /* OK, seems to work */
     434           1 :   return 0;
     435             : }
     436             : 
     437             : static int
     438           1 : test_clib_strncmp (vlib_main_t * vm, unformat_input_t * input)
     439             : {
     440           1 :   char s1[] = "Every moment is a fresh beginning";
     441           1 :   uword s1len = sizeof (s1) - 1;        // excluding null
     442             :   int indicator, v_indicator;
     443             : 
     444           1 :   vlib_cli_output (vm, "Test clib_strncmp...");
     445             : 
     446             :   /* s1 == s2, 0 is expected */
     447           1 :   indicator = clib_strncmp (s1, "Every moment is a fresh beginning", s1len);
     448           1 :   if (indicator != 0)
     449           0 :     return -1;
     450             :   /* verify it against strncmp */
     451           1 :   v_indicator = strncmp (s1, "Every moment is a fresh beginning", s1len);
     452           1 :   if (v_indicator != 0)
     453           0 :     return -1;
     454             : 
     455             :   /* s1 > s2, 0 is expected since comparison is no more than n character */
     456           1 :   indicator = clib_strncmp (s1, "Every moment is a fresh begin",
     457             :                             sizeof ("Every moment is a fresh begin") - 1);
     458           1 :   if (indicator != 0)
     459           0 :     return -1;
     460             :   /* verify it against strncmp */
     461           1 :   v_indicator = strncmp (s1, "Every moment is a fresh begin",
     462             :                          sizeof ("Every moment is a fresh begin") - 1);
     463           1 :   if (v_indicator != 0)
     464           0 :     return -1;
     465             : 
     466             :   /* s1 < s2, < 0 is expected */
     467           1 :   indicator = clib_strncmp (s1, "Every moment is fresh beginning",
     468             :                             sizeof ("Every moment is fresh beginning") - 1);
     469           1 :   if (!(indicator < 0))
     470           0 :     return -1;
     471             :   /* verify it against strncmp */
     472           1 :   v_indicator = strncmp (s1, "Every moment is fresh beginning",
     473             :                          sizeof ("Every moment is fresh beginning") - 1);
     474           1 :   if (!(v_indicator < 0))
     475           0 :     return -1;
     476           1 :   if (v_indicator != indicator)
     477           0 :     return -1;
     478             : 
     479             :   /* s1 > s2, > 0 is expected */
     480           1 :   indicator = clib_strncmp ("Every moment is fresh beginning. ", s1, s1len);
     481           1 :   if (!(indicator > 0))
     482           0 :     return -1;
     483             :   /* verify it against strncmp */
     484           1 :   v_indicator = strncmp ("Every moment is fresh beginning. ", s1, s1len);
     485           1 :   if (!(v_indicator > 0))
     486           0 :     return -1;
     487           1 :   if (v_indicator != indicator)
     488           0 :     return -1;
     489             : 
     490             :   /* Try some negative tests */
     491             : 
     492             :   /* Null pointers */
     493             : 
     494             :   /* make sure we don't crash */
     495           1 :   indicator = clib_strncmp (0, 0, 0);
     496           1 :   if (indicator != EOK)
     497           0 :     return -1;
     498             : 
     499             :   /* n > s1 len */
     500           1 :   indicator =
     501           1 :     clib_strncmp (s1, "Every moment is a fresh beginning", s1len + 1);
     502           1 :   if (indicator != 0)
     503           0 :     return -1;
     504             :   /* verify it against strncmp */
     505           1 :   v_indicator = strncmp (s1, "Every moment is a fresh beginning", s1len + 1);
     506           1 :   if (v_indicator != 0)
     507           0 :     return -1;
     508             : 
     509             :   /* unterminated s1 */
     510           1 :   s1[s1len] = 0x1;
     511           1 :   clib_mem_unpoison (s1, CLIB_STRING_MACRO_MAX);
     512           1 :   indicator = clib_strncmp (s1, "Every moment is a fresh beginning",
     513             :                             sizeof ("every moment is a fresh beginning") - 1);
     514           1 :   if (indicator != 0)
     515           0 :     return -1;
     516             :   /* verify it against strncmp */
     517           1 :   v_indicator = strncmp (s1, "Every moment is a fresh beginning",
     518             :                          sizeof ("Every moment is a fresh beginning") - 1);
     519           1 :   if (v_indicator != 0)
     520           0 :     return -1;
     521             : 
     522             :   /* OK, seems to work */
     523           1 :   return 0;
     524             : }
     525             : 
     526             : static int
     527           1 : test_strcpy_s (vlib_main_t * vm, unformat_input_t * input)
     528             : {
     529           1 :   char src[] = "To err is human.";
     530             :   char dst[64];
     531             :   int indicator;
     532           1 :   size_t s1size = sizeof (dst); // including null
     533             :   errno_t err;
     534             : 
     535           1 :   vlib_cli_output (vm, "Test strcpy_s...");
     536             : 
     537           1 :   err = strcpy_s (dst, s1size, src);
     538           1 :   if (err != EOK)
     539           0 :     return -1;
     540             : 
     541             :   /* This better not fail but check anyhow */
     542           1 :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
     543             :       EOK)
     544           0 :     return -1;
     545           1 :   if (indicator != 0)
     546           0 :     return -1;
     547             : 
     548             :   /* Negative tests */
     549             : 
     550           1 :   err = strcpy_s (0, 0, 0);
     551           1 :   if (err == EOK)
     552           0 :     return -1;
     553             : 
     554             :   /* Size fail */
     555           1 :   err = strcpy_s (dst, 10, src);
     556           1 :   if (err == EOK)
     557           0 :     return -1;
     558             : 
     559             :   /* overlap fail */
     560             : #if __GNUC__ < 8
     561             :   /* GCC 8 flunks this one at compile time... */
     562             :   err = strcpy_s (dst, s1size, dst);
     563             :   if (err == EOK)
     564             :     return -1;
     565             : #endif
     566             : 
     567             :   /* overlap fail */
     568           1 :   err = strcpy_s (dst, s1size, dst + 1);
     569           1 :   if (err == EOK)
     570           0 :     return -1;
     571             : 
     572             :   /* OK, seems to work */
     573           1 :   return 0;
     574             : }
     575             : 
     576             : static int
     577           1 : test_strncpy_s (vlib_main_t * vm, unformat_input_t * input)
     578             : {
     579           1 :   char src[] = "Those who dare to fail miserably can achieve greatly.";
     580             :   char dst[100], old_dst[100];
     581             :   int indicator, i;
     582           1 :   size_t s1size = sizeof (dst); // including null
     583             :   errno_t err;
     584             : 
     585           1 :   vlib_cli_output (vm, "Test strncpy_s...");
     586             : 
     587             :   /* dmax includes null, n excludes null */
     588             : 
     589             :   /* n == string len of src */
     590           1 :   err = strncpy_s (dst, s1size, src, clib_strnlen (src, sizeof (src)));
     591           1 :   if (err != EOK)
     592           0 :     return -1;
     593           1 :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
     594             :       EOK)
     595           0 :     return -1;
     596           1 :   if (indicator != 0)
     597           0 :     return -1;
     598             : 
     599             :   /* limited copy -- strlen src > n, copy up to n */
     600           1 :   err = strncpy_s (dst, s1size, "The price of greatness is responsibility.",
     601             :                    10);
     602           1 :   if (err != EOK)
     603           0 :     return -1;
     604           1 :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), "The price ",
     605             :                 &indicator) != EOK)
     606           0 :     return -1;
     607           1 :   if (indicator != 0)
     608           0 :     return -1;
     609             : 
     610             :   /* n > string len of src */
     611           1 :   err = clib_memset (dst, 1, sizeof (dst));
     612           1 :   if (err != EOK)
     613           0 :     return -1;
     614             : 
     615           1 :   err = strncpy_s (dst, s1size, src, clib_strnlen (src, sizeof (src)) + 10);
     616           1 :   if (err != EOK)
     617           0 :     return -1;
     618           1 :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
     619             :       EOK)
     620           0 :     return -1;
     621           1 :   if (indicator != 0)
     622           0 :     return -1;
     623             : 
     624             :   /* Make sure bytes after strlen(dst) is untouched */
     625          47 :   for (i = 1 + clib_strnlen (dst, sizeof (dst)); i < sizeof (dst); i++)
     626          46 :     if (dst[i] != 1)
     627           0 :       return -1;
     628             : 
     629             :   /* truncation, n >= dmax */
     630           1 :   err = strncpy_s (dst, clib_strnlen (src, sizeof (src)), src,
     631             :                    clib_strnlen (src, sizeof (src)));
     632           1 :   if (err != EOVERFLOW)
     633           0 :     return -1;
     634             : 
     635             :   /* Check dst content */
     636           1 :   if (dst[strlen (dst)] != '\0')
     637           0 :     return -1;
     638           1 :   if (strncmp_s (dst, clib_strnlen (dst, sizeof (dst)), src,
     639             :                  clib_strnlen (dst, sizeof (dst)), &indicator) != EOK)
     640           0 :     return -1;
     641           1 :   if (indicator != 0)
     642           0 :     return -1;
     643             : 
     644             :   /* zero length copy */
     645           1 :   clib_strncpy (old_dst, dst, clib_strnlen (dst, sizeof (dst)));
     646           1 :   err = strncpy_s (dst, sizeof (dst), src, 0);
     647           1 :   if (err != EOK)
     648           0 :     return -1;
     649             :   /* verify dst is untouched */
     650           1 :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), old_dst, &indicator) !=
     651             :       EOK)
     652           0 :     return -1;
     653           1 :   if (indicator != 0)
     654           0 :     return -1;
     655             : 
     656             :   /* Negative tests */
     657             : 
     658           1 :   err = strncpy_s (0, 0, 0, 1);
     659           1 :   if (err == EOK)
     660           0 :     return -1;
     661             : 
     662             :   /* overlap fail */
     663           1 :   err = strncpy_s (dst, s1size, dst + 1, s1size - 1);
     664           1 :   if (err == EOK)
     665           0 :     return -1;
     666             : 
     667             :   /* overlap fail */
     668             : #if __GNUC__ < 8
     669             :   /* GCC 8 flunks this one at compile time... */
     670             :   err = strncpy_s (dst, s1size, dst, s1size);
     671             :   if (err == EOK)
     672             :     return -1;
     673             : #endif
     674             : 
     675             :   /* OK, seems to work */
     676           1 :   return 0;
     677             : }
     678             : 
     679             : static int
     680           1 : test_clib_strncpy (vlib_main_t * vm, unformat_input_t * input)
     681             : {
     682           1 :   char src[] = "Those who dare to fail miserably can achieve greatly.";
     683             :   char dst[100], old_dst[100];
     684             :   int indicator;
     685           1 :   size_t s1size = sizeof (dst); // including null
     686             :   errno_t err;
     687             : 
     688           1 :   vlib_cli_output (vm, "Test clib_strncpy...");
     689             : 
     690             :   /* n == string len of src */
     691           1 :   err = clib_strncpy (dst, src, clib_strnlen (src, sizeof (src)));
     692           1 :   if (err != EOK)
     693           0 :     return -1;
     694             : 
     695             :   /* This better not fail but check anyhow */
     696           1 :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
     697             :       EOK)
     698           0 :     return -1;
     699           1 :   if (indicator != 0)
     700           0 :     return -1;
     701             : 
     702             :   /* Verify it against strncpy */
     703             : #if __GNUC__ < 8
     704             :   /* GCC 8 debian flunks this one at compile time */
     705             :   strncpy (dst, src, strlen (src));
     706             : 
     707             :   /* This better not fail but check anyhow */
     708             :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
     709             :       EOK)
     710             :     return -1;
     711             :   if (indicator != 0)
     712             :     return -1;
     713             : #endif
     714             : 
     715             :   /* limited copy -- strlen src > n, copy up to n */
     716           1 :   err = clib_strncpy (dst, "The price of greatness is responsibility.", 10);
     717           1 :   if (err != EOK)
     718           0 :     return -1;
     719           1 :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), "The price ",
     720             :                 &indicator) != EOK)
     721           0 :     return -1;
     722           1 :   if (indicator != 0)
     723           0 :     return -1;
     724             :   /* verify it against strncpy */
     725           1 :   memset_s (dst, sizeof (dst), 0, sizeof (dst));
     726             : 
     727             : #if __GNUC__ < 8
     728             :   /* GCC 8 flunks this one at compile time... */
     729             :   strncpy (dst, "The price of greatness is responsibility.", 10);
     730             :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), "The price ",
     731             :                 &indicator) != EOK)
     732             :     return -1;
     733             :   if (indicator != 0)
     734             :     return -1;
     735             : #endif
     736             : 
     737             :   /* n > string len of src */
     738           1 :   err = clib_strncpy (dst, src, clib_strnlen (src, sizeof (src)) + 10);
     739           1 :   if (err != EOK)
     740           0 :     return -1;
     741           1 :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
     742             :       EOK)
     743           0 :     return -1;
     744           1 :   if (indicator != 0)
     745           0 :     return -1;
     746             :   /* Verify it against strncpy */
     747             : #if __GNUC__ < 8
     748             :   /* GCC 8 debian flunks this one at compile time */
     749             :   strncpy (dst, src, strlen (src));
     750             :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), src, &indicator) !=
     751             :       EOK)
     752             :     return -1;
     753             :   if (indicator != 0)
     754             :     return -1;
     755             : #endif
     756             : 
     757             :   /* zero length copy */
     758           1 :   clib_strncpy (old_dst, dst, clib_strnlen (dst, sizeof (dst)));
     759           1 :   err = clib_strncpy (dst, src, 0);
     760           1 :   if (err != EOK)
     761           0 :     return -1;
     762             :   /* verify dst is untouched */
     763           1 :   if (strcmp_s (dst, clib_strnlen (dst, sizeof (dst)), old_dst, &indicator) !=
     764             :       EOK)
     765           0 :     return -1;
     766           1 :   if (indicator != 0)
     767           0 :     return -1;
     768             : 
     769             :   /* Negative tests */
     770             : 
     771           1 :   err = clib_strncpy (0, 0, 1);
     772           1 :   if (err == EOK)
     773           0 :     return -1;
     774             : 
     775             :   /* overlap fail */
     776           1 :   err = clib_strncpy (dst, dst + 1, s1size);
     777           1 :   if (err == EOK)
     778           0 :     return -1;
     779             : 
     780             :   /* overlap fail */
     781             : #if __GNUC__ < 8
     782             :   /* GCC 8 flunks this one at compile time... */
     783             :   err = clib_strncpy (dst, dst, s1size);
     784             :   if (err == EOK)
     785             :     return -1;
     786             : #endif
     787             : 
     788             :   /* OK, seems to work */
     789           1 :   return 0;
     790             : }
     791             : 
     792             : static int
     793           1 : test_strcat_s (vlib_main_t * vm, unformat_input_t * input)
     794             : {
     795             :   char src[100], dst[100], old_dst[100];
     796           1 :   size_t s1size = sizeof (dst); // including null
     797             :   errno_t err;
     798             :   int indicator;
     799             : 
     800           1 :   vlib_cli_output (vm, "Test strcat_s...");
     801             : 
     802           1 :   strcpy_s (dst, sizeof (dst), "Tough time never last ");
     803           1 :   strcpy_s (src, sizeof (src), "but tough people do");
     804           1 :   err = strcat_s (dst, s1size, src);
     805           1 :   if (err != EOK)
     806           0 :     return -1;
     807           1 :   if (strcmp_s (dst, s1size - 1,
     808             :                 "Tough time never last but tough people do",
     809             :                 &indicator) != EOK)
     810           0 :     return -1;
     811           1 :   if (indicator != 0)
     812           0 :     return -1;
     813             : 
     814             :   /* empty string concatenation */
     815           1 :   clib_strncpy (old_dst, dst, clib_strnlen (dst, sizeof (dst)));
     816           1 :   err = strcat_s (dst, s1size, "");
     817           1 :   if (err != EOK)
     818           0 :     return -1;
     819             :   /* verify dst is untouched */
     820           1 :   if (strcmp_s (dst, s1size - 1, old_dst, &indicator) != EOK)
     821           0 :     return -1;
     822           1 :   if (indicator != 0)
     823           0 :     return -1;
     824             : 
     825             :   /* negative stuff */
     826           1 :   err = strcat_s (0, 0, 0);
     827           1 :   if (err != EINVAL)
     828           0 :     return -1;
     829             : 
     830             :   /* overlap fail */
     831           1 :   err = strcat_s (dst, s1size, dst + 1);
     832           1 :   if (err != EINVAL)
     833           0 :     return -1;
     834             : 
     835             :   /* overlap fail */
     836             : #if __GNUC__ < 8
     837             :   /* GCC 8 flunks this one at compile time... */
     838             :   err = strcat_s (dst, s1size, dst);
     839             :   if (err != EINVAL)
     840             :     return -1;
     841             : #endif
     842             : 
     843             :   /* not enough space for dst */
     844           1 :   err = strcat_s (dst, 10, src);
     845           1 :   if (err != EINVAL)
     846           0 :     return -1;
     847             : 
     848             :   /* OK, seems to work */
     849           1 :   return 0;
     850             : }
     851             : 
     852             : static int
     853           1 : test_strncat_s (vlib_main_t * vm, unformat_input_t * input)
     854             : {
     855             :   char src[100], dst[100], old_dst[100];
     856           1 :   size_t s1size = sizeof (dst); // including null
     857             :   errno_t err;
     858           1 :   char s1[] = "Two things are infinite: ";
     859           1 :   char s2[] = "the universe and human stupidity; ";
     860           1 :   char s3[] = "I am not sure about the universe.";
     861             :   int indicator;
     862             : 
     863           1 :   vlib_cli_output (vm, "Test strncat_s...");
     864             : 
     865           1 :   strcpy_s (dst, sizeof (dst), s1);
     866           1 :   strcpy_s (src, sizeof (src), s2);
     867           1 :   err = strncat_s (dst, s1size, src, clib_strnlen (src, sizeof (src)));
     868           1 :   if (err != EOK)
     869           0 :     return -1;
     870           1 :   if (strcmp_s (dst, s1size - 1,
     871             :                 "Two things are infinite: the universe and human stupidity; ",
     872             :                 &indicator) != EOK)
     873           0 :     return -1;
     874           1 :   if (indicator != 0)
     875           0 :     return -1;
     876             : 
     877             :   /* truncation, n >= dmax - strnlen_s (dst, dmax) */
     878           2 :   err = strncat_s (dst, clib_strnlen (dst, sizeof (dst)) +
     879           1 :                    clib_strnlen (s3, sizeof (s3)), s3,
     880             :                    clib_strnlen (s3, sizeof (s3)));
     881           1 :   if (err != EOVERFLOW)
     882           0 :     return -1;
     883             :   /*
     884             :    * resulting string is dst + strlen (s3) - 1 characters + null.
     885             :    * notice the "." is missing at the end of the resulting string because
     886             :    * the space is needed to accommodate the null
     887             :    * Notice strcmp_s will check s1 or dst to make sure it is null terminated
     888             :    */
     889           1 :   if (strcmp_s (dst, s1size - 1,
     890             :                 "Two things are infinite: the universe and human stupidity; "
     891             :                 "I am not sure about the universe", &indicator) != EOK)
     892           0 :     return -1;
     893           1 :   if (indicator != 0)
     894           0 :     return -1;
     895             : 
     896             :   /* n > strlen src */
     897           1 :   strcpy_s (dst, sizeof (dst), s1);
     898           1 :   err = strncat_s (dst, s1size, src, clib_strnlen (src, sizeof (src)) + 10);
     899           1 :   if (err != EOK)
     900           0 :     return -1;
     901           1 :   if (strcmp_s (dst, s1size - 1,
     902             :                 "Two things are infinite: the universe and human stupidity; ",
     903             :                 &indicator) != EOK)
     904           0 :     return -1;
     905           1 :   if (indicator != 0)
     906           0 :     return -1;
     907             : 
     908             :   /* zero length strncat */
     909           1 :   clib_strncpy (old_dst, dst, clib_strnlen (dst, sizeof (dst)));
     910           1 :   err = strncat_s (dst, sizeof (dst), src, 0);
     911           1 :   if (err != EOK)
     912           0 :     return -1;
     913             :   /* verify dst is untouched */
     914           1 :   if (strcmp_s (dst, s1size - 1, old_dst, &indicator) != EOK)
     915           0 :     return -1;
     916           1 :   if (indicator != 0)
     917           0 :     return -1;
     918             : 
     919             :   /* empty string, wrong n concatenation */
     920           1 :   err = strncat_s (dst, sizeof (dst), "", 10);
     921           1 :   if (err != EOK)
     922           0 :     return -1;
     923             :   /* verify dst is untouched */
     924           1 :   if (strcmp_s (dst, s1size - 1, old_dst, &indicator) != EOK)
     925           0 :     return -1;
     926           1 :   if (indicator != 0)
     927           0 :     return -1;
     928             : 
     929             :   /* limited concatenation, string > n, copy up to n */
     930           1 :   strcpy_s (dst, sizeof (dst), s1);
     931           1 :   err = strncat_s (dst, s1size, s2, 13);
     932           1 :   if (err != EOK)
     933           0 :     return -1;
     934           1 :   if (strcmp_s (dst, s1size - 1, "Two things are infinite: the universe ",
     935             :                 &indicator) != EOK)
     936           0 :     return -1;
     937           1 :   if (indicator != 0)
     938           0 :     return -1;
     939             :   /* verify it against strncat */
     940             : #if __GNUC__ < 8
     941             :   /* GCC 8 debian flunks this one at compile time */
     942             :   strcpy_s (dst, sizeof (dst), s1);
     943             :   strncat (dst, s2, 13);
     944             :   if (strcmp_s (dst, s1size - 1, "Two things are infinite: the universe ",
     945             :                 &indicator) != EOK)
     946             :     return -1;
     947             :   if (indicator != 0)
     948             :     return -1;
     949             : #endif
     950             : 
     951             :   /* negative stuff */
     952           1 :   err = strncat_s (0, 0, 0, 1);
     953           1 :   if (err != EINVAL)
     954           0 :     return -1;
     955             : 
     956             :   /* no room for dst -- dmax - strnlen_s (dst, dmax) == 0 */
     957           1 :   err = strncat_s (dst, clib_strnlen (dst, sizeof (dst)), s2,
     958             :                    clib_strnlen (s2, sizeof (s2)));
     959           1 :   if (err != EINVAL)
     960           0 :     return -1;
     961             : 
     962             :   /* overlap fail */
     963           1 :   err = strncat_s (dst, s1size, dst + 1, clib_strnlen (dst + 1, s1size - 1));
     964           1 :   if (err != EINVAL)
     965           0 :     return -1;
     966             : 
     967             :   /* overlap fail */
     968             : #if __GNUC__ < 8
     969             :   /* GCC 8 flunks this one at compile time... */
     970             :   err = strncat_s (dst, s1size, dst, clib_strnlen (dst, sizeof (dst)));
     971             :   if (err != EINVAL)
     972             :     return -1;
     973             : #endif
     974             : 
     975             :   /* OK, seems to work */
     976           1 :   return 0;
     977             : }
     978             : 
     979             : static int
     980           1 : test_strtok_s (vlib_main_t * vm, unformat_input_t * input)
     981             : {
     982             :   int indicator;
     983             :   char *tok, *ptr;
     984             :   char str2[20];
     985             :   char str1[40];
     986             :   uword len;
     987           1 :   char *p2str = 0;
     988             :   char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7;
     989             : 
     990           1 :   vlib_cli_output (vm, "Test strtok_s...");
     991           1 :   strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
     992           1 :   len = strnlen_s (str1, sizeof (str1));
     993           1 :   tok1 = strtok_s (str1, &len, " ", &p2str);
     994           1 :   tok2 = strtok_s (0, &len, " ", &p2str);
     995           1 :   tok3 = strtok_s (0, &len, " ", &p2str);
     996           1 :   tok4 = strtok_s (0, &len, " ", &p2str);
     997           1 :   tok5 = strtok_s (0, &len, " ", &p2str);
     998           1 :   tok6 = strtok_s (0, &len, " ", &p2str);
     999           1 :   tok7 = strtok_s (0, &len, " ", &p2str);
    1000           2 :   if ((tok1 == 0) ||
    1001           1 :       strcmp_s (tok1, strlen (tok1), "brevity", &indicator) != EOK)
    1002           0 :     return -1;
    1003           1 :   if (indicator != 0)
    1004           0 :     return -1;
    1005           1 :   if ((tok2 == 0) || strcmp_s (tok2, strlen (tok2), "is", &indicator) != EOK)
    1006           0 :     return -1;
    1007           1 :   if (indicator != 0)
    1008           0 :     return -1;
    1009           1 :   if ((tok3 == 0) || strcmp_s (tok3, strlen (tok3), "the", &indicator) != EOK)
    1010           0 :     return -1;
    1011           1 :   if (indicator != 0)
    1012           0 :     return -1;
    1013           1 :   if ((tok4 == 0)
    1014           1 :       || strcmp_s (tok4, strlen (tok4), "soul", &indicator) != EOK)
    1015           0 :     return -1;
    1016           1 :   if (indicator != 0)
    1017           0 :     return -1;
    1018           1 :   if ((tok5 == 0) || strcmp_s (tok5, strlen (tok5), "of", &indicator) != EOK)
    1019           0 :     return -1;
    1020           1 :   if (indicator != 0)
    1021           0 :     return -1;
    1022           1 :   if ((tok6 == 0) || strcmp_s (tok6, strlen (tok6), "wit", &indicator) != EOK)
    1023           0 :     return -1;
    1024           1 :   if (indicator != 0)
    1025           0 :     return -1;
    1026           1 :   if (tok7 != 0)
    1027           0 :     return -1;
    1028             : 
    1029             :   /* delimiter not present in the string -- the whole string is returned */
    1030           1 :   strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
    1031           1 :   len = strnlen_s (str1, sizeof (str1) - 1);
    1032           1 :   p2str = 0;
    1033           1 :   tok1 = strtok_s (str1, &len, ",", &p2str);
    1034           1 :   if ((tok1 == 0) || strcmp_s (tok1, strlen (tok1), str1, &indicator) != EOK)
    1035           0 :     return -1;
    1036           1 :   if (indicator != 0)
    1037           0 :     return -1;
    1038             : 
    1039             :   /* negative stuff */
    1040           1 :   tok = strtok_s (0, 0, 0, 0);
    1041           1 :   if (tok != 0)
    1042           0 :     return -1;
    1043             : 
    1044             :   /* s1 and ptr contents are null */
    1045           1 :   ptr = 0;
    1046           1 :   tok = strtok_s (0, 0, 0, &ptr);
    1047           1 :   if (tok != 0)
    1048           0 :     return -1;
    1049             : 
    1050             :   /* unterminate s1 */
    1051           1 :   p2str = 0;
    1052           1 :   len = strnlen_s (str1, sizeof (str1) - 1);
    1053           1 :   str1[strlen (str1)] = 0x2;
    1054           1 :   tok = strtok_s (str1, &len, ",", &p2str);
    1055           1 :   if (tok != 0)
    1056           0 :     return -1;
    1057             : 
    1058             :   /*
    1059             :    * unterminated s2. This test case in not perfect because there is no
    1060             :    * argument for s2max. But s2 len is limited to 16 characters. If the API
    1061             :    * does not find the null character at s2[15], it declares the string s2
    1062             :    * as unterminated.
    1063             :    */
    1064           1 :   memset_s (str2, sizeof (str2), 0xfa, sizeof (str2));
    1065           1 :   tok = strtok_s (str1, &len, str2, &p2str);
    1066           1 :   if (tok != 0)
    1067           0 :     return -1;
    1068             : 
    1069             :   /* OK, seems to work */
    1070           1 :   return 0;
    1071             : }
    1072             : 
    1073             : static int
    1074           1 : test_clib_strtok (vlib_main_t * vm, unformat_input_t * input)
    1075             : {
    1076             :   int indicator;
    1077             :   char *s1 __attribute__ ((unused));
    1078             :   char *tok __attribute__ ((unused));
    1079             :   char *ptr __attribute__ ((unused));
    1080             :   char str1[40];
    1081             :   char *p2str;
    1082             :   char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7;
    1083             : 
    1084           1 :   vlib_cli_output (vm, "Test clib_strtok...");
    1085           1 :   strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
    1086           1 :   p2str = 0;
    1087           1 :   tok1 = clib_strtok (str1, " ", &p2str);
    1088           1 :   tok2 = clib_strtok (0, " ", &p2str);
    1089           1 :   tok3 = clib_strtok (0, " ", &p2str);
    1090           1 :   tok4 = clib_strtok (0, " ", &p2str);
    1091           1 :   tok5 = clib_strtok (0, " ", &p2str);
    1092           1 :   tok6 = clib_strtok (0, " ", &p2str);
    1093           1 :   tok7 = clib_strtok (0, " ", &p2str);
    1094           2 :   if ((tok1 == 0) ||
    1095           1 :       strcmp_s (tok1, strlen (tok1), "brevity", &indicator) != EOK)
    1096           0 :     return -1;
    1097           1 :   if (indicator != 0)
    1098           0 :     return -1;
    1099           1 :   if ((tok2 == 0) || strcmp_s (tok2, strlen (tok2), "is", &indicator) != EOK)
    1100           0 :     return -1;
    1101           1 :   if (indicator != 0)
    1102           0 :     return -1;
    1103           1 :   if ((tok3 == 0) || strcmp_s (tok3, strlen (tok3), "the", &indicator) != EOK)
    1104           0 :     return -1;
    1105           1 :   if (indicator != 0)
    1106           0 :     return -1;
    1107           1 :   if ((tok4 == 0)
    1108           1 :       || strcmp_s (tok4, strlen (tok4), "soul", &indicator) != EOK)
    1109           0 :     return -1;
    1110           1 :   if (indicator != 0)
    1111           0 :     return -1;
    1112           1 :   if ((tok5 == 0) || strcmp_s (tok5, strlen (tok5), "of", &indicator) != EOK)
    1113           0 :     return -1;
    1114           1 :   if (indicator != 0)
    1115           0 :     return -1;
    1116           1 :   if ((tok6 == 0) || strcmp_s (tok6, strlen (tok6), "wit", &indicator) != EOK)
    1117           0 :     return -1;
    1118           1 :   if (indicator != 0)
    1119           0 :     return -1;
    1120           1 :   if (tok7 != 0)
    1121           0 :     return -1;
    1122             :   /* verify it againest strtok_r */
    1123           1 :   strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
    1124           1 :   p2str = 0;
    1125           1 :   tok1 = strtok_r (str1, " ", &p2str);
    1126           1 :   tok2 = strtok_r (0, " ", &p2str);
    1127           1 :   tok3 = strtok_r (0, " ", &p2str);
    1128           1 :   tok4 = strtok_r (0, " ", &p2str);
    1129           1 :   tok5 = strtok_r (0, " ", &p2str);
    1130           1 :   tok6 = strtok_r (0, " ", &p2str);
    1131           1 :   tok7 = strtok_r (0, " ", &p2str);
    1132           2 :   if ((tok1 == 0) ||
    1133           1 :       strcmp_s (tok1, strlen (tok1), "brevity", &indicator) != EOK)
    1134           0 :     return -1;
    1135           1 :   if (indicator != 0)
    1136           0 :     return -1;
    1137           1 :   if ((tok2 == 0) || strcmp_s (tok2, strlen (tok2), "is", &indicator) != EOK)
    1138           0 :     return -1;
    1139           1 :   if (indicator != 0)
    1140           0 :     return -1;
    1141           1 :   if ((tok3 == 0) || strcmp_s (tok3, strlen (tok3), "the", &indicator) != EOK)
    1142           0 :     return -1;
    1143           1 :   if (indicator != 0)
    1144           0 :     return -1;
    1145           1 :   if ((tok4 == 0)
    1146           1 :       || strcmp_s (tok4, strlen (tok4), "soul", &indicator) != EOK)
    1147           0 :     return -1;
    1148           1 :   if (indicator != 0)
    1149           0 :     return -1;
    1150           1 :   if ((tok5 == 0) || strcmp_s (tok5, strlen (tok5), "of", &indicator) != EOK)
    1151           0 :     return -1;
    1152           1 :   if (indicator != 0)
    1153           0 :     return -1;
    1154           1 :   if ((tok6 == 0) || strcmp_s (tok6, strlen (tok6), "wit", &indicator) != EOK)
    1155           0 :     return -1;
    1156           1 :   if (indicator != 0)
    1157           0 :     return -1;
    1158           1 :   if (tok7 != 0)
    1159           0 :     return -1;
    1160             : 
    1161             :   /* delimiter not present in the string -- the whole string is returned */
    1162           1 :   strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
    1163           1 :   p2str = 0;
    1164           1 :   tok1 = clib_strtok (str1, ",", &p2str);
    1165           1 :   if ((tok1 == 0) || strcmp_s (tok1, strlen (tok1), str1, &indicator) != EOK)
    1166           0 :     return -1;
    1167           1 :   if (indicator != 0)
    1168           0 :     return -1;
    1169             :   /* verify it against strtok_r */
    1170           1 :   strcpy_s (str1, sizeof (str1), "brevity is the soul of wit");
    1171           1 :   p2str = 0;
    1172           1 :   tok1 = strtok_r (str1, ",", &p2str);
    1173           1 :   if ((tok1 == 0) || strcmp_s (tok1, strlen (tok1), str1, &indicator) != EOK)
    1174           0 :     return -1;
    1175           1 :   if (indicator != 0)
    1176           0 :     return -1;
    1177             : 
    1178             :   /* negative stuff */
    1179           1 :   s1 = 0;
    1180           1 :   ptr = 0;
    1181             : #if __GNUC__ < 8
    1182             :   /* GCC 8 flunks this one at compile time... */
    1183             :   tok = clib_strtok (s1, s1, (char **) 0);
    1184             :   if (tok != 0)
    1185             :     return -1;
    1186             : 
    1187             :   /* s1 and ptr contents are null */
    1188             :   tok = clib_strtok (s1, s1, &ptr);
    1189             :   if (tok != 0)
    1190             :     return -1;
    1191             : #endif
    1192             : 
    1193             :   /* verify it against strtok_r */
    1194             :   /* No can do. This causes a crash in strtok_r */
    1195             :   // tok = strtok_r (s1, " ", &ptr);
    1196             :   // if (tok != 0)
    1197             :   //  return -1;
    1198             : 
    1199             :   /*
    1200             :    * Can't test unterminated string s1 and s2 becuase clib_strtok does not
    1201             :    * supply s1 and s2 max
    1202             :    */
    1203             : 
    1204             :   /* OK, seems to work */
    1205           1 :   return 0;
    1206             : }
    1207             : 
    1208             : static int
    1209           1 : test_strnlen_s (vlib_main_t * vm, unformat_input_t * input)
    1210             : {
    1211           1 :   const char s1[] = "Truth is incontrovertible";
    1212             :   size_t len;
    1213             : 
    1214           1 :   vlib_cli_output (vm, "Test strnlen_s...");
    1215             : 
    1216           1 :   len = strnlen_s (s1, sizeof (s1));
    1217           1 :   if (len != sizeof (s1) - 1)
    1218           0 :     return -1;
    1219             : 
    1220           1 :   len = strnlen_s (s1, 5);
    1221           1 :   if (len != 5)
    1222           0 :     return -1;
    1223             : 
    1224             :   /* negative stuff */
    1225           1 :   len = strnlen_s (0, 0);
    1226           1 :   if (len != 0)
    1227           0 :     return -1;
    1228             : 
    1229             :   /* OK, seems to work */
    1230           1 :   return 0;
    1231             : }
    1232             : 
    1233             : static int
    1234           1 : test_clib_strnlen (vlib_main_t * vm, unformat_input_t * input)
    1235             : {
    1236           1 :   const char s1[] = "Truth is incontrovertible";
    1237             :   size_t len;
    1238             : 
    1239           1 :   vlib_cli_output (vm, "Test clib_strnlen...");
    1240             : 
    1241           1 :   len = clib_strnlen (s1, sizeof (s1));
    1242           1 :   if (len != sizeof (s1) - 1)
    1243           0 :     return -1;
    1244             : 
    1245           1 :   len = clib_strnlen (s1, 5);
    1246           1 :   if (len != 5)
    1247           0 :     return -1;
    1248             : 
    1249             :   /* negative stuff */
    1250           1 :   len = clib_strnlen (0, 0);
    1251           1 :   if (len != 0)
    1252           0 :     return -1;
    1253             : 
    1254             :   /* OK, seems to work */
    1255           1 :   return 0;
    1256             : }
    1257             : 
    1258             : static int
    1259           1 : test_strstr_s (vlib_main_t * vm, unformat_input_t * input)
    1260             : {
    1261             :   errno_t err;
    1262           1 :   char *sub = 0;
    1263             :   char s1[64];
    1264           1 :   size_t s1len = sizeof (s1) - 1;       // excluding null
    1265             :   int indicator;
    1266             : 
    1267           1 :   vlib_cli_output (vm, "Test strstr_s...");
    1268             : 
    1269             :   /* substring not present */
    1270           1 :   strcpy_s (s1, s1len, "success is not final, failure is not fatal.");
    1271           1 :   err = strstr_s (s1, s1len, "failures", sizeof ("failures"), &sub);;
    1272           1 :   if (err != ESRCH)
    1273           0 :     return -1;
    1274             : 
    1275             :   /* substring present */
    1276           1 :   err = strstr_s (s1, s1len, "failure", sizeof ("failure"), &sub);
    1277           1 :   if (err != EOK)
    1278           0 :     return -1;
    1279             : 
    1280           2 :   if ((sub == 0) ||
    1281           1 :       strcmp_s (sub, strlen (sub), "failure is not fatal.", &indicator)
    1282             :       != EOK)
    1283           0 :     return -1;
    1284           1 :   if (indicator != 0)
    1285           0 :     return -1;
    1286             : 
    1287             :   /* negative stuff */
    1288             : 
    1289             :   /* Null pointers test */
    1290           1 :   err = strstr_s (0, 0, 0, 0, 0);
    1291           1 :   if (err != EINVAL)
    1292           0 :     return -1;
    1293             : 
    1294             :   /* unterminated s1 and s2 */
    1295           1 :   memset_s (s1, ARRAY_LEN (s1), 0xfe, ARRAY_LEN (s1));
    1296           1 :   err = strstr_s (s1, s1len, s1, s1len, &sub);
    1297           1 :   if (err != EINVAL)
    1298           0 :     return -1;
    1299             : 
    1300             :   /* OK, seems to work */
    1301           1 :   return 0;
    1302             : }
    1303             : 
    1304             : #define foreach_string_test                                                   \
    1305             :   _ (0, MEMCPY_S, "memcpy_s", memcpy_s)                                       \
    1306             :   _ (1, CLIB_MEMCPY, "clib_memcpy", clib_memcpy)                              \
    1307             :   _ (2, MEMSET_S, "memset_s", memset_s)                                       \
    1308             :   _ (3, CLIB_MEMSET, "clib_memset", clib_memset)                              \
    1309             :   _ (4, MEMCMP_S, "memcmp_s", memcmp_s)                                       \
    1310             :   _ (5, CLIB_MEMCMP, "clib_memcmp", clib_memcmp)                              \
    1311             :   _ (6, STRCMP_S, "strcmp_s", strcmp_s)                                       \
    1312             :   _ (7, CLIB_STRCMP, "clib_strcmp", clib_strcmp)                              \
    1313             :   _ (8, STRNCMP_S, "strncmp_s", strncmp_s)                                    \
    1314             :   _ (9, CLIB_STRNCMP, "clib_strncmp", clib_strncmp)                           \
    1315             :   _ (10, STRCPY_S, "strcpy_s", strcpy_s)                                      \
    1316             :   _ (11, STRNCPY_S, "strncpy_s", strncpy_s)                                   \
    1317             :   _ (12, CLIB_STRNCPY, "clib_strncpy", clib_strncpy)                          \
    1318             :   _ (13, STRCAT_S, "strcat_s", strcat_s)                                      \
    1319             :   _ (14, STRNCAT_S, "strncat_s", strncat_s)                                   \
    1320             :   _ (15, STRTOK_S, "strtok_s", strtok_s)                                      \
    1321             :   _ (16, CLIB_STRTOK, "clib_strtok", clib_strtok)                             \
    1322             :   _ (17, STRNLEN_S, "strnlen_s", strnlen_s)                                   \
    1323             :   _ (18, CLIB_STRNLEN, "clib_strnlen", clib_strnlen)                          \
    1324             :   _ (19, STRSTR_S, "strstr_s", strstr_s)
    1325             : 
    1326             : typedef enum
    1327             : {
    1328             : #define _(v,f,s,p) STRING_TEST_##f = v,
    1329             :   foreach_string_test
    1330             : #undef _
    1331             : #define STRING_TEST_FIRST       STRING_TEST_MEMCPY_S
    1332             : #define STRING_TEST_LAST        STRING_TEST_STRSTR_S
    1333             : } string_test_t;
    1334             : 
    1335             : static uword
    1336          21 : unformat_string_test (unformat_input_t * input, va_list * args)
    1337             : {
    1338          21 :   u8 *r = va_arg (*args, u8 *);
    1339             : 
    1340             :   if (0)
    1341             :     ;
    1342             : #define _(v,f,s,p) else if (unformat (input, s)) *r = STRING_TEST_##f;
    1343          21 :   foreach_string_test
    1344             : #undef _
    1345             :     else
    1346           0 :     return 0;
    1347             : 
    1348          21 :   return 1;
    1349             : }
    1350             : 
    1351             : typedef int (*string_test_func) (vlib_main_t * vm, unformat_input_t * input);
    1352             : 
    1353             : typedef struct
    1354             : {
    1355             :   string_test_func test;
    1356             : } string_test_func_t;
    1357             : 
    1358             : static clib_error_t *
    1359          21 : string_test_command_fn (vlib_main_t * vm,
    1360             :                         unformat_input_t * input,
    1361             :                         vlib_cli_command_t * cmd_arg)
    1362             : {
    1363          21 :   string_test_func_t string_func[] = {
    1364             : #define _(v,f,s,p) { test_##p },
    1365             :     foreach_string_test
    1366             : #undef _
    1367             :   };
    1368          21 :   const char *string_table[] = {
    1369             : #define _(v,f,s,p) s,
    1370             :     foreach_string_test
    1371             : #undef _
    1372             :   };
    1373          21 :   int res = 0, ok;
    1374          21 :   i8 specific_test = ~0;
    1375             : 
    1376          21 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1377             :     {
    1378          21 :       if (unformat (input, "%U", unformat_string_test, &specific_test))
    1379          21 :         break;
    1380             :       else
    1381           0 :         return clib_error_return (0, "unknown input `%U'",
    1382             :                                   format_unformat_error, input);
    1383             :     }
    1384             : 
    1385          21 :   if (specific_test == ~0)
    1386             :     {
    1387           0 :       for (specific_test = STRING_TEST_FIRST;
    1388           0 :            specific_test <= STRING_TEST_LAST; specific_test++)
    1389             :         {
    1390           0 :           ok = (string_func[specific_test]).test (vm, input);
    1391           0 :           res += ok;
    1392           0 :           if (ok != 0)
    1393           0 :             vlib_cli_output (vm, "test_%s failed",
    1394             :                              string_table[specific_test]);
    1395             :         }
    1396             :     }
    1397             :   else
    1398          21 :     res = (string_func[specific_test]).test (vm, input);
    1399          21 :   if (res)
    1400           0 :     vlib_cli_output (vm, "String unit test(s) failed...");
    1401             :   else
    1402          21 :     vlib_cli_output (vm, "String unit test(s) OK...");
    1403          21 :   return 0;
    1404             : }
    1405             : 
    1406             : /* *INDENT-OFF* */
    1407       16239 : VLIB_CLI_COMMAND (string_test_command, static) = {
    1408             :   .path = "test string",
    1409             :   .short_help =
    1410             :     "test string [memcpy_s | clib_memcpy | memset_s | "
    1411             :     "clib_memset | memcmp_s | clib_memcmp | strcmp_s | clib_strcmp | "
    1412             :     "strncmp_s | clib_strncmp | strcpy_s | strncpy_s | "
    1413             :     "clib_strncpy | strcat_s | strncat_s | "
    1414             :     "strtok_s |  clib_strtok | strnlen_s | clib_strnlen | strstr_s ]",
    1415             :   .function = string_test_command_fn,
    1416             : };
    1417             : /* *INDENT-ON* */
    1418             : 
    1419             : /*
    1420             :  * fd.io coding-style-patch-verification: ON
    1421             :  *
    1422             :  * Local Variables:
    1423             :  * eval: (c-set-style "gnu")
    1424             :  * End:
    1425             :  */

Generated by: LCOV version 1.14