blob: b39b4b09bd5e32dba87b0335a16476d5e8554a7a [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
Radek Krejcib7db73a2018-10-24 14:18:40 +020015#include "common.h"
Radek Krejcif3f47842018-11-15 11:22:15 +010016#include "../../src/set.c"
17#include "../../src/xml.c"
18#include "../../src/common.c"
19#include "../../src/log.c"
Radek Krejcid91dbaf2018-09-21 15:51:39 +020020#include <stdarg.h>
21#include <stddef.h>
22#include <setjmp.h>
23#include <cmocka.h>
24
25#include <stdio.h>
26#include <string.h>
27
Radek Krejcie7b95092019-05-15 11:03:07 +020028#include "../../src/printer.c"
Radek Krejcid91dbaf2018-09-21 15:51:39 +020029#include "libyang.h"
Radek Krejcid91dbaf2018-09-21 15:51:39 +020030
31#define BUFSIZE 1024
32char logbuf[BUFSIZE] = {0};
33
34/* set to 0 to printing error messages to stderr instead of checking them in code */
35#define ENABLE_LOGGER_CHECKING 1
36
37static void
38logger(LY_LOG_LEVEL level, const char *msg, const char *path)
39{
40 (void) level; /* unused */
41
42 if (path) {
43 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
44 } else {
45 strncpy(logbuf, msg, BUFSIZE - 1);
46 }
47}
48
49static int
50logger_setup(void **state)
51{
52 (void) state; /* unused */
53#if ENABLE_LOGGER_CHECKING
54 ly_set_log_clb(logger, 1);
55#endif
56 return 0;
57}
58
59void
60logbuf_clean(void)
61{
62 logbuf[0] = '\0';
63}
64
65#if ENABLE_LOGGER_CHECKING
66# define logbuf_assert(str) assert_string_equal(logbuf, str)
67#else
68# define logbuf_assert(str)
69#endif
70
71static void
72test_element(void **state)
73{
74 (void) state; /* unused */
75
76 size_t name_len, prefix_len;
Radek Krejci28e8cb52019-03-08 11:31:31 +010077 size_t buf_len, len;
Radek Krejcid91dbaf2018-09-21 15:51:39 +020078 const char *name, *prefix;
Radek Krejci28e8cb52019-03-08 11:31:31 +010079 char *buf = NULL, *out = NULL;
Radek Krejcid91dbaf2018-09-21 15:51:39 +020080 const char *str, *p;
Radek Krejci28e8cb52019-03-08 11:31:31 +010081 int dynamic;
Radek Krejcid91dbaf2018-09-21 15:51:39 +020082
83 struct lyxml_context ctx;
84 memset(&ctx, 0, sizeof ctx);
85 ctx.line = 1;
86
87 /* empty */
88 str = "";
Radek Krejci7a7fa902018-09-25 17:08:21 +020089 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +020090 assert_null(name);
Radek Krejcib1890642018-10-03 14:05:40 +020091 assert_int_equal(LYXML_END, ctx.status);
Radek Krejcid91dbaf2018-09-21 15:51:39 +020092 assert_true(str[0] == '\0');
93
Radek Krejcib1890642018-10-03 14:05:40 +020094 /* end element */
95 str = "</element>";
96 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejci3fbc9872019-04-16 16:50:01 +020097 logbuf_assert("Opening and closing elements tag missmatch (\"element\"). Line number 1.");
Radek Krejcib1890642018-10-03 14:05:40 +020098
99
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200100 /* no element */
101 logbuf_clean();
102 str = p = "no data present";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200103 assert_int_equal(LY_EINVAL, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200104 assert_null(name);
105 assert_ptr_equal(p, str); /* input data not eaten */
106 logbuf_assert("");
107
108 /* not supported DOCTYPE */
109 str = p = "<!DOCTYPE greeting SYSTEM \"hello.dtd\"><greeting/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200110 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200111 assert_null(name);
112 assert_ptr_equal(p, str); /* input data not eaten */
113 logbuf_assert("Document Type Declaration not supported. Line number 1.");
114
Radek Krejcic5c31bb2019-04-08 14:40:52 +0200115 /* invalid XML */
116 str = p = "<!NONSENCE/>";
117 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
118 assert_null(name);
119 assert_ptr_equal(p, str); /* input data not eaten */
120 logbuf_assert("Unknown XML section \"<!NONSENCE/>\". Line number 1.");
121
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200122 /* unqualified element */
123 str = " < element/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200124 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200125 assert_null(prefix);
126 assert_false(strncmp("element", name, name_len));
127 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200128 assert_int_equal(LYXML_ELEMENT, ctx.status);
129 assert_string_equal("", str);
Radek Krejci28e8cb52019-03-08 11:31:31 +0100130 assert_int_equal(0, ctx.elements.count);
131
132 str = " < element attr=\'x\'/>";
133 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
134 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
135 assert_string_equal("attr=\'x\'/>", str);
136 assert_int_equal(1, ctx.elements.count);
137 assert_int_equal(LY_SUCCESS, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
138 assert_int_equal(LYXML_ATTR_CONTENT, ctx.status);
139 assert_string_equal("\'x\'/>", str);
140 assert_int_equal(1, ctx.elements.count);
141 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
142 assert_int_equal(LYXML_ELEMENT, ctx.status);
143 assert_string_equal("", str);
144 assert_int_equal(0, ctx.elements.count);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200145
Radek Krejcifb7c6582018-09-21 16:12:45 +0200146 str = "<?xml version=\"1.0\"?> <!-- comment --> <![CDATA[<greeting>Hello, world!</greeting>]]> <?TEST xxx?> <element/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200147 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200148 assert_null(prefix);
149 assert_false(strncmp("element", name, name_len));
150 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200151 assert_int_equal(LYXML_ELEMENT, ctx.status);
152 assert_string_equal("", str);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200153
154 str = "<element xmlns=\"urn\"></element>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200155 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200156 assert_null(prefix);
157 assert_false(strncmp("element", name, name_len));
158 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200159 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
160 assert_string_equal("xmlns=\"urn\"></element>", str);
161 /* cleean context by getting closing tag */
162 str += 12;
163 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200164
165 /* qualified element */
166 str = " < yin:element/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200167 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200168 assert_false(strncmp("yin", prefix, prefix_len));
169 assert_false(strncmp("element", name, name_len));
170 assert_int_equal(3, prefix_len);
171 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200172 assert_int_equal(LYXML_ELEMENT, ctx.status);
173 assert_string_equal("", str);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200174
175 str = "<yin:element xmlns=\"urn\"></element>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200176 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200177 assert_false(strncmp("yin", prefix, prefix_len));
178 assert_false(strncmp("element", name, name_len));
179 assert_int_equal(3, prefix_len);
180 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200181 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
182 assert_string_equal("xmlns=\"urn\"></element>", str);
183 /* cleean context by getting closing tag */
184 str += 12;
185 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejci3fbc9872019-04-16 16:50:01 +0200186 logbuf_assert("Opening and closing elements tag missmatch (\"element\"). Line number 1.");
Radek Krejcia93621b2018-10-18 11:13:38 +0200187 str = "</yin:element/>";
188 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
189 logbuf_assert("Unexpected data \"/>\" in closing element tag. Line number 1.");
Radek Krejcib1890642018-10-03 14:05:40 +0200190 lyxml_context_clear(&ctx);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200191
192 /* UTF8 characters */
193 str = "<𠜎€𠜎Øn:𠜎€𠜎Øn/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200194 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200195 assert_false(strncmp("𠜎€𠜎Øn", prefix, prefix_len));
196 assert_false(strncmp("𠜎€𠜎Øn", name, name_len));
197 assert_int_equal(14, prefix_len);
198 assert_int_equal(14, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200199 assert_int_equal(LYXML_ELEMENT, ctx.status);
200 assert_string_equal("", str);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200201
202 /* invalid UTF-8 character */
203 str = "<¢:element>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200204 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200205 logbuf_assert("Identifier \"¢:element>\" starts with invalid character. Line number 1.");
206 str = "<yin:c⁐element>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200207 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200208 logbuf_assert("Invalid character sequence \"⁐element>\", expected whitespace or element tag termination ('>' or '/>'. Line number 1.");
209}
210
211static void
212test_attribute(void **state)
213{
214 (void) state; /* unused */
215
216 size_t name_len, prefix_len;
217 const char *name, *prefix;
218 const char *str, *p;
219
220 struct lyxml_context ctx;
221 memset(&ctx, 0, sizeof ctx);
222 ctx.line = 1;
223
224 /* empty - without element tag termination */
225 str = "";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200226 assert_int_equal(LY_EINVAL, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200227
Radek Krejcid972c252018-09-25 13:23:39 +0200228 /* not an attribute */
229 str = p = "unknown/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200230 assert_int_equal(LY_EVALID, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200231 assert_ptr_equal(p, str); /* input data not eaten */
232 logbuf_assert("Invalid character sequence \"/>\", expected whitespace or '='. Line number 1.");
233 str = p = "unknown />";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200234 assert_int_equal(LY_EVALID, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200235 assert_ptr_equal(p, str); /* input data not eaten */
236 logbuf_assert("Invalid character sequence \"/>\", expected '='. Line number 1.");
237 str = p = "xxx=/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200238 assert_int_equal(LY_EVALID, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200239 assert_ptr_equal(p, str); /* input data not eaten */
240 logbuf_assert("Invalid character sequence \"/>\", expected either single or double quotation mark. Line number 1.");
241 str = p = "xxx\n = yyy/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200242 assert_int_equal(LY_EVALID, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200243 assert_ptr_equal(p, str); /* input data not eaten */
244 logbuf_assert("Invalid character sequence \"yyy/>\", expected either single or double quotation mark. Line number 2.");
245
246 /* valid attribute */
247 str = "xmlns=\"urn\">";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200248 assert_int_equal(LY_SUCCESS, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200249 assert_non_null(name);
250 assert_null(prefix);
251 assert_int_equal(5, name_len);
252 assert_int_equal(0, prefix_len);
253 assert_false(strncmp("xmlns", name, name_len));
254 assert_string_equal("\"urn\">", str);
Radek Krejcib1890642018-10-03 14:05:40 +0200255 assert_int_equal(LYXML_ATTR_CONTENT, ctx.status);
Radek Krejcid972c252018-09-25 13:23:39 +0200256
Radek Krejci28e8cb52019-03-08 11:31:31 +0100257 str = "xmlns:nc\n = \'urn\'/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200258 assert_int_equal(LY_SUCCESS, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200259 assert_non_null(name);
260 assert_non_null(prefix);
261 assert_int_equal(2, name_len);
262 assert_int_equal(5, prefix_len);
263 assert_int_equal(3, ctx.line);
264 assert_false(strncmp("xmlns", prefix, prefix_len));
265 assert_false(strncmp("nc", name, name_len));
Radek Krejci28e8cb52019-03-08 11:31:31 +0100266 assert_string_equal("\'urn\'/>", str);
Radek Krejcib1890642018-10-03 14:05:40 +0200267 assert_int_equal(LYXML_ATTR_CONTENT, ctx.status);
Radek Krejci28e8cb52019-03-08 11:31:31 +0100268
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200269}
270
Radek Krejci7a7fa902018-09-25 17:08:21 +0200271static void
272test_text(void **state)
273{
274 (void) state; /* unused */
275
Radek Krejcid70d1072018-10-09 14:20:47 +0200276 size_t buf_len, len;
277 int dynamic;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200278 const char *str, *p;
Radek Krejcid70d1072018-10-09 14:20:47 +0200279 char *buf = NULL, *out = NULL;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200280
281 struct lyxml_context ctx;
282 memset(&ctx, 0, sizeof ctx);
283 ctx.line = 1;
284
285 /* empty attribute value */
Radek Krejcib1890642018-10-03 14:05:40 +0200286 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200287 str = "\"\"";
Radek Krejcid70d1072018-10-09 14:20:47 +0200288 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
289 assert_null(buf);
290 assert_ptr_equal(&str[-1], out);
291 assert_int_equal(0, dynamic);
292 assert_int_equal(0, len);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200293 assert_true(str[0] == '\0'); /* everything eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200294 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
295
296 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200297 str = "\'\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200298 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
299 assert_null(buf);
300 assert_ptr_equal(&str[-1], out);
301 assert_int_equal(0, dynamic);
302 assert_int_equal(0, len);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200303 assert_true(str[0] == '\0'); /* everything eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200304 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200305
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200306 /* empty element content - only formating before defining child */
Radek Krejcib1890642018-10-03 14:05:40 +0200307 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200308 str = "\n <";
Radek Krejcid70d1072018-10-09 14:20:47 +0200309 assert_int_equal(LY_EINVAL, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
310 assert_null(buf);
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200311 assert_string_equal("<", str);
312
Radek Krejci7a7fa902018-09-25 17:08:21 +0200313 /* empty element content is invalid - missing content terminating character < */
Radek Krejcib1890642018-10-03 14:05:40 +0200314 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200315 str = "";
Radek Krejcid70d1072018-10-09 14:20:47 +0200316 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
317 assert_null(buf);
Radek Krejci117d2082018-09-26 10:05:14 +0200318 logbuf_assert("Unexpected end-of-file. Line number 2.");
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200319
Radek Krejcib1890642018-10-03 14:05:40 +0200320 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200321 str = p = "xxx";
Radek Krejcid70d1072018-10-09 14:20:47 +0200322 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
323 assert_null(buf);
Radek Krejci117d2082018-09-26 10:05:14 +0200324 logbuf_assert("Unexpected end-of-file. Line number 2.");
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200325 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejci7a7fa902018-09-25 17:08:21 +0200326
Radek Krejci7a7fa902018-09-25 17:08:21 +0200327 /* valid strings */
Radek Krejcib1890642018-10-03 14:05:40 +0200328 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200329 str = "€𠜎Øn \n&lt;&amp;&quot;&apos;&gt; &#82;&#x4f;&#x4B;<";
Radek Krejcid70d1072018-10-09 14:20:47 +0200330 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
331 assert_int_not_equal(0, dynamic);
332 assert_non_null(buf);
333 assert_ptr_equal(out, buf);
334 assert_int_equal(22, buf_len);
335 assert_int_equal(21, len);
336 assert_string_equal("€𠜎Øn \n<&\"\'> ROK", buf);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200337 assert_string_equal("<", str);
Radek Krejcib1890642018-10-03 14:05:40 +0200338 assert_int_equal(LYXML_ELEMENT, ctx.status);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200339
Radek Krejci117d2082018-09-26 10:05:14 +0200340 /* test using n-bytes UTF8 hexadecimal code points */
Radek Krejcib1890642018-10-03 14:05:40 +0200341 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200342 str = "\'&#x0024;&#x00A2;&#x20ac;&#x10348;\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200343 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
344 assert_int_not_equal(0, dynamic);
345 assert_non_null(buf);
346 assert_ptr_equal(out, buf);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200347 assert_int_equal(22, buf_len);
Radek Krejcid70d1072018-10-09 14:20:47 +0200348 assert_int_equal(10, len);
349 assert_string_equal("$¢€𐍈", buf);
Radek Krejcib1890642018-10-03 14:05:40 +0200350 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
Radek Krejci117d2082018-09-26 10:05:14 +0200351
Radek Krejcid70d1072018-10-09 14:20:47 +0200352 free(buf);
353 buf = NULL;
354
Radek Krejci7a7fa902018-09-25 17:08:21 +0200355 /* invalid characters in string */
Radek Krejcib1890642018-10-03 14:05:40 +0200356 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200357 str = p = "\'&#x52\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200358 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200359 logbuf_assert("Invalid character sequence \"'\", expected ;. Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200360 assert_null(buf);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200361 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200362 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200363 str = p = "\"&#82\"";
Radek Krejcid70d1072018-10-09 14:20:47 +0200364 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200365 logbuf_assert("Invalid character sequence \"\"\", expected ;. Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200366 assert_null(buf);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200367 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200368 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200369 str = p = "\"&nonsence;\"";
Radek Krejcid70d1072018-10-09 14:20:47 +0200370 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200371 logbuf_assert("Entity reference \"&nonsence;\" not supported, only predefined references allowed. Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200372 assert_null(buf);
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200373 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200374 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200375 str = p = "&#o122;";
Radek Krejcid70d1072018-10-09 14:20:47 +0200376 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200377 logbuf_assert("Invalid character reference \"&#o122;\". Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200378 assert_null(buf);
Radek Krejci117d2082018-09-26 10:05:14 +0200379 assert_ptr_equal(p, str); /* input data not eaten */
380
Radek Krejcib1890642018-10-03 14:05:40 +0200381 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200382 str = p = "\'&#x06;\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200383 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200384 logbuf_assert("Invalid character reference \"&#x06;\'\" (0x00000006). Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200385 assert_null(buf);
Radek Krejci117d2082018-09-26 10:05:14 +0200386 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200387 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200388 str = p = "\'&#xfdd0;\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200389 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200390 logbuf_assert("Invalid character reference \"&#xfdd0;\'\" (0x0000fdd0). Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200391 assert_null(buf);
Radek Krejci117d2082018-09-26 10:05:14 +0200392 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200393 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200394 str = p = "\'&#xffff;\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200395 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200396 logbuf_assert("Invalid character reference \"&#xffff;\'\" (0x0000ffff). Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200397 assert_null(buf);
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200398 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejci7a7fa902018-09-25 17:08:21 +0200399}
400
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200401static void
402test_ns(void **state)
403{
404 (void) state; /* unused */
405
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200406 const struct lyxml_ns *ns;
407
408 struct lyxml_context ctx;
409 memset(&ctx, 0, sizeof ctx);
410 ctx.line = 1;
411
Radek Krejcie0734d22019-04-05 15:54:28 +0200412 /* simulate adding open element1 into context */
413 ctx.elements.count++;
414 /* processing namespace definitions */
Radek Krejci17a78d82019-05-15 15:49:55 +0200415 assert_int_equal(LY_SUCCESS, lyxml_ns_add(&ctx, NULL, 0, strdup("urn:default")));
416 assert_int_equal(LY_SUCCESS, lyxml_ns_add(&ctx, "nc", 2, strdup("urn:nc1")));
Radek Krejcie0734d22019-04-05 15:54:28 +0200417 /* simulate adding open element2 into context */
418 ctx.elements.count++;
419 /* processing namespace definitions */
Radek Krejci17a78d82019-05-15 15:49:55 +0200420 assert_int_equal(LY_SUCCESS, lyxml_ns_add(&ctx, "nc", 2, strdup("urn:nc2")));
Radek Krejcie0734d22019-04-05 15:54:28 +0200421 assert_int_equal(3, ctx.ns.count);
422 assert_int_not_equal(0, ctx.ns.size);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200423
424 ns = lyxml_ns_get(&ctx, NULL, 0);
425 assert_non_null(ns);
426 assert_null(ns->prefix);
427 assert_string_equal("urn:default", ns->uri);
428
429 ns = lyxml_ns_get(&ctx, "nc", 2);
430 assert_non_null(ns);
431 assert_string_equal("nc", ns->prefix);
432 assert_string_equal("urn:nc2", ns->uri);
433
Radek Krejcie0734d22019-04-05 15:54:28 +0200434 /* simulate closing element2 */
435 ctx.elements.count--;
Radek Krejci17a78d82019-05-15 15:49:55 +0200436 assert_int_equal(LY_SUCCESS, lyxml_ns_rm(&ctx));
Radek Krejcie0734d22019-04-05 15:54:28 +0200437 assert_int_equal(2, ctx.ns.count);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200438
439 ns = lyxml_ns_get(&ctx, "nc", 2);
440 assert_non_null(ns);
441 assert_string_equal("nc", ns->prefix);
442 assert_string_equal("urn:nc1", ns->uri);
443
Radek Krejcie0734d22019-04-05 15:54:28 +0200444 /* simulate closing element1 */
445 ctx.elements.count--;
Radek Krejci17a78d82019-05-15 15:49:55 +0200446 assert_int_equal(LY_SUCCESS, lyxml_ns_rm(&ctx));
Radek Krejcie0734d22019-04-05 15:54:28 +0200447 assert_int_equal(0, ctx.ns.count);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200448
449 assert_null(lyxml_ns_get(&ctx, "nc", 2));
450 assert_null(lyxml_ns_get(&ctx, NULL, 0));
451}
452
Radek Krejcie0734d22019-04-05 15:54:28 +0200453static void
454test_ns2(void **state)
455{
456 (void) state; /* unused */
457
Radek Krejcie0734d22019-04-05 15:54:28 +0200458 struct lyxml_context ctx;
459 memset(&ctx, 0, sizeof ctx);
460 ctx.line = 1;
461
Radek Krejcie0734d22019-04-05 15:54:28 +0200462 /* simulate adding open element1 into context */
463 ctx.elements.count++;
464 /* default namespace defined in parent element1 */
Radek Krejci17a78d82019-05-15 15:49:55 +0200465 assert_int_equal(LY_SUCCESS, lyxml_ns_add(&ctx, NULL, 0, strdup("urn:default")));
Radek Krejcie0734d22019-04-05 15:54:28 +0200466 assert_int_equal(1, ctx.ns.count);
467 /* going into child element1 */
Radek Krejcie0734d22019-04-05 15:54:28 +0200468 /* simulate adding open element1 into context */
469 ctx.elements.count++;
470 /* no namespace defined, going out (first, simulate closing of so far open element) */
471 ctx.elements.count--;
Radek Krejci17a78d82019-05-15 15:49:55 +0200472 assert_int_equal(LY_SUCCESS, lyxml_ns_rm(&ctx));
Radek Krejcie0734d22019-04-05 15:54:28 +0200473 assert_int_equal(1, ctx.ns.count);
474 /* nothing else, going out of the parent element1 (first, simulate closing of so far open element) */
475 ctx.elements.count--;
Radek Krejci17a78d82019-05-15 15:49:55 +0200476 assert_int_equal(LY_SUCCESS, lyxml_ns_rm(&ctx));
Radek Krejcie0734d22019-04-05 15:54:28 +0200477 assert_int_equal(0, ctx.ns.count);
478}
479
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200480int main(void)
481{
482 const struct CMUnitTest tests[] = {
Radek Krejcid972c252018-09-25 13:23:39 +0200483 cmocka_unit_test_setup(test_element, logger_setup),
484 cmocka_unit_test_setup(test_attribute, logger_setup),
Radek Krejci7a7fa902018-09-25 17:08:21 +0200485 cmocka_unit_test_setup(test_text, logger_setup),
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200486 cmocka_unit_test_setup(test_ns, logger_setup),
Radek Krejcie0734d22019-04-05 15:54:28 +0200487 cmocka_unit_test_setup(test_ns2, logger_setup),
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200488 };
489
490 return cmocka_run_group_tests(tests, NULL, NULL);
491}