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