blob: 7710082cb7f6ea4236a99ea8bfde24d89bf0f120 [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
Radek Krejcib7db73a2018-10-24 14:18:40 +020017
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"
Michal Vaskob36053d2020-03-26 15:49:30 +010028#include "../../src/context.h"
Radek Krejci2d7a47b2019-05-16 13:34:10 +020029
Michal Vaskob36053d2020-03-26 15:49:30 +010030LY_ERR lyxml_ns_add(struct lyxml_ctx *xmlctx, const char *prefix, size_t prefix_len, char *uri);
31LY_ERR lyxml_ns_rm(struct lyxml_ctx *xmlctx);
32
33static int
34setup(void **state)
35{
36 if (ly_ctx_new(NULL, 0, (struct ly_ctx **)state)) {
37 return 1;
38 }
39
40 return 0;
41}
42
43static int
44teardown(void **state)
45{
46 ly_ctx_destroy(*state, NULL);
47 return 0;
48}
Radek Krejcid91dbaf2018-09-21 15:51:39 +020049
50#define BUFSIZE 1024
51char logbuf[BUFSIZE] = {0};
52
53/* set to 0 to printing error messages to stderr instead of checking them in code */
54#define ENABLE_LOGGER_CHECKING 1
55
56static void
57logger(LY_LOG_LEVEL level, const char *msg, const char *path)
58{
59 (void) level; /* unused */
60
61 if (path) {
62 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
63 } else {
64 strncpy(logbuf, msg, BUFSIZE - 1);
65 }
66}
67
68static int
69logger_setup(void **state)
70{
71 (void) state; /* unused */
72#if ENABLE_LOGGER_CHECKING
73 ly_set_log_clb(logger, 1);
74#endif
75 return 0;
76}
77
78void
79logbuf_clean(void)
80{
81 logbuf[0] = '\0';
82}
83
84#if ENABLE_LOGGER_CHECKING
85# define logbuf_assert(str) assert_string_equal(logbuf, str)
86#else
87# define logbuf_assert(str)
88#endif
89
90static void
91test_element(void **state)
92{
Michal Vaskob36053d2020-03-26 15:49:30 +010093 struct lyxml_ctx *xmlctx;
94 const char *str;
Radek Krejcid91dbaf2018-09-21 15:51:39 +020095
96 /* empty */
97 str = "";
Michal Vaskob36053d2020-03-26 15:49:30 +010098 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
99 assert_int_equal(LYXML_END, xmlctx->status);
100 assert_true(xmlctx->input[0] == '\0');
101 lyxml_ctx_free(xmlctx);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200102
Radek Krejcib1890642018-10-03 14:05:40 +0200103 /* end element */
104 str = "</element>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100105 assert_int_equal(LY_EVALID, lyxml_ctx_new(*state, str, &xmlctx));
106 logbuf_assert("Stray closing element tag (\"element\"). Line number 1.");
Radek Krejcib1890642018-10-03 14:05:40 +0200107
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200108 /* no element */
Michal Vaskob36053d2020-03-26 15:49:30 +0100109 //logbuf_clean();
110 str = "no data present";
111 assert_int_equal(LY_EVALID, lyxml_ctx_new(*state, str, &xmlctx));
112 logbuf_assert("Invalid character sequence \"no data present\", expected element tag start ('<'). Line number 1.");
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200113
114 /* not supported DOCTYPE */
Michal Vaskob36053d2020-03-26 15:49:30 +0100115 str = "<!DOCTYPE greeting SYSTEM \"hello.dtd\"><greeting/>";
116 assert_int_equal(LY_EVALID, lyxml_ctx_new(*state, str, &xmlctx));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200117 logbuf_assert("Document Type Declaration not supported. Line number 1.");
118
Radek Krejcic5c31bb2019-04-08 14:40:52 +0200119 /* invalid XML */
Michal Vaskob36053d2020-03-26 15:49:30 +0100120 str = "<!NONSENSE/>";
121 assert_int_equal(LY_EVALID, lyxml_ctx_new(*state, str, &xmlctx));
122 logbuf_assert("Unknown XML section \"<!NONSENSE/>\". Line number 1.");
Radek Krejcic5c31bb2019-04-08 14:40:52 +0200123
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200124 /* unqualified element */
125 str = " < element/>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100126 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
127 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
128 assert_null(xmlctx->prefix);
129 assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
130 assert_int_equal(1, xmlctx->elements.count);
Radek Krejci28e8cb52019-03-08 11:31:31 +0100131
Michal Vaskob36053d2020-03-26 15:49:30 +0100132 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
133 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
134 assert_true(!strncmp("", xmlctx->value, xmlctx->value_len));
135
136 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
137 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
138
139 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
140 assert_int_equal(LYXML_END, xmlctx->status);
141 lyxml_ctx_free(xmlctx);
142
143 /* element with attribute */
Radek Krejci28e8cb52019-03-08 11:31:31 +0100144 str = " < element attr=\'x\'/>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100145 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
146 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
147 assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
148 assert_null(xmlctx->prefix);
149 assert_int_equal(1, xmlctx->elements.count);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200150
Michal Vaskob36053d2020-03-26 15:49:30 +0100151 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
152 assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
153 assert_true(!strncmp("attr", xmlctx->name, xmlctx->name_len));
154 assert_null(xmlctx->prefix);
155
156 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
157 assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
158 assert_int_equal(1, xmlctx->elements.count);
159 assert_true(!strncmp("x", xmlctx->value, xmlctx->value_len));
160
161 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
162 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
163
164 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
165 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
166 assert_int_equal(0, xmlctx->elements.count);
167
168 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
169 assert_int_equal(LYXML_END, xmlctx->status);
170 lyxml_ctx_free(xmlctx);
171
172 /* headers and comments */
Radek Krejcifb7c6582018-09-21 16:12:45 +0200173 str = "<?xml version=\"1.0\"?> <!-- comment --> <![CDATA[<greeting>Hello, world!</greeting>]]> <?TEST xxx?> <element/>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100174 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
175 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
176 assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
177 assert_null(xmlctx->prefix);
178 assert_int_equal(1, xmlctx->elements.count);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200179
Michal Vaskob36053d2020-03-26 15:49:30 +0100180 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
181 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
182
183 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
184 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
185
186 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
187 assert_int_equal(LYXML_END, xmlctx->status);
188 lyxml_ctx_free(xmlctx);
189
190 /* separate opening and closing tags, neamespaced parsed internally */
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200191 str = "<element xmlns=\"urn\"></element>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100192 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
193 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
194 assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
195 assert_null(xmlctx->prefix);
196 assert_int_equal(1, xmlctx->elements.count);
197 assert_int_equal(1, xmlctx->ns.count);
198
199 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
200 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
201
202 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
203 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
204 assert_int_equal(0, xmlctx->elements.count);
205 assert_int_equal(0, xmlctx->ns.count);
206
207 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
208 assert_int_equal(LYXML_END, xmlctx->status);
209 lyxml_ctx_free(xmlctx);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200210
211 /* qualified element */
212 str = " < yin:element/>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100213 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
214 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
215 assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
216 assert_true(!strncmp("yin", xmlctx->prefix, xmlctx->prefix_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200217
Michal Vaskob36053d2020-03-26 15:49:30 +0100218 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
219 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
220
221 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
222 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
223
224 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
225 assert_int_equal(LYXML_END, xmlctx->status);
226 lyxml_ctx_free(xmlctx);
227
228 /* non-matching closing tag */
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200229 str = "<yin:element xmlns=\"urn\"></element>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100230 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
231 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
232 assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
233 assert_true(!strncmp("yin", xmlctx->prefix, xmlctx->prefix_len));
234 assert_int_equal(1, xmlctx->elements.count);
235 assert_int_equal(1, xmlctx->ns.count);
236
237 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
238 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
239
240 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
241 logbuf_assert("Opening (\"yin:element\") and closing (\"element\") elements tag mismatch. Line number 1.");
242
243 /* just replace closing tag */
244 xmlctx->input = "</yin:element/>";
245 xmlctx->status = LYXML_ELEM_CONTENT;
246 xmlctx->dynamic = 0;
247 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
248 logbuf_assert("Invalid character sequence \"/>\", expected element tag termination ('>'). Line number 1.");
249 lyxml_ctx_free(xmlctx);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200250
251 /* UTF8 characters */
252 str = "<𠜎€𠜎Øn:𠜎€𠜎Øn/>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100253 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
254 assert_true(!strncmp("𠜎€𠜎Øn", xmlctx->name, xmlctx->name_len));
255 assert_true(!strncmp("𠜎€𠜎Øn", xmlctx->prefix, xmlctx->prefix_len));
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200256
Michal Vaskob36053d2020-03-26 15:49:30 +0100257 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
258 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
259
260 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
261 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
262
263 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
264 assert_int_equal(LYXML_END, xmlctx->status);
265 lyxml_ctx_free(xmlctx);
266
267 /* invalid UTF-8 characters */
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200268 str = "<¢:element>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100269 assert_int_equal(LY_EVALID, lyxml_ctx_new(*state, str, &xmlctx));
270 logbuf_assert("Identifier \"¢:element>\" starts with an invalid character. Line number 1.");
271
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200272 str = "<yin:c⁐element>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100273 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
274 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
275 logbuf_assert("Invalid character sequence \"⁐element>\", expected element tag end ('>' or '/>') or an attribute. Line number 1.");
276 lyxml_ctx_free(xmlctx);
Radek Krejci339e2de2019-05-17 14:28:24 +0200277
278 /* mixed content */
279 str = "<a>text <b>x</b></a>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100280 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
281 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
282 assert_true(!strncmp("a", xmlctx->name, xmlctx->name_len));
283 assert_null(xmlctx->prefix);
Radek Krejci339e2de2019-05-17 14:28:24 +0200284
Michal Vaskob36053d2020-03-26 15:49:30 +0100285 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
286 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
287 assert_true(!strncmp("text ", xmlctx->value, xmlctx->value_len));
288
289 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
290 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
291 assert_true(!strncmp("b", xmlctx->name, xmlctx->name_len));
292 assert_null(xmlctx->prefix);
293
294 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
295 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
296 assert_true(!strncmp("x", xmlctx->value, xmlctx->value_len));
297
298 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
299 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
300
301 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
302 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
303
304 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
305 assert_int_equal(LYXML_END, xmlctx->status);
306 lyxml_ctx_free(xmlctx);
307
308 /* tag mismatch */
David Sedlák54a6f132019-07-16 15:14:18 +0200309 str = "<a>text</b>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100310 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
311 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
312 assert_true(!strncmp("a", xmlctx->name, xmlctx->name_len));
313 assert_null(xmlctx->prefix);
David Sedlák54a6f132019-07-16 15:14:18 +0200314
Michal Vaskob36053d2020-03-26 15:49:30 +0100315 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
316 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
317 assert_true(!strncmp("text", xmlctx->value, xmlctx->value_len));
318
319 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
320 logbuf_assert("Opening (\"a\") and closing (\"b\") elements tag mismatch. Line number 1.");
321 lyxml_ctx_free(xmlctx);
Radek Krejcid972c252018-09-25 13:23:39 +0200322}
323
324static void
325test_attribute(void **state)
326{
Michal Vaskob36053d2020-03-26 15:49:30 +0100327 const char *str;
328 struct lyxml_ctx *xmlctx;
329 struct lyxml_ns *ns;
Radek Krejcid972c252018-09-25 13:23:39 +0200330
Radek Krejcid972c252018-09-25 13:23:39 +0200331 /* not an attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +0100332 str = "<e unknown/>";
333 assert_int_equal(LY_EVALID, lyxml_ctx_new(*state, str, &xmlctx));
Radek Krejcid972c252018-09-25 13:23:39 +0200334 logbuf_assert("Invalid character sequence \"/>\", expected '='. Line number 1.");
Michal Vaskob36053d2020-03-26 15:49:30 +0100335
336 str = "<e xxx=/>";
337 assert_int_equal(LY_EVALID, lyxml_ctx_new(*state, str, &xmlctx));
Radek Krejcid972c252018-09-25 13:23:39 +0200338 logbuf_assert("Invalid character sequence \"/>\", expected either single or double quotation mark. Line number 1.");
Michal Vaskob36053d2020-03-26 15:49:30 +0100339
340 str = "<e xxx\n = yyy/>";
341 assert_int_equal(LY_EVALID, lyxml_ctx_new(*state, str, &xmlctx));
Radek Krejcid972c252018-09-25 13:23:39 +0200342 logbuf_assert("Invalid character sequence \"yyy/>\", expected either single or double quotation mark. Line number 2.");
343
344 /* valid attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +0100345 str = "<e attr=\"val\"";
346 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
347 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
348 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
349 assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
350 assert_true(!strncmp("attr", xmlctx->name, xmlctx->name_len));
351 assert_null(xmlctx->prefix);
Radek Krejcid972c252018-09-25 13:23:39 +0200352
Michal Vaskob36053d2020-03-26 15:49:30 +0100353 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
354 assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
355 assert_true(!strncmp("val", xmlctx->name, xmlctx->name_len));
356 assert_int_equal(xmlctx->ws_only, 0);
357 assert_int_equal(xmlctx->dynamic, 0);
358 lyxml_ctx_free(xmlctx);
Radek Krejci28e8cb52019-03-08 11:31:31 +0100359
Michal Vaskob36053d2020-03-26 15:49:30 +0100360 /* valid namespace with prefix */
361 str = "<e xmlns:nc\n = \'urn\'/>";
362 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
363 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
364 assert_int_equal(1, xmlctx->ns.count);
365 ns = (struct lyxml_ns *)xmlctx->ns.objs[0];
366 assert_string_equal(ns->prefix, "nc");
367 assert_string_equal(ns->uri, "urn");
368 lyxml_ctx_free(xmlctx);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200369}
370
Radek Krejci7a7fa902018-09-25 17:08:21 +0200371static void
372test_text(void **state)
373{
Michal Vaskob36053d2020-03-26 15:49:30 +0100374 const char *str;
375 struct lyxml_ctx *xmlctx;
Radek Krejci7a7fa902018-09-25 17:08:21 +0200376
377 /* empty attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +0100378 str = "<e a=\"\"";
379 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
380 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
381 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
382 assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
Radek Krejcib1890642018-10-03 14:05:40 +0200383
Michal Vaskob36053d2020-03-26 15:49:30 +0100384 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
385 assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
386 assert_true(!strncmp("", xmlctx->value, xmlctx->value_len));
387 assert_int_equal(xmlctx->ws_only, 1);
388 assert_int_equal(xmlctx->dynamic, 0);
389
390 /* empty value but in single quotes */
391 xmlctx->status = LYXML_ATTRIBUTE;
392 xmlctx->input = "=\'\'";
393 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
394 assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
395 assert_true(!strncmp("", xmlctx->value, xmlctx->value_len));
396 assert_int_equal(xmlctx->ws_only, 1);
397 assert_int_equal(xmlctx->dynamic, 0);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200398
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200399 /* empty element content - only formating before defining child */
Michal Vaskob36053d2020-03-26 15:49:30 +0100400 xmlctx->status = LYXML_ELEMENT;
401 xmlctx->input = ">\n <y>";
402 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
403 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
404 assert_true(!strncmp("\n ", xmlctx->value, xmlctx->value_len));
405 assert_int_equal(xmlctx->ws_only, 1);
406 assert_int_equal(xmlctx->dynamic, 0);
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200407
Radek Krejci7a7fa902018-09-25 17:08:21 +0200408 /* empty element content is invalid - missing content terminating character < */
Michal Vaskob36053d2020-03-26 15:49:30 +0100409 xmlctx->status = LYXML_ELEM_CONTENT;
410 xmlctx->input = "";
411 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
Radek Krejci0a1d0d42019-05-16 15:14:51 +0200412 logbuf_assert("Unexpected end-of-input. Line number 2.");
Radek Krejcied6c6ad2018-09-26 09:10:18 +0200413
Michal Vaskob36053d2020-03-26 15:49:30 +0100414 xmlctx->status = LYXML_ELEM_CONTENT;
415 xmlctx->input = "xxx";
416 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
417 logbuf_assert("Invalid character sequence \"xxx\", expected element tag start ('<'). Line number 2.");
418
419 lyxml_ctx_free(xmlctx);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200420
Radek Krejci7a7fa902018-09-25 17:08:21 +0200421 /* valid strings */
Radek Krejci339e2de2019-05-17 14:28:24 +0200422 str = "<a>€𠜎Øn \n&lt;&amp;&quot;&apos;&gt; &#82;&#x4f;&#x4B;</a>";
Michal Vaskob36053d2020-03-26 15:49:30 +0100423 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
424 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
425
426 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
427 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
428 assert_true(!strncmp("€𠜎Øn \n<&\"\'> ROK", xmlctx->value, xmlctx->value_len));
429 assert_int_equal(xmlctx->ws_only, 0);
430 assert_int_equal(xmlctx->dynamic, 1);
431 free((char *)xmlctx->value);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200432
Radek Krejci117d2082018-09-26 10:05:14 +0200433 /* test using n-bytes UTF8 hexadecimal code points */
Michal Vaskob36053d2020-03-26 15:49:30 +0100434 xmlctx->status = LYXML_ATTRIBUTE;
435 xmlctx->input = "=\'&#x0024;&#x00A2;&#x20ac;&#x10348;\'";
436 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
437 assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
438 assert_true(!strncmp("$¢€𐍈", xmlctx->value, xmlctx->value_len));
439 assert_int_equal(xmlctx->ws_only, 0);
440 assert_int_equal(xmlctx->dynamic, 1);
441 free((char *)xmlctx->value);
Radek Krejcid70d1072018-10-09 14:20:47 +0200442
Radek Krejci7a7fa902018-09-25 17:08:21 +0200443 /* invalid characters in string */
Michal Vaskob36053d2020-03-26 15:49:30 +0100444 xmlctx->status = LYXML_ATTRIBUTE;
445 xmlctx->input = "=\'&#x52\'";
446 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
447 logbuf_assert("Invalid character sequence \"'\", expected ;. Line number 2.");
Radek Krejci117d2082018-09-26 10:05:14 +0200448
Michal Vaskob36053d2020-03-26 15:49:30 +0100449 xmlctx->status = LYXML_ATTRIBUTE;
450 xmlctx->input = "=\"&#82\"";
451 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
452 logbuf_assert("Invalid character sequence \"\"\", expected ;. Line number 2.");
453
454 xmlctx->status = LYXML_ATTRIBUTE;
455 xmlctx->input = "=\"&nonsense;\"";
456 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
457 logbuf_assert("Entity reference \"&nonsense;\" not supported, only predefined references allowed. Line number 2.");
458
459 xmlctx->status = LYXML_ELEMENT;
460 xmlctx->input = ">&#o122;";
461 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
462 logbuf_assert("Invalid character reference \"&#o122;\". Line number 2.");
463
464 xmlctx->status = LYXML_ATTRIBUTE;
465 xmlctx->input = "=\'&#x06;\'";
466 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
467 logbuf_assert("Invalid character reference \"&#x06;\'\" (0x00000006). Line number 2.");
468
469 xmlctx->status = LYXML_ATTRIBUTE;
470 xmlctx->input = "=\'&#xfdd0;\'";
471 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
472 logbuf_assert("Invalid character reference \"&#xfdd0;\'\" (0x0000fdd0). Line number 2.");
473
474 xmlctx->status = LYXML_ATTRIBUTE;
475 xmlctx->input = "=\'&#xffff;\'";
476 assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
477 logbuf_assert("Invalid character reference \"&#xffff;\'\" (0x0000ffff). Line number 2.");
478
479 lyxml_ctx_free(xmlctx);
Radek Krejci7a7fa902018-09-25 17:08:21 +0200480}
481
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200482static void
483test_ns(void **state)
484{
Michal Vaskob36053d2020-03-26 15:49:30 +0100485 const char *str;
486 struct lyxml_ctx *xmlctx;
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200487 const struct lyxml_ns *ns;
488
Michal Vaskob36053d2020-03-26 15:49:30 +0100489 /* opening element1 */
490 str = "<element1/>";
491 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200492
Radek Krejcie0734d22019-04-05 15:54:28 +0200493 /* processing namespace definitions */
Michal Vaskob36053d2020-03-26 15:49:30 +0100494 assert_int_equal(LY_SUCCESS, lyxml_ns_add(xmlctx, NULL, 0, strdup("urn:default")));
495 assert_int_equal(LY_SUCCESS, lyxml_ns_add(xmlctx, "nc", 2, strdup("urn:nc1")));
Radek Krejcie0734d22019-04-05 15:54:28 +0200496 /* simulate adding open element2 into context */
Michal Vaskob36053d2020-03-26 15:49:30 +0100497 xmlctx->elements.count++;
Radek Krejcie0734d22019-04-05 15:54:28 +0200498 /* processing namespace definitions */
Michal Vaskob36053d2020-03-26 15:49:30 +0100499 assert_int_equal(LY_SUCCESS, lyxml_ns_add(xmlctx, "nc", 2, strdup("urn:nc2")));
500 assert_int_equal(3, xmlctx->ns.count);
501 assert_int_not_equal(0, xmlctx->ns.size);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200502
Michal Vaskob36053d2020-03-26 15:49:30 +0100503 ns = lyxml_ns_get(xmlctx, NULL, 0);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200504 assert_non_null(ns);
505 assert_null(ns->prefix);
506 assert_string_equal("urn:default", ns->uri);
507
Michal Vaskob36053d2020-03-26 15:49:30 +0100508 ns = lyxml_ns_get(xmlctx, "nc", 2);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200509 assert_non_null(ns);
510 assert_string_equal("nc", ns->prefix);
511 assert_string_equal("urn:nc2", ns->uri);
512
Radek Krejcie0734d22019-04-05 15:54:28 +0200513 /* simulate closing element2 */
Michal Vaskob36053d2020-03-26 15:49:30 +0100514 xmlctx->elements.count--;
515 lyxml_ns_rm(xmlctx);
516 assert_int_equal(2, xmlctx->ns.count);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200517
Michal Vaskob36053d2020-03-26 15:49:30 +0100518 ns = lyxml_ns_get(xmlctx, "nc", 2);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200519 assert_non_null(ns);
520 assert_string_equal("nc", ns->prefix);
521 assert_string_equal("urn:nc1", ns->uri);
522
Michal Vaskob36053d2020-03-26 15:49:30 +0100523 /* close element1 */
524 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
525 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
526 assert_int_equal(0, xmlctx->ns.count);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200527
Michal Vaskob36053d2020-03-26 15:49:30 +0100528 assert_null(lyxml_ns_get(xmlctx, "nc", 2));
529 assert_null(lyxml_ns_get(xmlctx, NULL, 0));
530
531 lyxml_ctx_free(xmlctx);
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200532}
533
David Sedlákb3bed7a2019-03-08 11:53:37 +0100534static void
Radek Krejcie0734d22019-04-05 15:54:28 +0200535test_ns2(void **state)
536{
Michal Vaskob36053d2020-03-26 15:49:30 +0100537 const char *str;
538 struct lyxml_ctx *xmlctx;
Radek Krejcie0734d22019-04-05 15:54:28 +0200539
Michal Vaskob36053d2020-03-26 15:49:30 +0100540 /* opening element1 */
541 str = "<element1/>";
542 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, str, &xmlctx));
Radek Krejcie0734d22019-04-05 15:54:28 +0200543
Radek Krejcie0734d22019-04-05 15:54:28 +0200544 /* default namespace defined in parent element1 */
Michal Vaskob36053d2020-03-26 15:49:30 +0100545 assert_int_equal(LY_SUCCESS, lyxml_ns_add(xmlctx, NULL, 0, strdup("urn:default")));
546 assert_int_equal(1, xmlctx->ns.count);
Radek Krejcie0734d22019-04-05 15:54:28 +0200547 /* going into child element1 */
Radek Krejcie0734d22019-04-05 15:54:28 +0200548 /* simulate adding open element1 into context */
Michal Vaskob36053d2020-03-26 15:49:30 +0100549 xmlctx->elements.count++;
Radek Krejcie0734d22019-04-05 15:54:28 +0200550 /* no namespace defined, going out (first, simulate closing of so far open element) */
Michal Vaskob36053d2020-03-26 15:49:30 +0100551 xmlctx->elements.count--;
552 lyxml_ns_rm(xmlctx);
553 assert_int_equal(1, xmlctx->ns.count);
554
555 /* nothing else, going out of the parent element1 */
556 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
557 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
558 assert_int_equal(0, xmlctx->ns.count);
559
560 lyxml_ctx_free(xmlctx);
Radek Krejcie0734d22019-04-05 15:54:28 +0200561}
562
Radek Krejcifad79c92019-06-04 11:43:30 +0200563static void
564test_simple_xml(void **state)
565{
Michal Vaskob36053d2020-03-26 15:49:30 +0100566 struct lyxml_ctx *xmlctx;
Radek Krejcie553e6d2019-06-07 15:33:18 +0200567 const char *test_input = "<elem1 attr1=\"value\"> <elem2 attr2=\"value\" /> </elem1>";
Radek Krejcifad79c92019-06-04 11:43:30 +0200568
Michal Vaskob36053d2020-03-26 15:49:30 +0100569 assert_int_equal(LY_SUCCESS, lyxml_ctx_new(*state, test_input, &xmlctx));
570 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
571 assert_string_equal(xmlctx->input, "attr1=\"value\"> <elem2 attr2=\"value\" /> </elem1>");
Radek Krejcifad79c92019-06-04 11:43:30 +0200572
Michal Vaskob36053d2020-03-26 15:49:30 +0100573 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
574 assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
575 assert_string_equal(xmlctx->input, "=\"value\"> <elem2 attr2=\"value\" /> </elem1>");
Radek Krejcifad79c92019-06-04 11:43:30 +0200576
Michal Vaskob36053d2020-03-26 15:49:30 +0100577 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
578 assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
579 assert_string_equal(xmlctx->input, "> <elem2 attr2=\"value\" /> </elem1>");
Radek Krejcifad79c92019-06-04 11:43:30 +0200580
Michal Vaskob36053d2020-03-26 15:49:30 +0100581 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
582 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
583 assert_string_equal(xmlctx->input, "<elem2 attr2=\"value\" /> </elem1>");
Radek Krejcifad79c92019-06-04 11:43:30 +0200584
Michal Vaskob36053d2020-03-26 15:49:30 +0100585 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
586 assert_int_equal(LYXML_ELEMENT, xmlctx->status);
587 assert_string_equal(xmlctx->input, "attr2=\"value\" /> </elem1>");
Radek Krejcifad79c92019-06-04 11:43:30 +0200588
Michal Vaskob36053d2020-03-26 15:49:30 +0100589 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
590 assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
591 assert_string_equal(xmlctx->input, "=\"value\" /> </elem1>");
Radek Krejcie553e6d2019-06-07 15:33:18 +0200592
Michal Vaskob36053d2020-03-26 15:49:30 +0100593 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
594 assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
595 assert_string_equal(xmlctx->input, " /> </elem1>");
Radek Krejcie553e6d2019-06-07 15:33:18 +0200596
Michal Vaskob36053d2020-03-26 15:49:30 +0100597 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
598 assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
599 assert_string_equal(xmlctx->input, "/> </elem1>");
Radek Krejcie553e6d2019-06-07 15:33:18 +0200600
Michal Vaskob36053d2020-03-26 15:49:30 +0100601 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
602 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
603 assert_string_equal(xmlctx->input, " </elem1>");
Radek Krejcifad79c92019-06-04 11:43:30 +0200604
Michal Vaskob36053d2020-03-26 15:49:30 +0100605 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
606 assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
607 assert_string_equal(xmlctx->input, "");
608
609 assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
610 assert_int_equal(LYXML_END, xmlctx->status);
611 assert_string_equal(xmlctx->input, "");
612
613 lyxml_ctx_free(xmlctx);
Radek Krejcifad79c92019-06-04 11:43:30 +0200614}
615
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200616int main(void)
617{
618 const struct CMUnitTest tests[] = {
Radek Krejcid972c252018-09-25 13:23:39 +0200619 cmocka_unit_test_setup(test_element, logger_setup),
620 cmocka_unit_test_setup(test_attribute, logger_setup),
Radek Krejci7a7fa902018-09-25 17:08:21 +0200621 cmocka_unit_test_setup(test_text, logger_setup),
Radek Krejci4b74d5e2018-09-26 14:30:55 +0200622 cmocka_unit_test_setup(test_ns, logger_setup),
Radek Krejcie0734d22019-04-05 15:54:28 +0200623 cmocka_unit_test_setup(test_ns2, logger_setup),
Radek Krejcifad79c92019-06-04 11:43:30 +0200624 cmocka_unit_test_setup(test_simple_xml, logger_setup),
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200625 };
626
Michal Vaskob36053d2020-03-26 15:49:30 +0100627 return cmocka_run_group_tests(tests, setup, teardown);
Radek Krejcid91dbaf2018-09-21 15:51:39 +0200628}