blob: 13ffce600f0945180afad7f7377692d18302b51a [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
Radek Krejcifb7c6582018-09-21 16:12:45 +020068
69static void
70test_utf8(void **state)
71{
72 (void) state; /* unused */
73
74 char buf[5] = {0};
75 const char *str = buf;
76 unsigned int c;
77 size_t len;
78
79 /* test invalid UTF-8 characters in lyxml_getutf8
80 * - https://en.wikipedia.org/wiki/UTF-8 */
81 buf[0] = 0x80;
82 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
83
84 buf[1] = 0xe0;
85 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
86 buf[1] = 0x80;
87 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
88
89 buf[2] = 0xf0;
90 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
91 buf[2] = 0xc0;
92 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
93 buf[2] = 0x80;
94 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
95
96 buf[3] = 0xf8;
97 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
98 buf[3] = 0xe0;
99 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
100 buf[3] = 0xc0;
101 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
102 buf[3] = 0x80;
103 assert_int_equal(LY_EINVAL, lyxml_getutf8(&str, &c, &len));
104}
105
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200106static void
107test_element(void **state)
108{
109 (void) state; /* unused */
110
111 size_t name_len, prefix_len;
112 const char *name, *prefix;
113 const char *str, *p;
114
115 struct lyxml_context ctx;
116 memset(&ctx, 0, sizeof ctx);
117 ctx.line = 1;
118
119 /* empty */
120 str = "";
121 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
122 assert_null(name);
123 assert_true(str[0] == '\0');
124
125 /* no element */
126 logbuf_clean();
127 str = p = "no data present";
128 assert_int_equal(LY_EINVAL, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
129 assert_null(name);
130 assert_ptr_equal(p, str); /* input data not eaten */
131 logbuf_assert("");
132
133 /* not supported DOCTYPE */
134 str = p = "<!DOCTYPE greeting SYSTEM \"hello.dtd\"><greeting/>";
135 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
136 assert_null(name);
137 assert_ptr_equal(p, str); /* input data not eaten */
138 logbuf_assert("Document Type Declaration not supported. Line number 1.");
139
140 /* unqualified element */
141 str = " < element/>";
142 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
143 assert_null(prefix);
144 assert_false(strncmp("element", name, name_len));
145 assert_int_equal(7, name_len);
146 assert_string_equal("/>", str);
147
Radek Krejcifb7c6582018-09-21 16:12:45 +0200148 str = "<?xml version=\"1.0\"?> <!-- comment --> <![CDATA[<greeting>Hello, world!</greeting>]]> <?TEST xxx?> <element/>";
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200149 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
150 assert_null(prefix);
151 assert_false(strncmp("element", name, name_len));
152 assert_int_equal(7, name_len);
153 assert_string_equal("/>", str);
154
155 str = "<element xmlns=\"urn\"></element>";
156 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
157 assert_null(prefix);
158 assert_false(strncmp("element", name, name_len));
159 assert_int_equal(7, name_len);
160 assert_string_equal(" xmlns=\"urn\"></element>", str);
161
162 /* qualified element */
163 str = " < yin:element/>";
164 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
165 assert_false(strncmp("yin", prefix, prefix_len));
166 assert_false(strncmp("element", name, name_len));
167 assert_int_equal(3, prefix_len);
168 assert_int_equal(7, name_len);
169 assert_string_equal("/>", str);
170
171 str = "<yin:element xmlns=\"urn\"></element>";
172 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
173 assert_false(strncmp("yin", prefix, prefix_len));
174 assert_false(strncmp("element", name, name_len));
175 assert_int_equal(3, prefix_len);
176 assert_int_equal(7, name_len);
177 assert_string_equal(" xmlns=\"urn\"></element>", str);
178
179 /* UTF8 characters */
180 str = "<𠜎€𠜎Øn:𠜎€𠜎Øn/>";
181 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
182 assert_false(strncmp("𠜎€𠜎Øn", prefix, prefix_len));
183 assert_false(strncmp("𠜎€𠜎Øn", name, name_len));
184 assert_int_equal(14, prefix_len);
185 assert_int_equal(14, name_len);
186 assert_string_equal("/>", str);
187
188 /* invalid UTF-8 character */
189 str = "<¢:element>";
190 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
191 logbuf_assert("Identifier \"¢:element>\" starts with invalid character. Line number 1.");
192 str = "<yin:c⁐element>";
193 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, 0, &prefix, &prefix_len, &name, &name_len));
194 logbuf_assert("Invalid character 0x9081e2. Line number 1.");
195}
196
197int main(void)
198{
199 const struct CMUnitTest tests[] = {
Radek Krejcifb7c6582018-09-21 16:12:45 +0200200 cmocka_unit_test_setup(test_utf8, logger_setup),
201 cmocka_unit_test(test_element),
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200202 };
203
204 return cmocka_run_group_tests(tests, NULL, NULL);
205}