blob: 16066ca6430c6c2a1de8d09c7592ad6bed51bc7f [file] [log] [blame]
Mislav Novakovic3b799cb2016-03-16 17:21:56 +01001/*
2 * @file test_xml.c
3 * @author: Mislav Novakovic <mislav.novakovic@sartura.hr>
4 * @brief unit tests for functions from xml.h header
5 *
6 * Copyright (C) 2016 Deutsche Telekom AG.
7 *
8 * Author: Mislav Novakovic <mislav.novakovic@sartura.hr>
9 *
Luka Perkov01484582016-09-08 13:57:14 +020010 * This source code is licensed under BSD 3-Clause License (the "License").
11 * You may not use this file except in compliance with the License.
Mislav Novakovic3b799cb2016-03-16 17:21:56 +010012 * You may obtain a copy of the License at
13 *
Luka Perkov01484582016-09-08 13:57:14 +020014 * https://opensource.org/licenses/BSD-3-Clause
Mislav Novakovic3b799cb2016-03-16 17:21:56 +010015 */
16
17#include <stdarg.h>
18#include <stddef.h>
19#include <setjmp.h>
20#include <cmocka.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <sys/mman.h>
27#include <unistd.h>
28#include <string.h>
29
Jan Kundrátfd7a5c72017-10-26 17:45:06 +020030#include "tests/config.h"
31#include "libyang.h"
Mislav Novakovic3b799cb2016-03-16 17:21:56 +010032
Denis Volpato Martinse7416282016-10-05 00:57:32 -030033#define TMP_TEMPLATE "/tmp/libyang-XXXXXX"
34
Mislav Novakovic3b799cb2016-03-16 17:21:56 +010035struct ly_ctx *ctx = NULL;
36struct lyd_node *root = NULL;
37
38const char *a_data_xml = "\
39<x xmlns=\"urn:a\">\n\
40 <bubba>test</bubba>\n\
41 </x>\n";
42
43const char *a_data_xml_attr = "\
44<x xmlns=\"urn:a\" bubba=\"test\">\n\
45 <bubba xmlns=\"urn:a\" name=\"test\"/>\n\
46</x>\n";
47
48const char *res_xml = "<x xmlns=\"urn:a\"><bubba>test</bubba></x>";
49
50int
51generic_init(char *yang_file, char *yang_folder)
52{
53 LYS_INFORMAT yang_format;
54 char *schema = NULL;
55 struct stat sb_schema;
56 int fd = -1;
57
58 if (!yang_file || !yang_folder) {
59 goto error;
60 }
61
62 yang_format = LYS_IN_YIN;
63
Radek Krejcidd3263a2017-07-15 11:50:09 +020064 ctx = ly_ctx_new(yang_folder, 0);
Mislav Novakovic3b799cb2016-03-16 17:21:56 +010065 if (!ctx) {
66 goto error;
67 }
68
69 fd = open(yang_file, O_RDONLY);
70 if (fd == -1 || fstat(fd, &sb_schema) == -1 || !S_ISREG(sb_schema.st_mode)) {
71 goto error;
72 }
73
74 schema = mmap(NULL, sb_schema.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
75 close(fd);
76
77 if (!lys_parse_mem(ctx, schema, yang_format)) {
78 goto error;
79 }
80
81 /* cleanup */
82 munmap(schema, sb_schema.st_size);
83
84 return 0;
85
86error:
87 if (schema) {
88 munmap(schema, sb_schema.st_size);
89 }
90 if (fd != -1) {
91 close(fd);
92 }
93
94 return -1;
95}
96
97static int
98setup_f(void **state)
99{
100 (void) state; /* unused */
101 char *yang_file = TESTS_DIR"/api/files/a.yin";
102 char *yang_folder = TESTS_DIR"/api/files";
103 int rc;
104
105 rc = generic_init(yang_file, yang_folder);
106
107 if (rc) {
108 return -1;
109 }
110
111 return 0;
112}
113
114static int
115teardown_f(void **state)
116{
117 (void) state; /* unused */
118 if (root)
119 lyd_free(root);
120 if (ctx)
121 ly_ctx_destroy(ctx, NULL);
122
123 return 0;
124}
125
126static void
127test_lyxml_parse_mem(void **state)
128{
129 (void) state; /* unused */
130 struct lyxml_elem *xml = NULL;
131
132 xml = lyxml_parse_mem(ctx, a_data_xml, 0);
133
134 assert_string_equal("x", xml->name);
135
136 lyxml_free(ctx, xml);
137}
138
139static void
140test_lyxml_free(void **state)
141{
142 (void) state; /* unused */
143 struct lyxml_elem *xml = NULL;
144
145 xml = lyxml_parse_mem(ctx, a_data_xml, 0);
146
147 assert_string_equal("x", xml->name);
148
149 lyxml_free(ctx, xml);
150}
151
152static void
153test_lyxml_parse_path(void **state)
154{
155 (void) state; /* unused */
156 struct lyxml_elem *xml = NULL;
157 const char *path = TESTS_DIR"/api/files/a.xml";
158
159 xml = lyxml_parse_path(ctx, path, 0);
160 if (!xml) {
161 fail();
162 }
163
164 assert_string_equal("x", xml->name);
165
166 lyxml_free(ctx, xml);
167}
168
169static void
170test_lyxml_print_fd(void **state)
171{
172 (void) state; /* unused */
173 struct lyxml_elem *xml = NULL;
174 const char *path = TESTS_DIR"/api/files/a.xml";
175
176 xml = lyxml_parse_path(ctx, path, 0);
177 if (!xml) {
178 fail();
179 }
180
181 assert_string_equal("x", xml->name);
182
183 (void) state; /* unused */
184 char *result = NULL;
185 struct stat sb;
Radek Krejcica73f502016-09-30 14:48:54 +0200186 char file_name[20];
Mislav Novakovic3b799cb2016-03-16 17:21:56 +0100187 int rc;
188 int fd;
189
190 memset(file_name, 0, sizeof(file_name));
Jan Kundrát0ef7e5b2018-05-22 19:38:01 +0200191 strncpy(file_name, TMP_TEMPLATE, sizeof(file_name));
Mislav Novakovic3b799cb2016-03-16 17:21:56 +0100192
193 fd = mkstemp(file_name);
194 if (fd < 1) {
195 goto error;
196 }
197
198 rc = lyxml_print_fd(fd, xml, 0);
199 if (!rc) {
200 goto error;
201 }
202
203 if (fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode)) {
204 goto error;
205 }
206
207 result = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
208
209 assert_string_equal(res_xml, result);
210
211 close(fd);
212 unlink(file_name);
213 lyxml_free(ctx, xml);
214
215 return;
216error:
217 if (fd > 0) {
218 close(fd);
219 unlink(file_name);
220 }
221 if (!xml)
222 lyxml_free(ctx, xml);
223 fail();
224}
225
226static void
227test_lyxml_print_file(void **state)
228{
229 (void) state; /* unused */
230 struct lyxml_elem *xml = NULL;
231 const char *path = TESTS_DIR"/api/files/a.xml";
232 struct stat sb;
Radek Krejcica73f502016-09-30 14:48:54 +0200233 char file_name[20];
Mislav Novakovic3b799cb2016-03-16 17:21:56 +0100234 char *result;
235 FILE *f = NULL;
236 int rc;
237 int fd;
238
239 xml = lyxml_parse_path(ctx, path, 0);
240 if (!xml) {
241 fail();
242 }
243
244 assert_string_equal("x", xml->name);
245
246 memset(file_name, 0, sizeof(file_name));
Jan Kundrát0ef7e5b2018-05-22 19:38:01 +0200247 strncpy(file_name, TMP_TEMPLATE, sizeof(file_name));
Mislav Novakovic3b799cb2016-03-16 17:21:56 +0100248
249 fd = mkstemp(file_name);
250 if (fd < 1) {
251 goto error;
252 }
253 close(fd);
254
255 f = (fopen(file_name,"r+"));
256 if (f == NULL) {
257 goto error;
258 }
259
260 rc = lyxml_print_file(f, xml, 0);
261 if (!rc) {
262 goto error;
263 }
264
265 fclose(f);
266
267 fd = open(file_name, O_RDONLY);
Radek Krejci849ba332016-03-24 10:23:16 +0100268 if (fd == -1 || fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode)) {
Mislav Novakovic3b799cb2016-03-16 17:21:56 +0100269 goto error;
270 }
271
272 result = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
273
274 assert_string_equal(res_xml, result);
275
276 close(fd);
277 unlink(file_name);
278 lyxml_free(ctx, xml);
279
280 return;
281error:
282 if (f)
283 fclose(f);
284 if (fd > 0) {
285 unlink(file_name);
286 close(fd);
287 }
288 if (xml)
289 lyxml_free(ctx, xml);
290 fail();
291}
292
293static void
294test_lyxml_print_mem(void **state)
295{
296 (void) state; /* unused */
297 struct lyxml_elem *xml = NULL;
298 const char *path = TESTS_DIR"/api/files/a.xml";
299 char *result = NULL;
300 int rc;
301
302 xml = lyxml_parse_path(ctx, path, 0);
303 if (!xml) {
304 fail();
305 }
306
307 assert_string_equal("x", xml->name);
308
309 rc = lyxml_print_mem(&result, xml, 0);
310 if (!rc) {
311 lyxml_free(ctx, xml);
312 fail();
313 }
314
315 assert_string_equal(res_xml, result);
316
317 lyxml_free(ctx, xml);
318 free(result);
319}
320
321struct buff {
322 int len;
323 const char *cmp;
324};
325
326ssize_t custom_lyxml_print_clb(void *arg, const void *buf, size_t count) {
327 int rc;
328 int len;
329 struct buff *pos = arg;
330
331 len = pos->len + count;
332
333 const char *chunk = &pos->cmp[pos->len];
334
335 rc = strncmp(chunk, buf, count);
336 if (rc) {
337 fail();
338 }
339
340 pos->len = len;
341 return count;
342}
343
344static void
345test_lyxml_print_clb(void **state)
346{
347 (void) state; /* unused */
348 struct lyxml_elem *xml = NULL;
349 const char *path = TESTS_DIR"/api/files/a.xml";
350 int rc;
351
352 xml = lyxml_parse_path(ctx, path, 0);
353 if (!xml) {
354 fail();
355 }
356
357 assert_string_equal("x", xml->name);
358
359 struct buff *buf = calloc(1, sizeof(struct buff));
360 if (!buf) {
361 fail();
362 lyxml_free(ctx, xml);
363 }
364
365 buf->len = 0;
366 buf->cmp = res_xml;
367 void *arg = buf;
368
369 rc = lyxml_print_clb(custom_lyxml_print_clb, arg, xml, 0);
370 if (!rc) {
371 fail();
372 free(buf);
373 lyxml_free(ctx, xml);
374 }
375
376 free(buf);
377 lyxml_free(ctx, xml);
378}
379
380static void
381test_lyxml_unlink(void **state)
382{
383 (void) state; /* unused */
384 struct lyxml_elem *xml = NULL;
385
386 xml = lyxml_parse_mem(ctx, a_data_xml, 0);
387
388 assert_string_equal("bubba", xml->child->name);
389 lyxml_free(ctx, xml->child);
390 lyxml_unlink(ctx, xml->child);
391
392 if (xml->child) {
393 fail();
394 }
395
396 lyxml_free(ctx, xml);
397}
398
399static void
400test_lyxml_get_attr(void **state)
401{
402 (void) state; /* unused */
403 struct lyxml_elem *xml = NULL;
404 const char *result = NULL;
405
406 xml = lyxml_parse_mem(ctx, a_data_xml_attr, 0);
407
408 result = lyxml_get_attr(xml, "bubba", NULL);
409 if (!result) {
410 lyxml_free(ctx, xml);
411 fail();
412 }
413
414 assert_string_equal("test", result);
415
416 lyxml_free(ctx, xml);
417}
418
419static void
420test_lyxml_get_ns(void **state)
421{
422 (void) state; /* unused */
423 struct lyxml_elem *xml = NULL;
424 const struct lyxml_ns *ns = NULL;
425
426 xml = lyxml_parse_mem(ctx, a_data_xml, 0);
427
428 ns = lyxml_get_ns(xml, NULL);
429 if (!ns) {
430 lyxml_free(ctx, xml);
431 fail();
432 }
433
434 assert_string_equal("urn:a", ns->value);
435
436 lyxml_free(ctx, xml);
437}
438
jospudja216c1f72018-08-20 15:16:55 +0200439void
440test_lyxml_dup(void **state)
441{
442 (void) state;
443 struct lyxml_elem *first_xml = NULL;
444 struct lyxml_elem *second_xml = NULL;
445 const char *path = TESTS_DIR"/api/files/a.xml";
446
447 first_xml = lyxml_parse_path(ctx, path, 0);
448
449 if (!first_xml) {
450 fail();
451 }
452
453 /* Making sure that the first and the second element aren't the same */
454 if (first_xml == second_xml) {
455 fail();
456 }
457
458 second_xml = lyxml_dup(ctx, first_xml);
459
460 /* Checking whether the first element is duplicated into the second */
461 if (!second_xml) {
462 fail();
463 }
464
465 /* Freeing the elements */
466 lyxml_free(ctx, first_xml);
467 lyxml_free(ctx, second_xml);
468}
469
470void
471test_lyxml_free_withsiblings(void **state)
472{
473 (void) state;
474 struct lyxml_elem *xml = NULL;
475 const char *path = TESTS_DIR"/api/files/a.xml";
476 xml = lyxml_parse_path(ctx, path, 0);
477
478 /* Making sure the element is not null */
479 if (!xml) {
480 fail();
481 }
482
483 /* Freeing the element with its siblings */
484 lyxml_free_withsiblings(ctx, xml);
485}
486
Mislav Novakovic3b799cb2016-03-16 17:21:56 +0100487int main(void)
488{
489 const struct CMUnitTest tests[] = {
490 cmocka_unit_test_setup_teardown(test_lyxml_parse_mem, setup_f, teardown_f),
491 cmocka_unit_test_setup_teardown(test_lyxml_free, setup_f, teardown_f),
492 cmocka_unit_test_setup_teardown(test_lyxml_parse_path, setup_f, teardown_f),
493 cmocka_unit_test_setup_teardown(test_lyxml_print_file, setup_f, teardown_f),
494 cmocka_unit_test_setup_teardown(test_lyxml_print_fd, setup_f, teardown_f),
495 cmocka_unit_test_setup_teardown(test_lyxml_print_mem, setup_f, teardown_f),
496 cmocka_unit_test_setup_teardown(test_lyxml_print_clb, setup_f, teardown_f),
497 cmocka_unit_test_setup_teardown(test_lyxml_unlink, setup_f, teardown_f),
498 cmocka_unit_test_setup_teardown(test_lyxml_get_attr, setup_f, teardown_f),
499 cmocka_unit_test_setup_teardown(test_lyxml_get_ns, setup_f, teardown_f),
jospudja216c1f72018-08-20 15:16:55 +0200500 cmocka_unit_test_setup_teardown(test_lyxml_dup, setup_f, teardown_f),
501 cmocka_unit_test_setup_teardown(test_lyxml_free_withsiblings, setup_f, teardown_f),
Mislav Novakovic3b799cb2016-03-16 17:21:56 +0100502 };
503
504 return cmocka_run_group_tests(tests, NULL, NULL);
505}