Line data Source code
1 : /*
2 : INI LIBRARY
3 :
4 : Unit test for the value object.
5 :
6 : Copyright (C) Dmitri Pal <dpal@redhat.com> 2010
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "config.h"
21 : #include <errno.h> /* for errors */
22 : #include <stdint.h>
23 : #include <stdio.h>
24 : #include <string.h>
25 : #include <stdlib.h>
26 : #include <limits.h>
27 :
28 : #include "ini_valueobj.h"
29 : #include "ini_defines.h"
30 : #define TRACE_HOME
31 : #include "trace.h"
32 :
33 : #define TEST_SIZE 80
34 :
35 : int verbose = 0;
36 :
37 : #define VOOUT(foo) \
38 : do { \
39 : if (verbose) foo; \
40 : } while(0)
41 :
42 :
43 : typedef int (*test_fn)(void);
44 :
45 84 : static int create_comment(int i, struct ini_comment **ic)
46 : {
47 84 : int error = EOK;
48 84 : const char *template = ";Line 0 of the value %d";
49 : char comment[TEST_SIZE];
50 84 : struct ini_comment *new_ic = NULL;
51 :
52 : TRACE_FLOW_ENTRY();
53 :
54 84 : snprintf(comment, TEST_SIZE, template, i);
55 :
56 :
57 168 : if ((error = ini_comment_create(&new_ic)) ||
58 168 : (error = ini_comment_build(new_ic, comment)) ||
59 168 : (error = ini_comment_build(new_ic, NULL)) ||
60 168 : (error = ini_comment_build(new_ic, "#This is the second line")) ||
61 168 : (error = ini_comment_build(new_ic, ";This is the third line")) ||
62 84 : (error = ini_comment_build(new_ic, ""))) {
63 0 : printf("Failed to create comment object. Error %d.\n", error);
64 0 : ini_comment_destroy(new_ic);
65 0 : return -1;
66 : }
67 :
68 84 : *ic = new_ic;
69 :
70 : TRACE_FLOW_EXIT();
71 84 : return EOK;
72 : }
73 :
74 : /* Save value to the file */
75 : /* NOTE: might be moved into the API in future */
76 164 : static int save_value(FILE *ff, const char *key, struct value_obj *vo)
77 : {
78 :
79 164 : int error = EOK;
80 164 : struct simplebuffer *sbobj = NULL;
81 164 : uint32_t left = 0;
82 :
83 : TRACE_FLOW_ENTRY();
84 :
85 164 : error = simplebuffer_alloc(&sbobj);
86 164 : if (error) {
87 : TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error);
88 : return error;
89 : }
90 :
91 : /* Serialize */
92 164 : error = value_serialize(vo, key, sbobj);
93 164 : if (error) {
94 0 : printf("Failed to serialize a value object %d.\n", error);
95 0 : simplebuffer_free(sbobj);
96 0 : return error;
97 : }
98 :
99 : /* Add CR */
100 164 : error = simplebuffer_add_cr(sbobj);
101 164 : if (error) {
102 : TRACE_ERROR_NUMBER("Failed to add CR", error);
103 0 : simplebuffer_free(sbobj);
104 0 : return error;
105 : }
106 :
107 : /* Save */
108 164 : left = simplebuffer_get_len(sbobj);
109 492 : while (left > 0) {
110 164 : error = simplebuffer_write(fileno(ff), sbobj, &left);
111 164 : if (error) {
112 0 : printf("Failed to write value object %d.\n", error);
113 0 : simplebuffer_free(sbobj);
114 0 : return error;
115 : }
116 : }
117 :
118 164 : simplebuffer_free(sbobj);
119 :
120 : TRACE_FLOW_EXIT();
121 164 : return EOK;
122 : }
123 :
124 : /* Test to create value object using arrays */
125 1 : static int other_create_test(FILE *ff, struct value_obj **vo)
126 : {
127 1 : int error = EOK;
128 1 : struct value_obj *new_vo = NULL;
129 : struct ref_array *raw_lines;
130 : struct ref_array *raw_lengths;
131 1 : struct ini_comment *ic = NULL;
132 1 : struct ini_comment *ic2 = NULL;
133 : char *val;
134 1 : const char *vallines[] = { "Domain1,",
135 : " Domain2 ,",
136 : " Domain3 " };
137 : const char *fullstr;
138 1 : const char *expected = "Domain1, Domain2 , Domain3";
139 : int i;
140 1 : uint32_t origin = 0;
141 1 : uint32_t line = 0;
142 1 : uint32_t len = 0;
143 1 : uint32_t expected_len = 0;
144 :
145 :
146 : TRACE_FLOW_ENTRY();
147 :
148 : /* Create a pair of arrays */
149 1 : error = value_create_arrays(&raw_lines,
150 : &raw_lengths);
151 1 : if (error) {
152 0 : printf("Failed to create arrays %d.\n", error);
153 0 : return error;
154 : }
155 :
156 3 : for (i=0; i< 3; i++) {
157 3 : errno = 0;
158 3 : val = strdup(vallines[i]);
159 3 : if (val == NULL) {
160 0 : error = errno;
161 0 : printf("Failed to dup memory %d.\n", error);
162 0 : value_destroy_arrays(raw_lines,
163 : raw_lengths);
164 0 : return error;
165 : }
166 :
167 : /* Add line to the arrays */
168 6 : error = value_add_to_arrays(val,
169 3 : strlen(val),
170 : raw_lines,
171 : raw_lengths);
172 3 : if (error) {
173 0 : printf("Failed to add to arrays %d.\n", error);
174 0 : value_destroy_arrays(raw_lines,
175 : raw_lengths);
176 0 : return error;
177 : }
178 :
179 : }
180 :
181 : /* Create a comment */
182 1 : error = create_comment(1000, &ic);
183 1 : if (error) {
184 0 : printf("Failed to create comment %d.\n", error);
185 0 : value_destroy_arrays(raw_lines,
186 : raw_lengths);
187 0 : return error;
188 : }
189 :
190 : /* Create object */
191 1 : error = value_create_from_refarray(raw_lines,
192 : raw_lengths,
193 : 1,
194 : INI_VALUE_READ,
195 : 3,
196 : 70,
197 : ic,
198 : &new_vo);
199 :
200 1 : if (error) {
201 0 : printf("Failed to create comment %d.\n", error);
202 0 : value_destroy_arrays(raw_lines,
203 : raw_lengths);
204 0 : ini_comment_destroy(ic);
205 0 : return error;
206 : }
207 :
208 : /* Save value to the file */
209 1 : error = save_value(ff, "baz", new_vo);
210 1 : if (error) {
211 0 : printf("Failed to save value to file %d.\n", error);
212 0 : value_destroy(new_vo);
213 0 : return error;
214 : }
215 :
216 : /* Now do assertions and modifications to the object */
217 :
218 : /* NOTE: Below this line do not need to free arrays or comment
219 : * they became internal parts of the value object
220 : * and will be freed as a part of it.
221 : */
222 :
223 : /* Get concatenated value */
224 1 : error = value_get_concatenated(new_vo,
225 : &fullstr);
226 :
227 1 : if (error) {
228 0 : printf("Failed to get the string %d.\n", error);
229 0 : value_destroy(new_vo);
230 0 : return error;
231 : }
232 :
233 : /* Get length of the concatenated value */
234 1 : value_get_concatenated_len(new_vo, &len);
235 1 : expected_len = strlen(expected);
236 :
237 2 : if ((len != expected_len) ||
238 1 : (strncmp(fullstr, expected, expected_len + 1) != 0)) {
239 0 : printf("The expected value is different.\n");
240 0 : printf("The expected value is %s\n", expected);
241 0 : printf("The real value is %s\n", fullstr);
242 0 : printf("The expected len is %d, real %d.\n", expected_len, len);
243 0 : value_destroy(new_vo);
244 0 : return EINVAL;
245 : }
246 :
247 : /* Get value's origin */
248 1 : error = value_get_origin(new_vo, &origin);
249 1 : if (error) {
250 0 : printf("Failed to get origin %d.\n", error);
251 0 : value_destroy(new_vo);
252 0 : return error;
253 : }
254 :
255 1 : if (origin != INI_VALUE_READ) {
256 0 : printf("The expected origin is different.\n%d\n", origin);
257 0 : value_destroy(new_vo);
258 0 : return EINVAL;
259 : }
260 :
261 : /* Get value's line */
262 1 : error = value_get_line(new_vo, &line);
263 1 : if (error) {
264 0 : printf("Failed to get origin %d.\n", error);
265 0 : value_destroy(new_vo);
266 0 : return error;
267 : }
268 :
269 1 : if (line != 1) {
270 0 : printf("The expected line is different.\n%d\n", origin);
271 0 : value_destroy(new_vo);
272 0 : return EINVAL;
273 : }
274 :
275 : /* Get comment from the value */
276 1 : ic = NULL;
277 1 : error = value_extract_comment(new_vo, &ic);
278 1 : if (error) {
279 0 : printf("Failed to extract comment %d.\n", error);
280 0 : value_destroy(new_vo);
281 0 : return error;
282 : }
283 :
284 1 : if (ic == NULL) {
285 0 : printf("The expected comment to be there.\n");
286 0 : value_destroy(new_vo);
287 0 : return error;
288 : }
289 :
290 1 : VOOUT(ini_comment_print(ic, stdout));
291 :
292 : /* Get comment again */
293 1 : ic2 = NULL;
294 1 : error = value_extract_comment(new_vo, &ic2);
295 1 : if (error) {
296 0 : printf("Failed to extract comment %d.\n", error);
297 0 : value_destroy(new_vo);
298 0 : ini_comment_destroy(ic);
299 0 : return error;
300 : }
301 :
302 1 : if (ic2 != NULL) {
303 0 : printf("The expected NO comment to be there.\n");
304 0 : value_destroy(new_vo);
305 0 : ini_comment_destroy(ic);
306 : /* No free for ic2 since it is the same object */
307 :
308 : /* But this should not happen anyways -
309 : * it will be coding error.
310 : */
311 0 : return EINVAL;
312 : }
313 :
314 : /* Put comment back */
315 1 : error = value_put_comment(new_vo, ic);
316 1 : if (error) {
317 0 : printf("Failed to put comment back %d.\n", error);
318 0 : value_destroy(new_vo);
319 0 : ini_comment_destroy(ic);
320 0 : return error;
321 : }
322 :
323 : /* Save value to the file */
324 1 : error = save_value(ff, "bar", new_vo);
325 1 : if (error) {
326 0 : printf("Failed to save value to file %d.\n", error);
327 0 : value_destroy(new_vo);
328 0 : return error;
329 : }
330 :
331 1 : *vo = new_vo;
332 :
333 : TRACE_FLOW_EXIT();
334 1 : return EOK;
335 : }
336 :
337 : /* Modify the value object */
338 1 : static int modify_test(FILE *ff, struct value_obj *vo)
339 : {
340 1 : int error = EOK;
341 1 : const char *strval = "Domain100, Domain200, Domain300";
342 :
343 : TRACE_FLOW_ENTRY();
344 :
345 :
346 : /* Update key length */
347 1 : error = value_set_keylen(vo, strlen("foobar"));
348 1 : if (error) {
349 0 : printf("Failed to change key length %d.\n", error);
350 0 : return error;
351 : }
352 :
353 : /* Update value */
354 1 : error = value_update(vo,
355 : strval,
356 : strlen(strval),
357 : INI_VALUE_CREATED,
358 : 10);
359 1 : if (error) {
360 0 : printf("Failed to update value %d.\n", error);
361 0 : return error;
362 : }
363 :
364 :
365 : /* Save value to the file */
366 1 : error = save_value(ff, "foobar", vo);
367 1 : if (error) {
368 0 : printf("Failed to save value to file %d.\n", error);
369 0 : return error;
370 : }
371 :
372 : TRACE_FLOW_EXIT();
373 : return EOK;
374 : }
375 :
376 :
377 1 : static int vo_basic_test(void)
378 : {
379 1 : int error = EOK;
380 1 : const char *strvalue = "Test multi_word_value_that_will_"
381 : "be_split_between_several_lines_!";
382 :
383 : /* Other testing can be done with the following string:
384 : * const char *strvalue = "Test multi word value that "
385 : * "will be split between several lines";
386 : */
387 :
388 1 : struct value_obj *vo = NULL;
389 1 : uint32_t wrap = 0;
390 1 : struct ini_comment *ic = NULL;
391 1 : FILE *ff = NULL;
392 :
393 : TRACE_FLOW_ENTRY();
394 :
395 1 : errno = 0;
396 1 : ff = fopen("test.ini","wt");
397 1 : if (ff == NULL) {
398 0 : error = errno;
399 0 : printf("Failed to open file. Error %d.\n", error);
400 0 : return error;
401 : }
402 :
403 :
404 80 : for (wrap = 0; wrap < 80; wrap++) {
405 :
406 80 : ic = NULL;
407 80 : error = create_comment(wrap, &ic);
408 80 : if (error) {
409 0 : printf("Failed to create a new comment object %d.\n", error);
410 0 : fclose(ff);
411 0 : return error;
412 : }
413 :
414 80 : vo = NULL;
415 80 : error = value_create_new(strvalue,
416 : strlen(strvalue),
417 : INI_VALUE_CREATED,
418 : 3,
419 : wrap,
420 : ic,
421 : &vo);
422 80 : if (error) {
423 0 : printf("Failed to create a new value object %d.\n", error);
424 0 : ini_comment_destroy(ic);
425 0 : fclose(ff);
426 0 : return error;
427 : }
428 :
429 80 : error = save_value(ff, "key", vo);
430 80 : if (error) {
431 0 : printf("Failed to save value to file %d.\n", error);
432 0 : value_destroy(vo);
433 0 : fclose(ff);
434 0 : return error;
435 : }
436 :
437 80 : value_destroy(vo);
438 : }
439 :
440 1 : vo = NULL;
441 :
442 : /* Run other create test here */
443 1 : error = other_create_test(ff, &vo);
444 1 : if (error) {
445 0 : printf("Create test failed %d.\n", error);
446 0 : fclose(ff);
447 0 : return error;
448 : }
449 :
450 : /* Run modify test here */
451 1 : error = modify_test(ff, vo);
452 1 : if (error) {
453 0 : printf("Modify test failed %d.\n", error);
454 0 : fclose(ff);
455 0 : value_destroy(vo);
456 0 : return error;
457 : }
458 :
459 1 : value_destroy(vo);
460 :
461 :
462 1 : ic = NULL;
463 1 : error = create_comment(100, &ic);
464 1 : if (error) {
465 0 : printf("Failed to create a new comment object %d.\n", error);
466 0 : fclose(ff);
467 0 : return error;
468 : }
469 :
470 1 : ini_comment_print(ic, ff);
471 :
472 1 : ini_comment_destroy(ic);
473 :
474 1 : fclose(ff);
475 :
476 : TRACE_FLOW_EXIT();
477 1 : return EOK;
478 : }
479 :
480 1 : static int vo_copy_test(void)
481 : {
482 1 : int error = EOK;
483 1 : const char *strvalue = "Test multi word value that "
484 : "will be split between several lines";
485 :
486 1 : struct value_obj *vo = NULL;
487 1 : struct value_obj *vo_copy = NULL;
488 1 : uint32_t wrap = 0;
489 1 : struct ini_comment *ic = NULL;
490 1 : FILE *ff = NULL;
491 : char comment[100];
492 :
493 : TRACE_FLOW_ENTRY();
494 :
495 1 : VOOUT(printf("Copy test\n"));
496 :
497 1 : errno = 0;
498 1 : ff = fopen("test.ini","a");
499 1 : if (ff == NULL) {
500 0 : error = errno;
501 0 : printf("Failed to open file. Error %d.\n", error);
502 0 : return error;
503 : }
504 :
505 1 : error = ini_comment_create(&ic);
506 1 : if (error) {
507 0 : printf("Failed to create comment object\n");
508 0 : fclose(ff);
509 0 : return -1;
510 : }
511 :
512 1 : error = ini_comment_append(ic, "#This is a copy test!");
513 1 : if (error) {
514 0 : printf("Failed to add a line to the comment %d.\n", error);
515 0 : ini_comment_destroy(ic);
516 0 : fclose(ff);
517 0 : return error;
518 : }
519 :
520 1 : error = ini_comment_append(ic, "#Replacable comment line");
521 1 : if (error) {
522 0 : printf("Failed to add a line to the comment %d.\n", error);
523 0 : ini_comment_destroy(ic);
524 0 : fclose(ff);
525 0 : return error;
526 : }
527 :
528 1 : error = value_create_new(strvalue,
529 : strlen(strvalue),
530 : INI_VALUE_CREATED,
531 : 3,
532 : 20,
533 : ic,
534 : &vo);
535 1 : if (error) {
536 0 : printf("Failed to create a new value object %d.\n", error);
537 0 : ini_comment_destroy(ic);
538 0 : fclose(ff);
539 0 : return error;
540 : }
541 :
542 1 : error = save_value(ff, "key", vo);
543 1 : if (error) {
544 0 : printf("Failed to save value to file %d.\n", error);
545 0 : value_destroy(vo);
546 0 : fclose(ff);
547 0 : return error;
548 : }
549 :
550 80 : for (wrap = 0; wrap < 80; wrap++) {
551 :
552 : TRACE_INFO_NUMBER("Iteration:", wrap);
553 :
554 80 : vo_copy = NULL;
555 80 : error = value_copy(vo, &vo_copy);
556 80 : if (error) {
557 0 : printf("Failed to create a new value object %d.\n", error);
558 0 : value_destroy(vo);
559 0 : fclose(ff);
560 0 : return error;
561 : }
562 :
563 80 : error = value_set_boundary(vo_copy, wrap);
564 80 : if (error) {
565 0 : printf("Failed to set boundary %d.\n", error);
566 0 : value_destroy(vo);
567 0 : value_destroy(vo_copy);
568 0 : fclose(ff);
569 0 : return error;
570 : }
571 :
572 : /* Get comment from the value */
573 80 : ic = NULL;
574 80 : error = value_extract_comment(vo_copy, &ic);
575 80 : if (error) {
576 0 : printf("Failed to extract comment %d.\n", error);
577 0 : value_destroy(vo);
578 0 : value_destroy(vo_copy);
579 0 : fclose(ff);
580 0 : return error;
581 : }
582 :
583 : /* Replace comment in the value */
584 80 : snprintf(comment, TEST_SIZE, ";This is value with boundary %d", wrap);
585 80 : VOOUT(printf("Comment: %s\n", comment));
586 80 : error = ini_comment_replace(ic, 1, comment);
587 80 : if (error) {
588 0 : printf("Failed to replace comment %d.\n", error);
589 0 : value_destroy(vo);
590 0 : value_destroy(vo_copy);
591 0 : fclose(ff);
592 0 : return error;
593 : }
594 :
595 : /* Set comment into the value */
596 80 : error = value_put_comment(vo_copy, ic);
597 80 : if (error) {
598 0 : printf("Failed to set comment %d.\n", error);
599 0 : value_destroy(vo);
600 0 : value_destroy(vo_copy);
601 0 : fclose(ff);
602 0 : return error;
603 : }
604 :
605 80 : error = save_value(ff, "key", vo_copy);
606 80 : if (error) {
607 0 : printf("Failed to save value to file %d.\n", error);
608 0 : value_destroy(vo);
609 0 : value_destroy(vo_copy);
610 0 : fclose(ff);
611 0 : return error;
612 : }
613 :
614 80 : value_destroy(vo_copy);
615 : }
616 :
617 1 : value_destroy(vo);
618 1 : fclose(ff);
619 : TRACE_FLOW_EXIT();
620 1 : return EOK;
621 : }
622 :
623 1 : static int vo_show_test(void)
624 : {
625 1 : VOOUT(system("cat test.ini"));
626 1 : return EOK;
627 : }
628 :
629 1 : static int vo_mc_test(void)
630 : {
631 1 : int error = EOK;
632 1 : struct value_obj *vo1 = NULL;
633 1 : struct value_obj *vo2 = NULL;
634 1 : struct ini_comment *ic = NULL;
635 :
636 : TRACE_FLOW_ENTRY();
637 :
638 1 : VOOUT(printf("<=== Merge Comment Test ===>\n"));
639 :
640 1 : error = create_comment(1, &ic);
641 1 : if (error) {
642 0 : printf("Failed to create a new comment object %d.\n", error);
643 0 : return error;
644 : }
645 :
646 1 : error = value_create_new("test1",
647 : 5,
648 : INI_VALUE_CREATED,
649 : 3,
650 : 80,
651 : ic,
652 : &vo1);
653 1 : if (error) {
654 0 : printf("Failed to create the first value object %d.\n", error);
655 0 : ini_comment_destroy(ic);
656 0 : return error;
657 : }
658 :
659 1 : error = create_comment(2, &ic);
660 1 : if (error) {
661 0 : printf("Failed to create a new comment object %d.\n", error);
662 0 : value_destroy(vo1);
663 0 : return error;
664 : }
665 :
666 1 : error = value_create_new("test2",
667 : 5,
668 : INI_VALUE_CREATED,
669 : 3,
670 : 80,
671 : ic,
672 : &vo2);
673 1 : if (error) {
674 0 : printf("Failed to create the second value object %d.\n", error);
675 0 : ini_comment_destroy(ic);
676 0 : value_destroy(vo1);
677 0 : return error;
678 : }
679 :
680 : /* Merge comment from one value into another */
681 1 : error = value_merge_comment(vo2, vo1);
682 1 : if (error) {
683 0 : printf("Failed to merge comments %d.\n", error);
684 0 : value_destroy(vo1);
685 0 : value_destroy(vo2);
686 0 : return error;
687 : }
688 :
689 1 : value_destroy(vo2);
690 :
691 1 : VOOUT(printf("<=== Key ===>\n"));
692 1 : VOOUT(value_print("key", vo1));
693 :
694 1 : error = value_extract_comment(vo1, &ic);
695 1 : if (error) {
696 0 : printf("Failed to extract comment %d.\n", error);
697 0 : value_destroy(vo1);
698 0 : return error;
699 : }
700 :
701 1 : value_destroy(vo1);
702 :
703 1 : VOOUT(printf("<=== Comment ===>\n"));
704 1 : VOOUT(ini_comment_print(ic, stdout));
705 1 : ini_comment_destroy(ic);
706 :
707 : TRACE_FLOW_EXIT();
708 1 : return EOK;
709 : }
710 :
711 :
712 : /* Main function of the unit test */
713 1 : int main(int argc, char *argv[])
714 : {
715 1 : int error = 0;
716 1 : test_fn tests[] = { vo_basic_test,
717 : vo_copy_test,
718 : vo_show_test,
719 : vo_mc_test,
720 : NULL };
721 : test_fn t;
722 1 : int i = 0;
723 : char *var;
724 :
725 1 : if ((argc > 1) && (strcmp(argv[1], "-v") == 0)) verbose = 1;
726 : else {
727 1 : var = getenv("COMMON_TEST_VERBOSE");
728 1 : if (var) verbose = 1;
729 : }
730 :
731 1 : VOOUT(printf("Start\n"));
732 :
733 5 : while ((t = tests[i++])) {
734 4 : error = t();
735 4 : if (error) {
736 0 : VOOUT(printf("Failed with error %d!\n", error));
737 0 : return error;
738 : }
739 : }
740 :
741 1 : VOOUT(printf("Success!\n"));
742 : return 0;
743 : }
|