blob: 3731fbeafe467aaf74c726c7acba2da923b6793e [file] [log] [blame]
Radek Krejcid91dbaf2018-09-21 15:51:39 +02001/*
2 * @file xml.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for functions from xml.c
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#define _BSD_SOURCE
16#define _DEFAULT_SOURCE
17#include <stdarg.h>
18#include <stddef.h>
19#include <setjmp.h>
20#include <cmocka.h>
21
22#include <stdio.h>
23#include <string.h>
24
25#include "libyang.h"
26#include "../../src/xml.c"
27
28#define BUFSIZE 1024
29char logbuf[BUFSIZE] = {0};
30
31/* set to 0 to printing error messages to stderr instead of checking them in code */
32#define ENABLE_LOGGER_CHECKING 1
33
34static void
35logger(LY_LOG_LEVEL level, const char *msg, const char *path)
36{
37 (void) level; /* unused */
38
39 if (path) {
40 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
41 } else {
42 strncpy(logbuf, msg, BUFSIZE - 1);
43 }
44}
45
46static int
47logger_setup(void **state)
48{
49 (void) state; /* unused */
50#if ENABLE_LOGGER_CHECKING
51 ly_set_log_clb(logger, 1);
52#endif
53 return 0;
54}
55
56void
57logbuf_clean(void)
58{
59 logbuf[0] = '\0';
60}
61
62#if ENABLE_LOGGER_CHECKING
63# define logbuf_assert(str) assert_string_equal(logbuf, str)
64#else
65# define logbuf_assert(str)
66#endif
67
68static void
69test_element(void **state)
70{
71 (void) state; /* unused */
72
73 size_t name_len, prefix_len;
74 const char *name, *prefix;
75 const char *str, *p;
76
77 struct lyxml_context ctx;
78 memset(&ctx, 0, sizeof ctx);
79 ctx.line = 1;
80
81 /* empty */
82 str = "";
83 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
84 assert_null(name);
85 assert_true(str[0] == '\0');
86
87 /* no element */
88 logbuf_clean();
89 str = p = "no data present";
90 assert_int_equal(LY_EINVAL, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
91 assert_null(name);
92 assert_ptr_equal(p, str); /* input data not eaten */
93 logbuf_assert("");
94
95 /* not supported DOCTYPE */
96 str = p = "<!DOCTYPE greeting SYSTEM \"hello.dtd\"><greeting/>";
97 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
98 assert_null(name);
99 assert_ptr_equal(p, str); /* input data not eaten */
100 logbuf_assert("Document Type Declaration not supported. Line number 1.");
101
102 /* unqualified element */
103 str = " < element/>";
104 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
105 assert_null(prefix);
106 assert_false(strncmp("element", name, name_len));
107 assert_int_equal(7, name_len);
108 assert_string_equal("/>", str);
109
110 str = "<?xml version=\"1.0\"?> <!-- comment --> <?TEST xxx?> <element/>";
111 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
112 assert_null(prefix);
113 assert_false(strncmp("element", name, name_len));
114 assert_int_equal(7, name_len);
115 assert_string_equal("/>", str);
116
117 str = "<element xmlns=\"urn\"></element>";
118 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
119 assert_null(prefix);
120 assert_false(strncmp("element", name, name_len));
121 assert_int_equal(7, name_len);
122 assert_string_equal(" xmlns=\"urn\"></element>", str);
123
124 /* qualified element */
125 str = " < yin:element/>";
126 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
127 assert_false(strncmp("yin", prefix, prefix_len));
128 assert_false(strncmp("element", name, name_len));
129 assert_int_equal(3, prefix_len);
130 assert_int_equal(7, name_len);
131 assert_string_equal("/>", str);
132
133 str = "<yin:element xmlns=\"urn\"></element>";
134 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
135 assert_false(strncmp("yin", prefix, prefix_len));
136 assert_false(strncmp("element", name, name_len));
137 assert_int_equal(3, prefix_len);
138 assert_int_equal(7, name_len);
139 assert_string_equal(" xmlns=\"urn\"></element>", str);
140
141 /* UTF8 characters */
142 str = "<𠜎€𠜎Øn:𠜎€𠜎Øn/>";
143 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
144 assert_false(strncmp("𠜎€𠜎Øn", prefix, prefix_len));
145 assert_false(strncmp("𠜎€𠜎Øn", name, name_len));
146 assert_int_equal(14, prefix_len);
147 assert_int_equal(14, name_len);
148 assert_string_equal("/>", str);
149
150 /* invalid UTF-8 character */
151 str = "<¢:element>";
152 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
153 logbuf_assert("Identifier \"¢:element>\" starts with invalid character. Line number 1.");
154 str = "<yin:c⁐element>";
155 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
156 logbuf_assert("Invalid character 0x9081e2. Line number 1.");
157}
158
159int main(void)
160{
161 const struct CMUnitTest tests[] = {
162 cmocka_unit_test_setup(test_element, logger_setup),
163 };
164
165 return cmocka_run_group_tests(tests, NULL, NULL);
166}