| 381 |
381 |
| 382 free(long_key); |
382 free(long_key); |
| 383 free(long_value); |
383 free(long_value); |
| 384 } |
384 } |
| 385 |
385 |
| 386 CX_TEST(test_properties_load_string_to_map) { |
386 CX_TEST(test_properties_load) { |
| 387 CxTestingAllocator talloc; |
387 char fname[16] = "ucxtestXXXXXX"; |
| 388 cx_testing_allocator_init(&talloc); |
388 int tmpfd = mkstemp(fname); |
| 389 CxAllocator *alloc = &talloc.base; |
389 FILE *f = tmpfd < 0 ? NULL : fdopen(tmpfd, "w"); |
| 390 CX_TEST_DO { |
390 CX_TEST_DO { |
| 391 char buffer[512]; |
|
| 392 CxProperties prop; |
|
| 393 cxPropertiesInitDefault(&prop); |
|
| 394 cxPropertiesUseStack(&prop, buffer, 512); |
|
| 395 |
|
| 396 const char *str = "key1 = value1\nkey2 = value2\n\n#comment\n\nkey3 = value3\n"; |
|
| 397 |
|
| 398 CxMap *map = cxHashMapCreateSimple(CX_STORE_POINTERS); |
|
| 399 cxDefineAdvancedDestructor(map, cxFree, alloc); |
|
| 400 CxPropertiesSink sink = cxPropertiesMapSink(map); |
|
| 401 sink.data = alloc; // use the testing allocator |
|
| 402 CxPropertiesSource src = cxPropertiesCstrSource(str); |
|
| 403 CxPropertiesStatus status = cxPropertiesLoad(&prop, sink, src); |
|
| 404 |
|
| 405 CX_TEST_ASSERT(status == CX_PROPERTIES_NO_ERROR); |
|
| 406 CX_TEST_ASSERT(cxMapSize(map) == 3); |
|
| 407 |
|
| 408 char *v1 = cxMapGet(map, "key1"); |
|
| 409 char *v2 = cxMapGet(map, "key2"); |
|
| 410 char *v3 = cxMapGet(map, "key3"); |
|
| 411 |
|
| 412 CX_TEST_ASSERTM(v1, "value for key1 not found"); |
|
| 413 CX_TEST_ASSERTM(v2, "value for key2 not found"); |
|
| 414 CX_TEST_ASSERTM(v3, "value for key3 not found"); |
|
| 415 |
|
| 416 CX_TEST_ASSERT(!strcmp(v1, "value1")); |
|
| 417 CX_TEST_ASSERT(!strcmp(v2, "value2")); |
|
| 418 CX_TEST_ASSERT(!strcmp(v3, "value3")); |
|
| 419 |
|
| 420 // second test |
|
| 421 cxMapClear(map); |
|
| 422 |
|
| 423 str = "\n#comment\n"; |
|
| 424 src = cxPropertiesCstrnSource(str, strlen(str)); |
|
| 425 status = cxPropertiesLoad(&prop, sink, src); |
|
| 426 |
|
| 427 CX_TEST_ASSERT(status == CX_PROPERTIES_NO_DATA); |
|
| 428 CX_TEST_ASSERT(cxMapSize(map) == 0); |
|
| 429 |
|
| 430 str = "key1 = value1\nsyntax error line\n"; |
|
| 431 src = cxPropertiesStringSource(cx_str(str)); |
|
| 432 status = cxPropertiesLoad(&prop, sink, src); |
|
| 433 |
|
| 434 CX_TEST_ASSERT(status == CX_PROPERTIES_INVALID_MISSING_DELIMITER); |
|
| 435 |
|
| 436 // the successfully read k/v-pair is in the map, nevertheless |
|
| 437 CX_TEST_ASSERT(cxMapSize(map) == 1); |
|
| 438 char *v = cxMapGet(map, "key1"); |
|
| 439 CX_TEST_ASSERT(!strcmp(v, "value1")); |
|
| 440 |
|
| 441 cxMapFree(map); |
|
| 442 cxPropertiesDestroy(&prop); |
|
| 443 |
|
| 444 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
| 445 } |
|
| 446 cx_testing_allocator_destroy(&talloc); |
|
| 447 } |
|
| 448 |
|
| 449 CX_TEST(test_properties_load_file_to_map) { |
|
| 450 CxTestingAllocator talloc; |
|
| 451 cx_testing_allocator_init(&talloc); |
|
| 452 CxAllocator *alloc = &talloc.base; |
|
| 453 CX_TEST_DO { |
|
| 454 FILE *f = tmpfile(); |
|
| 455 CX_TEST_ASSERTM(f, "test file cannot be opened, test aborted"); |
391 CX_TEST_ASSERTM(f, "test file cannot be opened, test aborted"); |
| 456 fprintf(f, "# properties file\n\nkey1 = value1\nkey2 = value2\n"); |
392 fprintf(f, "# properties file\n\nkey1 = value1\nkey2 = value2\n"); |
| 457 fprintf(f, "\n\nkey3 = value3\n\n"); |
393 fprintf(f, "\n\nkey3 = value3\n\n"); |
| 458 |
394 |
| 459 size_t key_len = 512; |
395 size_t key_len = 512; |
| 468 fprintf(f, " = "); |
404 fprintf(f, " = "); |
| 469 fwrite(long_value, 1, value_len, f); |
405 fwrite(long_value, 1, value_len, f); |
| 470 fprintf(f, " \n"); |
406 fprintf(f, " \n"); |
| 471 |
407 |
| 472 fprintf(f, "\n\n\n\nlast_key = property value\n"); |
408 fprintf(f, "\n\n\n\nlast_key = property value\n"); |
| 473 |
409 fclose(f); |
| 474 fflush(f); |
410 f = NULL; |
| 475 fseek(f, 0, SEEK_SET); |
|
| 476 |
|
| 477 // preparation of test file complete |
411 // preparation of test file complete |
| 478 |
412 |
| |
413 // we want to load the properties into a map of char* pointers |
| 479 CxMap *map = cxHashMapCreateSimple(CX_STORE_POINTERS); |
414 CxMap *map = cxHashMapCreateSimple(CX_STORE_POINTERS); |
| 480 cxDefineAdvancedDestructor(map, cxFree, alloc); |
415 cxDefineDestructor(map, cxFreeDefault); |
| 481 CxProperties prop; |
416 CxPropertiesStatus status = cxPropertiesLoadDefault(fname, map); |
| 482 cxPropertiesInitDefault(&prop); |
|
| 483 CxPropertiesSink sink = cxPropertiesMapSink(map); |
|
| 484 sink.data = alloc; // use the testing allocator |
|
| 485 CxPropertiesSource src = cxPropertiesFileSource(f, 512); |
|
| 486 CxPropertiesStatus status = cxPropertiesLoad(&prop, sink, src); |
|
| 487 fclose(f); |
|
| 488 |
417 |
| 489 CX_TEST_ASSERT(status == CX_PROPERTIES_NO_ERROR); |
418 CX_TEST_ASSERT(status == CX_PROPERTIES_NO_ERROR); |
| 490 CX_TEST_ASSERT(cxMapSize(map) == 5); |
419 CX_TEST_ASSERT(cxMapSize(map) == 5); |
| 491 |
420 |
| 492 char *v1 = cxMapGet(map, "key1"); |
421 char *v1 = cxMapGet(map, "key1"); |
| 510 CX_TEST_ASSERT(!strcmp(lk, "property value")); |
439 CX_TEST_ASSERT(!strcmp(lk, "property value")); |
| 511 |
440 |
| 512 free(long_key); |
441 free(long_key); |
| 513 free(long_value); |
442 free(long_value); |
| 514 cxMapFree(map); |
443 cxMapFree(map); |
| 515 cxPropertiesDestroy(&prop); |
444 } |
| 516 |
445 if (f) fclose(f); |
| 517 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
446 remove(fname); |
| 518 } |
|
| 519 cx_testing_allocator_destroy(&talloc); |
|
| 520 } |
|
| 521 |
|
| 522 CX_TEST(test_properties_load_incomplete) { |
|
| 523 CxTestingAllocator talloc; |
|
| 524 cx_testing_allocator_init(&talloc); |
|
| 525 CxAllocator *alloc = &talloc.base; |
|
| 526 CX_TEST_DO { |
|
| 527 char buffer[512]; |
|
| 528 CxProperties prop; |
|
| 529 cxPropertiesInitDefault(&prop); |
|
| 530 cxPropertiesUseStack(&prop, buffer, 512); |
|
| 531 |
|
| 532 CxMap *map = cxHashMapCreateSimple(CX_STORE_POINTERS); |
|
| 533 cxDefineAdvancedDestructor(map, cxFree, alloc); |
|
| 534 CxPropertiesSink sink = cxPropertiesMapSink(map); |
|
| 535 sink.data = alloc; // use the testing allocator |
|
| 536 CxPropertiesSource src = cxPropertiesCstrSource("key1 = value1\nkey2 = value2\n\n#comment\n\nkey3"); |
|
| 537 CxPropertiesStatus status = cxPropertiesLoad(&prop, sink, src); |
|
| 538 |
|
| 539 CX_TEST_ASSERT(status == CX_PROPERTIES_INCOMPLETE_DATA); |
|
| 540 CX_TEST_ASSERT(cxMapSize(map) == 2); |
|
| 541 |
|
| 542 char *v1 = cxMapGet(map, "key1"); |
|
| 543 char *v2 = cxMapGet(map, "key2"); |
|
| 544 char *v3 = cxMapGet(map, "key3"); |
|
| 545 |
|
| 546 CX_TEST_ASSERTM(v1, "value for key1 not found"); |
|
| 547 CX_TEST_ASSERTM(v2, "value for key2 not found"); |
|
| 548 CX_TEST_ASSERT(v3 == NULL); |
|
| 549 |
|
| 550 CX_TEST_ASSERT(!strcmp(v1, "value1")); |
|
| 551 CX_TEST_ASSERT(!strcmp(v2, "value2")); |
|
| 552 |
|
| 553 // provide a source with the remaining data |
|
| 554 src = cxPropertiesCstrSource(" = value3\n"); |
|
| 555 status = cxPropertiesLoad(&prop, sink, src); |
|
| 556 |
|
| 557 CX_TEST_ASSERT(status == CX_PROPERTIES_NO_ERROR); |
|
| 558 CX_TEST_ASSERT(cxMapSize(map) == 3); |
|
| 559 |
|
| 560 v1 = cxMapGet(map, "key1"); |
|
| 561 v2 = cxMapGet(map, "key2"); |
|
| 562 v3 = cxMapGet(map, "key3"); |
|
| 563 |
|
| 564 CX_TEST_ASSERTM(v1, "value for key1 not found"); |
|
| 565 CX_TEST_ASSERTM(v2, "value for key2 not found"); |
|
| 566 CX_TEST_ASSERTM(v3, "value for key3 not found"); |
|
| 567 |
|
| 568 CX_TEST_ASSERT(!strcmp(v1, "value1")); |
|
| 569 CX_TEST_ASSERT(!strcmp(v2, "value2")); |
|
| 570 CX_TEST_ASSERT(!strcmp(v3, "value3")); |
|
| 571 |
|
| 572 cxMapFree(map); |
|
| 573 cxPropertiesDestroy(&prop); |
|
| 574 |
|
| 575 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); |
|
| 576 } |
|
| 577 cx_testing_allocator_destroy(&talloc); |
|
| 578 } |
447 } |
| 579 |
448 |
| 580 CX_TEST(test_properties_multiple_fill) { |
449 CX_TEST(test_properties_multiple_fill) { |
| 581 const char *props1 = "key1 = value1\n"; |
450 const char *props1 = "key1 = value1\n"; |
| 582 const char *props2 = "key2 = value2\n"; |
451 const char *props2 = "key2 = value2\n"; |
| 682 cx_test_register(suite, test_properties_init); |
551 cx_test_register(suite, test_properties_init); |
| 683 cx_test_register(suite, test_properties_next); |
552 cx_test_register(suite, test_properties_next); |
| 684 cx_test_register(suite, test_properties_next_multi); |
553 cx_test_register(suite, test_properties_next_multi); |
| 685 cx_test_register(suite, test_properties_next_part); |
554 cx_test_register(suite, test_properties_next_part); |
| 686 cx_test_register(suite, test_properties_next_long_lines); |
555 cx_test_register(suite, test_properties_next_long_lines); |
| 687 cx_test_register(suite, test_properties_load_string_to_map); |
556 cx_test_register(suite, test_properties_load); |
| 688 cx_test_register(suite, test_properties_load_file_to_map); |
557 // TODO: test_properties_load_empty_file |
| 689 cx_test_register(suite, test_properties_load_incomplete); |
558 // TODO: test_properties_load_invalid_key |
| |
559 // TODO: test_properties_load_missing_delimiter |
| |
560 // TODO: test_properties_load_unexpected_end |
| |
561 // TODO: test_properties_load_file_not_exists |
| |
562 // TODO: test_properties_load_exceed_stack |
| |
563 // TODO: test_properties_load_incompatible_map |
| 690 cx_test_register(suite, test_properties_multiple_fill); |
564 cx_test_register(suite, test_properties_multiple_fill); |
| 691 cx_test_register(suite, test_properties_use_stack); |
565 cx_test_register(suite, test_properties_use_stack); |
| 692 cx_test_register(suite, test_properties_empty_key); |
566 cx_test_register(suite, test_properties_empty_key); |
| 693 |
567 |
| 694 return suite; |
568 return suite; |