1*a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2*a9de470cSBruce Richardson * Copyright(c) 2010-2014 Intel Corporation
3*a9de470cSBruce Richardson */
4*a9de470cSBruce Richardson
5*a9de470cSBruce Richardson #include <stdio.h>
6*a9de470cSBruce Richardson #include <stdarg.h>
7*a9de470cSBruce Richardson #include <stddef.h>
8*a9de470cSBruce Richardson #include <errno.h>
9*a9de470cSBruce Richardson #include <string.h>
10*a9de470cSBruce Richardson
11*a9de470cSBruce Richardson #include <rte_string_fns.h>
12*a9de470cSBruce Richardson
13*a9de470cSBruce Richardson #include "test.h"
14*a9de470cSBruce Richardson
15*a9de470cSBruce Richardson #define LOG(...) do {\
16*a9de470cSBruce Richardson fprintf(stderr, "%s() ln %d: ", __func__, __LINE__); \
17*a9de470cSBruce Richardson fprintf(stderr, __VA_ARGS__); \
18*a9de470cSBruce Richardson } while(0)
19*a9de470cSBruce Richardson
20*a9de470cSBruce Richardson #define DATA_BYTE 'a'
21*a9de470cSBruce Richardson
22*a9de470cSBruce Richardson static int
test_rte_strsplit(void)23*a9de470cSBruce Richardson test_rte_strsplit(void)
24*a9de470cSBruce Richardson {
25*a9de470cSBruce Richardson int i;
26*a9de470cSBruce Richardson do {
27*a9de470cSBruce Richardson /* =======================================================
28*a9de470cSBruce Richardson * split a mac address correct number of splits requested
29*a9de470cSBruce Richardson * =======================================================*/
30*a9de470cSBruce Richardson char test_string[] = "54:65:76:87:98:90";
31*a9de470cSBruce Richardson char *splits[6];
32*a9de470cSBruce Richardson
33*a9de470cSBruce Richardson LOG("Source string: '%s', to split on ':'\n", test_string);
34*a9de470cSBruce Richardson if (rte_strsplit(test_string, sizeof(test_string),
35*a9de470cSBruce Richardson splits, 6, ':') != 6) {
36*a9de470cSBruce Richardson LOG("Error splitting mac address\n");
37*a9de470cSBruce Richardson return -1;
38*a9de470cSBruce Richardson }
39*a9de470cSBruce Richardson for (i = 0; i < 6; i++)
40*a9de470cSBruce Richardson LOG("Token %d = %s\n", i + 1, splits[i]);
41*a9de470cSBruce Richardson } while (0);
42*a9de470cSBruce Richardson
43*a9de470cSBruce Richardson
44*a9de470cSBruce Richardson do {
45*a9de470cSBruce Richardson /* =======================================================
46*a9de470cSBruce Richardson * split on spaces smaller number of splits requested
47*a9de470cSBruce Richardson * =======================================================*/
48*a9de470cSBruce Richardson char test_string[] = "54 65 76 87 98 90";
49*a9de470cSBruce Richardson char *splits[6];
50*a9de470cSBruce Richardson
51*a9de470cSBruce Richardson LOG("Source string: '%s', to split on ' '\n", test_string);
52*a9de470cSBruce Richardson if (rte_strsplit(test_string, sizeof(test_string),
53*a9de470cSBruce Richardson splits, 3, ' ') != 3) {
54*a9de470cSBruce Richardson LOG("Error splitting mac address for max 2 splits\n");
55*a9de470cSBruce Richardson return -1;
56*a9de470cSBruce Richardson }
57*a9de470cSBruce Richardson for (i = 0; i < 3; i++)
58*a9de470cSBruce Richardson LOG("Token %d = %s\n", i + 1, splits[i]);
59*a9de470cSBruce Richardson } while (0);
60*a9de470cSBruce Richardson
61*a9de470cSBruce Richardson do {
62*a9de470cSBruce Richardson /* =======================================================
63*a9de470cSBruce Richardson * split on commas - more splits than commas requested
64*a9de470cSBruce Richardson * =======================================================*/
65*a9de470cSBruce Richardson char test_string[] = "a,b,c,d";
66*a9de470cSBruce Richardson char *splits[6];
67*a9de470cSBruce Richardson
68*a9de470cSBruce Richardson LOG("Source string: '%s', to split on ','\n", test_string);
69*a9de470cSBruce Richardson if (rte_strsplit(test_string, sizeof(test_string),
70*a9de470cSBruce Richardson splits, 6, ',') != 4) {
71*a9de470cSBruce Richardson LOG("Error splitting %s on ','\n", test_string);
72*a9de470cSBruce Richardson return -1;
73*a9de470cSBruce Richardson }
74*a9de470cSBruce Richardson for (i = 0; i < 4; i++)
75*a9de470cSBruce Richardson LOG("Token %d = %s\n", i + 1, splits[i]);
76*a9de470cSBruce Richardson } while(0);
77*a9de470cSBruce Richardson
78*a9de470cSBruce Richardson do {
79*a9de470cSBruce Richardson /* =======================================================
80*a9de470cSBruce Richardson * Try splitting on non-existent character.
81*a9de470cSBruce Richardson * =======================================================*/
82*a9de470cSBruce Richardson char test_string[] = "a,b,c,d";
83*a9de470cSBruce Richardson char *splits[6];
84*a9de470cSBruce Richardson
85*a9de470cSBruce Richardson LOG("Source string: '%s', to split on ' '\n", test_string);
86*a9de470cSBruce Richardson if (rte_strsplit(test_string, sizeof(test_string),
87*a9de470cSBruce Richardson splits, 6, ' ') != 1) {
88*a9de470cSBruce Richardson LOG("Error splitting %s on ' '\n", test_string);
89*a9de470cSBruce Richardson return -1;
90*a9de470cSBruce Richardson }
91*a9de470cSBruce Richardson LOG("String not split\n");
92*a9de470cSBruce Richardson } while(0);
93*a9de470cSBruce Richardson
94*a9de470cSBruce Richardson do {
95*a9de470cSBruce Richardson /* =======================================================
96*a9de470cSBruce Richardson * Invalid / edge case parameter checks
97*a9de470cSBruce Richardson * =======================================================*/
98*a9de470cSBruce Richardson char test_string[] = "a,b,c,d";
99*a9de470cSBruce Richardson char *splits[6];
100*a9de470cSBruce Richardson
101*a9de470cSBruce Richardson if (rte_strsplit(NULL, 0, splits, 6, ',') >= 0
102*a9de470cSBruce Richardson || errno != EINVAL){
103*a9de470cSBruce Richardson LOG("Error: rte_strsplit accepted NULL string parameter\n");
104*a9de470cSBruce Richardson return -1;
105*a9de470cSBruce Richardson }
106*a9de470cSBruce Richardson
107*a9de470cSBruce Richardson if (rte_strsplit(test_string, sizeof(test_string), NULL, 0, ',') >= 0
108*a9de470cSBruce Richardson || errno != EINVAL){
109*a9de470cSBruce Richardson LOG("Error: rte_strsplit accepted NULL array parameter\n");
110*a9de470cSBruce Richardson return -1;
111*a9de470cSBruce Richardson }
112*a9de470cSBruce Richardson
113*a9de470cSBruce Richardson errno = 0;
114*a9de470cSBruce Richardson if (rte_strsplit(test_string, 0, splits, 6, ',') != 0 || errno != 0) {
115*a9de470cSBruce Richardson LOG("Error: rte_strsplit did not accept 0 length string\n");
116*a9de470cSBruce Richardson return -1;
117*a9de470cSBruce Richardson }
118*a9de470cSBruce Richardson
119*a9de470cSBruce Richardson if (rte_strsplit(test_string, sizeof(test_string), splits, 0, ',') != 0
120*a9de470cSBruce Richardson || errno != 0) {
121*a9de470cSBruce Richardson LOG("Error: rte_strsplit did not accept 0 length array\n");
122*a9de470cSBruce Richardson return -1;
123*a9de470cSBruce Richardson }
124*a9de470cSBruce Richardson
125*a9de470cSBruce Richardson LOG("Parameter test cases passed\n");
126*a9de470cSBruce Richardson } while(0);
127*a9de470cSBruce Richardson
128*a9de470cSBruce Richardson LOG("%s - PASSED\n", __func__);
129*a9de470cSBruce Richardson return 0;
130*a9de470cSBruce Richardson }
131*a9de470cSBruce Richardson
132*a9de470cSBruce Richardson static int
test_rte_strlcat(void)133*a9de470cSBruce Richardson test_rte_strlcat(void)
134*a9de470cSBruce Richardson {
135*a9de470cSBruce Richardson /* only run actual unit tests if we have system-provided strlcat */
136*a9de470cSBruce Richardson #if defined(__BSD_VISIBLE) || defined(RTE_USE_LIBBSD)
137*a9de470cSBruce Richardson #define BUF_LEN 32
138*a9de470cSBruce Richardson const char dst[BUF_LEN] = "Test string";
139*a9de470cSBruce Richardson const char src[] = " appended";
140*a9de470cSBruce Richardson char bsd_dst[BUF_LEN];
141*a9de470cSBruce Richardson char rte_dst[BUF_LEN];
142*a9de470cSBruce Richardson size_t i, bsd_ret, rte_ret;
143*a9de470cSBruce Richardson
144*a9de470cSBruce Richardson LOG("dst = '%s', strlen(dst) = %zu\n", dst, strlen(dst));
145*a9de470cSBruce Richardson LOG("src = '%s', strlen(src) = %zu\n", src, strlen(src));
146*a9de470cSBruce Richardson LOG("---\n");
147*a9de470cSBruce Richardson
148*a9de470cSBruce Richardson for (i = 0; i < BUF_LEN; i++) {
149*a9de470cSBruce Richardson /* initialize destination buffers */
150*a9de470cSBruce Richardson memcpy(bsd_dst, dst, BUF_LEN);
151*a9de470cSBruce Richardson memcpy(rte_dst, dst, BUF_LEN);
152*a9de470cSBruce Richardson /* compare implementations */
153*a9de470cSBruce Richardson bsd_ret = strlcat(bsd_dst, src, i);
154*a9de470cSBruce Richardson rte_ret = rte_strlcat(rte_dst, src, i);
155*a9de470cSBruce Richardson if (bsd_ret != rte_ret) {
156*a9de470cSBruce Richardson LOG("Incorrect retval for buf length = %zu\n", i);
157*a9de470cSBruce Richardson LOG("BSD: '%zu', rte: '%zu'\n", bsd_ret, rte_ret);
158*a9de470cSBruce Richardson return -1;
159*a9de470cSBruce Richardson }
160*a9de470cSBruce Richardson if (memcmp(bsd_dst, rte_dst, BUF_LEN) != 0) {
161*a9de470cSBruce Richardson LOG("Resulting buffers don't match\n");
162*a9de470cSBruce Richardson LOG("BSD: '%s', rte: '%s'\n", bsd_dst, rte_dst);
163*a9de470cSBruce Richardson return -1;
164*a9de470cSBruce Richardson }
165*a9de470cSBruce Richardson LOG("buffer size = %zu: dst = '%s', ret = %zu\n",
166*a9de470cSBruce Richardson i, rte_dst, rte_ret);
167*a9de470cSBruce Richardson }
168*a9de470cSBruce Richardson LOG("Checked %zu combinations\n", i);
169*a9de470cSBruce Richardson #undef BUF_LEN
170*a9de470cSBruce Richardson #endif /* defined(__BSD_VISIBLE) || defined(RTE_USE_LIBBSD) */
171*a9de470cSBruce Richardson
172*a9de470cSBruce Richardson return 0;
173*a9de470cSBruce Richardson }
174*a9de470cSBruce Richardson
175*a9de470cSBruce Richardson static int
test_string_fns(void)176*a9de470cSBruce Richardson test_string_fns(void)
177*a9de470cSBruce Richardson {
178*a9de470cSBruce Richardson if (test_rte_strsplit() < 0)
179*a9de470cSBruce Richardson return -1;
180*a9de470cSBruce Richardson if (test_rte_strlcat() < 0)
181*a9de470cSBruce Richardson return -1;
182*a9de470cSBruce Richardson return 0;
183*a9de470cSBruce Richardson }
184*a9de470cSBruce Richardson
185*a9de470cSBruce Richardson REGISTER_TEST_COMMAND(string_autotest, test_string_fns);
186