1
0
Fork 0

Adding upstream version 3.1.0+dfsg.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-05 08:00:08 +01:00
parent 64dbec996d
commit cfcebb1a7d
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
569 changed files with 205393 additions and 0 deletions

View file

@ -0,0 +1,416 @@
/**
* @file test_common.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from common.c
*
* Copyright (c) 2018 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _UTEST_MAIN_
#include "utests.h"
#include "ly_common.h"
static void
test_utf8(void **UNUSED(state))
{
char buf[5] = {0};
const char *str = buf;
unsigned int c;
size_t len;
/* test invalid UTF-8 characters in lyxml_getutf8
* - https://en.wikipedia.org/wiki/UTF-8 */
buf[0] = (char)0x04;
assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
buf[0] = (char)0x80;
assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
buf[0] = (char)0xc0;
buf[1] = (char)0x00;
assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
buf[1] = (char)0x80;
assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
buf[0] = (char)0xe0;
buf[1] = (char)0x00;
buf[2] = (char)0x80;
assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
buf[1] = (char)0x80;
assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
buf[0] = (char)0xf0;
buf[1] = (char)0x00;
buf[2] = (char)0x80;
buf[3] = (char)0x80;
assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
buf[1] = (char)0x80;
assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
}
static void
test_parse_int(void **UNUSED(state))
{
const char *str;
int64_t i = 500;
str = "10";
assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
assert_int_equal(i, 10);
/* leading zeros are allowed, trailing whitespaces are allowed */
str = "000\n\t ";
assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
assert_int_equal(i, 0);
/* negative value */
str = "-10";
assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
assert_int_equal(i, -10);
/* non-NULL terminated string */
str = "+5sometext";
assert_int_equal(LY_SUCCESS, ly_parse_int(str, 2, -10, 10, 10, &i));
assert_int_equal(i, 5);
/* out of bounds value */
str = "11";
assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
str = "-11";
assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
/* NaN */
str = "zero";
assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
/* mixing number with text */
str = "10zero";
assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
str = "10 zero";
assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
}
static void
test_parse_uint(void **UNUSED(state))
{
const char *str;
uint64_t u = 500;
str = "10";
assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
assert_int_equal(u, 10);
/* leading zeros are allowed, trailing whitespaces are allowed */
str = "000\n\t ";
assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
assert_int_equal(u, 0);
/* non-NULL terminated string */
str = "+5sometext";
assert_int_equal(LY_SUCCESS, ly_parse_uint(str, 2, 10, 10, &u));
assert_int_equal(u, 5);
/* out of bounds value */
str = "11";
assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), 10, 10, &u));
str = "-1";
assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), (uint64_t)-1, 10, &u));
/* NaN */
str = "zero";
assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
/* mixing number with text */
str = "10zero";
assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
str = "10 zero";
assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
}
static void
test_parse_nodeid(void **UNUSED(state))
{
const char *str;
const char *prefix, *name;
size_t prefix_len, name_len;
str = "123";
assert_int_equal(LY_EINVAL, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
str = "a12_-.!";
assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
assert_null(prefix);
assert_int_equal(0, prefix_len);
assert_non_null(name);
assert_int_equal(6, name_len);
assert_int_equal(0, strncmp("a12_-.", name, name_len));
assert_string_equal("!", str);
str = "a12_-.:_b2 xxx";
assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
assert_non_null(prefix);
assert_int_equal(6, prefix_len);
assert_int_equal(0, strncmp("a12_-.", prefix, prefix_len));
assert_non_null(name);
assert_int_equal(3, name_len);
assert_int_equal(0, strncmp("_b2", name, name_len));
assert_string_equal(" xxx", str);
}
static void
test_parse_instance_predicate(void **UNUSED(state))
{
const char *str, *errmsg;
const char *prefix, *id, *value;
size_t prefix_len, id_len, value_len;
str = "[ex:name='fred']";
assert_int_equal(LY_SUCCESS, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(str, "");
assert_string_equal(prefix, "ex:name='fred']");
assert_int_equal(prefix_len, 2);
assert_string_equal(id, "name='fred']");
assert_int_equal(id_len, 4);
assert_string_equal(value, "fred']");
assert_int_equal(value_len, 4);
str = "[ex:ip = \"[192.0.2.1]\"][ex:port='80']";
assert_int_equal(LY_SUCCESS, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(str, "[ex:port='80']");
assert_string_equal(prefix, "ex:ip = \"[192.0.2.1]\"][ex:port='80']");
assert_int_equal(prefix_len, 2);
assert_string_equal(id, "ip = \"[192.0.2.1]\"][ex:port='80']");
assert_int_equal(id_len, 2);
assert_string_equal(value, "[192.0.2.1]\"][ex:port='80']");
assert_int_equal(value_len, 11);
str = "[. = 'blowfish-cbc']";
assert_int_equal(LY_SUCCESS, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(str, "");
assert_null(prefix);
assert_int_equal(prefix_len, 0);
assert_string_equal(id, ". = 'blowfish-cbc']");
assert_int_equal(id_len, 1);
assert_string_equal(value, "blowfish-cbc']");
assert_int_equal(value_len, 12);
str = "[ 3 ]";
assert_int_equal(LY_SUCCESS, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(str, "");
assert_null(prefix);
assert_int_equal(prefix_len, 0);
assert_null(id);
assert_int_equal(id_len, 0);
assert_string_equal(value, "3 ]");
assert_int_equal(value_len, 1);
/* invalid predicates */
/* position must be positive integer */
str = "[0]";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "The position predicate cannot be zero.");
str = "[-1]";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Invalid instance predicate format (negative position or invalid node-identifier).");
/* invalid node-identifier */
str = "[$node='value']";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Invalid node-identifier.");
str = "[.node='value']";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Unexpected character instead of '=' in leaf-list-predicate.");
str = "[13node='value']";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Predicate (pos) is not terminated by \']\' character.");
str = "[ex:node]";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Unexpected character instead of '=' in key-predicate.");
str = "[ex:node= value]";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "String value is not quoted.");
str = "[ex:node='value\"]";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Value is not terminated quoted-string.");
str = "[ex:node='value ]";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Value is not terminated quoted-string.");
str = "[ex:node=\"value\"[3]";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Predicate (key-predicate) is not terminated by \']\' character.");
str = "[.=\"value\"[3]";
assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Predicate (leaf-list-predicate) is not terminated by \']\' character.");
/* the limit of the string is too short, it ends one character earlier */
str = "[ex:node='value']";
assert_int_equal(LY_EINVAL, ly_parse_instance_predicate(&str, strlen(str) - 1, LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
assert_string_equal(errmsg, "Predicate is incomplete.");
}
static void
test_value_prefix_next(void **UNUSED(state))
{
const char *next;
ly_bool is_prefix;
uint32_t bytes;
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(NULL, NULL, &bytes, &is_prefix, &next));
assert_int_equal(0, bytes);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next("", NULL, &bytes, &is_prefix, &next));
assert_int_equal(0, bytes);
/* prefix */
next = "pref:";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_null(next);
assert_int_equal(1, is_prefix);
/* no-prefix */
next = "node";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_null(next);
assert_int_equal(0, is_prefix);
/* no-prefix */
next = "::::";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_null(next);
assert_int_equal(0, is_prefix);
/* no-prefix */
next = "//a/:";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(5, bytes);
assert_null(next);
assert_int_equal(0, is_prefix);
/* no-prefix */
next = "//a//";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(5, bytes);
assert_null(next);
assert_int_equal(0, is_prefix);
/* prefix, prefix */
next = "pref1:pref2:";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(5, bytes);
assert_string_equal(next, "pref2:");
assert_int_equal(1, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(5, bytes);
assert_null(next);
assert_int_equal(1, is_prefix);
/* prefix, no-prefix */
next = "pref:node";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_string_equal(next, "node");
assert_int_equal(1, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_null(next);
assert_int_equal(0, is_prefix);
/* no-prefix, prefix */
next = "/pref:";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(1, bytes);
assert_string_equal(next, "pref:");
assert_int_equal(0, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_null(next);
assert_int_equal(1, is_prefix);
/* no-prefix, prefix */
next = "//pref:";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(2, bytes);
assert_string_equal(next, "pref:");
assert_int_equal(0, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_null(next);
assert_int_equal(1, is_prefix);
/* no-prefix, prefix, no-prefix */
next = "/pref:node";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(1, bytes);
assert_string_equal(next, "pref:node");
assert_int_equal(0, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_string_equal(next, "node");
assert_int_equal(1, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_null(next);
assert_int_equal(0, is_prefix);
/* prefix, no-prefix, prefix */
next = "pref:node pref:";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_string_equal(next, "node pref:");
assert_int_equal(1, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(5, bytes);
assert_string_equal(next, "pref:");
assert_int_equal(0, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_null(next);
assert_int_equal(1, is_prefix);
/* prefix, no-prefix, prefix, no-prefix */
next = "pref:node /pref:node";
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_string_equal(next, "node /pref:node");
assert_int_equal(1, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(6, bytes);
assert_string_equal(next, "pref:node");
assert_int_equal(0, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_string_equal(next, "node");
assert_int_equal(1, is_prefix);
assert_int_equal(LY_SUCCESS, ly_value_prefix_next(next, NULL, &bytes, &is_prefix, &next));
assert_int_equal(4, bytes);
assert_null(next);
assert_int_equal(0, is_prefix);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_utf8),
UTEST(test_parse_int),
UTEST(test_parse_uint),
UTEST(test_parse_nodeid),
UTEST(test_parse_instance_predicate),
UTEST(test_value_prefix_next),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,262 @@
/**
* @file test_hash_table.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from hash_table.c
*
* Copyright (c) 2018 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _UTEST_MAIN_
#include "utests.h"
#include <stdlib.h>
#include "hash_table.h"
#include "ly_common.h"
static void
test_invalid_arguments(void **state)
{
assert_int_equal(LY_EINVAL, lydict_insert(NULL, NULL, 0, NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (lydict_insert()).");
assert_int_equal(LY_EINVAL, lydict_insert_zc(NULL, NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (lydict_insert_zc()).");
assert_int_equal(LY_EINVAL, lydict_insert_zc(UTEST_LYCTX, NULL, NULL));
CHECK_LOG_CTX("Invalid argument str_p (lydict_insert_zc()).", NULL, 0);
}
static void
test_dict_hit(void **state)
{
const char *str1, *str2, *str3;
/* insert 2 strings, one of them repeatedly */
assert_int_equal(LY_SUCCESS, lydict_insert(UTEST_LYCTX, "test1", 0, &str1));
assert_non_null(str1);
/* via zerocopy we have to get the same pointer as provided */
assert_non_null(str2 = strdup("test2"));
assert_int_equal(LY_SUCCESS, lydict_insert_zc(UTEST_LYCTX, (char *)str2, &str3));
assert_ptr_equal(str2, str3);
/* here we get the same pointer as in case the string was inserted first time */
assert_int_equal(LY_SUCCESS, lydict_insert(UTEST_LYCTX, "test1", 0, &str2));
assert_non_null(str2);
assert_ptr_equal(str1, str2);
/* remove strings, but the repeatedly inserted only once */
lydict_remove(UTEST_LYCTX, "test1");
lydict_remove(UTEST_LYCTX, "test2");
/* destroy dictionary - should raise warning about data presence */
ly_ctx_destroy(UTEST_LYCTX);
UTEST_LYCTX = NULL;
CHECK_LOG_LASTMSG("String \"test1\" not freed from the dictionary, refcount 1.");
#ifndef NDEBUG
/* cleanup */
free((char *)str1);
#endif
}
static uint8_t
ht_equal_clb(void *val1, void *val2, uint8_t mod, void *cb_data)
{
int *v1, *v2;
(void)mod;
(void)cb_data;
v1 = (int *)val1;
v2 = (int *)val2;
return *v1 == *v2;
}
static void
test_ht_basic(void **UNUSED(state))
{
uint32_t i;
struct ly_ht *ht;
assert_non_null(ht = lyht_new(8, sizeof(int), ht_equal_clb, NULL, 0));
i = 2;
assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, i, NULL));
assert_int_equal(LY_SUCCESS, lyht_insert(ht, &i, i, NULL));
assert_int_equal(LY_SUCCESS, lyht_find(ht, &i, i, NULL));
assert_int_equal(LY_SUCCESS, lyht_remove(ht, &i, i));
assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, i, NULL));
assert_int_equal(LY_ENOTFOUND, lyht_remove(ht, &i, i));
CHECK_LOG_LASTMSG("Invalid argument hash (lyht_remove_with_resize_cb()).");
lyht_free(ht, NULL);
}
static void
test_ht_resize(void **UNUSED(state))
{
uint32_t i;
struct ly_ht *ht;
assert_non_null(ht = lyht_new(8, sizeof(int), ht_equal_clb, NULL, 1));
assert_int_equal(8, ht->size);
/* insert records into indexes 2-7 */
for (i = 2; i < 8; ++i) {
assert_int_equal(LY_SUCCESS, lyht_insert(ht, &i, i, NULL));
}
/* check that table resized */
assert_int_equal(16, ht->size);
/* check expected content of the table */
for (i = 0; i < 16; ++i) {
if ((i >= 2) && (i < 8)) {
/* inserted data on indexes 2-7 */
assert_int_not_equal(UINT32_MAX, ht->hlists[i].first);
assert_int_equal(LY_SUCCESS, lyht_find(ht, &i, i, NULL));
} else {
/* nothing otherwise */
assert_int_equal(UINT32_MAX, ht->hlists[i].first);
assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, i, NULL));
}
}
/* removing not present data should fail */
for (i = 0; i < 2; ++i) {
assert_int_equal(LY_ENOTFOUND, lyht_remove(ht, &i, i));
CHECK_LOG_LASTMSG("Invalid argument hash (lyht_remove_with_resize_cb()).");
}
/* removing present data, resize should happened
* when we are below 25% of the table filled, so with 3 records left */
for ( ; i < 5; ++i) {
assert_int_equal(LY_SUCCESS, lyht_remove(ht, &i, i));
}
assert_int_equal(8, ht->size);
/* remove the rest */
for ( ; i < 8; ++i) {
assert_int_equal(LY_SUCCESS, lyht_remove(ht, &i, i));
}
for (i = 0; i < 8; ++i) {
assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, i, NULL));
}
/* cleanup */
lyht_free(ht, NULL);
}
static void
test_ht_collisions(void **UNUSED(state))
{
#define GET_REC_INT(rec) (*((uint32_t *)&(rec)->val))
uint32_t i;
struct ly_ht_rec *rec;
struct ly_ht *ht;
uint32_t rec_idx;
int count;
assert_non_null(ht = lyht_new(8, sizeof(int), ht_equal_clb, NULL, 1));
for (i = 2; i < 6; ++i) {
assert_int_equal(lyht_insert(ht, &i, 2, NULL), 0);
}
/* check all records */
for (i = 0; i < 8; ++i) {
if (i == 2) {
assert_int_not_equal(UINT32_MAX, ht->hlists[i].first);
} else {
assert_int_equal(UINT32_MAX, ht->hlists[i].first);
}
}
for (i = 0; i < 8; ++i) {
if ((i >= 2) && (i < 6)) {
assert_int_equal(LY_SUCCESS, lyht_find(ht, &i, 2, NULL));
} else {
assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, 2, NULL));
}
}
rec_idx = ht->hlists[2].first;
count = 0;
while (rec_idx != UINT32_MAX) {
rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx);
rec_idx = rec->next;
assert_int_equal(rec->hash, 2);
count++;
}
assert_int_equal(count, 4);
i = 4;
assert_int_equal(lyht_remove(ht, &i, 2), 0);
rec = lyht_get_rec(ht->recs, ht->rec_size, i);
i = 2;
assert_int_equal(lyht_remove(ht, &i, 2), 0);
/* check all records */
for (i = 0; i < 8; ++i) {
if (i == 2) {
assert_int_not_equal(UINT32_MAX, ht->hlists[i].first);
} else {
assert_int_equal(UINT32_MAX, ht->hlists[i].first);
}
}
for (i = 0; i < 8; ++i) {
if ((i == 3) || (i == 5)) {
assert_int_equal(LY_SUCCESS, lyht_find(ht, &i, 2, NULL));
} else {
assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, 2, NULL));
}
}
rec_idx = ht->hlists[2].first;
count = 0;
while (rec_idx != UINT32_MAX) {
rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx);
rec_idx = rec->next;
assert_int_equal(rec->hash, 2);
count++;
}
assert_int_equal(count, 2);
for (i = 0; i < 8; ++i) {
if ((i == 3) || (i == 5)) {
assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_SUCCESS);
} else {
assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_ENOTFOUND);
}
}
i = 3;
assert_int_equal(lyht_remove(ht, &i, 2), 0);
i = 5;
assert_int_equal(lyht_remove(ht, &i, 2), 0);
/* check all records */
for (i = 0; i < 8; ++i) {
assert_int_equal(UINT32_MAX, ht->hlists[i].first);
}
lyht_free(ht, NULL);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_invalid_arguments),
UTEST(test_dict_hit),
UTEST(test_ht_basic),
UTEST(test_ht_resize),
UTEST(test_ht_collisions),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

