1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stdio.h> 35 #include <stdarg.h> 36 #include <stddef.h> 37 #include <errno.h> 38 #include <string.h> 39 40 #include <rte_string_fns.h> 41 42 #include "test.h" 43 44 #define LOG(...) do {\ 45 fprintf(stderr, "%s() ln %d: ", __func__, __LINE__); \ 46 fprintf(stderr, __VA_ARGS__); \ 47 } while(0) 48 49 #define DATA_BYTE 'a' 50 51 static int 52 test_rte_snprintf(void) 53 { 54 /* ================================================= 55 * First test with a string that will fit in buffer 56 * =================================================*/ 57 do { 58 int retval; 59 const char source[] = "This is a string that will fit in buffer"; 60 char buf[sizeof(source)+2]; /* make buffer big enough to fit string */ 61 62 /* initialise buffer with characters so it can contain no nulls */ 63 memset(buf, DATA_BYTE, sizeof(buf)); 64 65 /* run rte_snprintf and check results */ 66 retval = rte_snprintf(buf, sizeof(buf), "%s", source); 67 if (retval != sizeof(source) - 1) { 68 LOG("Error, retval = %d, expected = %u\n", 69 retval, (unsigned)sizeof(source)); 70 return -1; 71 } 72 if (buf[retval] != '\0') { 73 LOG("Error, resultant is not null-terminated\n"); 74 return -1; 75 } 76 if (memcmp(source, buf, sizeof(source)-1) != 0){ 77 LOG("Error, corrupt data in buffer\n"); 78 return -1; 79 } 80 } while (0); 81 82 do { 83 /* ================================================= 84 * Test with a string that will get truncated 85 * =================================================*/ 86 int retval; 87 const char source[] = "This is a long string that won't fit in buffer"; 88 char buf[sizeof(source)/2]; /* make buffer half the size */ 89 90 /* initialise buffer with characters so it can contain no nulls */ 91 memset(buf, DATA_BYTE, sizeof(buf)); 92 93 /* run rte_snprintf and check results */ 94 retval = rte_snprintf(buf, sizeof(buf), "%s", source); 95 if (retval != sizeof(source) - 1) { 96 LOG("Error, retval = %d, expected = %u\n", 97 retval, (unsigned)sizeof(source)); 98 return -1; 99 } 100 if (buf[sizeof(buf)-1] != '\0') { 101 LOG("Error, buffer is not null-terminated\n"); 102 return -1; 103 } 104 if (memcmp(source, buf, sizeof(buf)-1) != 0){ 105 LOG("Error, corrupt data in buffer\n"); 106 return -1; 107 } 108 } while (0); 109 110 do { 111 /* =========================================================== 112 * Test using zero-size buf to check how long a buffer we need 113 * ===========================================================*/ 114 int retval; 115 const char source[] = "This is a string"; 116 char buf[10]; 117 118 /* call with a zero-sized non-NULL buffer, should tell how big a buffer 119 * we need */ 120 retval = rte_snprintf(buf, 0, "%s", source); 121 if (retval != sizeof(source) - 1) { 122 LOG("Call with 0-length buffer does not return correct size." 123 "Expected: %zu, got: %d\n", sizeof(source), retval); 124 return -1; 125 } 126 127 /* call with a zero-sized NULL buffer, should tell how big a buffer 128 * we need */ 129 retval = rte_snprintf(NULL, 0, "%s", source); 130 if (retval != sizeof(source) - 1) { 131 LOG("Call with 0-length buffer does not return correct size." 132 "Expected: %zu, got: %d\n", sizeof(source), retval); 133 return -1; 134 } 135 136 } while (0); 137 138 do { 139 /* ================================================= 140 * Test with invalid parameter values 141 * =================================================*/ 142 const char source[] = "This is a string"; 143 char buf[10]; 144 145 /* call with buffer value set to NULL is EINVAL */ 146 if (rte_snprintf(NULL, sizeof(buf), "%s\n", source) != -1 || 147 errno != EINVAL) { 148 LOG("Failed to get suitable error when passing NULL buffer\n"); 149 return -1; 150 } 151 152 memset(buf, DATA_BYTE, sizeof(buf)); 153 /* call with a NULL format and zero-size should return error 154 * without affecting the buffer */ 155 if (rte_snprintf(buf, 0, NULL) != -1 || 156 errno != EINVAL) { 157 LOG("Failed to get suitable error when passing NULL buffer\n"); 158 return -1; 159 } 160 if (buf[0] != DATA_BYTE) { 161 LOG("Error, zero-length buffer modified after call with NULL" 162 " format string\n"); 163 return -1; 164 } 165 166 /* call with a NULL format should return error but also null-terminate 167 * the buffer */ 168 if (rte_snprintf(buf, sizeof(buf), NULL) != -1 || 169 errno != EINVAL) { 170 LOG("Failed to get suitable error when passing NULL buffer\n"); 171 return -1; 172 } 173 if (buf[0] != '\0') { 174 LOG("Error, buffer not null-terminated after call with NULL" 175 " format string\n"); 176 return -1; 177 } 178 } while (0); 179 180 LOG("%s - PASSED\n", __func__); 181 return 0; 182 } 183 184 static int 185 test_rte_strsplit(void) 186 { 187 int i; 188 do { 189 /* ======================================================= 190 * split a mac address correct number of splits requested 191 * =======================================================*/ 192 char test_string[] = "54:65:76:87:98:90"; 193 char *splits[6]; 194 195 LOG("Source string: '%s', to split on ':'\n", test_string); 196 if (rte_strsplit(test_string, sizeof(test_string), 197 splits, 6, ':') != 6) { 198 LOG("Error splitting mac address\n"); 199 return -1; 200 } 201 for (i = 0; i < 6; i++) 202 LOG("Token %d = %s\n", i + 1, splits[i]); 203 } while (0); 204 205 206 do { 207 /* ======================================================= 208 * split on spaces smaller number of splits requested 209 * =======================================================*/ 210 char test_string[] = "54 65 76 87 98 90"; 211 char *splits[6]; 212 213 LOG("Source string: '%s', to split on ' '\n", test_string); 214 if (rte_strsplit(test_string, sizeof(test_string), 215 splits, 3, ' ') != 3) { 216 LOG("Error splitting mac address for max 2 splits\n"); 217 return -1; 218 } 219 for (i = 0; i < 3; i++) 220 LOG("Token %d = %s\n", i + 1, splits[i]); 221 } while (0); 222 223 do { 224 /* ======================================================= 225 * split on commas - more splits than commas requested 226 * =======================================================*/ 227 char test_string[] = "a,b,c,d"; 228 char *splits[6]; 229 230 LOG("Source string: '%s', to split on ','\n", test_string); 231 if (rte_strsplit(test_string, sizeof(test_string), 232 splits, 6, ',') != 4) { 233 LOG("Error splitting %s on ','\n", test_string); 234 return -1; 235 } 236 for (i = 0; i < 4; i++) 237 LOG("Token %d = %s\n", i + 1, splits[i]); 238 } while(0); 239 240 do { 241 /* ======================================================= 242 * Try splitting on non-existent character. 243 * =======================================================*/ 244 char test_string[] = "a,b,c,d"; 245 char *splits[6]; 246 247 LOG("Source string: '%s', to split on ' '\n", test_string); 248 if (rte_strsplit(test_string, sizeof(test_string), 249 splits, 6, ' ') != 1) { 250 LOG("Error splitting %s on ' '\n", test_string); 251 return -1; 252 } 253 LOG("String not split\n"); 254 } while(0); 255 256 do { 257 /* ======================================================= 258 * Invalid / edge case parameter checks 259 * =======================================================*/ 260 char test_string[] = "a,b,c,d"; 261 char *splits[6]; 262 263 if (rte_strsplit(NULL, 0, splits, 6, ',') >= 0 264 || errno != EINVAL){ 265 LOG("Error: rte_strsplit accepted NULL string parameter\n"); 266 return -1; 267 } 268 269 if (rte_strsplit(test_string, sizeof(test_string), NULL, 0, ',') >= 0 270 || errno != EINVAL){ 271 LOG("Error: rte_strsplit accepted NULL array parameter\n"); 272 return -1; 273 } 274 275 errno = 0; 276 if (rte_strsplit(test_string, 0, splits, 6, ',') != 0 || errno != 0) { 277 LOG("Error: rte_strsplit did not accept 0 length string\n"); 278 return -1; 279 } 280 281 if (rte_strsplit(test_string, sizeof(test_string), splits, 0, ',') != 0 282 || errno != 0) { 283 LOG("Error: rte_strsplit did not accept 0 length array\n"); 284 return -1; 285 } 286 287 LOG("Parameter test cases passed\n"); 288 } while(0); 289 290 LOG("%s - PASSED\n", __func__); 291 return 0; 292 } 293 294 int 295 test_string_fns(void) 296 { 297 if (test_rte_snprintf() < 0 || 298 test_rte_strsplit() < 0) 299 return -1; 300 return 0; 301 } 302