master
c 684 lines 23 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "../libnetdata.h"
4 #include "yaml.h"
5
6 static int test_yaml_parse_null(void) {
7 int failed = 0;
8
9 const char *yaml_inputs[] = {
10 "null",
11 "~",
12 "---\nnull",
13 NULL
14 };
15
16 for (int i = 0; yaml_inputs[i]; i++) {
17 BUFFER *error = buffer_create(0, NULL);
18 struct json_object *json = yaml_parse_string(yaml_inputs[i], error, YAML2JSON_DEFAULT);
19
20 if (json != NULL) {
21 fprintf(stderr, "FAILED: test_yaml_parse_null case %d: expected NULL, got %p\n",
22 i, (void*)json);
23 failed++;
24 json_object_put(json);
25 }
26
27 buffer_free(error);
28 }
29
30 return failed;
31 }
32
33 static int test_yaml_parse_boolean(void) {
34 int failed = 0;
35
36 struct {
37 const char *yaml;
38 int expected;
39 } test_cases[] = {
40 {"true", 1},
41 {"false", 0},
42 {"yes", 1},
43 {"no", 0},
44 {"on", 1},
45 {"off", 0},
46 {"True", 1},
47 {"False", 0},
48 {"YES", 1},
49 {"NO", 0},
50 {NULL, 0}
51 };
52
53 for (int i = 0; test_cases[i].yaml; i++) {
54 BUFFER *error = buffer_create(0, NULL);
55 struct json_object *json = yaml_parse_string(test_cases[i].yaml, error, YAML2JSON_DEFAULT);
56
57 if (!json || !json_object_is_type(json, json_type_boolean)) {
58 fprintf(stderr, "FAILED: test_yaml_parse_boolean case %d: expected boolean for '%s'\n",
59 i, test_cases[i].yaml);
60 failed++;
61 } else if (json_object_get_boolean(json) != test_cases[i].expected) {
62 fprintf(stderr, "FAILED: test_yaml_parse_boolean case %d: expected %d, got %d for '%s'\n",
63 i, test_cases[i].expected, json_object_get_boolean(json), test_cases[i].yaml);
64 failed++;
65 }
66
67 if (json) json_object_put(json);
68 buffer_free(error);
69 }
70
71 return failed;
72 }
73
74 static int test_yaml_parse_numbers(void) {
75 int failed = 0;
76
77 struct {
78 const char *yaml;
79 enum json_type expected_type;
80 int64_t expected_int;
81 double expected_double;
82 } test_cases[] = {
83 {"42", json_type_int, 42, 0},
84 {"-123", json_type_int, -123, 0},
85 {"0", json_type_int, 0, 0},
86 {"3.14", json_type_double, 0, 3.14},
87 {"-0.5", json_type_double, 0, -0.5},
88 {"1.23e10", json_type_double, 0, 1.23e10},
89 {"1.23e-10", json_type_double, 0, 1.23e-10},
90 {NULL, 0, 0, 0}
91 };
92
93 for (int i = 0; test_cases[i].yaml; i++) {
94 BUFFER *error = buffer_create(0, NULL);
95 struct json_object *json = yaml_parse_string(test_cases[i].yaml, error, YAML2JSON_DEFAULT);
96
97 if (!json || !json_object_is_type(json, test_cases[i].expected_type)) {
98 fprintf(stderr, "FAILED: test_yaml_parse_numbers case %d: wrong type for '%s'\n",
99 i, test_cases[i].yaml);
100 failed++;
101 } else {
102 if (test_cases[i].expected_type == json_type_int) {
103 if (json_object_get_int64(json) != test_cases[i].expected_int) {
104 fprintf(stderr, "FAILED: test_yaml_parse_numbers case %d: expected %" PRId64 ", got %" PRId64 " for '%s'\n",
105 i, test_cases[i].expected_int, json_object_get_int64(json), test_cases[i].yaml);
106 failed++;
107 }
108 } else {
109 double diff = fabs(json_object_get_double(json) - test_cases[i].expected_double);
110 if (diff > 0.000001) {
111 fprintf(stderr, "FAILED: test_yaml_parse_numbers case %d: expected %f, got %f for '%s'\n",
112 i, test_cases[i].expected_double, json_object_get_double(json), test_cases[i].yaml);
113 failed++;
114 }
115 }
116 }
117
118 if (json) json_object_put(json);
119 buffer_free(error);
120 }
121
122 return failed;
123 }
124
125 static int test_yaml_parse_strings(void) {
126 int failed = 0;
127
128 struct {
129 const char *yaml;
130 const char *expected;
131 } test_cases[] = {
132 {"hello", "hello"},
133 {"\"hello world\"", "hello world"},
134 {"'hello world'", "hello world"},
135 {"\"true\"", "true"},
136 {"\"123\"", "123"},
137 {"\"null\"", "null"},
138 {"multi\\nline", "multi\\nline"},
139 {"\"multi\\nline\"", "multi\nline"},
140 {"\" spaces \"", " spaces "},
141 {NULL, NULL}
142 };
143
144 for (int i = 0; test_cases[i].yaml; i++) {
145 BUFFER *error = buffer_create(0, NULL);
146 struct json_object *json = yaml_parse_string(test_cases[i].yaml, error, YAML2JSON_DEFAULT);
147
148 if (!json || !json_object_is_type(json, json_type_string)) {
149 fprintf(stderr, "FAILED: test_yaml_parse_strings case %d: expected string for '%s'\n",
150 i, test_cases[i].yaml);
151 failed++;
152 } else if (strcmp(json_object_get_string(json), test_cases[i].expected) != 0) {
153 fprintf(stderr, "FAILED: test_yaml_parse_strings case %d: expected '%s', got '%s' for '%s'\n",
154 i, test_cases[i].expected, json_object_get_string(json), test_cases[i].yaml);
155 failed++;
156 }
157
158 if (json) json_object_put(json);
159 buffer_free(error);
160 }
161
162 return failed;
163 }
164
165 static int test_yaml_parse_arrays(void) {
166 int failed = 0;
167
168 // Try both flow and block style arrays
169 const char *yaml = "- 1\n- 2\n- three\n- true\n- null\n- 4.5";
170
171 BUFFER *error = buffer_create(0, NULL);
172 struct json_object *json = yaml_parse_string(yaml, error, YAML2JSON_DEFAULT);
173
174 if (!json) {
175 fprintf(stderr, "FAILED: test_yaml_parse_arrays: json is NULL, error: %s\n", buffer_tostring(error));
176 failed++;
177 goto cleanup;
178 }
179
180 if (!json_object_is_type(json, json_type_array)) {
181 fprintf(stderr, "FAILED: test_yaml_parse_arrays: expected array but got type %u\n",
182 (unsigned int)json_object_get_type(json));
183 failed++;
184 goto cleanup;
185 }
186
187 if (json_object_array_length(json) != 6) {
188 fprintf(stderr, "FAILED: test_yaml_parse_arrays: expected 6 elements, got %zu\n",
189 json_object_array_length(json));
190 failed++;
191 goto cleanup;
192 }
193
194 // Check array elements
195 struct json_object *elem;
196
197 elem = json_object_array_get_idx(json, 0);
198 if (!elem || !json_object_is_type(elem, json_type_int) || json_object_get_int64(elem) != 1) {
199 fprintf(stderr, "FAILED: test_yaml_parse_arrays: element 0 check failed\n");
200 failed++;
201 }
202
203 elem = json_object_array_get_idx(json, 2);
204 if (!elem || !json_object_is_type(elem, json_type_string) ||
205 strcmp(json_object_get_string(elem), "three") != 0) {
206 fprintf(stderr, "FAILED: test_yaml_parse_arrays: element 2 check failed\n");
207 failed++;
208 }
209
210 elem = json_object_array_get_idx(json, 3);
211 if (!elem || !json_object_is_type(elem, json_type_boolean) || !json_object_get_boolean(elem)) {
212 fprintf(stderr, "FAILED: test_yaml_parse_arrays: element 3 check failed\n");
213 failed++;
214 }
215
216 elem = json_object_array_get_idx(json, 4);
217 if (elem != NULL) {
218 fprintf(stderr, "FAILED: test_yaml_parse_arrays: element 4 should be NULL (json-c represents null array elements as NULL)\n");
219 failed++;
220 }
221
222 cleanup:
223 if (json) json_object_put(json);
224 buffer_free(error);
225
226 return failed;
227 }
228
229 static int test_yaml_parse_objects(void) {
230 int failed = 0;
231
232 const char *yaml =
233 "name: John Doe\n"
234 "age: 30\n"
235 "active: true\n"
236 "salary: 50000.50\n"
237 "address:\n"
238 " street: 123 Main St\n"
239 " city: Anytown\n"
240 "tags:\n"
241 " - developer\n"
242 " - team-lead\n";
243
244 BUFFER *error = buffer_create(0, NULL);
245 struct json_object *json = yaml_parse_string(yaml, error, YAML2JSON_DEFAULT);
246
247 if (!json || !json_object_is_type(json, json_type_object)) {
248 fprintf(stderr, "FAILED: test_yaml_parse_objects: expected object\n");
249 failed++;
250 goto cleanup;
251 }
252
253 // Check object properties
254 struct json_object *prop;
255
256 if (!json_object_object_get_ex(json, "name", &prop) ||
257 !json_object_is_type(prop, json_type_string) ||
258 strcmp(json_object_get_string(prop), "John Doe") != 0) {
259 fprintf(stderr, "FAILED: test_yaml_parse_objects: name property check failed\n");
260 failed++;
261 }
262
263 if (!json_object_object_get_ex(json, "age", &prop) ||
264 !json_object_is_type(prop, json_type_int) ||
265 json_object_get_int64(prop) != 30) {
266 fprintf(stderr, "FAILED: test_yaml_parse_objects: age property check failed\n");
267 failed++;
268 }
269
270 if (!json_object_object_get_ex(json, "active", &prop) ||
271 !json_object_is_type(prop, json_type_boolean) ||
272 !json_object_get_boolean(prop)) {
273 fprintf(stderr, "FAILED: test_yaml_parse_objects: active property check failed\n");
274 failed++;
275 }
276
277 // Check nested object
278 if (!json_object_object_get_ex(json, "address", &prop) ||
279 !json_object_is_type(prop, json_type_object)) {
280 fprintf(stderr, "FAILED: test_yaml_parse_objects: address property check failed\n");
281 failed++;
282 } else {
283 struct json_object *street;
284 if (!json_object_object_get_ex(prop, "street", &street) ||
285 strcmp(json_object_get_string(street), "123 Main St") != 0) {
286 fprintf(stderr, "FAILED: test_yaml_parse_objects: street property check failed\n");
287 failed++;
288 }
289 }
290
291 // Check array
292 if (!json_object_object_get_ex(json, "tags", &prop) ||
293 !json_object_is_type(prop, json_type_array) ||
294 json_object_array_length(prop) != 2) {
295 fprintf(stderr, "FAILED: test_yaml_parse_objects: tags property check failed\n");
296 failed++;
297 }
298
299 cleanup:
300 if (json) json_object_put(json);
301 buffer_free(error);
302
303 return failed;
304 }
305
306 static int test_yaml_generation(void) {
307 int failed = 0;
308
309 // Create a more comprehensive JSON object
310 struct json_object *root = json_object_new_object();
311 json_object_object_add(root, "name", json_object_new_string("Test"));
312 json_object_object_add(root, "version", json_object_new_int(1));
313 json_object_object_add(root, "enabled", json_object_new_boolean(1));
314 json_object_object_add(root, "pi", json_object_new_double(3.14159));
315 // Test with NULL value
316 json_object_object_add(root, "nothing", NULL);
317
318 struct json_object *array = json_object_new_array();
319 json_object_array_add(array, json_object_new_string("item1"));
320 json_object_array_add(array, json_object_new_int(2));
321 json_object_array_add(array, json_object_new_boolean(0));
322 json_object_object_add(root, "items", array);
323
324 struct json_object *nested = json_object_new_object();
325 json_object_object_add(nested, "key", json_object_new_string("value"));
326 json_object_object_add(root, "nested", nested);
327
328 // Generate YAML
329 BUFFER *output = buffer_create(0, NULL);
330 BUFFER *error = buffer_create(0, NULL);
331
332 if (!yaml_generate_to_buffer(output, root, error)) {
333 fprintf(stderr, "FAILED: test_yaml_generation: failed to generate YAML: %s\n",
334 buffer_tostring(error));
335 failed++;
336 goto cleanup;
337 }
338
339 const char *yaml_str = buffer_tostring(output);
340 if (!yaml_str || strlen(yaml_str) == 0) {
341 fprintf(stderr, "FAILED: test_yaml_generation: generated empty YAML\n");
342 failed++;
343 goto cleanup;
344 }
345
346 // Parse the generated YAML back
347 buffer_flush(error);
348 struct json_object *parsed = yaml_parse_string(yaml_str, error, YAML2JSON_DEFAULT);
349 if (!parsed) {
350 const char *err_msg = buffer_tostring(error);
351 if (!err_msg || strlen(err_msg) == 0) {
352 err_msg = "(no error message but result is NULL)";
353 }
354 fprintf(stderr, "FAILED: test_yaml_generation: failed to parse generated YAML: %s\nYAML was:\n%s\n",
355 err_msg, yaml_str);
356 failed++;
357 goto cleanup;
358 }
359
360 // Verify the parsed object matches the original
361 struct json_object *prop;
362
363 if (!json_object_object_get_ex(parsed, "name", &prop) ||
364 strcmp(json_object_get_string(prop), "Test") != 0) {
365 fprintf(stderr, "FAILED: test_yaml_generation: name property mismatch\n");
366 failed++;
367 }
368
369 if (!json_object_object_get_ex(parsed, "version", &prop) ||
370 json_object_get_int64(prop) != 1) {
371 fprintf(stderr, "FAILED: test_yaml_generation: version property mismatch\n");
372 failed++;
373 }
374
375 if (!json_object_object_get_ex(parsed, "enabled", &prop) ||
376 !json_object_get_boolean(prop)) {
377 fprintf(stderr, "FAILED: test_yaml_generation: enabled property mismatch\n");
378 failed++;
379 }
380
381 if (!json_object_object_get_ex(parsed, "pi", &prop) ||
382 !json_object_is_type(prop, json_type_double)) {
383 fprintf(stderr, "FAILED: test_yaml_generation: pi property mismatch\n");
384 failed++;
385 }
386
387 // Check NULL value - in json-c, JSON null is represented as C NULL
388 if (!json_object_object_get_ex(parsed, "nothing", &prop)) {
389 fprintf(stderr, "FAILED: test_yaml_generation: nothing property should exist\n");
390 failed++;
391 } else if (prop != NULL) {
392 fprintf(stderr, "FAILED: test_yaml_generation: nothing property should be NULL\n");
393 failed++;
394 }
395
396 if (!json_object_object_get_ex(parsed, "items", &prop) ||
397 !json_object_is_type(prop, json_type_array) ||
398 json_object_array_length(prop) != 3) {
399 fprintf(stderr, "FAILED: test_yaml_generation: items property mismatch\n");
400 failed++;
401 }
402
403 if (!json_object_object_get_ex(parsed, "nested", &prop) ||
404 !json_object_is_type(prop, json_type_object)) {
405 fprintf(stderr, "FAILED: test_yaml_generation: nested property mismatch\n");
406 failed++;
407 } else {
408 struct json_object *nested_key;
409 if (!json_object_object_get_ex(prop, "key", &nested_key) ||
410 strcmp(json_object_get_string(nested_key), "value") != 0) {
411 fprintf(stderr, "FAILED: test_yaml_generation: nested.key property mismatch\n");
412 failed++;
413 }
414 }
415
416 json_object_put(parsed);
417
418 cleanup:
419 json_object_put(root);
420 buffer_free(output);
421 buffer_free(error);
422
423 return failed;
424 }
425
426 static int test_yaml_parse_errors(void) {
427 int failed = 0;
428
429 const char *invalid_yaml[] = {
430 "[unclosed array",
431 "{ unclosed: object",
432 NULL
433 };
434
435 for (int i = 0; invalid_yaml[i]; i++) {
436 BUFFER *error = buffer_create(0, NULL);
437 struct json_object *json = yaml_parse_string(invalid_yaml[i], error, YAML2JSON_DEFAULT);
438
439 if (json != NULL || buffer_strlen(error) == 0) {
440 fprintf(stderr, "FAILED: test_yaml_parse_errors case %d: expected parse error\n", i);
441 failed++;
442 }
443
444 if (json) json_object_put(json);
445 buffer_free(error);
446 }
447
448 return failed;
449 }
450
451 static int test_yaml_file_operations(void) {
452 int failed = 0;
453
454 const char *test_file = "/tmp/netdata_yaml_test.yaml";
455
456 // Create a test JSON object
457 struct json_object *root = json_object_new_object();
458 json_object_object_add(root, "test", json_object_new_string("file operations"));
459 json_object_object_add(root, "number", json_object_new_int(42));
460
461 BUFFER *error = buffer_create(0, NULL);
462
463 // Write to file
464 if (!yaml_generate_to_filename(test_file, root, error)) {
465 fprintf(stderr, "FAILED: test_yaml_file_operations: failed to write file: %s\n",
466 buffer_tostring(error));
467 failed++;
468 goto cleanup;
469 }
470
471 // Read from file
472 struct json_object *parsed = yaml_parse_filename(test_file, error, YAML2JSON_DEFAULT);
473 if (!parsed) {
474 fprintf(stderr, "FAILED: test_yaml_file_operations: failed to read file: %s\n",
475 buffer_tostring(error));
476 failed++;
477 goto cleanup;
478 }
479
480 // Verify content
481 struct json_object *prop;
482 if (!json_object_object_get_ex(parsed, "test", &prop) ||
483 strcmp(json_object_get_string(prop), "file operations") != 0) {
484 fprintf(stderr, "FAILED: test_yaml_file_operations: test property mismatch\n");
485 failed++;
486 }
487
488 if (!json_object_object_get_ex(parsed, "number", &prop) ||
489 json_object_get_int64(prop) != 42) {
490 fprintf(stderr, "FAILED: test_yaml_file_operations: number property mismatch\n");
491 failed++;
492 }
493
494 json_object_put(parsed);
495
496 cleanup:
497 // Cleanup
498 unlink(test_file);
499 json_object_put(root);
500 buffer_free(error);
501
502 return failed;
503 }
504
505 static int test_yaml_edge_cases(void) {
506 int failed = 0;
507
508 BUFFER *error = buffer_create(0, NULL);
509
510 // Empty string
511 struct json_object *json = yaml_parse_string("", error, YAML2JSON_DEFAULT);
512 if (json != NULL) {
513 fprintf(stderr, "FAILED: test_yaml_edge_cases: empty string should return NULL\n");
514 failed++;
515 json_object_put(json);
516 }
517
518 // NULL input
519 buffer_flush(error);
520 json = yaml_parse_string(NULL, error, YAML2JSON_DEFAULT);
521 if (json != NULL || buffer_strlen(error) == 0) {
522 fprintf(stderr, "FAILED: test_yaml_edge_cases: NULL input should fail\n");
523 failed++;
524 if (json) json_object_put(json);
525 }
526
527 // Empty object
528 buffer_flush(error);
529 json = yaml_parse_string("{}", error, YAML2JSON_DEFAULT);
530 if (!json || !json_object_is_type(json, json_type_object) ||
531 json_object_object_length(json) != 0) {
532 fprintf(stderr, "FAILED: test_yaml_edge_cases: empty object parse failed\n");
533 failed++;
534 }
535 if (json) json_object_put(json);
536
537 // Empty array
538 buffer_flush(error);
539 json = yaml_parse_string("[]", error, YAML2JSON_DEFAULT);
540 if (!json || !json_object_is_type(json, json_type_array) ||
541 json_object_array_length(json) != 0) {
542 fprintf(stderr, "FAILED: test_yaml_edge_cases: empty array parse failed\n");
543 failed++;
544 }
545 if (json) json_object_put(json);
546
547 buffer_free(error);
548
549 return failed;
550 }
551
552 static int test_yaml_special_strings(void) {
553 int failed = 0;
554
555 // Create JSON with special strings
556 struct json_object *root = json_object_new_object();
557 json_object_object_add(root, "str_null", json_object_new_string("null"));
558 json_object_object_add(root, "str_true", json_object_new_string("true"));
559 json_object_object_add(root, "str_false", json_object_new_string("false"));
560 json_object_object_add(root, "str_yes", json_object_new_string("yes"));
561 json_object_object_add(root, "str_no", json_object_new_string("no"));
562 json_object_object_add(root, "str_on", json_object_new_string("on"));
563 json_object_object_add(root, "str_off", json_object_new_string("off"));
564 json_object_object_add(root, "str_spaces", json_object_new_string(" spaces "));
565 json_object_object_add(root, "str_newline", json_object_new_string("line1\nline2"));
566 json_object_object_add(root, "str_empty", json_object_new_string(""));
567
568 BUFFER *output = buffer_create(0, NULL);
569 BUFFER *error = buffer_create(0, NULL);
570
571 // Generate YAML
572 if (!yaml_generate_to_buffer(output, root, error)) {
573 fprintf(stderr, "FAILED: test_yaml_special_strings: failed to generate YAML: %s\n",
574 buffer_tostring(error));
575 failed++;
576 goto cleanup;
577 }
578
579 // Parse back
580 struct json_object *parsed = yaml_parse_string(buffer_tostring(output), error, YAML2JSON_DEFAULT);
581 if (!parsed) {
582 fprintf(stderr, "FAILED: test_yaml_special_strings: failed to parse YAML: %s\n",
583 buffer_tostring(error));
584 failed++;
585 goto cleanup;
586 }
587
588 // Verify all strings are preserved correctly
589 struct json_object *prop;
590
591 if (!json_object_object_get_ex(parsed, "str_null", &prop) ||
592 !json_object_is_type(prop, json_type_string) ||
593 strcmp(json_object_get_string(prop), "null") != 0) {
594 fprintf(stderr, "FAILED: test_yaml_special_strings: str_null mismatch\n");
595 failed++;
596 }
597
598 if (!json_object_object_get_ex(parsed, "str_true", &prop) ||
599 !json_object_is_type(prop, json_type_string) ||
600 strcmp(json_object_get_string(prop), "true") != 0) {
601 fprintf(stderr, "FAILED: test_yaml_special_strings: str_true mismatch\n");
602 failed++;
603 }
604
605 if (!json_object_object_get_ex(parsed, "str_spaces", &prop) ||
606 !json_object_is_type(prop, json_type_string) ||
607 strcmp(json_object_get_string(prop), " spaces ") != 0) {
608 fprintf(stderr, "FAILED: test_yaml_special_strings: str_spaces mismatch\n");
609 failed++;
610 }
611
612 if (!json_object_object_get_ex(parsed, "str_empty", &prop) ||
613 !json_object_is_type(prop, json_type_string) ||
614 strcmp(json_object_get_string(prop), "") != 0) {
615 fprintf(stderr, "FAILED: test_yaml_special_strings: str_empty mismatch\n");
616 failed++;
617 }
618
619 json_object_put(parsed);
620
621 cleanup:
622 json_object_put(root);
623 buffer_free(output);
624 buffer_free(error);
625
626 return failed;
627 }
628
629 // Forward declaration
630 int yaml_comprehensive_unittest(void);
631
632 int yaml_unittest(void) {
633 int passed = 0;
634 int failed = 0;
635
636 printf("Starting YAML parser/generator unit tests\n");
637 printf("=========================================\n\n");
638
639 // Run all tests
640 struct {
641 const char *name;
642 int (*test_func)(void);
643 } tests[] = {
644 {"test_yaml_parse_null", test_yaml_parse_null},
645 {"test_yaml_parse_boolean", test_yaml_parse_boolean},
646 {"test_yaml_parse_numbers", test_yaml_parse_numbers},
647 {"test_yaml_parse_strings", test_yaml_parse_strings},
648 {"test_yaml_parse_arrays", test_yaml_parse_arrays},
649 {"test_yaml_parse_objects", test_yaml_parse_objects},
650 {"test_yaml_generation", test_yaml_generation},
651 {"test_yaml_parse_errors", test_yaml_parse_errors},
652 {"test_yaml_file_operations", test_yaml_file_operations},
653 {"test_yaml_edge_cases", test_yaml_edge_cases},
654 {"test_yaml_special_strings", test_yaml_special_strings},
655 {NULL, NULL}
656 };
657
658 for (int i = 0; tests[i].name; i++) {
659 printf("Running %s...\n", tests[i].name);
660 int test_failed = tests[i].test_func();
661 if (test_failed == 0) {
662 printf(" PASSED\n");
663 passed++;
664 } else {
665 printf(" FAILED (%d failures)\n", test_failed);
666 failed += test_failed;
667 }
668 }
669
670 printf("\n=========================================\n");
671 printf("YAML unit tests summary:\n");
672 int total = 0;
673 for (int i = 0; tests[i].name; i++) total++;
674 printf(" Tests run: %d\n", total);
675 printf(" Passed: %d\n", passed);
676 printf(" Failed: %d\n", failed);
677 printf("=========================================\n");
678
679 // Run comprehensive tests
680 int comprehensive_failed = yaml_comprehensive_unittest();
681 failed += comprehensive_failed;
682
683 return failed;
684 }