1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Wind River Systems, Inc. 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <stdint.h> 8 #include <unistd.h> 9 10 #ifdef RTE_EXEC_ENV_WINDOWS 11 #include <io.h> 12 #endif 13 14 #include <rte_cfgfile.h> 15 16 #include "test.h" 17 18 #include "test_cfgfiles.h" 19 20 static int 21 make_tmp_file(char *filename, const char *prefix, const char *data) 22 { 23 size_t len = strlen(data); 24 size_t count; 25 FILE *f; 26 27 #ifdef RTE_EXEC_ENV_WINDOWS 28 char tempDirName[MAX_PATH - 14]; 29 30 if (GetTempPathA(sizeof(tempDirName), tempDirName) == 0) 31 return -1; 32 33 if (GetTempFileNameA(tempDirName, prefix, 0, filename) == 0) 34 return -1; 35 36 f = fopen(filename, "wt"); 37 #else 38 snprintf(filename, PATH_MAX, "/tmp/%s_XXXXXXX", prefix); 39 40 int fd = mkstemp(filename); 41 if (fd < 0) 42 return -1; 43 44 f = fdopen(fd, "w"); 45 #endif 46 if (f == NULL) 47 return -1; 48 49 count = fwrite(data, sizeof(char), len, f); 50 fclose(f); 51 52 return (count == len) ? 0 : -1; 53 } 54 55 56 static int 57 _test_cfgfile_sample(struct rte_cfgfile *cfgfile) 58 { 59 const char *value; 60 int ret; 61 62 ret = rte_cfgfile_num_sections(cfgfile, NULL, 0); 63 TEST_ASSERT(ret == 2, "Unexpected number of sections: %d", ret); 64 65 ret = rte_cfgfile_has_section(cfgfile, "section1"); 66 TEST_ASSERT(ret, "section1 section missing"); 67 68 ret = rte_cfgfile_section_num_entries(cfgfile, "section1"); 69 TEST_ASSERT(ret == 1, "section1 unexpected number of entries: %d", ret); 70 71 value = rte_cfgfile_get_entry(cfgfile, "section1", "key1"); 72 TEST_ASSERT(strcmp("value1", value) == 0, 73 "key1 unexpected value: %s", value); 74 75 ret = rte_cfgfile_has_section(cfgfile, "section2"); 76 TEST_ASSERT(ret, "section2 section missing"); 77 78 ret = rte_cfgfile_section_num_entries(cfgfile, "section2"); 79 TEST_ASSERT(ret == 2, "section2 unexpected number of entries: %d", ret); 80 81 value = rte_cfgfile_get_entry(cfgfile, "section2", "key2"); 82 TEST_ASSERT(strcmp("value2", value) == 0, 83 "key2 unexpected value: %s", value); 84 85 value = rte_cfgfile_get_entry(cfgfile, "section2", "key3"); 86 TEST_ASSERT(strcmp("value3", value) == 0, 87 "key3 unexpected value: %s", value); 88 89 return 0; 90 } 91 92 static int 93 test_cfgfile_sample1(void) 94 { 95 struct rte_cfgfile *cfgfile; 96 char filename[PATH_MAX]; 97 int ret; 98 99 ret = make_tmp_file(filename, "sample1", sample1_ini); 100 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 101 102 cfgfile = rte_cfgfile_load(filename, 0); 103 TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file"); 104 105 ret = _test_cfgfile_sample(cfgfile); 106 TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret); 107 108 ret = rte_cfgfile_close(cfgfile); 109 TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile"); 110 111 ret = remove(filename); 112 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 113 114 return 0; 115 } 116 117 static int 118 test_cfgfile_sample2(void) 119 { 120 struct rte_cfgfile_parameters params; 121 struct rte_cfgfile *cfgfile; 122 char filename[PATH_MAX]; 123 int ret; 124 125 ret = make_tmp_file(filename, "sample2", sample2_ini); 126 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 127 128 /* override comment character */ 129 memset(¶ms, 0, sizeof(params)); 130 params.comment_character = '#'; 131 132 cfgfile = rte_cfgfile_load_with_params(filename, 0, ¶ms); 133 TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2"); 134 135 ret = _test_cfgfile_sample(cfgfile); 136 TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret); 137 138 ret = rte_cfgfile_close(cfgfile); 139 TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile"); 140 141 ret = remove(filename); 142 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 143 144 return 0; 145 } 146 147 static int 148 test_cfgfile_realloc_sections(void) 149 { 150 struct rte_cfgfile *cfgfile; 151 char filename[PATH_MAX]; 152 int ret; 153 const char *value; 154 155 ret = make_tmp_file(filename, "realloc", realloc_sections_ini); 156 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 157 158 cfgfile = rte_cfgfile_load(filename, 0); 159 TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file"); 160 161 ret = rte_cfgfile_num_sections(cfgfile, NULL, 0); 162 TEST_ASSERT(ret == 9, "Unexpected number of sections: %d", ret); 163 164 ret = rte_cfgfile_has_section(cfgfile, "section9"); 165 TEST_ASSERT(ret, "section9 missing"); 166 167 ret = rte_cfgfile_section_num_entries(cfgfile, "section3"); 168 TEST_ASSERT(ret == 21, 169 "section3 unexpected number of entries: %d", ret); 170 171 ret = rte_cfgfile_section_num_entries(cfgfile, "section9"); 172 TEST_ASSERT(ret == 8, "section9 unexpected number of entries: %d", ret); 173 174 value = rte_cfgfile_get_entry(cfgfile, "section9", "key8"); 175 TEST_ASSERT(strcmp("value8_section9", value) == 0, 176 "key unexpected value: %s", value); 177 178 ret = remove(filename); 179 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 180 181 char tmp[PATH_MAX] = "/tmp/"; 182 #ifdef RTE_EXEC_ENV_WINDOWS 183 ret = GetTempPathA(sizeof(tmp), tmp); 184 TEST_ASSERT(ret > 0, "Failed to get tmp directory"); 185 #endif 186 snprintf(filename, sizeof(filename), "%s%s", tmp, "cfg_save.ini"); 187 188 ret = rte_cfgfile_save(cfgfile, filename); 189 TEST_ASSERT_SUCCESS(ret, "Failed to save to %s", filename); 190 191 ret = remove(filename); 192 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 193 194 ret = rte_cfgfile_close(cfgfile); 195 TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile"); 196 197 return 0; 198 } 199 200 static int 201 test_cfgfile_invalid_section_header(void) 202 { 203 struct rte_cfgfile *cfgfile; 204 char filename[PATH_MAX]; 205 int ret; 206 207 ret = make_tmp_file(filename, "invalid", invalid_section_ini); 208 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 209 210 cfgfile = rte_cfgfile_load(filename, 0); 211 TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur"); 212 213 ret = remove(filename); 214 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 215 216 return 0; 217 } 218 219 static int 220 test_cfgfile_invalid_comment(void) 221 { 222 struct rte_cfgfile_parameters params; 223 struct rte_cfgfile *cfgfile; 224 char filename[PATH_MAX]; 225 int ret; 226 227 /* override comment character with an invalid one */ 228 memset(¶ms, 0, sizeof(params)); 229 params.comment_character = '$'; 230 231 ret = make_tmp_file(filename, "sample2", sample2_ini); 232 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 233 234 cfgfile = rte_cfgfile_load_with_params(filename, 0, ¶ms); 235 TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur"); 236 237 ret = remove(filename); 238 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 239 240 return 0; 241 } 242 243 static int 244 test_cfgfile_invalid_key_value_pair(void) 245 { 246 struct rte_cfgfile *cfgfile; 247 char filename[PATH_MAX]; 248 int ret; 249 250 ret = make_tmp_file(filename, "empty_key", empty_key_value_ini); 251 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 252 253 cfgfile = rte_cfgfile_load(filename, 0); 254 TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur"); 255 256 ret = remove(filename); 257 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 258 259 return 0; 260 } 261 262 static int 263 test_cfgfile_empty_key_value_pair(void) 264 { 265 struct rte_cfgfile *cfgfile; 266 const char *value; 267 char filename[PATH_MAX]; 268 int ret; 269 270 ret = make_tmp_file(filename, "empty_key_value", empty_key_value_ini); 271 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 272 273 cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES); 274 TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value"); 275 276 ret = rte_cfgfile_num_sections(cfgfile, NULL, 0); 277 TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret); 278 279 ret = rte_cfgfile_has_section(cfgfile, "section1"); 280 TEST_ASSERT(ret, "section1 missing"); 281 282 ret = rte_cfgfile_section_num_entries(cfgfile, "section1"); 283 TEST_ASSERT(ret == 1, "section1 unexpected number of entries: %d", ret); 284 285 value = rte_cfgfile_get_entry(cfgfile, "section1", "key"); 286 TEST_ASSERT(strlen(value) == 0, "key unexpected value: %s", value); 287 288 ret = rte_cfgfile_close(cfgfile); 289 TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile"); 290 291 ret = remove(filename); 292 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 293 294 return 0; 295 } 296 297 static int 298 test_cfgfile_missing_section(void) 299 { 300 struct rte_cfgfile *cfgfile; 301 char filename[PATH_MAX]; 302 int ret; 303 304 ret = make_tmp_file(filename, "missing_section", missing_section_ini); 305 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 306 307 cfgfile = rte_cfgfile_load(filename, 0); 308 TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur"); 309 310 ret = remove(filename); 311 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 312 313 return 0; 314 } 315 316 static int 317 test_cfgfile_global_properties(void) 318 { 319 struct rte_cfgfile *cfgfile; 320 const char *value; 321 char filename[PATH_MAX]; 322 int ret; 323 324 ret = make_tmp_file(filename, "missing_section", missing_section_ini); 325 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 326 327 cfgfile = rte_cfgfile_load(filename, CFG_FLAG_GLOBAL_SECTION); 328 TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file"); 329 330 ret = rte_cfgfile_num_sections(cfgfile, NULL, 0); 331 TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret); 332 333 ret = rte_cfgfile_has_section(cfgfile, "GLOBAL"); 334 TEST_ASSERT(ret, "global section missing"); 335 336 ret = rte_cfgfile_section_num_entries(cfgfile, "GLOBAL"); 337 TEST_ASSERT(ret == 1, "GLOBAL unexpected number of entries: %d", ret); 338 339 value = rte_cfgfile_get_entry(cfgfile, "GLOBAL", "key"); 340 TEST_ASSERT(strcmp("value", value) == 0, 341 "key unexpected value: %s", value); 342 343 ret = rte_cfgfile_close(cfgfile); 344 TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile"); 345 346 ret = remove(filename); 347 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 348 349 return 0; 350 } 351 352 static int 353 test_cfgfile_empty_file(void) 354 { 355 struct rte_cfgfile *cfgfile; 356 char filename[PATH_MAX]; 357 int ret; 358 359 ret = make_tmp_file(filename, "empty", empty_ini); 360 TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file"); 361 362 cfgfile = rte_cfgfile_load(filename, 0); 363 TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file"); 364 365 ret = rte_cfgfile_num_sections(cfgfile, NULL, 0); 366 TEST_ASSERT(ret == 0, "Unexpected number of sections: %d", ret); 367 368 ret = rte_cfgfile_close(cfgfile); 369 TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile"); 370 371 ret = remove(filename); 372 TEST_ASSERT_SUCCESS(ret, "Failed to remove file"); 373 374 return 0; 375 } 376 377 static struct 378 unit_test_suite test_cfgfile_suite = { 379 .suite_name = "Test Cfgfile Unit Test Suite", 380 .unit_test_cases = { 381 TEST_CASE(test_cfgfile_sample1), 382 TEST_CASE(test_cfgfile_sample2), 383 TEST_CASE(test_cfgfile_realloc_sections), 384 TEST_CASE(test_cfgfile_invalid_section_header), 385 TEST_CASE(test_cfgfile_invalid_comment), 386 TEST_CASE(test_cfgfile_invalid_key_value_pair), 387 TEST_CASE(test_cfgfile_empty_key_value_pair), 388 TEST_CASE(test_cfgfile_missing_section), 389 TEST_CASE(test_cfgfile_global_properties), 390 TEST_CASE(test_cfgfile_empty_file), 391 392 TEST_CASES_END() 393 } 394 }; 395 396 static int 397 test_cfgfile(void) 398 { 399 return unit_test_suite_runner(&test_cfgfile_suite); 400 } 401 402 REGISTER_FAST_TEST(cfgfile_autotest, true, true, test_cfgfile); 403