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