new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / tests / test_os_xml.c
1 /* Copyright (C) 2014 Trend Micro Inc.
2  * All rights reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation
8  */
9
10 #include <check.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <unistd.h>
14
15 #include "../os_xml/os_xml.h"
16 #include "../os_xml/os_xml_internal.h"
17
18 Suite *test_suite(void);
19
20
21 static void create_xml_file(const char *str, char file_name[], size_t length)
22 {
23     strncpy(file_name, "/tmp/tmp_file-XXXXXX", length);
24     int fd = mkstemp(file_name);
25
26     write(fd, str, strlen(str));
27     close(fd);
28 }
29
30 static void nodecat(XML_NODE node, OS_XML *xml, char *buffer)
31 {
32     int i = 0;
33     /* write node */
34     while (node[i]) {
35         strncat(buffer, "<", 1);
36         ck_assert_ptr_ne(node[i]->element, NULL);
37         strncat(buffer, node[i]->element, strlen(node[i]->element));
38         /* write attributes */
39         if (node[i]->attributes) {
40             ck_assert_ptr_ne(node[i]->values, NULL);
41             int j = 0;
42             while (node[i]->attributes[j]) {
43                 strncat(buffer, " ", 1);
44                 ck_assert_ptr_ne(node[i]->values[j], NULL);
45                 strncat(buffer, node[i]->attributes[j], strlen(node[i]->attributes[j]));
46                 strncat(buffer, "=", 1);
47                 strncat(buffer, "\"", 1);
48                 strncat(buffer, node[i]->values[j], strlen(node[i]->values[j]));
49                 strncat(buffer, "\"", 1);
50                 j++;
51             }
52             ck_assert_ptr_eq(node[i]->values[j], NULL);
53         } else {
54             ck_assert_ptr_eq(node[i]->values, NULL);
55         }
56         strncat(buffer, ">", 1);
57         ck_assert_ptr_ne(node[i]->content, NULL);
58         strncat(buffer, node[i]->content, strlen(node[i]->content));
59
60         /* write children */
61         XML_NODE child = OS_GetElementsbyNode(xml, node[i]);
62         if (child != NULL) {
63             nodecat(child, xml, buffer);
64             OS_ClearNode(child);
65         }
66
67         /* close node */
68         strncat(buffer, "</", 2);
69         strncat(buffer, node[i]->element, strlen(node[i]->element));
70         strncat(buffer, ">", 1);
71         i++;
72     }
73 }
74
75 static void assert_os_xml_eq_str(OS_XML *xml, const char *xml_str)
76 {
77     XML_NODE node = OS_GetElementsbyNode(xml, NULL);
78     if (node == NULL) {
79         ck_assert_str_eq(xml_str, "");
80         return;
81     }
82
83     char *buffer = (char *) malloc(6144 * sizeof(char));
84     buffer[0] = '\0';
85     nodecat(node, xml, buffer);
86     OS_ClearNode(node);
87
88     ck_assert_str_eq(buffer, xml_str);
89
90     free(buffer);
91 }
92
93 #define assert_os_xml_eq(PARSE_STR, XML_STR) do { \
94     char _ck_xml_file_name[256]; \
95     create_xml_file(PARSE_STR, _ck_xml_file_name, 256); \
96     OS_XML _ck_xml; \
97     ck_assert_int_eq(OS_ReadXML(_ck_xml_file_name, &_ck_xml), 0); \
98     ck_assert_int_eq(OS_ApplyVariables(&_ck_xml), 0); \
99     assert_os_xml_eq_str(&_ck_xml, XML_STR); \
100     OS_ClearXML(&_ck_xml); \
101     unlink(_ck_xml_file_name); \
102 } while (0)
103
104 START_TEST(test_simplenodes)
105 {
106     assert_os_xml_eq("", "");
107     assert_os_xml_eq("<root></root>", "<root></root>");
108     assert_os_xml_eq("<root/>", "<root></root>");
109     assert_os_xml_eq("<root />", "<root></root>");
110 }
111 END_TEST
112
113
114 START_TEST(test_multiplenodes)
115 {
116     assert_os_xml_eq(
117         "<root1></root1>"
118         "<root2></root2>"
119         "<root3/>",
120         "<root1></root1>"
121         "<root2></root2>"
122         "<root3></root3>");
123 }
124 END_TEST
125
126 START_TEST(test_children)
127 {
128     assert_os_xml_eq(
129         "<root1>"
130         "<child1></child1>"
131         "</root1>"
132         "<root2>"
133         "<child1></child1>"
134         "<child2/>"
135         "<child3>"
136         "<child3.1></child3.1>"
137         "</child3>"
138         "</root2>"
139         "<root3></root3>",
140         "<root1>"
141         "<child1></child1>"
142         "</root1>"
143         "<root2>"
144         "<child1></child1>"
145         "<child2></child2>"
146         "<child3>"
147         "<child3.1></child3.1>"
148         "</child3>"
149         "</root2>"
150         "<root3></root3>");
151 }
152 END_TEST
153
154 START_TEST(test_multiplecontent)
155 {
156     assert_os_xml_eq(
157         "<root>"
158         "value1"
159         "<child/>"
160         "</root>",
161         "<root><child></child></root>");
162     assert_os_xml_eq(
163         "<root>"
164         "value1"
165         "<child/>"
166         "value2"
167         "</root>",
168         "<root>value2<child></child></root>");
169 }
170 END_TEST
171
172
173 START_TEST(test_attributes)
174 {
175     assert_os_xml_eq(
176         "<root attr1=\"test\" attr2=\"1\"></root>",
177         "<root attr1=\"test\" attr2=\"1\"></root>");
178
179     assert_os_xml_eq(
180         "<root attr1=\"test\"\nattr2=\"test\"\tattr3=\"test\"></root>",
181         "<root attr1=\"test\" attr2=\"test\" attr3=\"test\"></root>");
182
183     assert_os_xml_eq(
184         "<root attr1=\"test/test\"></root>",
185         "<root attr1=\"test/test\"></root>");
186
187     assert_os_xml_eq(
188         "<root attr1=\"test1\"></root><root attr1=\"test2\"></root>",
189         "<root attr1=\"test1\"></root><root attr1=\"test2\"></root>");
190
191     assert_os_xml_eq(
192         "<root attr1=\"test\"\n\t  \t\n  \n\t  \nattr2=\"test\"></root>",
193         "<root attr1=\"test\" attr2=\"test\"></root>");
194
195     assert_os_xml_eq(
196         "<root\n\t  \t\n  \n\t  \nattr1=\"test\"></root>",
197         "<root attr1=\"test\"></root>");
198
199     assert_os_xml_eq(
200         "<root attr1=\n\t  \t\n  \n\t  \n\"test\"></root>",
201         "<root attr1=\"test\"></root>");
202
203     assert_os_xml_eq(
204         "<root attr=\"test\" />",
205         "<root attr=\"test\"></root>");
206
207     assert_os_xml_eq(
208         "<root attr=\"test\"/>",
209         "<root attr=\"test\"></root>");
210 }
211 END_TEST
212
213 START_TEST(test_variables)
214 {
215     assert_os_xml_eq(
216         "<var name=\"var1\">value1</var>"
217         "<var name=\"var2\">value2</var>"
218         "<root attr1=\"$var1\" attr2=\"1\">$var2</root>"
219         "<root attr1=\"blah$var1\" attr2=\"1\">blah$var2</root>"
220         "<root attr1=\"blah$var1$var2 blah\" attr2=\"1\">blah$var2$var1 blah</root>",
221         "<root attr1=\"value1\" attr2=\"1\">value2</root>"
222         "<root attr1=\"blahvalue1\" attr2=\"1\">blahvalue2</root>"
223         "<root attr1=\"blahvalue1value2 blah\" attr2=\"1\">blahvalue2value1 blah</root>");
224 }
225 END_TEST
226
227 START_TEST(test_comments)
228 {
229     assert_os_xml_eq(
230         "<root1/><!comment!><root2/>",
231         "<root1></root1><root2></root2>");
232     assert_os_xml_eq(
233         "<root1/><!--comment--><root2/>",
234         "<root1></root1><root2></root2>");
235
236     assert_os_xml_eq(
237         "<root1/><! comment with ! !><root2/>",
238         "<root1></root1><root2></root2>");
239
240     assert_os_xml_eq(
241         "<root1/><! comment with - --><root2/>",
242         "<root1></root1><root2></root2>");
243 }
244 END_TEST
245
246 START_TEST(test_specialchars)
247 {
248     assert_os_xml_eq(
249         "<var name=\"var1\">value1</var>"
250         "<root1>\\</root1\\></root1>",
251         "<root1>\\</root1\\></root1>");
252 }
253 END_TEST
254
255 START_TEST(test_linecounter)
256 {
257     char xml_file_name[256];
258     create_xml_file("<root1/>\n<root2/>\n<root3/>" , xml_file_name, 256);
259     OS_XML xml;
260     XML_NODE node;
261     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
262     ck_assert_int_eq(OS_ApplyVariables(&xml), 0);
263     ck_assert_ptr_ne(node = OS_GetElementsbyNode(&xml, NULL), NULL);
264     ck_assert_int_eq(xml.ln[0], 1);
265     ck_assert_int_eq(xml.ln[1], 2);
266     ck_assert_int_eq(xml.ln[2], 3);
267
268     OS_ClearNode(node);
269     OS_ClearXML(&xml);
270     unlink(xml_file_name);
271 }
272 END_TEST
273
274 START_TEST(test_invalidfile)
275 {
276     OS_XML xml;
277     ck_assert_int_ne(OS_ReadXML("invalid_file.inv", &xml), 0);
278     ck_assert_str_eq(xml.err, "XMLERR: File 'invalid_file.inv' not found.");
279     ck_assert_int_eq(xml.err_line, 0);
280
281     OS_ClearXML(&xml);
282 }
283 END_TEST
284
285 START_TEST(test_unclosednode)
286 {
287     char xml_file_name[256];
288     create_xml_file("<root>", xml_file_name, 256);
289     OS_XML xml;
290     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
291     ck_assert_str_eq(xml.err, "XMLERR: End of file and some elements were not closed.");
292     ck_assert_int_eq(xml.err_line, 1);
293
294     OS_ClearXML(&xml);
295     unlink(xml_file_name);
296 }
297 END_TEST
298
299 START_TEST(test_unclosednode2)
300 {
301     char xml_file_name[256];
302     create_xml_file("<root></root2>", xml_file_name, 256);
303     OS_XML xml;
304     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
305     ck_assert_str_eq(xml.err, "XMLERR: Element 'root' not closed.");
306     ck_assert_int_eq(xml.err_line, 1);
307
308     OS_ClearXML(&xml);
309     unlink(xml_file_name);
310 }
311 END_TEST
312
313 START_TEST(test_unclosedcomment)
314 {
315     char xml_file_name[256];
316     create_xml_file("<!-- comment", xml_file_name, 256);
317     OS_XML xml;
318     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
319     ck_assert_str_eq(xml.err, "XMLERR: Comment not closed.");
320     ck_assert_int_eq(xml.err_line, 1);
321
322     OS_ClearXML(&xml);
323     unlink(xml_file_name);
324 }
325 END_TEST
326
327 START_TEST(test_nodenotopened)
328 {
329     char xml_file_name[256];
330     create_xml_file("</root>", xml_file_name, 256);
331     OS_XML xml;
332     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
333     ck_assert_str_eq(xml.err, "XMLERR: Element not opened.");
334     ck_assert_int_eq(xml.err_line, 1);
335
336     OS_ClearXML(&xml);
337     unlink(xml_file_name);
338 }
339 END_TEST
340
341 START_TEST(test_unclosedattribute)
342 {
343     char xml_file_name[256];
344     create_xml_file("<root attr=\"attribute></root>", xml_file_name, 256);
345     OS_XML xml;
346     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
347     ck_assert_str_eq(xml.err, "XMLERR: Attribute 'attr' not closed.");
348     ck_assert_int_eq(xml.err_line, 1);
349
350     OS_ClearXML(&xml);
351     unlink(xml_file_name);
352 }
353 END_TEST
354
355 START_TEST(test_unquotedattribute)
356 {
357     char xml_file_name[256];
358     create_xml_file("<root attr=attribute></root>", xml_file_name, 256);
359     OS_XML xml;
360     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
361     ck_assert_str_eq(xml.err, "XMLERR: Attribute 'attr' not followed by a \" or '.");
362     ck_assert_int_eq(xml.err_line, 1);
363
364     OS_ClearXML(&xml);
365     unlink(xml_file_name);
366 }
367 END_TEST
368
369 START_TEST(test_infiniteattribute)
370 {
371     char xml_file_name[256];
372     create_xml_file("<root attr", xml_file_name, 256);
373     OS_XML xml;
374     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
375     ck_assert_str_eq(xml.err, "XMLERR: End of file while reading an attribute.");
376     ck_assert_int_eq(xml.err_line, 1);
377
378     OS_ClearXML(&xml);
379     unlink(xml_file_name);
380 }
381 END_TEST
382
383 START_TEST(test_invalidvariablename)
384 {
385     char xml_file_name[256];
386     create_xml_file("<var test=\"test\"></var>", xml_file_name, 256);
387     OS_XML xml;
388     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
389     ck_assert_int_ne(OS_ApplyVariables(&xml), 0);
390     ck_assert_str_eq(xml.err, "XMLERR: Only \"name\" is allowed as an attribute for a variable.");
391     ck_assert_int_eq(xml.err_line, 1);
392
393     OS_ClearXML(&xml);
394     unlink(xml_file_name);
395 }
396 END_TEST
397
398 START_TEST(test_invalidvariable)
399 {
400     char xml_file_name[256];
401     char overflow_string[XML_VARIABLE_MAXSIZE + 10];
402     memset(overflow_string, 'c', XML_VARIABLE_MAXSIZE + 9);
403     overflow_string[XML_VARIABLE_MAXSIZE + 9] = '\0';
404
405     char xml_string[2 * XML_VARIABLE_MAXSIZE];
406     snprintf(xml_string, 2 * XML_VARIABLE_MAXSIZE - 1, "<var name=\"%s\">test</var><root/>", overflow_string);
407     create_xml_file(xml_string, xml_file_name, 256);
408     OS_XML xml;
409     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
410     ck_assert_int_ne(OS_ApplyVariables(&xml), 0);
411     ck_assert_str_eq(xml.err, "XMLERR: Invalid variable name size.");
412     ck_assert_int_eq(xml.err_line, 1);
413
414     OS_ClearXML(&xml);
415     unlink(xml_file_name);
416 }
417 END_TEST
418
419 START_TEST(test_invalidvariable2)
420 {
421     char xml_file_name[256];
422     char overflow_string[XML_VARIABLE_MAXSIZE + 10];
423     memset(overflow_string, 'c', XML_VARIABLE_MAXSIZE + 9);
424     overflow_string[XML_VARIABLE_MAXSIZE + 9] = '\0';
425
426     char xml_string[3 * XML_VARIABLE_MAXSIZE];
427     snprintf(xml_string, 3 * XML_VARIABLE_MAXSIZE - 1, "<var name=\"%s\">test</var><test>$%s</test>", overflow_string, overflow_string);
428     create_xml_file(xml_string, xml_file_name, 256);
429     OS_XML xml;
430     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
431     ck_assert_int_ne(OS_ApplyVariables(&xml), 0);
432     ck_assert_str_eq(xml.err, "XMLERR: Invalid variable name size.");
433     ck_assert_int_eq(xml.err_line, 1);
434
435     OS_ClearXML(&xml);
436     unlink(xml_file_name);
437 }
438 END_TEST
439
440 START_TEST(test_unknownvariable1)
441 {
442     char xml_file_name[256];
443     create_xml_file("<var name=\"test\">content</var><root>$var</root>", xml_file_name, 256);
444     OS_XML xml;
445     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
446     ck_assert_int_ne(OS_ApplyVariables(&xml), 0);
447     ck_assert_str_eq(xml.err, "XMLERR: Unknown variable: 'var'.");
448     ck_assert_int_eq(xml.err_line, 1);
449
450     OS_ClearXML(&xml);
451     unlink(xml_file_name);
452 }
453 END_TEST
454
455 START_TEST(test_unknownvariable2)
456 {
457     assert_os_xml_eq("<root>$var</root>",
458                      "<root>$var</root>");
459 }
460 END_TEST
461
462 START_TEST(test_infiniteattribute2)
463 {
464     char xml_file_name[256];
465     create_xml_file("<root attr=", xml_file_name, 256);
466     OS_XML xml;
467     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
468     ck_assert_str_eq(xml.err, "XMLERR: Attribute 'attr' not followed by a \" or '.");
469     ck_assert_int_eq(xml.err_line, 1);
470
471     OS_ClearXML(&xml);
472     unlink(xml_file_name);
473 }
474 END_TEST
475
476 START_TEST(test_invalidattributestart)
477 {
478     char xml_file_name[256];
479     create_xml_file("<root attr=  test\"test\"/>", xml_file_name, 256);
480     OS_XML xml;
481     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
482     ck_assert_str_eq(xml.err, "XMLERR: Attribute 'attr' not followed by a \" or '.");
483     ck_assert_int_eq(xml.err_line, 1);
484
485     OS_ClearXML(&xml);
486     unlink(xml_file_name);
487 }
488 END_TEST
489
490 START_TEST(test_invalidattributeclosing)
491 {
492     char xml_file_name[256];
493     create_xml_file("<root attr=''", xml_file_name, 256);
494     OS_XML xml;
495     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
496     ck_assert_str_eq(xml.err, "XMLERR: Bad attribute closing for 'attr'=''.");
497     ck_assert_int_eq(xml.err_line, 1);
498
499     OS_ClearXML(&xml);
500     unlink(xml_file_name);
501 }
502 END_TEST
503
504 START_TEST(test_invalidattributeclosing2)
505 {
506     char xml_file_name[256];
507     create_xml_file("<root attr='test'test/>", xml_file_name, 256);
508     OS_XML xml;
509     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
510     ck_assert_str_eq(xml.err, "XMLERR: Bad attribute closing for 'attr'='test'.");
511     ck_assert_int_eq(xml.err_line, 1);
512
513     OS_ClearXML(&xml);
514     unlink(xml_file_name);
515 }
516 END_TEST
517
518 START_TEST(test_infiniteattribute3)
519 {
520     char xml_file_name[256];
521     create_xml_file("<root attr='", xml_file_name, 256);
522     OS_XML xml;
523     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
524     ck_assert_str_eq(xml.err, "XMLERR: End of file while reading an attribute.");
525     ck_assert_int_eq(xml.err_line, 1);
526
527     OS_ClearXML(&xml);
528     unlink(xml_file_name);
529 }
530 END_TEST
531
532 START_TEST(test_duplicateattribute)
533 {
534     char xml_file_name[256];
535     create_xml_file("<root attr='test' attr2='test' attr='test123'></root>", xml_file_name, 256);
536     OS_XML xml;
537     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
538     ck_assert_str_eq(xml.err, "XMLERR: Attribute 'attr' already defined.");
539     ck_assert_int_eq(xml.err_line, 1);
540
541     OS_ClearXML(&xml);
542     unlink(xml_file_name);
543 }
544 END_TEST
545
546 START_TEST(test_noattributevalue)
547 {
548     char xml_file_name[256];
549     create_xml_file("<root attr></root>", xml_file_name, 256);
550     OS_XML xml;
551     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
552     ck_assert_str_eq(xml.err, "XMLERR: Attribute 'attr' has no value.");
553     ck_assert_int_eq(xml.err_line, 1);
554
555     OS_ClearXML(&xml);
556     unlink(xml_file_name);
557 }
558 END_TEST
559
560 START_TEST(test_noattributevalue2)
561 {
562     char xml_file_name[256];
563     create_xml_file("<root attr attr2='test'></root>", xml_file_name, 256);
564     OS_XML xml;
565     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
566     ck_assert_str_eq(xml.err, "XMLERR: Attribute 'attr' has no value.");
567     ck_assert_int_eq(xml.err_line, 1);
568
569     OS_ClearXML(&xml);
570     unlink(xml_file_name);
571 }
572 END_TEST
573
574 //TODO
575 /*START_TEST(test_unknownvariable)
576 {
577     char xml_file_name[256];
578     create_xml_file("<root>$var</root>", xml_file_name, 256);
579     OS_XML xml;
580     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
581     ck_assert_int_ne(OS_ApplyVariables(&xml), 0);
582     ck_assert_str_eq(xml.err, "XML_ERR: Unknown variable: var");
583     ck_assert_int_eq(xml.err_line, 0);
584
585     OS_ClearXML(&xml);
586     unlink(xml_file_name);
587 }
588 END_TEST*/
589
590 START_TEST(test_oselementsexists)
591 {
592     char xml_file_name[256];
593     create_xml_file("<root></root><root1/><root/>", xml_file_name, 256);
594     OS_XML xml;
595     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
596     ck_assert_int_eq(OS_ApplyVariables(&xml), 0);
597     ck_assert_int_eq(OS_RootElementExist(&xml, "root"), 2);
598     ck_assert_int_eq(OS_RootElementExist(&xml, "root1"), 1);
599     ck_assert_int_eq(OS_RootElementExist(&xml, "root2"), 0);
600
601     OS_ClearXML(&xml);
602     unlink(xml_file_name);
603 }
604 END_TEST
605
606 START_TEST(test_osgetonecontentforelement)
607 {
608     char xml_file_name[256];
609     create_xml_file("<root><child>test</child><child>test2</child><child2>test</child2></root>", xml_file_name, 256);
610     OS_XML xml;
611     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
612     ck_assert_int_eq(OS_ApplyVariables(&xml), 0);
613     const char *xml_path1[] = { "root", "child", NULL };
614     const char *xml_path2[] = { "root", "child2", NULL };
615     const char *xml_path3[] = { "root", "child3", NULL };
616     char *content1, *content2;
617     ck_assert_str_eq(content1 = OS_GetOneContentforElement(&xml, xml_path1), "test");
618     ck_assert_str_eq(content2 = OS_GetOneContentforElement(&xml, xml_path2), "test");
619     ck_assert_ptr_eq(OS_GetOneContentforElement(&xml, xml_path3), NULL);
620
621     free(content1);
622     free(content2);
623     OS_ClearXML(&xml);
624     unlink(xml_file_name);
625 }
626 END_TEST
627
628 static void assert_ox_xml_write_eq(const char *xml_str_old, const char *xml_str_new, const char **xml_path, const char *oldval, const char *newval)
629 {
630     char xml_in_file_name[256];
631     create_xml_file(xml_str_old, xml_in_file_name, 256);
632     char xml_out_file_name[256];
633     create_xml_file("", xml_out_file_name, 256);
634
635     ck_assert_int_eq(OS_WriteXML(xml_in_file_name, xml_out_file_name, xml_path, oldval, newval), 0);
636
637     OS_XML xml;
638     ck_assert_int_eq(OS_ReadXML(xml_out_file_name, &xml), 0);
639     ck_assert_int_eq(OS_ApplyVariables(&xml), 0);
640     assert_os_xml_eq_str(&xml, xml_str_new);
641
642     OS_ClearXML(&xml);
643     unlink(xml_in_file_name);
644     unlink(xml_out_file_name);
645 }
646
647 START_TEST(test_oswritexml_success)
648 {
649     const char *xml_path[] = { "root", "child", NULL };
650     assert_ox_xml_write_eq(
651         "<root><child>test</child></root>",
652         "<root><child>test_new</child></root>",
653         xml_path, "test", "test_new");
654
655     assert_ox_xml_write_eq(
656         "<root><child>test</child></root>",
657         "<root><child>test</child></root>",
658         xml_path, "test", "test");
659
660     assert_ox_xml_write_eq(
661         "<root><child></child></root>",
662         "<root><child>test</child></root>",
663         xml_path, "test", "test");
664
665     assert_ox_xml_write_eq(
666         "<root2><child></child></root2>",
667         "<root2><child></child></root2><root>\n <child>test</child></root>",
668         xml_path, NULL, "test");
669 }
670 END_TEST
671
672 START_TEST(test_oswritexml_failures)
673 {
674     char xml_in_file_name[256];
675     create_xml_file("<root><child>test</child></root>", xml_in_file_name, 256);
676     char xml_out_file_name[256];
677     create_xml_file("", xml_out_file_name, 256);
678     const char *xml_path[] = { "root", "child", NULL };
679
680     ck_assert_int_eq(OS_WriteXML("invalid", xml_out_file_name, xml_path, "test", "test_new"), XMLW_NOIN);
681     ck_assert_int_eq(OS_WriteXML(xml_in_file_name, "??invalid<<!!\"\"//\\\\", xml_path, "test", "test_new"), XMLW_NOOUT);
682
683     unlink(xml_in_file_name);
684     unlink(xml_out_file_name);
685 }
686 END_TEST
687
688 START_TEST(test_osgetattributecontent)
689 {
690     char xml_file_name[256];
691     create_xml_file("<root attr=\"value\" attr2=\"value1\"></root>", xml_file_name, 256);
692     OS_XML xml;
693     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
694     ck_assert_int_eq(OS_ApplyVariables(&xml), 0);
695     const char *xml_path1[] = { "root", NULL };
696     const char *xml_path2[] = { NULL };
697     char *content1, *content2, *content3, *content4;
698     ck_assert_str_eq(content1 = OS_GetAttributeContent(&xml, xml_path1, "attr"), "value");
699     ck_assert_str_eq(content2 = OS_GetAttributeContent(&xml, xml_path1, "attr2"), "value1");
700     ck_assert_str_eq(content3 = OS_GetAttributeContent(&xml, xml_path1, "attr3"), "");
701     ck_assert_str_eq(content4 = OS_GetAttributeContent(&xml, xml_path1, NULL), "");
702     ck_assert_ptr_eq(OS_GetAttributeContent(&xml, xml_path2, NULL), NULL);
703
704
705     free(content1);
706     free(content2);
707     free(content3);
708     free(content4);
709     OS_ClearXML(&xml);
710     unlink(xml_file_name);
711 }
712 END_TEST
713
714 START_TEST(test_osgetcontents)
715 {
716     char xml_file_name[256];
717     create_xml_file("<root>value</root><root>value2</root><root2>value</root2>", xml_file_name, 256);
718     OS_XML xml;
719     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
720     ck_assert_int_eq(OS_ApplyVariables(&xml), 0);
721     const char *xml_path1[] = { "root", NULL };
722     const char *xml_path2[] = { "root2", NULL };
723     char **content1, **content2;
724     ck_assert_ptr_ne(content1 = OS_GetContents(&xml, xml_path1), NULL);
725     ck_assert_str_eq(content1[0], "value");
726     ck_assert_str_eq(content1[1], "value2");
727     ck_assert_ptr_eq(content1[2], NULL);
728
729     ck_assert_ptr_ne(content2 = OS_GetContents(&xml, xml_path2), NULL);
730     ck_assert_str_eq(content2[0], "value");
731     ck_assert_ptr_eq(content2[1], NULL);
732
733     ck_assert_ptr_eq(OS_GetContents(&xml, NULL), NULL);
734
735     int i = 0;
736     while (content1[i]) {
737         free(content1[i++]);
738     }
739     free(content1);
740
741     i = 0;
742     while (content2[i]) {
743         free(content2[i++]);
744     }
745     free(content2);
746     OS_ClearXML(&xml);
747     unlink(xml_file_name);
748 }
749 END_TEST
750
751 START_TEST(test_osgetelementcontent)
752 {
753     char xml_file_name[256];
754     create_xml_file("<root>value</root>", xml_file_name, 256);
755     OS_XML xml;
756     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
757     ck_assert_int_eq(OS_ApplyVariables(&xml), 0);
758     const char *xml_path[] = { "root", NULL };
759     char **content;
760     ck_assert_ptr_ne(content = OS_GetElementContent(&xml, xml_path), NULL);
761     ck_assert_str_eq(content[0], "value");
762     ck_assert_ptr_eq(content[1], NULL);
763
764     int i = 0;
765     while (content[i]) {
766         free(content[i++]);
767     }
768     free(content);
769     OS_ClearXML(&xml);
770     unlink(xml_file_name);
771 }
772 END_TEST
773
774 START_TEST(test_osgetelements)
775 {
776     char xml_file_name[256];
777     create_xml_file("<root><child1/><child2/></root>", xml_file_name, 256);
778     OS_XML xml;
779     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
780     ck_assert_int_eq(OS_ApplyVariables(&xml), 0);
781     const char *xml_path[] = { "root", NULL };
782     char **content1, **content2;
783     ck_assert_ptr_ne(content1 = OS_GetElements(&xml, xml_path), NULL);
784     ck_assert_str_eq(content1[0], "child1");
785     ck_assert_str_eq(content1[1], "child2");
786     ck_assert_ptr_eq(content1[2], NULL);
787     ck_assert_ptr_ne(content2 = OS_GetElements(&xml, NULL), NULL);
788     ck_assert_str_eq(content2[0], "root");
789     ck_assert_ptr_eq(content2[1], NULL);
790     const char *xml_path2[] = { NULL };
791     ck_assert_ptr_eq(OS_GetElements(&xml,  xml_path2), NULL);
792
793     int i = 0;
794     while (content1[i]) {
795         free(content1[i++]);
796     }
797     free(content1);
798     i = 0;
799     while (content2[i]) {
800         free(content2[i++]);
801     }
802     free(content2);
803     OS_ClearXML(&xml);
804     unlink(xml_file_name);
805 }
806 END_TEST
807
808 START_TEST(test_osgetattributes)
809 {
810     char xml_file_name[256];
811     create_xml_file("<root attr1=\"1\" attr2=\"2\"></root>", xml_file_name, 256);
812     OS_XML xml;
813     ck_assert_int_eq(OS_ReadXML(xml_file_name, &xml), 0);
814     ck_assert_int_eq(OS_ApplyVariables(&xml), 0);
815     const char *xml_path[] = { "root", NULL };
816     char **content;
817     ck_assert_ptr_ne(content = OS_GetAttributes(&xml, xml_path), NULL);
818     ck_assert_str_eq(content[0], "attr1");
819     ck_assert_str_eq(content[1], "attr2");
820     ck_assert_ptr_eq(content[2], NULL);
821
822     int i = 0;
823     while (content[i]) {
824         free(content[i++]);
825     }
826     free(content);
827     OS_ClearXML(&xml);
828     unlink(xml_file_name);
829 }
830 END_TEST
831
832 START_TEST(test_osclearnode)
833 {
834     OS_ClearNode(NULL);
835 }
836 END_TEST
837
838 START_TEST(test_stringoverflow)
839 {
840     char xml_file_name[256];
841     char overflow_string[XML_MAXSIZE + 10];
842     memset(overflow_string, 'c', XML_MAXSIZE + 9);
843     overflow_string[XML_MAXSIZE + 9] = '\0';
844
845     char xml_string[2 * XML_MAXSIZE];
846     snprintf(xml_string, 2 * XML_MAXSIZE - 1, "<%s/>", overflow_string);
847     create_xml_file(xml_string, xml_file_name, 256);
848     OS_XML xml;
849     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
850     ck_assert_str_eq(xml.err, "XMLERR: String overflow.");
851     ck_assert_int_eq(xml.err_line, 1);
852
853     OS_ClearXML(&xml);
854     unlink(xml_file_name);
855 }
856 END_TEST
857
858 START_TEST(test_stringoverflow2)
859 {
860     char xml_file_name[256];
861     char overflow_string[XML_MAXSIZE + 10];
862     memset(overflow_string, 'c', XML_MAXSIZE + 9);
863     overflow_string[XML_MAXSIZE + 9] = '\0';
864
865     char xml_string[2 * XML_MAXSIZE];
866     snprintf(xml_string, 2 * XML_MAXSIZE - 1, "<test>%s</test>", overflow_string);
867     create_xml_file(xml_string, xml_file_name, 256);
868     OS_XML xml;
869     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
870     ck_assert_str_eq(xml.err, "XMLERR: String overflow.");
871     ck_assert_int_eq(xml.err_line, 1);
872
873     OS_ClearXML(&xml);
874     unlink(xml_file_name);
875 }
876 END_TEST
877
878 START_TEST(test_stringoverflow3)
879 {
880     char xml_file_name[256];
881     char overflow_string[XML_MAXSIZE + 10];
882     memset(overflow_string, 'c', XML_MAXSIZE + 9);
883     overflow_string[XML_MAXSIZE + 9] = '\0';
884
885     char xml_string[2 * XML_MAXSIZE];
886     snprintf(xml_string, 2 * XML_MAXSIZE - 1, "<test %s=\"test\">test</test>", overflow_string);
887     create_xml_file(xml_string, xml_file_name, 256);
888     OS_XML xml;
889     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
890     ck_assert_str_eq(xml.err, "XMLERR: Overflow attempt at attribute 'cccccccccccccccccccc'.");
891     ck_assert_int_eq(xml.err_line, 1);
892
893     OS_ClearXML(&xml);
894     unlink(xml_file_name);
895 }
896 END_TEST
897
898 START_TEST(test_stringoverflow4)
899 {
900     char xml_file_name[256];
901     char overflow_string[XML_MAXSIZE + 10];
902     memset(overflow_string, 'c', XML_MAXSIZE + 9);
903     overflow_string[XML_MAXSIZE + 9] = '\0';
904
905     char xml_string[2 * XML_MAXSIZE];
906     snprintf(xml_string, 2 * XML_MAXSIZE - 1, "<test test=\"%s\">test</test>", overflow_string);
907     create_xml_file(xml_string, xml_file_name, 256);
908     OS_XML xml;
909     ck_assert_int_ne(OS_ReadXML(xml_file_name, &xml), 0);
910     ck_assert_str_eq(xml.err, "XMLERR: Overflow attempt at attribute 'test'.");
911     ck_assert_int_eq(xml.err_line, 1);
912
913     OS_ClearXML(&xml);
914     unlink(xml_file_name);
915 }
916 END_TEST
917
918 Suite *test_suite(void)
919 {
920     Suite *s = suite_create("os_xml");
921
922     /* Core test case */
923     TCase *tc_core = tcase_create("Core");
924     tcase_add_test(tc_core, test_simplenodes);
925     tcase_add_test(tc_core, test_multiplenodes);
926     tcase_add_test(tc_core, test_multiplecontent);
927     tcase_add_test(tc_core, test_children);
928     tcase_add_test(tc_core, test_attributes);
929     tcase_add_test(tc_core, test_variables);
930     tcase_add_test(tc_core, test_comments);
931     tcase_add_test(tc_core, test_specialchars);
932     tcase_add_test(tc_core, test_linecounter);
933     tcase_add_test(tc_core, test_invalidfile);
934     tcase_add_test(tc_core, test_unclosednode);
935     tcase_add_test(tc_core, test_unclosednode2);
936     tcase_add_test(tc_core, test_unclosedcomment);
937     tcase_add_test(tc_core, test_nodenotopened);
938     tcase_add_test(tc_core, test_unclosedattribute);
939     tcase_add_test(tc_core, test_infiniteattribute);
940     tcase_add_test(tc_core, test_unquotedattribute);
941     tcase_add_test(tc_core, test_invalidvariablename);
942     tcase_add_test(tc_core, test_invalidvariable);
943     tcase_add_test(tc_core, test_invalidvariable2);
944     tcase_add_test(tc_core, test_unknownvariable1);
945     tcase_add_test(tc_core, test_unknownvariable2);
946     tcase_add_test(tc_core, test_infiniteattribute2);
947     tcase_add_test(tc_core, test_invalidattributestart);
948     tcase_add_test(tc_core, test_invalidattributeclosing);
949     tcase_add_test(tc_core, test_invalidattributeclosing2);
950     tcase_add_test(tc_core, test_infiniteattribute3);
951     tcase_add_test(tc_core, test_duplicateattribute);
952     tcase_add_test(tc_core, test_noattributevalue);
953     tcase_add_test(tc_core, test_noattributevalue2);
954     tcase_add_test(tc_core, test_oselementsexists);
955     tcase_add_test(tc_core, test_osgetonecontentforelement);
956     tcase_add_test(tc_core, test_oswritexml_success);
957     tcase_add_test(tc_core, test_oswritexml_failures);
958     tcase_add_test(tc_core, test_osgetattributecontent);
959     tcase_add_test(tc_core, test_osgetcontents);
960     tcase_add_test(tc_core, test_osgetelementcontent);
961     tcase_add_test(tc_core, test_osgetelements);
962     tcase_add_test(tc_core, test_osgetattributes);
963     tcase_add_test(tc_core, test_osclearnode);
964     tcase_add_test(tc_core, test_stringoverflow);
965     tcase_add_test(tc_core, test_stringoverflow2);
966     tcase_add_test(tc_core, test_stringoverflow3);
967     tcase_add_test(tc_core, test_stringoverflow4);
968     suite_add_tcase(s, tc_core);
969
970     return (s);
971 }
972
973 int main(void)
974 {
975     Suite *s = test_suite();
976     SRunner *sr = srunner_create(s);
977     srunner_run_all(sr, CK_NORMAL);
978     int number_failed = srunner_ntests_failed(sr);
979     srunner_free(sr);
980
981     return ((number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
982 }