UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2024 Mike Becker, Olaf Wintermann All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "cx/test.h" 30 #include "util_allocator.h" 31 32 #include "cx/properties.h" 33 #include "cx/hash_map.h" 34 35 CX_TEST(test_properties_init) { 36 CxProperties prop; 37 CX_TEST_DO { 38 cxPropertiesInitDefault(&prop); 39 40 CX_TEST_ASSERT(prop.config.delimiter == '='); 41 CX_TEST_ASSERT(prop.config.comment1 == '#'); 42 CX_TEST_ASSERT(prop.config.comment2 == 0); 43 CX_TEST_ASSERT(prop.config.comment3 == 0); 44 CX_TEST_ASSERT(prop.input.space == NULL); 45 CX_TEST_ASSERT(prop.buffer.space == NULL); 46 47 cxPropertiesDestroy(&prop); 48 } 49 } 50 51 CX_TEST(test_properties_next) { 52 const char *tests[] = { 53 "name = value\n", 54 "name=value\n", 55 "n=value\n", 56 "name=v\n", 57 "n=v\n", 58 "name = value # comment\n", 59 "#comment\nn=v\n", 60 "# comment1\n# comment2\n\n \n\nname = value\n", 61 " name = value\n", 62 "name = value\n\n" 63 }; 64 65 const char *keys[] = { 66 "name", 67 "name", 68 "n", 69 "name", 70 "n", 71 "name", 72 "n", 73 "name", 74 "name", 75 "name" 76 }; 77 78 const char *values[] = { 79 "value", 80 "value", 81 "value", 82 "v", 83 "v", 84 "value", 85 "v", 86 "value", 87 "value", 88 "value" 89 }; 90 91 CxProperties prop; 92 cxPropertiesInitDefault(&prop); 93 CxPropertiesStatus result; 94 cxstring key; 95 cxstring value; 96 CX_TEST_DO { 97 for (int i = 0; i < 10; i++) { 98 cxPropertiesFill(&prop, tests[i]); 99 CX_TEST_ASSERT(prop.input.space == tests[i]); 100 CX_TEST_ASSERT(prop.input.size == strlen(tests[i])); 101 CX_TEST_ASSERT(prop.input.pos == 0); 102 103 result = cxPropertiesNext(&prop, &key, &value); 104 cxstring k = cx_str(keys[i]); 105 cxstring v = cx_str(values[i]); 106 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 107 CX_TEST_ASSERT(0 == cx_strcmp(key, k)); 108 CX_TEST_ASSERT(0 == cx_strcmp(value, v)); 109 110 result = cxPropertiesNext(&prop, &key, &value); 111 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); 112 } 113 } 114 cxPropertiesDestroy(&prop); 115 } 116 117 CX_TEST_SUBROUTINE(test_properties_next_multi_check, CxProperties *prop) { 118 const char *keys[] = { 119 "a", 120 "b", 121 "c", 122 "uap", 123 "name", 124 "key1", 125 "key2", 126 "key3" 127 }; 128 129 const char *values[] = { 130 "a value", 131 "b value", 132 "core", 133 "core", 134 "ucx", 135 "value1", 136 "value2", 137 "value3" 138 }; 139 CxPropertiesStatus result; 140 cxstring key; 141 cxstring value; 142 for (int i = 0; i < 8; i++) { 143 result = cxPropertiesNext(prop, &key, &value); 144 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 145 CX_TEST_ASSERT(!cx_strcmp(key, cx_str(keys[i]))); 146 CX_TEST_ASSERT(!cx_strcmp(value, cx_str(values[i]))); 147 } 148 result = cxPropertiesNext(prop, &key, &value); 149 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); 150 } 151 152 CX_TEST(test_properties_next_multi) { 153 const char *str = "#\n" 154 "# properties\n" 155 "# contains key/value pairs\n" 156 "#\n" 157 "a = a value\n" 158 "b = b value\n" 159 "c = core\n" 160 "\n# test\n" 161 "uap = core\n" 162 "name = ucx\n" 163 "# no = property\n" 164 "key1 = value1\n" 165 "#key1 = wrong value\n" 166 "#key2 = not value 2\n" 167 "key2 = value2\n" 168 "\n\n\n \n key3=value3\n"; 169 170 CxProperties prop; 171 cxPropertiesInitDefault(&prop); 172 173 CX_TEST_DO { 174 CxPropertiesStatus result; 175 cxstring key; 176 cxstring value; 177 result = cxPropertiesNext(&prop, &key, &value); 178 CX_TEST_ASSERT(result == CX_PROPERTIES_NULL_INPUT); 179 180 // check for C string 181 cxPropertiesFill(&prop, str); 182 CX_TEST_CALL_SUBROUTINE(test_properties_next_multi_check, &prop); 183 184 // check for cxstring 185 cxPropertiesFill(&prop, cx_str(str)); 186 CX_TEST_CALL_SUBROUTINE(test_properties_next_multi_check, &prop); 187 188 // check for mutstr 189 cxPropertiesFill(&prop, cx_mutstr((char*)str)); 190 CX_TEST_CALL_SUBROUTINE(test_properties_next_multi_check, &prop); 191 } 192 cxPropertiesDestroy(&prop); 193 } 194 195 CX_TEST(test_properties_next_part) { 196 CxProperties prop; 197 cxPropertiesInitDefault(&prop); 198 CxPropertiesStatus result; 199 cxstring key; 200 cxstring value; 201 const char *str; 202 203 CX_TEST_DO { 204 str = ""; 205 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 206 result = cxPropertiesNext(&prop, &key, &value); 207 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); 208 209 str = " \n"; 210 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 211 result = cxPropertiesNext(&prop, &key, &value); 212 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); 213 214 str = "name"; 215 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 216 result = cxPropertiesNext(&prop, &key, &value); 217 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 218 219 str = " "; 220 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 221 result = cxPropertiesNext(&prop, &key, &value); 222 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 223 224 // call fill twice in a row 225 str = "= "; 226 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 227 str = "value"; 228 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 229 result = cxPropertiesNext(&prop, &key, &value); 230 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 231 232 str = "\n"; 233 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 234 result = cxPropertiesNext(&prop, &key, &value); 235 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 236 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("name"))); 237 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("value"))); 238 239 // second round 240 str = "#comment\n"; 241 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 242 result = cxPropertiesNext(&prop, &key, &value); 243 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); 244 245 str = "#comment\nname2 = "; 246 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 247 result = cxPropertiesNext(&prop, &key, &value); 248 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 249 250 str = "value2\na = b\n"; 251 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 252 result = cxPropertiesNext(&prop, &key, &value); 253 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 254 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("name2"))); 255 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("value2"))); 256 257 result = cxPropertiesNext(&prop, &key, &value); 258 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 259 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("a"))); 260 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("b"))); 261 262 str = "# comment\n#\n#\ntests = "; 263 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 264 result = cxPropertiesNext(&prop, &key, &value); 265 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 266 267 str = "test1 "; 268 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 269 result = cxPropertiesNext(&prop, &key, &value); 270 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 271 272 str = "test2 test3 test4\n"; 273 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 274 result = cxPropertiesNext(&prop, &key, &value); 275 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 276 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("tests"))); 277 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("test1 test2 test3 test4"))); 278 279 // test if cxPropertiesNext finds a name/value after a comment 280 str = "# just a comment"; 281 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 282 result = cxPropertiesNext(&prop, &key, &value); 283 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 284 285 str = " in 3"; 286 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 287 result = cxPropertiesNext(&prop, &key, &value); 288 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 289 290 str = " parts\nx = 1\n"; 291 CX_TEST_ASSERT(0 == cxPropertiesFill(&prop, str)); 292 result = cxPropertiesNext(&prop, &key, &value); 293 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 294 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("x"))); 295 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("1"))); 296 297 // finally we are done 298 result = cxPropertiesNext(&prop, &key, &value); 299 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); 300 } 301 cxPropertiesDestroy(&prop); 302 } 303 304 CX_TEST(test_properties_next_long_lines) { 305 CxProperties prop; 306 cxPropertiesInitDefault(&prop); 307 CxPropertiesStatus result; 308 cxstring key; 309 cxstring value; 310 311 size_t key_len = 512; 312 char *long_key = (char*)malloc(key_len); 313 memset(long_key, 'a', 70); 314 memset(long_key + 70, 'b', 242); 315 memset(long_key + 312, 'c', 200); 316 317 size_t value_len = 2048; 318 char *long_value = (char*)malloc(value_len); 319 memset(long_value, 'x', 1024); 320 memset(long_value+1024, 'y', 1024); 321 322 CX_TEST_DO { 323 cxPropertiesFilln(&prop, long_key, 10); 324 result = cxPropertiesNext(&prop, &key, &value); 325 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 326 327 cxPropertiesFilln(&prop, long_key + 10, 202); 328 result = cxPropertiesNext(&prop, &key, &value); 329 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 330 331 cxPropertiesFilln(&prop, long_key + 212, 200); 332 result = cxPropertiesNext(&prop, &key, &value); 333 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 334 335 cxPropertiesFilln(&prop, long_key + 412, 100); 336 result = cxPropertiesNext(&prop, &key, &value); 337 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 338 339 const char *str = " = "; 340 cxPropertiesFill(&prop, str); 341 result = cxPropertiesNext(&prop, &key, &value); 342 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 343 344 cxPropertiesFilln(&prop, long_value, 512); 345 result = cxPropertiesNext(&prop, &key, &value); 346 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 347 348 cxPropertiesFilln(&prop, long_value + 512, 1024); 349 result = cxPropertiesNext(&prop, &key, &value); 350 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 351 352 cxPropertiesFilln(&prop, long_value + 1536, 512); 353 result = cxPropertiesNext(&prop, &key, &value); 354 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 355 356 str = "\n#comment\nkey = value\n"; 357 cxPropertiesFill(&prop, str); 358 result = cxPropertiesNext(&prop, &key, &value); 359 cxstring k = cx_strn(long_key, key_len); 360 cxstring v = cx_strn(long_value, value_len); 361 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 362 CX_TEST_ASSERT(0 == cx_strcmp(key, k)); 363 CX_TEST_ASSERT(0 == cx_strcmp(value, v)); 364 365 result = cxPropertiesNext(&prop, &key, &value); 366 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 367 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("key"))); 368 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("value"))); 369 370 result = cxPropertiesNext(&prop, &key, &value); 371 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); 372 373 CX_TEST_ASSERT(prop.buffer.capacity > 0); 374 CX_TEST_ASSERT(cxBufferEof(&prop.buffer)); 375 CX_TEST_ASSERT(cxBufferEof(&prop.input)); 376 cxPropertiesDestroy(&prop); 377 CX_TEST_ASSERT(prop.buffer.capacity == 0); 378 CX_TEST_ASSERT(prop.buffer.size == 0); 379 CX_TEST_ASSERT(prop.buffer.pos == 0); 380 } 381 382 free(long_key); 383 free(long_value); 384 } 385 386 CX_TEST(test_properties_load) { 387 CxTestingAllocator talloc; 388 cx_testing_allocator_init(&talloc); 389 char fname[16] = "ucxtestXXXXXX"; 390 int tmpfd = mkstemp(fname); 391 FILE *f = tmpfd < 0 ? NULL : fdopen(tmpfd, "w"); 392 CX_TEST_DO { 393 CX_TEST_ASSERTM(f, "test file cannot be opened, test aborted"); 394 fprintf(f, "# properties file\n\nkey1 = value1\nkey2 = value2\n"); 395 fprintf(f, "\n\nkey3 = value3\n\n"); 396 397 size_t key_len = 512; 398 char *long_key = (char *) malloc(key_len); 399 memset(long_key, 'k', 512); 400 401 size_t value_len = 2048; 402 char *long_value = (char *) malloc(value_len); 403 memset(long_value, 'v', 2048); 404 405 fwrite(long_key, 1, key_len, f); 406 fprintf(f, " = "); 407 fwrite(long_value, 1, value_len, f); 408 fprintf(f, " \n"); 409 410 fprintf(f, "\n\n\n\nlast_key = property value\n"); 411 fclose(f); 412 f = NULL; 413 // preparation of test file complete 414 415 // we want to load the properties into a map of char* pointers 416 CxMap *map = cxHashMapCreateSimple(CX_STORE_POINTERS); 417 cxDefineAdvancedDestructor(map, cxFree, &talloc); 418 CxPropertiesStatus status = cxPropertiesLoadDefault(&talloc.base, fname, map); 419 420 CX_TEST_ASSERT(status == CX_PROPERTIES_NO_ERROR); 421 CX_TEST_ASSERT(cxMapSize(map) == 5); 422 423 char *v1 = cxMapGet(map, "key1"); 424 char *v2 = cxMapGet(map, cx_str("key2")); 425 char *v3 = cxMapGet(map, "key3"); 426 char *lv = cxMapGet(map, cx_strn(long_key, key_len)); 427 char *lk = cxMapGet(map, "last_key"); 428 429 CX_TEST_ASSERTM(v1, "value for key1 not found"); 430 CX_TEST_ASSERTM(v2, "value for key2 not found"); 431 CX_TEST_ASSERTM(v3, "value for key3 not found"); 432 CX_TEST_ASSERTM(lv, "value for long key not found"); 433 CX_TEST_ASSERTM(lk, "value for last_key not found"); 434 435 CX_TEST_ASSERT(!strcmp(v1, "value1")); 436 CX_TEST_ASSERT(!strcmp(v2, "value2")); 437 CX_TEST_ASSERT(!strcmp(v3, "value3")); 438 cxstring expected = cx_strn(long_value, value_len); 439 cxstring actual = cx_str(lv); 440 CX_TEST_ASSERT(!cx_strcmp(expected, actual)); 441 CX_TEST_ASSERT(!strcmp(lk, "property value")); 442 443 free(long_key); 444 free(long_value); 445 CX_TEST_ASSERT(cx_testing_allocator_used(&talloc)); 446 cxMapFree(map); 447 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 448 } 449 cx_testing_allocator_destroy(&talloc); 450 if (f) fclose(f); 451 remove(fname); 452 } 453 454 CX_TEST(test_properties_multiple_fill) { 455 const char *props1 = "key1 = value1\n"; 456 const char *props2 = "key2 = value2\n"; 457 const char *props3 = "key3 = value3\n"; 458 459 CxProperties prop; 460 cxPropertiesInitDefault(&prop); 461 CxPropertiesStatus result; 462 cxstring key; 463 cxstring value; 464 CX_TEST_DO { 465 cxPropertiesFill(&prop, props1); 466 cxPropertiesFill(&prop, props2); 467 cxPropertiesFill(&prop, props3); 468 result = cxPropertiesNext(&prop, &key, &value); 469 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 470 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("key1"))); 471 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("value1"))); 472 result = cxPropertiesNext(&prop, &key, &value); 473 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 474 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("key2"))); 475 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("value2"))); 476 result = cxPropertiesNext(&prop, &key, &value); 477 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 478 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("key3"))); 479 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("value3"))); 480 481 result = cxPropertiesNext(&prop, &key, &value); 482 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); 483 } 484 cxPropertiesDestroy(&prop); 485 } 486 487 CX_TEST(test_properties_use_stack) { 488 const char *props1 = "key1 = val"; 489 const char *props2 = "ue1\nkey2 = value2"; 490 const char *props3 = "\nkey3 = value3\n"; 491 char stackmem[16]; 492 493 CxProperties prop; 494 cxPropertiesInitDefault(&prop); 495 cxPropertiesUseStack(&prop, stackmem, 16); 496 CxPropertiesStatus result; 497 cxstring key; 498 cxstring value; 499 CX_TEST_DO { 500 cxPropertiesFill(&prop, props1); 501 result = cxPropertiesNext(&prop, &key, &value); 502 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 503 cxPropertiesFill(&prop, props2); 504 result = cxPropertiesNext(&prop, &key, &value); 505 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 506 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("key1"))); 507 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("value1"))); 508 result = cxPropertiesNext(&prop, &key, &value); 509 CX_TEST_ASSERT(result == CX_PROPERTIES_INCOMPLETE_DATA); 510 cxPropertiesFill(&prop, props3); 511 result = cxPropertiesNext(&prop, &key, &value); 512 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 513 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("key2"))); 514 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("value2"))); 515 result = cxPropertiesNext(&prop, &key, &value); 516 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 517 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("key3"))); 518 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("value3"))); 519 result = cxPropertiesNext(&prop, &key, &value); 520 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_DATA); 521 } 522 cxPropertiesDestroy(&prop); 523 } 524 525 CX_TEST(test_properties_empty_key) { 526 const char *fail1 = "= val\n"; 527 const char *fail2 = " = val\n"; 528 const char *good = " key = val\n"; 529 530 CxProperties prop; 531 CxPropertiesStatus result; 532 cxstring key; 533 cxstring value; 534 CX_TEST_DO { 535 cxPropertiesInitDefault(&prop); 536 cxPropertiesFill(&prop, fail1); 537 result = cxPropertiesNext(&prop, &key, &value); 538 CX_TEST_ASSERT(result == CX_PROPERTIES_INVALID_EMPTY_KEY); 539 cxPropertiesReset(&prop); 540 cxPropertiesFill(&prop, fail2); 541 result = cxPropertiesNext(&prop, &key, &value); 542 CX_TEST_ASSERT(result == CX_PROPERTIES_INVALID_EMPTY_KEY); 543 cxPropertiesReset(&prop); 544 cxPropertiesFill(&prop, good); 545 result = cxPropertiesNext(&prop, &key, &value); 546 CX_TEST_ASSERT(result == CX_PROPERTIES_NO_ERROR); 547 CX_TEST_ASSERT(0 == cx_strcmp(key, cx_str("key"))); 548 CX_TEST_ASSERT(0 == cx_strcmp(value, cx_str("val"))); 549 cxPropertiesDestroy(&prop); 550 } 551 } 552 553 CxTestSuite *cx_test_suite_properties(void) { 554 CxTestSuite *suite = cx_test_suite_new("properties"); 555 556 cx_test_register(suite, test_properties_init); 557 cx_test_register(suite, test_properties_next); 558 cx_test_register(suite, test_properties_next_multi); 559 cx_test_register(suite, test_properties_next_part); 560 cx_test_register(suite, test_properties_next_long_lines); 561 cx_test_register(suite, test_properties_load); 562 // TODO: test_properties_load_empty_file 563 // TODO: test_properties_load_invalid_key 564 // TODO: test_properties_load_missing_delimiter 565 // TODO: test_properties_load_unexpected_end 566 // TODO: test_properties_load_file_not_exists 567 // TODO: test_properties_load_exceed_stack 568 // TODO: test_properties_load_incompatible_map 569 cx_test_register(suite, test_properties_multiple_fill); 570 cx_test_register(suite, test_properties_use_stack); 571 cx_test_register(suite, test_properties_empty_key); 572 573 return suite; 574 } 575