View file

@ -0,0 +1,407 @@
/**
* @file test_inout.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for input and output handlers functions
*
* Copyright (c) 2020 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _UTEST_MAIN_
#include "utests.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "in.h"
#include "log.h"
#include "ly_common.h"
#include "out.h"
#define TEST_INPUT_FILE TESTS_BIN "/libyang_test_input"
#define TEST_OUTPUT_FILE TESTS_BIN "/libyang_test_output"
#define TEST_OUTPUT_FILE2 TESTS_BIN "/libyang_test_output2"
static int
setup_files(void **state)
{
int fd;
UTEST_SETUP;
/* create input */
fd = open(TEST_INPUT_FILE, O_CREAT | O_WRONLY, 00600);
if (fd == -1) {
return 1;
}
/* write something */
if (write(fd, "data", 4) != 4) {
return 1;
}
close(fd);
/* create output */
fd = open(TEST_OUTPUT_FILE, O_CREAT | O_RDONLY, 00600);
if (fd == -1) {
return 1;
}
close(fd);
/* create output2 */
fd = open(TEST_OUTPUT_FILE2, O_CREAT | O_RDONLY, 00600);
if (fd == -1) {
return 1;
}
close(fd);
return 0;
}
static int
teardown_files(void **state)
{
unlink(TEST_INPUT_FILE);
unlink(TEST_OUTPUT_FILE);
unlink(TEST_OUTPUT_FILE2);
UTEST_TEARDOWN;
return 0;
}
static void
test_input_mem(void **UNUSED(state))
{
struct ly_in *in = NULL;
char *str1 = "a", *str2 = "b";
assert_int_equal(LY_EINVAL, ly_in_new_memory(NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument str (ly_in_new_memory()).");
assert_int_equal(LY_EINVAL, ly_in_new_memory(str1, NULL));
CHECK_LOG_LASTMSG("Invalid argument in (ly_in_new_memory()).");
assert_null(ly_in_memory(NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument in (ly_in_memory()).");
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str1, &in));
assert_int_equal(LY_IN_MEMORY, ly_in_type(in));
assert_ptr_equal(str1, ly_in_memory(in, str2));
assert_ptr_equal(str2, ly_in_memory(in, NULL));
assert_ptr_equal(str2, ly_in_memory(in, NULL));
ly_in_free(in, 0);
}
static void
test_input_fd(void **UNUSED(state))
{
struct ly_in *in = NULL;
int fd1, fd2;
struct stat statbuf;
assert_int_equal(LY_EINVAL, ly_in_new_fd(-1, NULL));
CHECK_LOG_LASTMSG("Invalid argument fd >= 0 (ly_in_new_fd()).");
assert_int_equal(-1, ly_in_fd(NULL, -1));
CHECK_LOG_LASTMSG("Invalid argument in (ly_in_fd()).");
assert_int_not_equal(-1, fd1 = open(TEST_INPUT_FILE, O_RDONLY));
assert_int_not_equal(-1, fd2 = open(TEST_INPUT_FILE, O_RDONLY));
assert_int_equal(LY_EINVAL, ly_in_new_fd(fd1, NULL));
CHECK_LOG_LASTMSG("Invalid argument in (ly_in_new_fd()).");
assert_int_equal(LY_SUCCESS, ly_in_new_fd(fd1, &in));
assert_int_equal(LY_IN_FD, ly_in_type(in));
assert_ptr_equal(fd1, ly_in_fd(in, fd2));
assert_ptr_equal(fd2, ly_in_fd(in, -1));
assert_ptr_equal(fd2, ly_in_fd(in, -1));
ly_in_free(in, 1);
/* fd1 is still open */
assert_int_equal(0, fstat(fd1, &statbuf));
close(fd1);
#ifndef _WIN32
/* But fd2 was closed by ly_in_free(). This results in an "invalid handler" on Windows. */
errno = 0;
assert_int_equal(-1, fstat(fd2, &statbuf));
assert_int_equal(errno, EBADF);
#endif
}
static void
test_input_file(void **UNUSED(state))
{
struct ly_in *in = NULL;
FILE *f1 = NULL, *f2 = NULL;
assert_int_equal(LY_EINVAL, ly_in_new_file(NULL, NULL));
assert_null(ly_in_file(NULL, NULL));
assert_non_null(f1 = fopen(TEST_INPUT_FILE, "rb"));
assert_non_null(f2 = fopen(TEST_INPUT_FILE, "rb"));
assert_int_equal(LY_EINVAL, ly_in_new_file(f1, NULL));
assert_int_equal(LY_SUCCESS, ly_in_new_file(f1, &in));
assert_int_equal(LY_IN_FILE, ly_in_type(in));
assert_ptr_equal(f1, ly_in_file(in, f2));
assert_ptr_equal(f2, ly_in_file(in, NULL));
assert_ptr_equal(f2, ly_in_file(in, NULL));
ly_in_free(in, 1);
/* f1 is still open */
assert_int_not_equal(-1, fileno(f1));
fclose(f1);
/* but f2 was closed by ly_in_free() */
}
static void
test_input_filepath(void **UNUSED(state))
{
struct ly_in *in = NULL;
const char *path1 = TEST_INPUT_FILE, *path2 = TEST_INPUT_FILE;
assert_int_equal(LY_EINVAL, ly_in_new_filepath(NULL, 0, NULL));
assert_int_equal(LY_EINVAL, ly_in_new_filepath(path1, 0, NULL));
assert_ptr_equal(((void *)-1), ly_in_filepath(NULL, NULL, 0));
assert_int_equal(LY_SUCCESS, ly_in_new_filepath(path1, 0, &in));
assert_int_equal(LY_IN_FILEPATH, ly_in_type(in));
assert_ptr_equal(NULL, ly_in_filepath(in, path2, 0));
assert_string_equal(path2, ly_in_filepath(in, NULL, 0));
ly_in_free(in, 0);
}
static void
test_output_mem(void **UNUSED(state))
{
struct ly_out *out = NULL;
char *buf1 = NULL, *buf2 = NULL;
/* manipulate with the handler */
assert_int_equal(LY_SUCCESS, ly_out_new_memory(&buf1, 0, &out));
assert_int_equal(LY_OUT_MEMORY, ly_out_type(out));
ly_write(out, "test", 4);
assert_ptr_equal(buf1, ly_out_memory(out, &buf2, 0));
assert_ptr_equal(buf2, ly_out_memory(out, NULL, 0));
assert_ptr_equal(buf2, ly_out_memory(out, &buf1, strlen(buf1)));
ly_out_free(out, NULL, 0);
assert_int_equal(LY_SUCCESS, ly_out_new_memory(&buf1, strlen(buf1), &out));
ly_out_free(out, NULL, 1);
/* writing data */
assert_int_equal(LY_SUCCESS, ly_out_new_memory(&buf1, 0, &out));
assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
assert_int_equal(10, ly_out_printed(out));
assert_string_equal("test print", buf1);
assert_int_equal(LY_SUCCESS, ly_out_reset(out));
assert_int_equal(LY_SUCCESS, ly_write(out, "rewrite", 8));
assert_int_equal(8, ly_out_printed(out));
assert_string_equal("rewrite", buf1);
ly_out_free(out, NULL, 1);
}
static void
test_output_fd(void **UNUSED(state))
{
struct ly_out *out = NULL;
int fd1, fd2;
char buf[31] = {0};
assert_int_not_equal(-1, fd1 = open(TEST_OUTPUT_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
assert_int_not_equal(-1, fd2 = open(TEST_OUTPUT_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
/* manipulate with the handler */
assert_int_equal(LY_SUCCESS, ly_out_new_fd(fd1, &out));
assert_int_equal(LY_OUT_FD, ly_out_type(out));
assert_ptr_equal(fd1, ly_out_fd(out, fd2));
assert_ptr_equal(fd2, ly_out_fd(out, -1));
assert_ptr_equal(fd2, ly_out_fd(out, fd1));
ly_out_free(out, NULL, 0);
assert_int_equal(0, close(fd2));
assert_int_equal(LY_SUCCESS, ly_out_new_fd(fd1, &out));
ly_out_free(out, NULL, 1);
/* writing data */
assert_int_not_equal(-1, fd1 = open(TEST_OUTPUT_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
assert_int_not_equal(-1, fd2 = open(TEST_OUTPUT_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
/* truncate file to start with no data */
assert_int_equal(0, ftruncate(fd1, 0));
assert_int_equal(LY_SUCCESS, ly_out_new_fd(fd1, &out));
assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
assert_int_equal(10, ly_out_printed(out));
ly_print_flush(out);
assert_int_equal(10, read(fd2, buf, 30));
assert_string_equal("test print", buf);
assert_int_equal(0, lseek(fd2, 0, SEEK_SET));
assert_int_equal(LY_SUCCESS, ly_out_reset(out));
assert_int_equal(LY_SUCCESS, ly_write(out, "rewrite", 8));
assert_int_equal(8, ly_out_printed(out));
ly_print_flush(out);
assert_int_equal(8, read(fd2, buf, 30));
assert_string_equal("rewrite", buf);
close(fd2);
ly_out_free(out, NULL, 1);
}
static void
test_output_file(void **UNUSED(state))
{
struct ly_out *out = NULL;
FILE *f1, *f2;
char buf[31] = {0};
assert_non_null(f1 = fopen(TEST_OUTPUT_FILE, "wb"));
assert_non_null(f2 = fopen(TEST_OUTPUT_FILE, "wb"));
/* manipulate with the handler */
assert_int_equal(LY_SUCCESS, ly_out_new_file(f1, &out));
assert_int_equal(LY_OUT_FILE, ly_out_type(out));
assert_ptr_equal(f1, ly_out_file(out, f2));
assert_ptr_equal(f2, ly_out_file(out, NULL));
assert_ptr_equal(f2, ly_out_file(out, f1));
ly_out_free(out, NULL, 0);
assert_int_equal(0, fclose(f2));
assert_int_equal(LY_SUCCESS, ly_out_new_file(f1, &out));
ly_out_free(out, NULL, 1);
/* writing data */
assert_non_null(f1 = fopen(TEST_OUTPUT_FILE, "wb"));
assert_non_null(f2 = fopen(TEST_OUTPUT_FILE, "rb"));
assert_int_equal(LY_SUCCESS, ly_out_new_file(f1, &out));
assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
assert_int_equal(10, ly_out_printed(out));
ly_print_flush(out);
assert_non_null(fgets(buf, 31, f2));
assert_string_equal("test print", buf);
assert_int_equal(0, fseek(f2, 0, SEEK_SET));
assert_int_equal(LY_SUCCESS, ly_out_reset(out));
assert_int_equal(LY_SUCCESS, ly_write(out, "rewrite", 8));
assert_int_equal(8, ly_out_printed(out));
ly_print_flush(out);
assert_non_null(fgets(buf, 31, f2));
assert_string_equal("rewrite", buf);
fclose(f2);
ly_out_free(out, NULL, 1);
}
static void
test_output_filepath(void **UNUSED(state))
{
struct ly_out *out = NULL;
FILE *f1;
char buf[31] = {0};
const char *fp1 = TEST_OUTPUT_FILE;
const char *fp2 = TEST_OUTPUT_FILE2;
/* manipulate with the handler */
assert_int_equal(LY_SUCCESS, ly_out_new_filepath(fp1, &out));
assert_int_equal(LY_OUT_FILEPATH, ly_out_type(out));
assert_ptr_equal(NULL, ly_out_filepath(out, fp2));
assert_string_equal(fp2, ly_out_filepath(out, NULL));
assert_ptr_equal(NULL, ly_out_filepath(out, fp1));
ly_out_free(out, NULL, 0);
assert_int_equal(LY_SUCCESS, ly_out_new_filepath(fp1, &out));
ly_out_free(out, NULL, 1);
/* writing data */
assert_non_null(f1 = fopen(fp1, "rb"));
assert_int_equal(LY_SUCCESS, ly_out_new_filepath(fp1, &out));
assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
assert_int_equal(10, ly_out_printed(out));
ly_print_flush(out);
assert_non_null(fgets(buf, 31, f1));
assert_string_equal("test print", buf);
assert_int_equal(0, fseek(f1, 0, SEEK_SET));
assert_int_equal(LY_SUCCESS, ly_out_reset(out));
assert_int_equal(LY_SUCCESS, ly_write(out, "rewrite", 8));
assert_int_equal(8, ly_out_printed(out));
ly_print_flush(out);
assert_non_null(fgets(buf, 31, f1));
assert_string_equal("rewrite", buf);
fclose(f1);
ly_out_free(out, NULL, 1);
}
static ssize_t
write_clb(void *user_data, const void *buf, size_t count)
{
return write((uintptr_t)user_data, buf, count);
}
void
close_clb(void *arg)
{
close((uintptr_t)arg);
}
static void
test_output_clb(void **UNUSED(state))
{
struct ly_out *out = NULL;
int fd1, fd2;
char buf[31] = {0};
assert_int_not_equal(-1, fd1 = open(TEST_OUTPUT_FILE, O_RDWR));
assert_int_not_equal(-1, fd2 = open(TEST_OUTPUT_FILE, O_RDWR));
/* manipulate with the handler */
assert_int_equal(LY_SUCCESS, ly_out_new_clb(write_clb, (void *)(intptr_t)fd1, &out));
assert_int_equal(LY_OUT_CALLBACK, ly_out_type(out));
assert_ptr_equal(fd1, ly_out_clb_arg(out, (void *)(intptr_t)fd2));
assert_ptr_equal(fd2, ly_out_clb_arg(out, NULL));
assert_ptr_equal(fd2, ly_out_clb_arg(out, (void *)(intptr_t)fd1));
assert_ptr_equal(write_clb, ly_out_clb(out, write_clb));
ly_out_free(out, NULL, 0);
assert_int_equal(0, close(fd2));
assert_int_equal(LY_SUCCESS, ly_out_new_clb(write_clb, (void *)(intptr_t)fd1, &out));
ly_out_free(out, close_clb, 0);
/* writing data */
assert_int_not_equal(-1, fd1 = open(TEST_OUTPUT_FILE, O_RDWR));
assert_int_not_equal(-1, fd2 = open(TEST_OUTPUT_FILE, O_RDWR));
/* truncate file to start with no data */
assert_int_equal(0, ftruncate(fd1, 0));
assert_int_equal(LY_SUCCESS, ly_out_new_clb(write_clb, (void *)(intptr_t)fd1, &out));
assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
assert_int_equal(10, ly_out_printed(out));
assert_int_equal(10, read(fd2, buf, 30));
assert_string_equal("test print", buf);
close(fd2);
ly_out_free(out, close_clb, 0);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_input_mem),
UTEST(test_input_fd, setup_files, teardown_files),
UTEST(test_input_file, setup_files, teardown_files),
UTEST(test_input_filepath, setup_files, teardown_files),
UTEST(test_output_mem),
UTEST(test_output_fd, setup_files, teardown_files),
UTEST(test_output_file, setup_files, teardown_files),
UTEST(test_output_filepath, setup_files, teardown_files),
UTEST(test_output_clb, setup_files, teardown_files),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

View file

@ -0,0 +1,773 @@
/**
* @file test_json.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for a generic JSON parser
*
* Copyright (c) 2020 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _UTEST_MAIN_
#include "utests.h"
#include "context.h"
#include "in_internal.h"
#include "json.h"
static void
test_general(void **state)
{
struct lyjson_ctx *jsonctx;
struct ly_in *in;
const char *str;
/* empty */
str = "";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Empty JSON file.", NULL, 1);
str = " \n\t \n";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Empty JSON file.", NULL, 3);
/* constant values */
str = "true";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_TRUE, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
str = "false";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_FALSE, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
str = "null";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
ly_in_free(in, 0);
}
static void
test_number(void **state)
{
struct lyjson_ctx *jsonctx;
struct ly_in *in;
const char *str;
/* simple value */
str = "11";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("11", jsonctx->value);
assert_int_equal(2, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
/* fraction number */
str = "37.7668";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("37.7668", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
/* negative number */
str = "-122.3959";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-122.3959", jsonctx->value);
assert_int_equal(9, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
/* integer, positive exponent */
str = "550E3";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("550000", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "-550E3";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-550000", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
/* integer, negative exponent */
str = "1E-1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.1", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "15E-1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("1.5", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "-15E-1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-1.5", jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "16E-2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.16", jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "-16E-2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-0.16", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "17E-3";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.017", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "-17E-3";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-0.017", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "21000E-2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("210", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "21000E-4";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("2.1", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "21000E-7";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.0021", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
/* decimal number, positive exponent */
str = "5.087E1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("50.87", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "-5.087E1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-50.87", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "5.087E5";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("508700", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "59.1e+1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("591", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.005087E1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.05087", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.005087E2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.5087", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.005087E6";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("5087", jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.05087E6";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("50870", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.005087E8";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("508700", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
/* decimal number, negative exponent */
str = "35.94e-1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("3.594", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "-35.94e-1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-3.594", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "35.94e-2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.3594", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "35.94e-3";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.03594", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.3594e-1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.03594", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.03594e-1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.003594", jsonctx->value);
assert_int_equal(8, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.003594e-1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.0003594", jsonctx->value);
assert_int_equal(9, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.3594e-2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.003594", jsonctx->value);
assert_int_equal(8, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.03594e-2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.0003594", jsonctx->value);
assert_int_equal(9, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0.003594e-2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.00003594", jsonctx->value);
assert_int_equal(10, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
/* zero */
str = "0";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '0');
assert_int_equal(1, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "-0";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '-');
assert_true(jsonctx->value[1] == '0');
assert_int_equal(2, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "94E0";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '9');
assert_true(jsonctx->value[1] == '4');
assert_int_equal(2, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "0E2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '0');
assert_int_equal(1, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "-0E2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '-');
assert_true(jsonctx->value[1] == '0');
assert_int_equal(2, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "5.320e+2";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("532", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
str = "5.320e-1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.532", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
lyjson_ctx_free(jsonctx);
/* various invalid inputs */
str = "-x";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character in JSON Number value (\"x\").", NULL, 1);
str = " -";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Unexpected end-of-input.", NULL, 1);
str = "--1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character in JSON Number value (\"-\").", NULL, 1);
str = "+1";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character sequence \"+1\", expected a JSON value.", NULL, 1);
str = " 1.x ";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character in JSON Number value (\"x\").", NULL, 1);
str = "1.";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Unexpected end-of-input.", NULL, 1);
str = " 1eo ";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character in JSON Number value (\"o\").", NULL, 1);
str = "1e";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Unexpected end-of-input.", NULL, 1);
str = "1E1000";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Number encoded as a string exceeded the LY_NUMBER_MAXLEN limit.", NULL, 1);
str = "1e9999999999999999999";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Exponent out-of-bounds in a JSON Number value (1e9999999999999999999).", NULL, 1);
str = "1.1e66000";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Exponent out-of-bounds in a JSON Number value (1.1e66000).", NULL, 1);
str = "1.1e-66000";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Exponent out-of-bounds in a JSON Number value (1.1e-66000).", NULL, 1);
ly_in_free(in, 0);
}
/* now string is tested in file ./tests/utests/types/string.c */
static void
test_string(void **state)
{
struct lyjson_ctx *jsonctx;
struct ly_in *in = NULL;
const char *str;
str = "";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
/* unterminated string */
str = "\"unterminated string";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Missing quotation-mark at the end of a JSON string.", NULL, 1);
CHECK_LOG_CTX("Unexpected end-of-input.", NULL, 1);
ly_in_free(in, 0);
}
static void
test_object(void **state)
{
struct lyjson_ctx *jsonctx;
struct ly_in *in;
const char *str;
/* empty */
str = " { } ";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* simple value */
str = "{\"name\" : \"Radek\"}";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_ptr_equal(&str[2], jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx));
assert_string_equal("Radek\"}", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* two values */
str = "{\"smart\" : true,\"handsom\":false}";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("smart\" : true,\"handsom\":false}", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_TRUE, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_NEXT, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("handsom\":false}", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_FALSE, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* inherited objects */
str = "{\"person\" : {\"name\":\"Radek\"}}";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("person\" : {\"name\":\"Radek\"}}", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("name\":\"Radek\"}}", jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx));
assert_string_equal("Radek\"}}", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* unquoted string */
str = "{ unquoted : \"data\"}";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_EVALID, lyjson_ctx_next(jsonctx, NULL));
CHECK_LOG_CTX("Invalid character sequence \"unquoted : \"data\"}\", expected a JSON object name.", NULL, 1);
lyjson_ctx_free(jsonctx);
ly_in_free(in, 0);
}
static void
test_array(void **state)
{
struct lyjson_ctx *jsonctx;
struct ly_in *in;
const char *str;
/* empty */
str = " [ ] ";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* simple value */
str = "[ null]";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx));
assert_null(jsonctx->value);
assert_int_equal(0, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* two values */
str = "[{\"a\":null},\"x\"]";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx));
assert_null(jsonctx->value);
assert_int_equal(0, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("a\":null},\"x\"]", jsonctx->value);
assert_int_equal(1, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_ARRAY_NEXT, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx));
assert_string_equal("x\"]", jsonctx->value);
assert_int_equal(1, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx));
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* new line is allowed only as escaped character in JSON */
str = "[ , null]";
assert_non_null(ly_in_memory(in, str));
assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LY_EVALID, lyjson_ctx_next(jsonctx, NULL));
CHECK_LOG_CTX("Invalid character sequence \", null]\", expected a JSON value.", NULL, 1);
lyjson_ctx_free(jsonctx);
ly_in_free(in, 0);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_general),
UTEST(test_number),
UTEST(test_string),
UTEST(test_object),
UTEST(test_array),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

View file

@ -0,0 +1,153 @@
/**
* @file test_plugins.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from set.c
*
* Copyright (c) 2018 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _UTEST_MAIN_
#include "utests.h"
#include <stdlib.h>
#include <string.h>
#include "ly_config.h"
#include "plugins.h"
#include "plugins_internal.h"
const char *simple = "module libyang-plugins-simple {"
" namespace urn:libyang:tests:plugins:simple;"
" prefix s;"
" typedef note { type string; }"
" extension hint { argument value; }"
" leaf test {"
" type s:note {length 255;}"
" s:hint \"some hint here\";"
" }"
"}";
static void
test_add_invalid(void **state)
{
(void)state;
assert_int_equal(LY_ESYS, lyplg_add(TESTS_BIN "/plugins/plugin_does_not_exist" LYPLG_SUFFIX));
}
static void
test_add_simple(void **state)
{
struct lys_module *mod;
struct lysc_node_leaf *leaf;
struct lyplg_ext_record *record_e;
struct lyplg_type *plugin_t;
assert_int_equal(LY_SUCCESS, lyplg_add(TESTS_BIN "/plugins/plugin_simple" LYPLG_SUFFIX));
UTEST_ADD_MODULE(simple, LYS_IN_YANG, NULL, &mod);
leaf = (struct lysc_node_leaf *)mod->compiled->data;
assert_int_equal(LYS_LEAF, leaf->nodetype);
assert_non_null(plugin_t = lyplg_type_plugin_find(NULL, "libyang-plugins-simple", NULL, "note"));
assert_string_equal("ly2 simple test v1", plugin_t->id);
assert_ptr_equal(leaf->type->plugin, plugin_t);
assert_int_equal(1, LY_ARRAY_COUNT(leaf->exts));
assert_non_null(record_e = lyplg_ext_record_find(NULL, "libyang-plugins-simple", NULL, "hint"));
assert_string_equal("ly2 simple test v1", record_e->plugin.id);
assert_ptr_equal(leaf->exts[0].def->plugin, &record_e->plugin);
/* the second loading of the same plugin - still success */
assert_int_equal(LY_SUCCESS, lyplg_add(TESTS_BIN "/plugins/plugin_simple" LYPLG_SUFFIX));
}
static void
test_not_implemented(void **state)
{
struct lys_module *mod;
struct lyd_node *tree;
const char *schema = "module libyang-plugins-unknown {"
" namespace urn:libyang:tests:plugins:unknown;"
" prefix u;"
" extension myext;"
" typedef mytype { type string;}"
" leaf test {"
" u:myext;"
" type mytype;"
" }"
"}";
const char *data = "<test xmlns=\"urn:libyang:tests:plugins:unknown\">xxx</test>";
char *printed = NULL;
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
free(printed);
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
CHECK_LOG_CTX(NULL, NULL, 0);
lyd_free_all(tree);
}
static LY_ERR
parse_clb(struct lysp_ctx *UNUSED(pctx), struct lysp_ext_instance *ext)
{
struct lysp_node_leaf *leaf;
leaf = (struct lysp_node_leaf *)ext->parent;
leaf->flags |= LYS_STATUS_OBSLT;
return LY_SUCCESS;
}
struct lyplg_ext_record memory_recs[] = {
{
.module = "libyang-plugins-simple",
.revision = NULL,
.name = "hint",
.plugin.id = "memory-plugin-v1",
.plugin.parse = parse_clb,
.plugin.compile = NULL,
.plugin.printer_info = NULL,
.plugin.node = NULL,
.plugin.snode = NULL,
.plugin.validate = NULL,
.plugin.pfree = NULL,
.plugin.cfree = NULL
},
{0} /* terminating zeroed item */
};
static void
test_simple_from_memory(void **state)
{
struct lys_module *mod;
struct lysc_node_leaf *leaf;
lyplg_add_extension_plugin(UTEST_LYCTX, LYPLG_EXT_API_VERSION, memory_recs);
UTEST_ADD_MODULE(simple, LYS_IN_YANG, NULL, &mod);
leaf = (struct lysc_node_leaf *)mod->compiled->data;
assert_int_equal(LYS_LEAF, leaf->nodetype);
assert_true(leaf->flags & LYS_STATUS_OBSLT);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_add_invalid),
UTEST(test_add_simple),
UTEST(test_not_implemented),
UTEST(test_simple_from_memory),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

View file

@ -0,0 +1,276 @@
/**
* @file test_set.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from set.c
*
* Copyright (c) 2018 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _POSIX_C_SOURCE 200809L /* strdup */
#define _UTEST_MAIN_
#include "utests.h"
#include <stdlib.h>
#include <string.h>
#include "set.h"
static void
test_basics(void **UNUSED(state))
{
struct ly_set *set;
char *str;
unsigned int u;
void *ptr;
uint32_t index;
/* creation - everything is empty */
assert_int_equal(LY_SUCCESS, ly_set_new(&set));
assert_non_null(set);
assert_int_equal(0, set->count);
assert_int_equal(0, set->size);
assert_null(set->objs);
/* add a testing object */
str = strdup("test string");
assert_non_null(str);
assert_int_equal(LY_SUCCESS, ly_set_add(set, str, 0, NULL));
assert_int_not_equal(0, set->size);
assert_int_equal(1, set->count);
assert_non_null(set->objs);
assert_non_null(set->objs[0]);
/* check the presence of the testing data */
assert_int_equal(1, ly_set_contains(set, str, &index));
assert_int_equal(0, index);
assert_int_equal(0, ly_set_contains(set, str - 1, NULL));
/* remove data, but keep the set */
u = set->size;
ptr = set->objs;
ly_set_clean(set, free);
assert_int_equal(0, set->count);
assert_int_equal(u, set->size);
assert_ptr_equal(ptr, set->objs);
/* remove buffer, but keep the set object */
ly_set_erase(set, NULL);
assert_int_equal(0, set->count);
assert_int_equal(0, set->size);
assert_ptr_equal(NULL, set->objs);
/* final cleanup */
ly_set_free(set, NULL);
}
static void
test_inval(void **UNUSED(state))
{
struct ly_set set = {0};
assert_int_equal(LY_EINVAL, ly_set_dup(NULL, NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument set (ly_set_dup()).");
assert_int_equal(LY_EINVAL, ly_set_add(NULL, NULL, 0, NULL));
CHECK_LOG_LASTMSG("Invalid argument set (ly_set_add()).");
assert_int_equal(LY_EINVAL, ly_set_merge(NULL, NULL, 0, NULL));
CHECK_LOG_LASTMSG("Invalid argument trg (ly_set_merge()).");
assert_int_equal(LY_SUCCESS, ly_set_merge(&set, NULL, 0, NULL));
assert_int_equal(LY_EINVAL, ly_set_rm_index(NULL, 0, NULL));
CHECK_LOG_LASTMSG("Invalid argument set (ly_set_rm_index()).");
assert_int_equal(LY_EINVAL, ly_set_rm_index(&set, 1, NULL));
CHECK_LOG_LASTMSG("Invalid argument index (ly_set_rm_index()).");
assert_int_equal(LY_EINVAL, ly_set_rm(NULL, NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument set (ly_set_rm()).");
assert_int_equal(LY_EINVAL, ly_set_rm(&set, NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument object (ly_set_rm()).");
assert_int_equal(LY_EINVAL, ly_set_rm(&set, &set, NULL));
CHECK_LOG_LASTMSG("Invalid argument object (ly_set_rm()).");
}
static void
test_duplication(void **UNUSED(state))
{
struct ly_set *orig, *new;
char *str;
uint32_t index;
assert_int_equal(LY_SUCCESS, ly_set_new(&orig));
assert_non_null(orig);
/* add a testing object */
str = strdup("test string");
assert_non_null(str);
assert_int_equal(LY_SUCCESS, ly_set_add(orig, str, 0, &index));
assert_int_equal(0, index);
/* duplicate the set - without duplicator, so the new set will point to the same string */
assert_int_equal(LY_SUCCESS, ly_set_dup(orig, NULL, &new));
assert_non_null(new);
assert_ptr_not_equal(orig, new);
assert_int_equal(orig->count, new->count);
assert_ptr_equal(orig->objs[0], new->objs[0]);
ly_set_free(new, NULL);
/* duplicate the set - with duplicator, so the new set will point to a different buffer with the same content */
assert_int_equal(LY_SUCCESS, ly_set_dup(orig, (void *(*)(const void *))strdup, &new));
assert_non_null(new);
assert_ptr_not_equal(orig, new);
assert_int_equal(orig->count, new->count);
assert_ptr_not_equal(orig->objs[0], new->objs[0]);
assert_string_equal(orig->objs[0], new->objs[0]);
/* cleanup */
ly_set_free(new, free);
ly_set_free(orig, free);
}
static void
test_add(void **UNUSED(state))
{
uint32_t u, index;
char *str = "test string";
struct ly_set set;
memset(&set, 0, sizeof set);
/* add a testing object */
assert_int_equal(LY_SUCCESS, ly_set_add(&set, str, 0, &index));
assert_int_equal(0, index);
/* test avoiding data duplicities */
assert_int_equal(LY_SUCCESS, ly_set_add(&set, str, 0, &index));
assert_int_equal(0, index);
assert_int_equal(1, set.count);
assert_int_equal(LY_SUCCESS, ly_set_add(&set, str, 1, &index));
assert_int_equal(1, index);
assert_int_equal(2, set.count);
/* test array resizing */
u = set.size;
for (uint32_t expected_index = 2; expected_index <= u; ++expected_index) {
assert_int_equal(LY_SUCCESS, ly_set_add(&set, str, 1, &index));
assert_int_equal(expected_index, index);
}
assert_true(u != set.size);
/* cleanup */
ly_set_erase(&set, NULL);
}
static void
test_merge(void **UNUSED(state))
{
char *str1, *str2;
struct ly_set one, two;
memset(&one, 0, sizeof one);
memset(&two, 0, sizeof two);
str1 = strdup("string1");
str2 = strdup("string2");
/* fill first set
* - str1 is the same as in two, so it must not be freed! */
assert_int_equal(LY_SUCCESS, ly_set_add(&one, str1, 0, NULL));
/* fill second set */
assert_int_equal(LY_SUCCESS, ly_set_add(&two, str1, 0, NULL));
assert_int_equal(LY_SUCCESS, ly_set_add(&two, str2, 0, NULL));
/* merge with checking duplicities - only one item is added into one;
* also without duplicating data, so it must not be freed at the end */
assert_int_equal(LY_SUCCESS, ly_set_merge(&one, &two, 0, NULL));
assert_int_equal(2, one.count);
assert_ptr_equal(one.objs[1], two.objs[1]);
/* clean and re-fill one (now duplicating str1, to allow testing duplicator) */
ly_set_clean(&one, NULL);
assert_int_equal(LY_SUCCESS, ly_set_add(&one, strdup(str1), 0, NULL));
/* merge without checking duplicities - two items are added into one;
* here also with duplicator */
assert_int_equal(LY_SUCCESS, ly_set_merge(&one, &two, 1, (void *(*)(const void *))strdup));
assert_int_equal(3, one.count);
assert_ptr_not_equal(one.objs[1], two.objs[0]);
assert_string_equal(one.objs[1], two.objs[0]);
/* cleanup */
ly_set_erase(&one, free);
ly_set_erase(&two, free);
}
static void
test_rm(void **UNUSED(state))
{
char *str1, *str2, *str3;
struct ly_set set;
memset(&set, 0, sizeof set);
/* fill the set */
assert_int_equal(LY_SUCCESS, ly_set_add(&set, "string1", 0, NULL));
assert_int_equal(LY_SUCCESS, ly_set_add(&set, strdup("string2"), 0, NULL));
assert_int_equal(LY_SUCCESS, ly_set_add(&set, "string3", 0, NULL));
/* remove by index ... */
/* ... in the middle ... */
assert_int_equal(LY_SUCCESS, ly_set_rm_index(&set, 1, free));
assert_int_equal(2, set.count);
assert_string_not_equal("string2", set.objs[0]);
assert_string_not_equal("string2", set.objs[1]);
/* ... last .. */
assert_int_equal(LY_SUCCESS, ly_set_rm_index(&set, 1, NULL));
assert_int_equal(1, set.count);
assert_string_not_equal("string3", set.objs[0]);
/* ... first .. */
assert_int_equal(LY_SUCCESS, ly_set_rm_index(&set, 0, NULL));
assert_int_equal(0, set.count);
/* fill the set */
assert_int_equal(LY_SUCCESS, ly_set_add(&set, str1 = "string1", 0, NULL));
assert_int_equal(LY_SUCCESS, ly_set_add(&set, str2 = "string2", 0, NULL));
assert_int_equal(LY_SUCCESS, ly_set_add(&set, str3 = strdup("string3"), 0, NULL));
/* remove by pointer ... */
/* ... in the middle ... */
assert_int_equal(LY_SUCCESS, ly_set_rm(&set, str2, NULL));
assert_int_equal(2, set.count);
assert_string_not_equal("string2", set.objs[0]);
assert_string_not_equal("string2", set.objs[1]);
/* ... last (with destructor) .. */
assert_int_equal(LY_SUCCESS, ly_set_rm(&set, str3, free));
assert_int_equal(1, set.count);
assert_string_not_equal("string3", set.objs[0]);
/* ... first .. */
assert_int_equal(LY_SUCCESS, ly_set_rm(&set, str1, NULL));
assert_int_equal(0, set.count);
/* cleanup */
ly_set_erase(&set, NULL);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_basics),
UTEST(test_duplication),
UTEST(test_add),
UTEST(test_merge),
UTEST(test_rm),
UTEST(test_inval),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

View file

@ -0,0 +1,689 @@
/**
* @file test_xml.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from xml.c
*
* Copyright (c) 2018 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _UTEST_MAIN_
#include "utests.h"
#define _POSIX_C_SOURCE 200809L /* strdup */
#include <string.h>
#include "context.h"
#include "in_internal.h"
#include "xml.h"
LY_ERR lyxml_ns_add(struct lyxml_ctx *xmlctx, const char *prefix, size_t prefix_len, char *uri);
static void
test_element(void **state)
{
struct lyxml_ctx *xmlctx;
struct ly_in *in;
const char *str;
/* empty */
str = "";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_END, xmlctx->status);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* end element */
str = "</element>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Stray closing element tag (\"element\").", NULL, 1);
ly_in_free(in, 0);
/* no element */
str = "no data present";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Invalid character sequence \"no data present\", expected element tag start ('<').", NULL, 1);
ly_in_free(in, 0);
/* not supported DOCTYPE */
str = "<!DOCTYPE greeting SYSTEM \"hello.dtd\"><greeting/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Document Type Declaration not supported.", NULL, 1);
ly_in_free(in, 0);
/* invalid XML */
str = "<!NONSENSE/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Unknown XML section \"<!NONSENSE/>\".", NULL, 1);
ly_in_free(in, 0);
/* namespace ambiguity */
str = "<element xmlns=\"urn1\" xmlns=\"urn2\"/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Duplicate default XML namespaces \"urn1\" and \"urn2\".", NULL, 1);
ly_in_free(in, 0);
/* prefix duplicate */
str = "<element xmlns:a=\"urn1\" xmlns:a=\"urn2\"/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Duplicate XML NS prefix \"a\" used for namespaces \"urn1\" and \"urn2\".", NULL, 1);
ly_in_free(in, 0);
/* unqualified element */
str = " < element/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_null(xmlctx->prefix);
assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
assert_int_equal(1, xmlctx->elements.count);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_true(!strncmp("", xmlctx->value, xmlctx->value_len));
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_END, xmlctx->status);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* element with attribute */
str = " < element attr=\'x\'/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
assert_null(xmlctx->prefix);
assert_int_equal(1, xmlctx->elements.count);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
assert_true(!strncmp("attr", xmlctx->name, xmlctx->name_len));
assert_null(xmlctx->prefix);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
assert_int_equal(1, xmlctx->elements.count);
assert_true(!strncmp("x", xmlctx->value, xmlctx->value_len));
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_int_equal(0, xmlctx->elements.count);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_END, xmlctx->status);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* headers and comments */
str = "<?xml version=\"1.0\"?> <!-- comment --> <?TEST xxx?> <element/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
assert_null(xmlctx->prefix);
assert_int_equal(1, xmlctx->elements.count);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_END, xmlctx->status);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* separate opening and closing tags, neamespaced parsed internally */
str = "<element xmlns=\"urn\"></element>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
assert_null(xmlctx->prefix);
assert_int_equal(1, xmlctx->elements.count);
assert_int_equal(1, xmlctx->ns.count);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_int_equal(0, xmlctx->elements.count);
assert_int_equal(0, xmlctx->ns.count);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_END, xmlctx->status);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* qualified element */
str = " < yin:element/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
assert_true(!strncmp("yin", xmlctx->prefix, xmlctx->prefix_len));
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_END, xmlctx->status);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* non-matching closing tag */
str = "<yin:element xmlns=\"urn\"></element>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_true(!strncmp("element", xmlctx->name, xmlctx->name_len));
assert_true(!strncmp("yin", xmlctx->prefix, xmlctx->prefix_len));
assert_int_equal(1, xmlctx->elements.count);
assert_int_equal(1, xmlctx->ns.count);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Opening (\"yin:element\") and closing (\"element\") elements tag mismatch.", NULL, 1);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* invalid closing tag */
str = "<yin:element xmlns=\"urn\"></yin:element/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Invalid character sequence \"/>\", expected element tag termination ('>').", NULL, 1);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* UTF8 characters */
str = "<𠜎€𠜎Øn:𠜎€𠜎Øn/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_true(!strncmp("𠜎€𠜎Øn", xmlctx->name, xmlctx->name_len));
assert_true(!strncmp("𠜎€𠜎Øn", xmlctx->prefix, xmlctx->prefix_len));
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_END, xmlctx->status);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* invalid UTF-8 characters */
str = "<¢:element>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Identifier \"¢:element>\" starts with an invalid character.", NULL, 1);
ly_in_free(in, 0);
str = "<yin:c⁐element>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Invalid character sequence \"⁐element>\", expected element tag end ('>' or '/>') or an attribute.", NULL, 1);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* mixed content */
str = "<a>text <b>x</b></a>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_true(!strncmp("a", xmlctx->name, xmlctx->name_len));
assert_null(xmlctx->prefix);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_true(!strncmp("text ", xmlctx->value, xmlctx->value_len));
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_true(!strncmp("b", xmlctx->name, xmlctx->name_len));
assert_null(xmlctx->prefix);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_true(!strncmp("x", xmlctx->value, xmlctx->value_len));
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_END, xmlctx->status);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* tag mismatch */
str = "<a>text</b>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_true(!strncmp("a", xmlctx->name, xmlctx->name_len));
assert_null(xmlctx->prefix);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_true(!strncmp("text", xmlctx->value, xmlctx->value_len));
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Opening (\"a\") and closing (\"b\") elements tag mismatch.", NULL, 1);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
}
static void
test_attribute(void **state)
{
const char *str;
struct lyxml_ctx *xmlctx;
struct ly_in *in;
struct lyxml_ns *ns;
/* not an attribute */
str = "<e unknown/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Invalid character sequence \"/>\", expected '='.", NULL, 1);
ly_in_free(in, 0);
str = "<e xxx=/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Invalid character sequence \"/>\", expected either single or double quotation mark.", NULL, 1);
ly_in_free(in, 0);
str = "<e xxx\n = yyy/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EVALID, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
CHECK_LOG_CTX("Invalid character sequence \"yyy/>\", expected either single or double quotation mark.", NULL, 2);
ly_in_free(in, 0);
/* valid attribute */
str = "<e attr=\"val\"";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
assert_true(!strncmp("attr", xmlctx->name, xmlctx->name_len));
assert_null(xmlctx->prefix);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
assert_true(!strncmp("val", xmlctx->value, xmlctx->value_len));
assert_int_equal(xmlctx->ws_only, 0);
assert_int_equal(xmlctx->dynamic, 0);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
/* valid namespace with prefix */
str = "<e xmlns:nc\n = \'urn\'/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_int_equal(1, xmlctx->ns.count);
ns = (struct lyxml_ns *)xmlctx->ns.objs[0];
assert_string_equal(ns->prefix, "nc");
assert_string_equal(ns->uri, "urn");
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
}
static void
test_text(void **state)
{
const char *str;
struct lyxml_ctx *xmlctx;
struct ly_in *in;
/* empty attribute value */
str = "<e a=\"\"";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
assert_true(!strncmp("", xmlctx->value, xmlctx->value_len));
assert_int_equal(xmlctx->ws_only, 1);
assert_int_equal(xmlctx->dynamic, 0);
ly_in_free(in, 0);
/* empty value but in single quotes */
assert_int_equal(LY_SUCCESS, ly_in_new_memory("=\'\'", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ATTRIBUTE;
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
assert_true(!strncmp("", xmlctx->value, xmlctx->value_len));
assert_int_equal(xmlctx->ws_only, 1);
assert_int_equal(xmlctx->dynamic, 0);
ly_in_free(in, 0);
/* empty element content - only formating before defining child */
assert_int_equal(LY_SUCCESS, ly_in_new_memory(">\n <y>", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ELEMENT;
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_true(!strncmp("\n ", xmlctx->value, xmlctx->value_len));
assert_int_equal(xmlctx->ws_only, 1);
assert_int_equal(xmlctx->dynamic, 0);
ly_in_free(in, 0);
/* empty element content is invalid - missing content terminating character < */
assert_int_equal(LY_SUCCESS, ly_in_new_memory("", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ELEM_CONTENT;
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Unexpected end-of-input.", NULL, 1);
ly_in_free(in, 0);
assert_int_equal(LY_SUCCESS, ly_in_new_memory("xxx", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ELEM_CONTENT;
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Invalid character sequence \"xxx\", expected element tag start ('<').", NULL, 1);
ly_in_free(in, 0);
lyxml_ctx_free(xmlctx);
ly_log_location_revert(0, 0, 0, 4);
/* valid strings */
str = "<a>€𠜎Øn \n&lt;&amp;&quot;&apos;&gt; &#82;&#x4f;&#x4B;</a>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_true(!strncmp("€𠜎Øn \n<&\"\'> ROK", xmlctx->value, xmlctx->value_len));
assert_int_equal(xmlctx->ws_only, 0);
assert_int_equal(xmlctx->dynamic, 1);
free((char *)xmlctx->value);
ly_in_free(in, 0);
/* test using n-bytes UTF8 hexadecimal code points */
assert_int_equal(LY_SUCCESS, ly_in_new_memory("=\'&#x0024;&#x00A2;&#x20ac;&#x10348;\'", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ATTRIBUTE;
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
assert_true(!strncmp("$¢€𐍈", xmlctx->value, xmlctx->value_len));
assert_int_equal(xmlctx->ws_only, 0);
assert_int_equal(xmlctx->dynamic, 1);
ly_in_free(in, 0);
/* CDATA value */
assert_int_equal(LY_SUCCESS, ly_in_new_memory("> <![CDATA[ special non-escaped chars <>&\"' ]]> </a>", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ATTR_CONTENT;
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_true(!strncmp(" special non-escaped chars <>&\"' ", xmlctx->value, xmlctx->value_len));
assert_int_equal(xmlctx->ws_only, 0);
assert_int_equal(xmlctx->dynamic, 1);
free((char *)xmlctx->value);
ly_in_free(in, 0);
/* invalid characters in string */
assert_int_equal(LY_SUCCESS, ly_in_new_memory("=\'&#x52\'", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ATTRIBUTE;
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Invalid character sequence \"'\", expected ;.", NULL, 1);
ly_in_free(in, 0);
assert_int_equal(LY_SUCCESS, ly_in_new_memory("=\"&#82\"", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ATTRIBUTE;
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Invalid character sequence \"\"\", expected ;.", NULL, 1);
ly_in_free(in, 0);
assert_int_equal(LY_SUCCESS, ly_in_new_memory("=\"&nonsense;\"", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ATTRIBUTE;
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Entity reference \"&nonsense;\" not supported, only predefined references allowed.", NULL, 1);
ly_in_free(in, 0);
assert_int_equal(LY_SUCCESS, ly_in_new_memory(">&#o122;", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ELEMENT;
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Invalid character reference \"&#o122;\".", NULL, 1);
ly_in_free(in, 0);
assert_int_equal(LY_SUCCESS, ly_in_new_memory("=\'&#x06;\'", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ATTRIBUTE;
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Invalid character reference \"&#x06;\'\" (0x00000006).", NULL, 1);
ly_in_free(in, 0);
assert_int_equal(LY_SUCCESS, ly_in_new_memory("=\'&#xfdd0;\'", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ATTRIBUTE;
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Invalid character reference \"&#xfdd0;\'\" (0x0000fdd0).", NULL, 1);
ly_in_free(in, 0);
assert_int_equal(LY_SUCCESS, ly_in_new_memory("=\'&#xffff;\'", &in));
xmlctx->in = in;
ly_log_location(NULL, NULL, NULL, in);
xmlctx->status = LYXML_ATTRIBUTE;
assert_int_equal(LY_EVALID, lyxml_ctx_next(xmlctx));
CHECK_LOG_CTX("Invalid character reference \"&#xffff;\'\" (0x0000ffff).", NULL, 1);
ly_in_free(in, 0);
lyxml_ctx_free(xmlctx);
ly_log_location_revert(0, 0, 0, 9);
}
static void
test_ns(void **state)
{
const char *str;
struct lyxml_ctx *xmlctx;
struct ly_in *in;
const struct lyxml_ns *ns;
/* opening element1 */
str = "<element1/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
/* processing namespace definitions */
assert_int_equal(LY_SUCCESS, lyxml_ns_add(xmlctx, NULL, 0, strdup("urn:default")));
assert_int_equal(LY_SUCCESS, lyxml_ns_add(xmlctx, "nc", 2, strdup("urn:nc1")));
/* simulate adding open element2 into context */
xmlctx->elements.count++;
/* processing namespace definitions */
assert_int_equal(LY_SUCCESS, lyxml_ns_add(xmlctx, "nc", 2, strdup("urn:nc2")));
assert_int_equal(3, xmlctx->ns.count);
assert_int_not_equal(0, xmlctx->ns.size);
ns = lyxml_ns_get(&xmlctx->ns, NULL, 0);
assert_non_null(ns);
assert_null(ns->prefix);
assert_string_equal("urn:default", ns->uri);
ns = lyxml_ns_get(&xmlctx->ns, "nc", 2);
assert_non_null(ns);
assert_string_equal("nc", ns->prefix);
assert_string_equal("urn:nc2", ns->uri);
/* simulate closing element2 */
xmlctx->elements.count--;
lyxml_ns_rm(xmlctx);
assert_int_equal(2, xmlctx->ns.count);
ns = lyxml_ns_get(&xmlctx->ns, "nc", 2);
assert_non_null(ns);
assert_string_equal("nc", ns->prefix);
assert_string_equal("urn:nc1", ns->uri);
/* close element1 */
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(0, xmlctx->ns.count);
assert_null(lyxml_ns_get(&xmlctx->ns, "nc", 2));
assert_null(lyxml_ns_get(&xmlctx->ns, NULL, 0));
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
}
static void
test_ns2(void **state)
{
const char *str;
struct lyxml_ctx *xmlctx;
struct ly_in *in;
/* opening element1 */
str = "<element1/>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
/* default namespace defined in parent element1 */
assert_int_equal(LY_SUCCESS, lyxml_ns_add(xmlctx, NULL, 0, strdup("urn:default")));
assert_int_equal(1, xmlctx->ns.count);
/* going into child element1 */
/* simulate adding open element1 into context */
xmlctx->elements.count++;
/* no namespace defined, going out (first, simulate closing of so far open element) */
xmlctx->elements.count--;
lyxml_ns_rm(xmlctx);
assert_int_equal(1, xmlctx->ns.count);
/* nothing else, going out of the parent element1 */
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(0, xmlctx->ns.count);
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
}
static void
test_simple_xml(void **state)
{
struct lyxml_ctx *xmlctx;
struct ly_in *in;
const char *test_input = "<elem1 attr1=\"value\"> <elem2 attr2=\"value\" /> </elem1>";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(test_input, &in));
assert_int_equal(LY_SUCCESS, lyxml_ctx_new(UTEST_LYCTX, in, &xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_string_equal(xmlctx->in->current, "attr1=\"value\"> <elem2 attr2=\"value\" /> </elem1>");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
assert_string_equal(xmlctx->in->current, "=\"value\"> <elem2 attr2=\"value\" /> </elem1>");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
assert_string_equal(xmlctx->in->current, "> <elem2 attr2=\"value\" /> </elem1>");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_string_equal(xmlctx->in->current, "<elem2 attr2=\"value\" /> </elem1>");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEMENT, xmlctx->status);
assert_string_equal(xmlctx->in->current, "attr2=\"value\" /> </elem1>");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTRIBUTE, xmlctx->status);
assert_string_equal(xmlctx->in->current, "=\"value\" /> </elem1>");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ATTR_CONTENT, xmlctx->status);
assert_string_equal(xmlctx->in->current, " /> </elem1>");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CONTENT, xmlctx->status);
assert_string_equal(xmlctx->in->current, "/> </elem1>");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_string_equal(xmlctx->in->current, " </elem1>");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_ELEM_CLOSE, xmlctx->status);
assert_string_equal(xmlctx->in->current, "");
assert_int_equal(LY_SUCCESS, lyxml_ctx_next(xmlctx));
assert_int_equal(LYXML_END, xmlctx->status);
assert_string_equal(xmlctx->in->current, "");
lyxml_ctx_free(xmlctx);
ly_in_free(in, 0);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_element),
UTEST(test_attribute),
UTEST(test_text),
UTEST(test_ns),
UTEST(test_ns2),
UTEST(test_simple_xml),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,144 @@
/**
* @file test_yanglib.c
* @author: Michal Vasko <mvasko@cesnet.cz>
* @brief unit tests for ietf-yang-library data
*
* Copyright (c) 2020 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _UTEST_MAIN_
#include "utests.h"
#include <string.h>
#include "context.h"
#include "in.h"
#include "log.h"
#include "set.h"
#include "tests_config.h"
#include "tree_data.h"
#include "tree_schema.h"
const char *schema_a =
"module a {\n"
" namespace urn:tests:a;\n"
" prefix a;\n"
" yang-version 1.1;\n"
"\n"
" include a_sub;\n"
"\n"
" list l2 {\n"
" key \"a\";\n"
" leaf a {\n"
" type uint16;\n"
" }\n"
" leaf b {\n"
" type uint16;\n"
" }\n"
" }\n"
"}";
const char *schema_b =
"module b {\n"
" namespace urn:tests:b;\n"
" prefix b;\n"
" yang-version 1.1;\n"
"\n"
" import a {\n"
" prefix a;\n"
" }\n"
"\n"
" deviation /a:l2 {\n"
" deviate add {\n"
" max-elements 40;\n"
" }\n"
" }\n"
"\n"
" leaf foo {\n"
" type string;\n"
" }\n"
"}";
static LY_ERR
test_imp_clb(const char *mod_name, const char *mod_rev, const char *submod_name, const char *sub_rev, void *user_data,
LYS_INFORMAT *format, const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
{
const char *schema_a_sub =
"submodule a_sub {\n"
" belongs-to a {\n"
" prefix a;\n"
" }\n"
" yang-version 1.1;\n"
"\n"
" feature feat1;\n"
"\n"
" list l3 {\n"
" key \"a\";\n"
" leaf a {\n"
" type uint16;\n"
" }\n"
" leaf b {\n"
" type uint16;\n"
" }\n"
" }\n"
"}\n";
assert_string_equal(mod_name, "a");
assert_null(mod_rev);
if (!submod_name) {
return LY_ENOTFOUND;
}
assert_string_equal(submod_name, "a_sub");
assert_null(sub_rev);
assert_null(user_data);
*format = LYS_IN_YANG;
*module_data = schema_a_sub;
*free_module_data = NULL;
return LY_SUCCESS;
}
static void
test_yanglib(void **state)
{
const char *feats[] = {"feat1", NULL};
struct lyd_node *tree;
struct ly_set *set;
LY_ERR ret;
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, NULL);
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, feats, NULL);
UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
assert_int_equal(LY_SUCCESS, ly_ctx_get_yanglib_data(UTEST_LYCTX, &tree, "<<%u>>", ly_ctx_get_change_count(UTEST_LYCTX)));
lyd_free_all(tree);
assert_int_equal(LY_SUCCESS, ly_ctx_get_yanglib_data(UTEST_LYCTX, &tree, "%u", -10));
lyd_free_all(tree);
assert_int_equal(LY_SUCCESS, ly_ctx_get_yanglib_data(UTEST_LYCTX, &tree, ""));
lyd_free_all(tree);
assert_int_equal(LY_SUCCESS, ly_ctx_get_yanglib_data(UTEST_LYCTX, &tree, "%u", ly_ctx_get_change_count(UTEST_LYCTX)));
/* make sure there is "a" with a submodule and deviation */
ret = lyd_find_xpath(tree, "/ietf-yang-library:yang-library/module-set/module[name='a'][submodule/name='a_sub']"
"[feature='feat1'][deviation='b']", &set);
assert_int_equal(ret, LY_SUCCESS);
assert_int_equal(set->count, 1);
ly_set_free(set, NULL);
lyd_free_all(tree);
}
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_yanglib),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}