blob: 216e6b2ae0ad4e3a42a11370147ec114b2de9df2 [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 Krejci2d7a47b2019-05-16 13:34:10 +020015#define _DEFAULT_SOURCE
16#define _GNU_SOURCE
17
Radek Krejcid91dbaf2018-09-21 15:51:39 +020018#include <stdarg.h>
19#include <stddef.h>
20#include <setjmp.h>
21#include <cmocka.h>
22
Radek Krejci2d7a47b2019-05-16 13:34:10 +020023#include <stdlib.h>
Radek Krejcid91dbaf2018-09-21 15:51:39 +020024#include <stdio.h>
25#include <string.h>
26
Radek Krejci2d7a47b2019-05-16 13:34:10 +020027#include "../../src/xml.h"
28
29LY_ERR lyxml_ns_add(struct lyxml_context *context, const char *prefix, size_t prefix_len, char *uri);
30LY_ERR lyxml_ns_rm(struct lyxml_context *context);
Radek Krejcid91dbaf2018-09-21 15:51:39 +020031
32#define BUFSIZE 1024
33char logbuf[BUFSIZE] = {0};
34
35/* set to 0 to printing error messages to stderr instead of checking them in code */
36#define ENABLE_LOGGER_CHECKING 1
37
38static void
39logger(LY_LOG_LEVEL level, const char *msg, const char *path)
40{
41 (void) level; /* unused */
42
43 if (path) {
44 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
45 } else {
46 strncpy(logbuf, msg, BUFSIZE - 1);
47 }
48}
49
50static int
51logger_setup(void **state)
52{
53 (void) state; /* unused */
54#if ENABLE_LOGGER_CHECKING
55 ly_set_log_clb(logger, 1);
56#endif
57 return 0;
58}
59
60void
61logbuf_clean(void)
62{
63 logbuf[0] = '\0';
64}
65
66#if ENABLE_LOGGER_CHECKING
67# define logbuf_assert(str) assert_string_equal(logbuf, str)
68#else
69# define logbuf_assert(str)
70#endif
71
72static void
73test_element(void **state)
74{
75 (void) state; /* unused */
76
77 size_t name_len, prefix_len;
Radek Krejci28e8cb52019-03-08 11:31:31 +010078 size_t buf_len, len;
Radek Krejcid91dbaf2018-09-21 15:51:39 +020079 const char *name, *prefix;
Radek Krejci28e8cb52019-03-08 11:31:31 +010080 char *buf = NULL, *out = NULL;
Radek Krejcid91dbaf2018-09-21 15:51:39 +020081 const char *str, *p;
Radek Krejci28e8cb52019-03-08 11:31:31 +010082 int dynamic;
Radek Krejcid91dbaf2018-09-21 15:51:39 +020083
84 struct lyxml_context ctx;
85 memset(&ctx, 0, sizeof ctx);
86 ctx.line = 1;
87
88 /* empty */
89 str = "";
Radek Krejci7a7fa902018-09-25 17:08:21 +020090 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +020091 assert_null(name);
Radek Krejcib1890642018-10-03 14:05:40 +020092 assert_int_equal(LYXML_END, ctx.status);
Radek Krejcid91dbaf2018-09-21 15:51:39 +020093 assert_true(str[0] == '\0');
94
Radek Krejcib1890642018-10-03 14:05:40 +020095 /* end element */
96 str = "</element>";
97 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejci3fbc9872019-04-16 16:50:01 +020098 logbuf_assert("Opening and closing elements tag missmatch (\"element\"). Line number 1.");
Radek Krejcib1890642018-10-03 14:05:40 +020099
100
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200101 /* no element */
102 logbuf_clean();
103 str = p = "no data present";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200104 assert_int_equal(LY_EINVAL, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200105 assert_null(name);
106 assert_ptr_equal(p, str); /* input data not eaten */
107 logbuf_assert("");
108
109 /* not supported DOCTYPE */
110 str = p = "<!DOCTYPE greeting SYSTEM \"hello.dtd\"><greeting/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200111 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200112 assert_null(name);
113 assert_ptr_equal(p, str); /* input data not eaten */
114 logbuf_assert("Document Type Declaration not supported. Line number 1.");
115
Radek Krejcic5c31bb2019-04-08 14:40:52 +0200116 /* invalid XML */
117 str = p = "<!NONSENCE/>";
118 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
119 assert_null(name);
120 assert_ptr_equal(p, str); /* input data not eaten */
121 logbuf_assert("Unknown XML section \"<!NONSENCE/>\". Line number 1.");
122
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200123 /* unqualified element */
124 str = " < element/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200125 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200126 assert_null(prefix);
127 assert_false(strncmp("element", name, name_len));
128 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200129 assert_int_equal(LYXML_ELEMENT, ctx.status);
130 assert_string_equal("", str);
Radek Krejci28e8cb52019-03-08 11:31:31 +0100131 assert_int_equal(0, ctx.elements.count);
132
133 str = " < element attr=\'x\'/>";
134 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
135 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
136 assert_string_equal("attr=\'x\'/>", str);
137 assert_int_equal(1, ctx.elements.count);
138 assert_int_equal(LY_SUCCESS, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
139 assert_int_equal(LYXML_ATTR_CONTENT, ctx.status);
140 assert_string_equal("\'x\'/>", str);
141 assert_int_equal(1, ctx.elements.count);
142 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
143 assert_int_equal(LYXML_ELEMENT, ctx.status);
144 assert_string_equal("", str);
145 assert_int_equal(0, ctx.elements.count);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200146
Radek Krejcifb7c6582018-09-21 16:12:45 +0200147 str = "<?xml version=\"1.0\"?> <!-- comment --> <![CDATA[<greeting>Hello, world!</greeting>]]> <?TEST xxx?> <element/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200148 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200149 assert_null(prefix);
150 assert_false(strncmp("element", name, name_len));
151 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200152 assert_int_equal(LYXML_ELEMENT, ctx.status);
153 assert_string_equal("", str);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200154
155 str = "<element xmlns=\"urn\"></element>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200156 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200157 assert_null(prefix);
158 assert_false(strncmp("element", name, name_len));
159 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200160 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
161 assert_string_equal("xmlns=\"urn\"></element>", str);
162 /* cleean context by getting closing tag */
163 str += 12;
164 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200165
166 /* qualified element */
167 str = " < yin:element/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200168 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200169 assert_false(strncmp("yin", prefix, prefix_len));
170 assert_false(strncmp("element", name, name_len));
171 assert_int_equal(3, prefix_len);
172 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200173 assert_int_equal(LYXML_ELEMENT, ctx.status);
174 assert_string_equal("", str);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200175
176 str = "<yin:element xmlns=\"urn\"></element>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200177 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200178 assert_false(strncmp("yin", prefix, prefix_len));
179 assert_false(strncmp("element", name, name_len));
180 assert_int_equal(3, prefix_len);
181 assert_int_equal(7, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200182 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
183 assert_string_equal("xmlns=\"urn\"></element>", str);
184 /* cleean context by getting closing tag */
185 str += 12;
186 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejci3fbc9872019-04-16 16:50:01 +0200187 logbuf_assert("Opening and closing elements tag missmatch (\"element\"). Line number 1.");
Radek Krejcia93621b2018-10-18 11:13:38 +0200188 str = "</yin:element/>";
189 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
190 logbuf_assert("Unexpected data \"/>\" in closing element tag. Line number 1.");
Radek Krejcib1890642018-10-03 14:05:40 +0200191 lyxml_context_clear(&ctx);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200192
193 /* UTF8 characters */
194 str = "<𠜎€𠜎Øn:𠜎€𠜎Øn/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200195 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200196 assert_false(strncmp("𠜎€𠜎Øn", prefix, prefix_len));
197 assert_false(strncmp("𠜎€𠜎Øn", name, name_len));
198 assert_int_equal(14, prefix_len);
199 assert_int_equal(14, name_len);
Radek Krejcib1890642018-10-03 14:05:40 +0200200 assert_int_equal(LYXML_ELEMENT, ctx.status);
201 assert_string_equal("", str);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200202
203 /* invalid UTF-8 character */
204 str = "<¢:element>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200205 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200206 logbuf_assert("Identifier \"¢:element>\" starts with invalid character. Line number 1.");
207 str = "<yin:c⁐element>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200208 assert_int_equal(LY_EVALID, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200209 logbuf_assert("Invalid character sequence \"⁐element>\", expected whitespace or element tag termination ('>' or '/>'. Line number 1.");
Radek Krejci339e2de2019-05-17 14:28:24 +0200210
211 /* mixed content */
212 str = "<a>text <b>x</b></a>";
213 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
214 assert_string_equal("text <b>x</b></a>", str);
215 assert_int_equal(LYXML_ELEM_CONTENT, ctx.status);
216 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
217 logbuf_assert("Mixed XML content is not allowed (text <b>). Line number 1.");
218 lyxml_context_clear(&ctx);
219
Radek Krejcid972c252018-09-25 13:23:39 +0200220}
221
222static void
223test_attribute(void **state)
224{
225 (void) state; /* unused */
226
227 size_t name_len, prefix_len;
228 const char *name, *prefix;
229 const char *str, *p;
230
231 struct lyxml_context ctx;
232 memset(&ctx, 0, sizeof ctx);
233 ctx.line = 1;
234
235 /* empty - without element tag termination */
236 str = "";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200237 assert_int_equal(LY_EINVAL, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200238
Radek Krejcid972c252018-09-25 13:23:39 +0200239 /* not an attribute */
240 str = p = "unknown/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200241 assert_int_equal(LY_EVALID, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200242 assert_ptr_equal(p, str); /* input data not eaten */
243 logbuf_assert("Invalid character sequence \"/>\", expected whitespace or '='. Line number 1.");
244 str = p = "unknown />";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200245 assert_int_equal(LY_EVALID, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200246 assert_ptr_equal(p, str); /* input data not eaten */
247 logbuf_assert("Invalid character sequence \"/>\", expected '='. Line number 1.");
248 str = p = "xxx=/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200249 assert_int_equal(LY_EVALID, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200250 assert_ptr_equal(p, str); /* input data not eaten */
251 logbuf_assert("Invalid character sequence \"/>\", expected either single or double quotation mark. Line number 1.");
252 str = p = "xxx\n = yyy/>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200253 assert_int_equal(LY_EVALID, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid972c252018-09-25 13:23:39 +0200254 assert_ptr_equal(p, str); /* input data not eaten */
255 logbuf_assert("Invalid character sequence \"yyy/>\", expected either single or double quotation mark. Line number 2.");
256
257 /* valid attribute */
258 str = "xmlns=\"urn\">";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200259 assert_int_equal(LY_SUCCESS, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejci49165732019-05-15 16:41:58 +0200260 assert_null(name);
Radek Krejcid972c252018-09-25 13:23:39 +0200261 assert_null(prefix);
Radek Krejci49165732019-05-15 16:41:58 +0200262 assert_int_equal(0, name_len);
Radek Krejcid972c252018-09-25 13:23:39 +0200263 assert_int_equal(0, prefix_len);
Radek Krejci49165732019-05-15 16:41:58 +0200264 assert_int_equal(1, ctx.ns.count);
265 assert_string_equal("", str);
266 assert_int_equal(LYXML_ELEM_CONTENT, ctx.status);
Radek Krejcid972c252018-09-25 13:23:39 +0200267
Radek Krejci49165732019-05-15 16:41:58 +0200268 str = "xmlns:nc\n = \'urn\'>";
Radek Krejci7a7fa902018-09-25 17:08:21 +0200269 assert_int_equal(LY_SUCCESS, lyxml_get_attribute(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejci49165732019-05-15 16:41:58 +0200270 assert_null(name);
271 assert_null(prefix);
272 assert_int_equal(0, name_len);
273 assert_int_equal(0, prefix_len);
Radek Krejcid972c252018-09-25 13:23:39 +0200274 assert_int_equal(3, ctx.line);
Radek Krejci49165732019-05-15 16:41:58 +0200275 assert_int_equal(2, ctx.ns.count);
276 assert_string_equal("", str);
277 assert_int_equal(LYXML_ELEM_CONTENT, ctx.status);
Radek Krejci28e8cb52019-03-08 11:31:31 +0100278
Radek Krejci49165732019-05-15 16:41:58 +0200279 lyxml_context_clear(&ctx);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200280}
281
Radek Krejci7a7fa902018-09-25 17:08:21 +0200282static void
283test_text(void **state)
284{
285 (void) state; /* unused */
286
Radek Krejcid70d1072018-10-09 14:20:47 +0200287 size_t buf_len, len;
288 int dynamic;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200289 const char *str, *p;
Radek Krejcid70d1072018-10-09 14:20:47 +0200290 char *buf = NULL, *out = NULL;
Radek Krejci339e2de2019-05-17 14:28:24 +0200291 const char *prefix, *name;
292 size_t prefix_len, name_len;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200293
294 struct lyxml_context ctx;
295 memset(&ctx, 0, sizeof ctx);
296 ctx.line = 1;
297
298 /* empty attribute value */
Radek Krejcib1890642018-10-03 14:05:40 +0200299 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200300 str = "\"\"";
Radek Krejcid70d1072018-10-09 14:20:47 +0200301 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
302 assert_null(buf);
303 assert_ptr_equal(&str[-1], out);
304 assert_int_equal(0, dynamic);
305 assert_int_equal(0, len);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200306 assert_true(str[0] == '\0'); /* everything eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200307 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
308
309 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200310 str = "\'\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200311 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
312 assert_null(buf);
313 assert_ptr_equal(&str[-1], out);
314 assert_int_equal(0, dynamic);
315 assert_int_equal(0, len);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200316 assert_true(str[0] == '\0'); /* everything eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200317 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200318
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200319 /* empty element content - only formating before defining child */
Radek Krejcib1890642018-10-03 14:05:40 +0200320 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejci339e2de2019-05-17 14:28:24 +0200321 str = "<x>\n <y>";
322 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid70d1072018-10-09 14:20:47 +0200323 assert_int_equal(LY_EINVAL, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
324 assert_null(buf);
Radek Krejci339e2de2019-05-17 14:28:24 +0200325 assert_string_equal("<y>", str);
326 lyxml_context_clear(&ctx);
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200327
Radek Krejci7a7fa902018-09-25 17:08:21 +0200328 /* empty element content is invalid - missing content terminating character < */
Radek Krejcib1890642018-10-03 14:05:40 +0200329 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200330 str = "";
Radek Krejcid70d1072018-10-09 14:20:47 +0200331 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
332 assert_null(buf);
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200333 logbuf_assert("Unexpected end-of-input. Line number 2.");
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200334
Radek Krejcib1890642018-10-03 14:05:40 +0200335 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200336 str = p = "xxx";
Radek Krejcid70d1072018-10-09 14:20:47 +0200337 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
338 assert_null(buf);
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200339 logbuf_assert("Unexpected end-of-input. Line number 2.");
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200340 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejci7a7fa902018-09-25 17:08:21 +0200341
Radek Krejci7a7fa902018-09-25 17:08:21 +0200342 /* valid strings */
Radek Krejcib1890642018-10-03 14:05:40 +0200343 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejci339e2de2019-05-17 14:28:24 +0200344 str = "<a>€𠜎Øn \n&lt;&amp;&quot;&apos;&gt; &#82;&#x4f;&#x4B;</a>";
345 assert_int_equal(LY_SUCCESS, lyxml_get_element(&ctx, &str, &prefix, &prefix_len, &name, &name_len));
Radek Krejcid70d1072018-10-09 14:20:47 +0200346 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
347 assert_int_not_equal(0, dynamic);
348 assert_non_null(buf);
349 assert_ptr_equal(out, buf);
350 assert_int_equal(22, buf_len);
351 assert_int_equal(21, len);
352 assert_string_equal("€𠜎Øn \n<&\"\'> ROK", buf);
Radek Krejci339e2de2019-05-17 14:28:24 +0200353 assert_string_equal("", str);
Radek Krejcib1890642018-10-03 14:05:40 +0200354 assert_int_equal(LYXML_ELEMENT, ctx.status);
Radek Krejci339e2de2019-05-17 14:28:24 +0200355 lyxml_context_clear(&ctx);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200356
Radek Krejci117d2082018-09-26 10:05:14 +0200357 /* test using n-bytes UTF8 hexadecimal code points */
Radek Krejcib1890642018-10-03 14:05:40 +0200358 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200359 str = "\'&#x0024;&#x00A2;&#x20ac;&#x10348;\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200360 assert_int_equal(LY_SUCCESS, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
361 assert_int_not_equal(0, dynamic);
362 assert_non_null(buf);
363 assert_ptr_equal(out, buf);
Radek Krejcid5f2b5f2018-10-11 10:54:36 +0200364 assert_int_equal(22, buf_len);
Radek Krejcid70d1072018-10-09 14:20:47 +0200365 assert_int_equal(10, len);
366 assert_string_equal("$¢€𐍈", buf);
Radek Krejcib1890642018-10-03 14:05:40 +0200367 assert_int_equal(LYXML_ATTRIBUTE, ctx.status);
Radek Krejci117d2082018-09-26 10:05:14 +0200368
Radek Krejcid70d1072018-10-09 14:20:47 +0200369 free(buf);
370 buf = NULL;
371
Radek Krejci7a7fa902018-09-25 17:08:21 +0200372 /* invalid characters in string */
Radek Krejcib1890642018-10-03 14:05:40 +0200373 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200374 str = p = "\'&#x52\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200375 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200376 logbuf_assert("Invalid character sequence \"'\", expected ;. Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200377 assert_null(buf);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200378 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200379 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200380 str = p = "\"&#82\"";
Radek Krejcid70d1072018-10-09 14:20:47 +0200381 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200382 logbuf_assert("Invalid character sequence \"\"\", expected ;. Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200383 assert_null(buf);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200384 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200385 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200386 str = p = "\"&nonsence;\"";
Radek Krejcid70d1072018-10-09 14:20:47 +0200387 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200388 logbuf_assert("Entity reference \"&nonsence;\" not supported, only predefined references allowed. Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200389 assert_null(buf);
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200390 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200391 ctx.status = LYXML_ELEM_CONTENT;
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200392 str = p = "&#o122;";
Radek Krejcid70d1072018-10-09 14:20:47 +0200393 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200394 logbuf_assert("Invalid character reference \"&#o122;\". Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200395 assert_null(buf);
Radek Krejci117d2082018-09-26 10:05:14 +0200396 assert_ptr_equal(p, str); /* input data not eaten */
397
Radek Krejcib1890642018-10-03 14:05:40 +0200398 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200399 str = p = "\'&#x06;\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200400 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200401 logbuf_assert("Invalid character reference \"&#x06;\'\" (0x00000006). Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200402 assert_null(buf);
Radek Krejci117d2082018-09-26 10:05:14 +0200403 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200404 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200405 str = p = "\'&#xfdd0;\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200406 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200407 logbuf_assert("Invalid character reference \"&#xfdd0;\'\" (0x0000fdd0). Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200408 assert_null(buf);
Radek Krejci117d2082018-09-26 10:05:14 +0200409 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejcib1890642018-10-03 14:05:40 +0200410 ctx.status = LYXML_ATTR_CONTENT;
Radek Krejci117d2082018-09-26 10:05:14 +0200411 str = p = "\'&#xffff;\'";
Radek Krejcid70d1072018-10-09 14:20:47 +0200412 assert_int_equal(LY_EVALID, lyxml_get_string(&ctx, &str, &buf, &buf_len, &out, &len, &dynamic));
Radek Krejci117d2082018-09-26 10:05:14 +0200413 logbuf_assert("Invalid character reference \"&#xffff;\'\" (0x0000ffff). Line number 3.");
Radek Krejcid70d1072018-10-09 14:20:47 +0200414 assert_null(buf);
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200415 assert_ptr_equal(p, str); /* input data not eaten */
Radek Krejci7a7fa902018-09-25 17:08:21 +0200416}
417
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200418static void
419test_ns(void **state)
420{
421 (void) state; /* unused */
422
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200423 const struct lyxml_ns *ns;
424
425 struct lyxml_context ctx;
426 memset(&ctx, 0, sizeof ctx);
427 ctx.line = 1;
428
Radek Krejcie0734d22019-04-05 15:54:28 +0200429 /* simulate adding open element1 into context */
430 ctx.elements.count++;
431 /* processing namespace definitions */
Radek Krejci17a78d82019-05-15 15:49:55 +0200432 assert_int_equal(LY_SUCCESS, lyxml_ns_add(&ctx, NULL, 0, strdup("urn:default")));
433 assert_int_equal(LY_SUCCESS, lyxml_ns_add(&ctx, "nc", 2, strdup("urn:nc1")));
Radek Krejcie0734d22019-04-05 15:54:28 +0200434 /* simulate adding open element2 into context */
435 ctx.elements.count++;
436 /* processing namespace definitions */
Radek Krejci17a78d82019-05-15 15:49:55 +0200437 assert_int_equal(LY_SUCCESS, lyxml_ns_add(&ctx, "nc", 2, strdup("urn:nc2")));
Radek Krejcie0734d22019-04-05 15:54:28 +0200438 assert_int_equal(3, ctx.ns.count);
439 assert_int_not_equal(0, ctx.ns.size);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200440
441 ns = lyxml_ns_get(&ctx, NULL, 0);
442 assert_non_null(ns);
443 assert_null(ns->prefix);
444 assert_string_equal("urn:default", ns->uri);
445
446 ns = lyxml_ns_get(&ctx, "nc", 2);
447 assert_non_null(ns);
448 assert_string_equal("nc", ns->prefix);
449 assert_string_equal("urn:nc2", ns->uri);
450
Radek Krejcie0734d22019-04-05 15:54:28 +0200451 /* simulate closing element2 */
452 ctx.elements.count--;
Radek Krejci17dca992019-05-17 10:53:27 +0200453 lyxml_ns_rm(&ctx);
Radek Krejcie0734d22019-04-05 15:54:28 +0200454 assert_int_equal(2, ctx.ns.count);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200455
456 ns = lyxml_ns_get(&ctx, "nc", 2);
457 assert_non_null(ns);
458 assert_string_equal("nc", ns->prefix);
459 assert_string_equal("urn:nc1", ns->uri);
460
Radek Krejcie0734d22019-04-05 15:54:28 +0200461 /* simulate closing element1 */
462 ctx.elements.count--;
Radek Krejci17dca992019-05-17 10:53:27 +0200463 lyxml_ns_rm(&ctx);
Radek Krejcie0734d22019-04-05 15:54:28 +0200464 assert_int_equal(0, ctx.ns.count);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200465
466 assert_null(lyxml_ns_get(&ctx, "nc", 2));
467 assert_null(lyxml_ns_get(&ctx, NULL, 0));
468}
469
Radek Krejcie0734d22019-04-05 15:54:28 +0200470static void
471test_ns2(void **state)
472{
473 (void) state; /* unused */
474
Radek Krejcie0734d22019-04-05 15:54:28 +0200475 struct lyxml_context ctx;
476 memset(&ctx, 0, sizeof ctx);
477 ctx.line = 1;
478
Radek Krejcie0734d22019-04-05 15:54:28 +0200479 /* simulate adding open element1 into context */
480 ctx.elements.count++;
481 /* default namespace defined in parent element1 */
Radek Krejci17a78d82019-05-15 15:49:55 +0200482 assert_int_equal(LY_SUCCESS, lyxml_ns_add(&ctx, NULL, 0, strdup("urn:default")));
Radek Krejcie0734d22019-04-05 15:54:28 +0200483 assert_int_equal(1, ctx.ns.count);
484 /* going into child element1 */
Radek Krejcie0734d22019-04-05 15:54:28 +0200485 /* simulate adding open element1 into context */
486 ctx.elements.count++;
487 /* no namespace defined, going out (first, simulate closing of so far open element) */
488 ctx.elements.count--;
Radek Krejci17dca992019-05-17 10:53:27 +0200489 lyxml_ns_rm(&ctx);
Radek Krejcie0734d22019-04-05 15:54:28 +0200490 assert_int_equal(1, ctx.ns.count);
491 /* nothing else, going out of the parent element1 (first, simulate closing of so far open element) */
492 ctx.elements.count--;
Radek Krejci17dca992019-05-17 10:53:27 +0200493 lyxml_ns_rm(&ctx);
Radek Krejcie0734d22019-04-05 15:54:28 +0200494 assert_int_equal(0, ctx.ns.count);
495}
496
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200497int main(void)
498{
499 const struct CMUnitTest tests[] = {
Radek Krejcid972c252018-09-25 13:23:39 +0200500 cmocka_unit_test_setup(test_element, logger_setup),
501 cmocka_unit_test_setup(test_attribute, logger_setup),
Radek Krejci7a7fa902018-09-25 17:08:21 +0200502 cmocka_unit_test_setup(test_text, logger_setup),
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200503 cmocka_unit_test_setup(test_ns, logger_setup),
Radek Krejcie0734d22019-04-05 15:54:28 +0200504 cmocka_unit_test_setup(test_ns2, logger_setup),
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200505 };
506
507 return cmocka_run_group_tests(tests, NULL, NULL);
508}