Adding upstream version 3.1.0+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
64dbec996d
commit
cfcebb1a7d
569 changed files with 205393 additions and 0 deletions
79
tests/utests/CMakeLists.txt
Normal file
79
tests/utests/CMakeLists.txt
Normal file
|
@ -0,0 +1,79 @@
|
|||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set(format_sources
|
||||
${format_sources}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/basic/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/data/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/extensions/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/schema/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/types/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/restriction/*.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/node/*.c
|
||||
PARENT_SCOPE)
|
||||
|
||||
ly_add_utest(NAME uint8 SOURCES types/uint8.c)
|
||||
ly_add_utest(NAME uint16 SOURCES types/uint16.c)
|
||||
ly_add_utest(NAME uint32 SOURCES types/uint32.c)
|
||||
ly_add_utest(NAME uint64 SOURCES types/uint64.c)
|
||||
ly_add_utest(NAME int8 SOURCES types/int8.c)
|
||||
ly_add_utest(NAME int16 SOURCES types/int16.c)
|
||||
ly_add_utest(NAME int32 SOURCES types/int32.c)
|
||||
ly_add_utest(NAME int64 SOURCES types/int64.c)
|
||||
ly_add_utest(NAME string SOURCES types/string.c)
|
||||
ly_add_utest(NAME bits SOURCES types/bits.c)
|
||||
ly_add_utest(NAME binary SOURCES types/binary.c)
|
||||
ly_add_utest(NAME inet_types SOURCES types/inet_types.c)
|
||||
ly_add_utest(NAME yang_types SOURCES types/yang_types.c)
|
||||
ly_add_utest(NAME enumeration SOURCES types/enumeration.c)
|
||||
ly_add_utest(NAME instanceid SOURCES types/instanceid.c)
|
||||
ly_add_utest(NAME instanceid_keys SOURCES types/instanceid_keys.c)
|
||||
ly_add_utest(NAME union SOURCES types/union.c)
|
||||
ly_add_utest(NAME boolean SOURCES types/boolean.c)
|
||||
ly_add_utest(NAME decimal64 SOURCES types/decimal64.c)
|
||||
ly_add_utest(NAME empty SOURCES types/empty.c)
|
||||
ly_add_utest(NAME identityref SOURCES types/identityref.c)
|
||||
ly_add_utest(NAME leafref SOURCES types/leafref.c)
|
||||
|
||||
ly_add_utest(NAME range SOURCES restriction/test_range.c)
|
||||
ly_add_utest(NAME pattern SOURCES restriction/test_pattern.c)
|
||||
|
||||
ly_add_utest(NAME list SOURCES node/list.c)
|
||||
|
||||
ly_add_utest(NAME common SOURCES basic/test_common.c)
|
||||
ly_add_utest(NAME set SOURCES basic/test_set.c)
|
||||
ly_add_utest(NAME hash_table SOURCES basic/test_hash_table.c)
|
||||
ly_add_utest(NAME inout SOURCES basic/test_inout.c)
|
||||
ly_add_utest(NAME context SOURCES basic/test_context.c)
|
||||
if(NOT WIN32)
|
||||
ly_add_utest(NAME plugins SOURCES basic/test_plugins.c)
|
||||
endif()
|
||||
ly_add_utest(NAME xml SOURCES basic/test_xml.c)
|
||||
ly_add_utest(NAME json SOURCES basic/test_json.c)
|
||||
ly_add_utest(NAME xpath SOURCES basic/test_xpath.c)
|
||||
ly_add_utest(NAME yanglib SOURCES basic/test_yanglib.c)
|
||||
|
||||
ly_add_utest(NAME schema SOURCES schema/test_schema.c)
|
||||
ly_add_utest(NAME yang SOURCES schema/test_yang.c)
|
||||
ly_add_utest(NAME yin SOURCES schema/test_yin.c)
|
||||
ly_add_utest(NAME tree_schema_compile SOURCES schema/test_tree_schema_compile.c)
|
||||
ly_add_utest(NAME printer_tree SOURCES schema/test_printer_tree.c)
|
||||
|
||||
ly_add_utest(NAME tree_data SOURCES data/test_tree_data.c)
|
||||
ly_add_utest(NAME tree_data_sorted SOURCES data/test_tree_data_sorted.c)
|
||||
ly_add_utest(NAME new SOURCES data/test_new.c)
|
||||
ly_add_utest(NAME parser_xml SOURCES data/test_parser_xml.c)
|
||||
ly_add_utest(NAME printer_xml SOURCES data/test_printer_xml.c)
|
||||
ly_add_utest(NAME printer_json SOURCES data/test_printer_json.c)
|
||||
ly_add_utest(NAME parser_json SOURCES data/test_parser_json.c)
|
||||
ly_add_utest(NAME lyb SOURCES data/test_lyb.c)
|
||||
ly_add_utest(NAME validation SOURCES data/test_validation.c)
|
||||
ly_add_utest(NAME merge SOURCES data/test_merge.c)
|
||||
ly_add_utest(NAME diff SOURCES data/test_diff.c)
|
||||
|
||||
ly_add_utest(NAME metadata SOURCES extensions/test_metadata.c)
|
||||
ly_add_utest(NAME nacm SOURCES extensions/test_nacm.c)
|
||||
ly_add_utest(NAME yangdata SOURCES extensions/test_yangdata.c)
|
||||
ly_add_utest(NAME schema_mount SOURCES extensions/test_schema_mount.c)
|
||||
ly_add_utest(NAME structure SOURCES extensions/test_structure.c)
|
416
tests/utests/basic/test_common.c
Normal file
416
tests/utests/basic/test_common.c
Normal 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);
|
||||
}
|
1103
tests/utests/basic/test_context.c
Normal file
1103
tests/utests/basic/test_context.c
Normal file
File diff suppressed because it is too large
Load diff
262
tests/utests/basic/test_hash_table.c
Normal file
262
tests/utests/basic/test_hash_table.c
Normal 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);
|
||||
}
|
407
tests/utests/basic/test_inout.c
Normal file
407
tests/utests/basic/test_inout.c
Normal 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);
|
||||
}
|
773
tests/utests/basic/test_json.c
Normal file
773
tests/utests/basic/test_json.c
Normal 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);
|
||||
}
|
153
tests/utests/basic/test_plugins.c
Normal file
153
tests/utests/basic/test_plugins.c
Normal 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);
|
||||
}
|
276
tests/utests/basic/test_set.c
Normal file
276
tests/utests/basic/test_set.c
Normal 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);
|
||||
}
|
689
tests/utests/basic/test_xml.c
Normal file
689
tests/utests/basic/test_xml.c
Normal 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<&"'> ROK</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("=\'$¢€𐍈\'", &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("=\'R\'", &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("=\"R\"", &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("=\'\'", &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 \"\'\" (0x00000006).", NULL, 1);
|
||||
ly_in_free(in, 0);
|
||||
|
||||
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_EVALID, lyxml_ctx_next(xmlctx));
|
||||
CHECK_LOG_CTX("Invalid character reference \"\'\" (0x0000fdd0).", NULL, 1);
|
||||
ly_in_free(in, 0);
|
||||
|
||||
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_EVALID, lyxml_ctx_next(xmlctx));
|
||||
CHECK_LOG_CTX("Invalid character reference \"\'\" (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);
|
||||
}
|
1263
tests/utests/basic/test_xpath.c
Normal file
1263
tests/utests/basic/test_xpath.c
Normal file
File diff suppressed because it is too large
Load diff
144
tests/utests/basic/test_yanglib.c
Normal file
144
tests/utests/basic/test_yanglib.c
Normal 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);
|
||||
}
|
1463
tests/utests/data/test_diff.c
Normal file
1463
tests/utests/data/test_diff.c
Normal file
File diff suppressed because it is too large
Load diff
2841
tests/utests/data/test_lyb.c
Normal file
2841
tests/utests/data/test_lyb.c
Normal file
File diff suppressed because it is too large
Load diff
756
tests/utests/data/test_merge.c
Normal file
756
tests/utests/data/test_merge.c
Normal file
|
@ -0,0 +1,756 @@
|
|||
/**
|
||||
* @file test_merge.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief tests for complex data merges.
|
||||
*
|
||||
* 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 "libyang.h"
|
||||
|
||||
#define LYD_TREE_CREATE(INPUT, MODEL) \
|
||||
CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, MODEL)
|
||||
|
||||
#define CONTEXT_CREATE \
|
||||
CONTEXT_CREATE_PATH(NULL)
|
||||
|
||||
#define LYD_TREE_CHECK_CHAR(MODEL, TEXT, PARAMS) \
|
||||
CHECK_LYD_STRING_PARAM(MODEL, TEXT, LYD_XML, LYD_PRINT_WITHSIBLINGS | PARAMS)
|
||||
|
||||
static void
|
||||
test_batch(void **state)
|
||||
{
|
||||
const char *start =
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>yang</name>\n"
|
||||
" <revision>2016-02-11</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n";
|
||||
const char *data[] = {
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-yang-library</name>\n"
|
||||
" <revision>2016-02-01</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-acm</name>\n"
|
||||
" <revision>2012-02-22</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-monitoring</name>\n"
|
||||
" <revision>2010-10-04</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-with-defaults</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>yang</name>\n"
|
||||
" <revision>2016-02-11</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-yang-library</name>\n"
|
||||
" <revision>2016-02-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-acm</name>\n"
|
||||
" <revision>2012-02-22</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-acm</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace>\n"
|
||||
" <feature>writable-running</feature>\n"
|
||||
" <feature>candidate</feature>\n"
|
||||
" <feature>rollback-on-error</feature>\n"
|
||||
" <feature>validate</feature>\n"
|
||||
" <feature>startup</feature>\n"
|
||||
" <feature>xpath</feature>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-monitoring</name>\n"
|
||||
" <revision>2010-10-04</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-with-defaults</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n"
|
||||
};
|
||||
const char *output_template =
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>yang</name>\n"
|
||||
" <revision>2016-02-11</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-yang-library</name>\n"
|
||||
" <revision>2016-02-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-acm</name>\n"
|
||||
" <revision>2012-02-22</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-acm</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace>\n"
|
||||
" <feature>writable-running</feature>\n"
|
||||
" <feature>candidate</feature>\n"
|
||||
" <feature>rollback-on-error</feature>\n"
|
||||
" <feature>validate</feature>\n"
|
||||
" <feature>startup</feature>\n"
|
||||
" <feature>xpath</feature>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-monitoring</name>\n"
|
||||
" <revision>2010-10-04</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-with-defaults</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n";
|
||||
|
||||
struct lyd_node *target;
|
||||
|
||||
CHECK_PARSE_LYD_PARAM(start, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, target);
|
||||
|
||||
for (int32_t i = 0; i < 11; ++i) {
|
||||
struct lyd_node *source;
|
||||
|
||||
CHECK_PARSE_LYD_PARAM(data[i], LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, source);
|
||||
assert_int_equal(LY_SUCCESS, lyd_merge_siblings(&target, source, LYD_MERGE_DESTRUCT));
|
||||
}
|
||||
|
||||
LYD_TREE_CHECK_CHAR(target, output_template, 0);
|
||||
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_leaf(void **state)
|
||||
{
|
||||
const char *sch = "module x {"
|
||||
" namespace urn:x;"
|
||||
" prefix x;"
|
||||
" container A {"
|
||||
" leaf f1 {type string;}"
|
||||
" container B {"
|
||||
" leaf f2 {type string;}"
|
||||
" }"
|
||||
" }"
|
||||
" }";
|
||||
const char *trg = "<A xmlns=\"urn:x\"> <f1>block</f1> </A>";
|
||||
const char *src = "<A xmlns=\"urn:x\"> <f1>aa</f1> <B> <f2>bb</f2> </B> </A>";
|
||||
const char *result = "<A xmlns=\"urn:x\"><f1>aa</f1><B><f2>bb</f2></B></A>";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, LYD_PRINT_SHRINK);
|
||||
|
||||
lyd_free_all(target);
|
||||
lyd_free_all(source);
|
||||
}
|
||||
|
||||
static void
|
||||
test_container(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module A {\n"
|
||||
" namespace \"aa:A\";\n"
|
||||
" prefix A;\n"
|
||||
" container A {\n"
|
||||
" leaf f1 {type string;}\n"
|
||||
" container B {\n"
|
||||
" leaf f2 {type string;}\n"
|
||||
" }\n"
|
||||
" container C {\n"
|
||||
" leaf f3 {type string;}\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg = "<A xmlns=\"aa:A\"> <B> <f2>aaa</f2> </B> </A>";
|
||||
const char *src = "<A xmlns=\"aa:A\"> <C> <f3>bbb</f3> </C> </A>";
|
||||
const char *result = "<A xmlns=\"aa:A\"><B><f2>aaa</f2></B><C><f3>bbb</f3></C></A>";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, LYD_PRINT_SHRINK);
|
||||
|
||||
/* destroy */
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_list(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
"\n"
|
||||
" container inner1 {\n"
|
||||
" list b-list1 {\n"
|
||||
" key p1;\n"
|
||||
" leaf p1 {\n"
|
||||
" type uint8;\n"
|
||||
" }\n"
|
||||
" leaf p2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf p3 {\n"
|
||||
" type boolean;\n"
|
||||
" default false;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" <p3>true</p3>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *src =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *result =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" <p3>true</p3>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(target);
|
||||
lyd_free_all(source);
|
||||
}
|
||||
|
||||
static void
|
||||
test_list2(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
"\n"
|
||||
" container inner1 {\n"
|
||||
" list b-list1 {\n"
|
||||
" key p1;\n"
|
||||
" leaf p1 {\n"
|
||||
" type uint8;\n"
|
||||
" }\n"
|
||||
" leaf p2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" container inner2 {\n"
|
||||
" leaf p3 {\n"
|
||||
" type boolean;\n"
|
||||
" default false;\n"
|
||||
" }\n"
|
||||
" leaf p4 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" <inner2>\n"
|
||||
" <p4>val</p4>\n"
|
||||
" </inner2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *src =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *result =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" <inner2>\n"
|
||||
" <p4>val</p4>\n"
|
||||
" </inner2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dup_inst_list(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
"\n"
|
||||
" container inner1 {\n"
|
||||
" config false;\n"
|
||||
" list b-list1 {\n"
|
||||
" leaf p1 {\n"
|
||||
" type uint8;\n"
|
||||
" }\n"
|
||||
" leaf p2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" container inner2 {\n"
|
||||
" leaf p4 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" <inner2>\n"
|
||||
" <p4>val</p4>\n"
|
||||
" </inner2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *src =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>2</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *result =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" <inner2>\n"
|
||||
" <p4>val</p4>\n"
|
||||
" </inner2>\n"
|
||||
" </b-list1>\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>2</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dup_inst_llist(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
"\n"
|
||||
" container inner1 {\n"
|
||||
" config false;\n"
|
||||
" leaf-list b-llist1 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
"</inner1>\n";
|
||||
const char *src =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>f</b-llist1>\n"
|
||||
" <b-llist1>f</b-llist1>\n"
|
||||
"</inner1>\n";
|
||||
const char *result =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>f</b-llist1>\n"
|
||||
" <b-llist1>f</b-llist1>\n"
|
||||
"</inner1>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_case(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
" container cont {\n"
|
||||
" choice ch {\n"
|
||||
" container inner {\n"
|
||||
" leaf p1 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" case c2 {\n"
|
||||
" leaf p1 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<cont xmlns=\"http://test/merge\">\n"
|
||||
" <inner>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" </inner>\n"
|
||||
"</cont>\n";
|
||||
const char *src =
|
||||
"<cont xmlns=\"http://test/merge\">\n"
|
||||
" <p1>1</p1>\n"
|
||||
"</cont>\n";
|
||||
const char *result =
|
||||
"<cont xmlns=\"http://test/merge\">\n"
|
||||
" <p1>1</p1>\n"
|
||||
"</cont>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dflt(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge-dflt {\n"
|
||||
" namespace \"urn:merge-dflt\";\n"
|
||||
" prefix md;\n"
|
||||
" container top {\n"
|
||||
" leaf a {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf c {\n"
|
||||
" type string;\n"
|
||||
" default \"c_dflt\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
struct lyd_node *target = NULL;
|
||||
struct lyd_node *source = NULL;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/c", "c_dflt", 0, &target), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/a", "a_val", 0, &source), LY_SUCCESS);
|
||||
assert_int_equal(lyd_new_path(source, UTEST_LYCTX, "/merge-dflt:top/b", "b_val", 0, NULL), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&source, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, LYD_MERGE_DESTRUCT | LYD_MERGE_DEFAULTS), LY_SUCCESS);
|
||||
source = NULL;
|
||||
|
||||
/* c should be replaced and now be default */
|
||||
assert_string_equal(lyd_child(target)->prev->schema->name, "c");
|
||||
assert_true(lyd_child(target)->prev->flags & LYD_DEFAULT);
|
||||
|
||||
lyd_free_all(target);
|
||||
lyd_free_all(source);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dflt2(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge-dflt {\n"
|
||||
" namespace \"urn:merge-dflt\";\n"
|
||||
" prefix md;\n"
|
||||
" container top {\n"
|
||||
" leaf a {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf c {\n"
|
||||
" type string;\n"
|
||||
" default \"c_dflt\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
struct lyd_node *target;
|
||||
struct lyd_node *source;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/c", "c_dflt", 0, &target), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/a", "a_val", 0, &source), LY_SUCCESS);
|
||||
assert_int_equal(lyd_new_path(source, UTEST_LYCTX, "/merge-dflt:top/b", "b_val", 0, NULL), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&source, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
|
||||
/* c should not be replaced, so c remains not default */
|
||||
assert_false(lyd_child(target)->flags & LYD_DEFAULT);
|
||||
|
||||
lyd_free_all(target);
|
||||
lyd_free_all(source);
|
||||
}
|
||||
|
||||
static void
|
||||
test_leafrefs(void **state)
|
||||
{
|
||||
const char *sch = "module x {"
|
||||
" namespace urn:x;"
|
||||
" prefix x;"
|
||||
" list l {"
|
||||
" key n;"
|
||||
" leaf n { type string; }"
|
||||
" leaf t { type string; }"
|
||||
" leaf r { type leafref { path '/l/n'; } }}}";
|
||||
const char *trg = "<l xmlns=\"urn:x\"><n>a</n></l>"
|
||||
"<l xmlns=\"urn:x\"><n>b</n><r>a</r></l>";
|
||||
const char *src = "<l xmlns=\"urn:x\"><n>c</n><r>a</r></l>"
|
||||
"<l xmlns=\"urn:x\"><n>a</n><t>*</t></l>";
|
||||
const char *res = "<l xmlns=\"urn:x\"><n>a</n><t>*</t></l>"
|
||||
"<l xmlns=\"urn:x\"><n>b</n><r>a</r></l>"
|
||||
"<l xmlns=\"urn:x\"><n>c</n><r>a</r></l>";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
|
||||
LYD_TREE_CHECK_CHAR(target, res, LYD_PRINT_SHRINK);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_batch),
|
||||
UTEST(test_leaf),
|
||||
UTEST(test_container),
|
||||
UTEST(test_list),
|
||||
UTEST(test_list2),
|
||||
UTEST(test_dup_inst_list),
|
||||
UTEST(test_dup_inst_llist),
|
||||
UTEST(test_case),
|
||||
UTEST(test_dflt),
|
||||
UTEST(test_dflt2),
|
||||
UTEST(test_leafrefs),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
536
tests/utests/data/test_new.c
Normal file
536
tests/utests/data/test_new.c
Normal file
|
@ -0,0 +1,536 @@
|
|||
/**
|
||||
* @file test_new.c
|
||||
* @author: Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief unit tests for functions for creating 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 "libyang.h"
|
||||
|
||||
/* common module for the tests */
|
||||
const char *schema_a = "module a {\n"
|
||||
" namespace urn:tests:a;\n"
|
||||
" prefix a;yang-version 1.1;\n"
|
||||
" list l1 {\n"
|
||||
" key \"a b\";\n"
|
||||
" leaf a {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf c {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" list l11 {\n"
|
||||
" key \"a\";\n"
|
||||
" leaf a {\n"
|
||||
" type uint32;\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type uint32;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" leaf foo {\n"
|
||||
" type uint16;\n"
|
||||
" }\n"
|
||||
" leaf-list ll {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" container c {\n"
|
||||
" leaf-list x {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" anydata any {\n"
|
||||
" config false;\n"
|
||||
" }\n"
|
||||
" anyxml anyx;\n"
|
||||
" leaf-list ll2 {\n"
|
||||
" config false;\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" list l2 {\n"
|
||||
" config false;\n"
|
||||
" container c {\n"
|
||||
" leaf x {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" container c2 {\n"
|
||||
" config false;\n"
|
||||
" list l3 {\n"
|
||||
" leaf x {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf y {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" rpc oper {\n"
|
||||
" input {\n"
|
||||
" leaf param {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" output {\n"
|
||||
" leaf param {\n"
|
||||
" type int8;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
static void
|
||||
test_top_level(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lyd_node *node, *rpc;
|
||||
|
||||
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, &mod);
|
||||
|
||||
/* list */
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", 0, &node, "val_a", "val_b"), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[]", 0, &node), LY_EVALID);
|
||||
CHECK_LOG_CTX("Unexpected XPath token \"]\" (\"]\").", "/a:l1", 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[key1='a'][key2='b']", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("Not found node \"key1\" in path.", "/a:l1", 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a='a'][b='b'][c='c']", 0, &node), LY_EVALID);
|
||||
CHECK_LOG_CTX("Key expected instead of leaf \"c\" in path.", "/a:l1", 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "c", "[a='a'][b='b']", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("List node \"c\" not found.", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a='a'][b='b']", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a=''][b='']", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a:a='a'][a:b='b']", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a= 'a']\n[b =\t'b']", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
const char *key_vals[] = {"a", "b"};
|
||||
|
||||
assert_int_equal(lyd_new_list3(NULL, mod, "l1", key_vals, NULL, 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
uint32_t val_lens[] = {1, 1};
|
||||
|
||||
assert_int_equal(lyd_new_list3(NULL, mod, "l1", key_vals, val_lens, LYD_NEW_VAL_BIN, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list3(NULL, mod, "l1", key_vals, val_lens, LYD_NEW_VAL_CANON, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_list3(NULL, mod, "l1", key_vals, val_lens, LYD_NEW_VAL_CANON | LYD_NEW_VAL_STORE_ONLY, &node), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (lyd_new_list3()).", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", LYD_NEW_VAL_BIN, &node, "val_a", 5, "val_b", 5), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", LYD_NEW_VAL_BIN | LYD_NEW_VAL_STORE_ONLY, &node, "val_a", 5, "val_b", 5), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (lyd_new_list()).", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", LYD_NEW_VAL_CANON, &node, "val_a", "val_b"), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", LYD_NEW_VAL_CANON | LYD_NEW_VAL_STORE_ONLY, &node, "val_a", "val_b"), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (lyd_new_list()).", NULL, 0);
|
||||
|
||||
/* leaf */
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "[a='a'][b='b'][c='c']", 0, &node), LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid type uint16 value \"[a='a'][b='b'][c='c']\".", "/a:foo", 0);
|
||||
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "c", "value", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("Term node \"c\" not found.", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "256", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "25", LYD_NEW_VAL_BIN, &node), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(options & 0x04) (lyd_new_term()).", NULL, 0);
|
||||
assert_int_equal(lyd_new_term_bin(NULL, mod, "foo", "25", 2, LYD_NEW_VAL_BIN, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_term_bin(NULL, mod, "foo", "25", 2, LYD_NEW_VAL_STORE_ONLY, &node), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (_lyd_new_term()).", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "25", LYD_NEW_VAL_CANON, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "25", LYD_NEW_VAL_CANON | LYD_NEW_VAL_STORE_ONLY, &node), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (_lyd_new_term()).", NULL, 0);
|
||||
|
||||
/* leaf-list */
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "ll", "ahoy", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
/* container */
|
||||
assert_int_equal(lyd_new_inner(NULL, mod, "c", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_inner(NULL, mod, "l1", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("Inner node (container, notif, RPC, or action) \"l1\" not found.", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_inner(NULL, mod, "l2", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("Inner node (container, notif, RPC, or action) \"l2\" not found.", NULL, 0);
|
||||
|
||||
/* anydata */
|
||||
assert_int_equal(lyd_new_any(NULL, mod, "any", "{\"node\":\"val\"}", LYD_ANYDATA_STRING, 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_any(NULL, mod, "any", "<node>val</node>", LYD_ANYDATA_STRING, 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
/* key-less list */
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l2", "[a='a'][b='b']", 0, &node), LY_EVALID);
|
||||
CHECK_LOG_CTX("List predicate defined for keyless list \"l2\" in path.", "/a:l2", 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l2", "", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l2", NULL, 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l2", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
/* RPC */
|
||||
assert_int_equal(lyd_new_inner(NULL, mod, "oper", 0, &rpc), LY_SUCCESS);
|
||||
assert_int_equal(lyd_new_term(rpc, mod, "param", "22", 0, &node), LY_SUCCESS);
|
||||
assert_int_equal(LY_TYPE_STRING, ((struct lysc_node_leaf *)node->schema)->type->basetype);
|
||||
assert_int_equal(lyd_new_term(rpc, mod, "param", "22", LYD_NEW_VAL_OUTPUT, &node), LY_SUCCESS);
|
||||
assert_int_equal(LY_TYPE_INT8, ((struct lysc_node_leaf *)node->schema)->type->basetype);
|
||||
lyd_free_tree(rpc);
|
||||
}
|
||||
|
||||
static void
|
||||
test_opaq(void **state)
|
||||
{
|
||||
struct lyd_node *root, *node;
|
||||
struct lyd_node_opaq *opq;
|
||||
|
||||
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
assert_int_equal(lyd_new_opaq(NULL, UTEST_LYCTX, "node1", NULL, NULL, "my-module", &root), LY_SUCCESS);
|
||||
assert_null(root->schema);
|
||||
opq = (struct lyd_node_opaq *)root;
|
||||
assert_string_equal(opq->name.name, "node1");
|
||||
assert_string_equal(opq->name.module_name, "my-module");
|
||||
assert_string_equal(opq->value, "");
|
||||
|
||||
assert_int_equal(lyd_new_opaq(root, NULL, "node2", "value", NULL, "my-module2", &node), LY_SUCCESS);
|
||||
assert_null(node->schema);
|
||||
opq = (struct lyd_node_opaq *)node;
|
||||
assert_string_equal(opq->name.name, "node2");
|
||||
assert_string_equal(opq->name.module_name, "my-module2");
|
||||
assert_string_equal(opq->value, "value");
|
||||
assert_ptr_equal(opq->parent, root);
|
||||
|
||||
lyd_free_tree(root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_path(void **state)
|
||||
{
|
||||
LY_ERR ret;
|
||||
struct lyd_node *root, *node, *parent;
|
||||
struct lys_module *mod;
|
||||
char *str;
|
||||
|
||||
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, &mod);
|
||||
|
||||
/* create 2 nodes */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:c/x[.='val']", "vvv", 0, 0, 0, &root, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_string_equal(root->schema->name, "c");
|
||||
assert_non_null(node);
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("val", lyd_get_value(node));
|
||||
|
||||
/* append another */
|
||||
ret = lyd_new_path2(root, NULL, "/a:c/x", "val2", 0, 0, 0, &parent, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_ptr_equal(parent, node);
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("val2", lyd_get_value(node));
|
||||
|
||||
/* and a last one */
|
||||
ret = lyd_new_path2(root, NULL, "x", "val3", 0, 0, 0, &parent, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_ptr_equal(parent, node);
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("val3", lyd_get_value(node));
|
||||
|
||||
lyd_free_tree(root);
|
||||
|
||||
/* try LYD_NEWOPT_OPAQ */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:l1", NULL, 0, 0, 0, NULL, NULL);
|
||||
assert_int_equal(ret, LY_EINVAL);
|
||||
CHECK_LOG_CTX("Predicate missing for list \"l1\" in path \"/a:l1\".", "/a:l1", 0);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:l1", NULL, 0, 0, LYD_NEW_PATH_OPAQ, NULL, &root);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_null(root->schema);
|
||||
|
||||
lyd_free_tree(root);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:foo", NULL, 0, 0, 0, NULL, NULL);
|
||||
assert_int_equal(ret, LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid type uint16 empty value.", "/a:foo", 0);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:foo", NULL, 0, 0, LYD_NEW_PATH_OPAQ, NULL, &root);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_null(root->schema);
|
||||
|
||||
lyd_free_tree(root);
|
||||
|
||||
ret = lyd_new_path(NULL, UTEST_LYCTX, "/a:l11", NULL, LYD_NEW_PATH_OPAQ, &root);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_null(root->schema);
|
||||
|
||||
ret = lyd_new_path(root, NULL, "a", NULL, LYD_NEW_PATH_OPAQ, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(lyd_child(root));
|
||||
assert_null(lyd_child(root)->schema);
|
||||
|
||||
ret = lyd_new_path(root, NULL, "b", NULL, LYD_NEW_PATH_OPAQ, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(lyd_child(root)->next);
|
||||
assert_null(lyd_child(root)->next->schema);
|
||||
|
||||
lyd_free_tree(root);
|
||||
|
||||
/* key-less list */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:c2/l3/x", "val1", 0, 0, 0, &root, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("val1", lyd_get_value(node));
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[1]", NULL, 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_EEXIST);
|
||||
CHECK_LOG_CTX("Path \"/a:c2/l3[1]\" already exists.", "/a:c2/l3[1]", 0);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[2]/x", "val2", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3/x", "val3", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[4]/x", "empty", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[4]/x", "val4", 0, 0, LYD_NEW_PATH_UPDATE, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[5]/x", "val5", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[6]/x", "val6", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<c2 xmlns=\"urn:tests:a\">\n"
|
||||
" <l3>\n"
|
||||
" <x>val1</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val2</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val3</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val4</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val5</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val6</x>\n"
|
||||
" </l3>\n"
|
||||
"</c2>\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
/* state leaf-list */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:ll2", "val_first", 0, 0, 0, &root, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_string_equal(node->schema->name, "ll2");
|
||||
assert_string_equal("val_first", lyd_get_value(node));
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:ll2[1]", "", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_EEXIST);
|
||||
CHECK_LOG_CTX("Path \"/a:ll2[1]\" already exists.", "/a:ll2[1]", 0);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:ll2[2]", "val2", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:ll2[1]", "val", 0, 0, LYD_NEW_PATH_UPDATE, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, UTEST_LYCTX, "/a:ll2", "val3", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:ll2[3][.='val3']", NULL, 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_EVALID);
|
||||
CHECK_LOG_CTX("Unparsed characters \"[.='val3']\" left at the end of path.", NULL, 0);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<ll2 xmlns=\"urn:tests:a\">val</ll2>\n"
|
||||
"<ll2 xmlns=\"urn:tests:a\">val2</ll2>\n"
|
||||
"<ll2 xmlns=\"urn:tests:a\">val3</ll2>\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
/* anydata */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:any", "<elem>val</elem>", 0, LYD_ANYDATA_XML, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<any xmlns=\"urn:tests:a\">\n"
|
||||
" <elem>val</elem>\n"
|
||||
"</any>\n");
|
||||
free(str);
|
||||
lyd_print_mem(&str, root, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"{\n"
|
||||
" \"a:any\": {\n"
|
||||
" \"elem\": \"val\"\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
/* anyxml */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:anyx", "<a/><b/><c/>", 0, LYD_ANYDATA_XML, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<anyx xmlns=\"urn:tests:a\">\n"
|
||||
" <a/>\n"
|
||||
" <b/>\n"
|
||||
" <c/>\n"
|
||||
"</anyx>\n");
|
||||
free(str);
|
||||
lyd_print_mem(&str, root, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"{\n"
|
||||
" \"a:anyx\": {\n"
|
||||
" \"a\": [null],\n"
|
||||
" \"b\": [null],\n"
|
||||
" \"c\": [null]\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:anyx", "{\"a\":[null],\"b\":[null],\"c\":[null]}", 0, LYD_ANYDATA_JSON, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<anyx xmlns=\"urn:tests:a\">\n"
|
||||
" <a/>\n"
|
||||
" <b/>\n"
|
||||
" <c/>\n"
|
||||
"</anyx>\n");
|
||||
free(str);
|
||||
lyd_print_mem(&str, root, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"{\n"
|
||||
" \"a:anyx\": {\n"
|
||||
" \"a\": [null],\n"
|
||||
" \"b\": [null],\n"
|
||||
" \"c\": [null]\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_path_ext(void **state)
|
||||
{
|
||||
LY_ERR ret;
|
||||
struct lyd_node *root, *node;
|
||||
struct lys_module *mod;
|
||||
const char *mod_str = "module ext {yang-version 1.1; namespace urn:tests:extensions:ext; prefix e;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data template {container c {leaf x {type string;} leaf y {type string;} leaf z {type string;}}}}";
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-restconf", "2017-01-26", NULL));
|
||||
|
||||
UTEST_ADD_MODULE(mod_str, LYS_IN_YANG, NULL, &mod);
|
||||
|
||||
/* create x */
|
||||
ret = lyd_new_ext_path(NULL, &mod->compiled->exts[0], "/ext:c/x", "xxx", 0, &root);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_string_equal(root->schema->name, "c");
|
||||
assert_non_null(node = lyd_child(root));
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("xxx", lyd_get_value(node));
|
||||
|
||||
/* append y */
|
||||
ret = lyd_new_ext_path(root, &mod->compiled->exts[0], "/ext:c/y", "yyy", 0, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_string_equal(node->schema->name, "y");
|
||||
assert_string_equal("yyy", lyd_get_value(node));
|
||||
|
||||
/* append z */
|
||||
ret = lyd_new_path(root, NULL, "ext:z", "zzz", 0, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_string_equal(node->schema->name, "z");
|
||||
assert_string_equal("zzz", lyd_get_value(node));
|
||||
|
||||
lyd_free_tree(root);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_top_level),
|
||||
UTEST(test_opaq),
|
||||
UTEST(test_path),
|
||||
UTEST(test_path_ext),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
945
tests/utests/data/test_parser_json.c
Normal file
945
tests/utests/data/test_parser_json.c
Normal file
|
@ -0,0 +1,945 @@
|
|||
/**
|
||||
* @file test_parser_json.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief unit tests for JSON parser
|
||||
*
|
||||
* Copyright (c) 2019 - 2023 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.h"
|
||||
#include "out.h"
|
||||
#include "parser_data.h"
|
||||
#include "printer_data.h"
|
||||
#include "tests_config.h"
|
||||
#include "tree_data_internal.h"
|
||||
#include "tree_schema.h"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
const char *schema = "module a {namespace urn:tests:a;prefix a;yang-version 1.1; import ietf-yang-metadata {prefix md;}"
|
||||
"md:annotation hint { type int8;}"
|
||||
"list l1 { key \"a b c\"; leaf a {type string;} leaf b {type string;} leaf c {type int16;}"
|
||||
" leaf d {type string;}"
|
||||
" container cont {leaf e {type boolean;}}"
|
||||
"}"
|
||||
"leaf foo { type string;}"
|
||||
"container c {"
|
||||
" leaf x {type string;}"
|
||||
" action act { input { leaf al {type string;} } output { leaf al {type uint8;} } }"
|
||||
" notification n1 { leaf nl {type string;} }"
|
||||
"}"
|
||||
"container cp {presence \"container switch\"; leaf y {type string;} leaf z {type int8;}}"
|
||||
"anydata any {config false;}"
|
||||
"anyxml axml;"
|
||||
"leaf-list ll1 { type uint8; }"
|
||||
"leaf foo2 { type string; default \"default-val\"; }"
|
||||
"leaf foo3 { type uint32; }"
|
||||
"leaf foo4 { type uint64; }"
|
||||
"rpc r1 {input {leaf l1 {type string;} leaf l2 {type string;}}}"
|
||||
"notification n2;"
|
||||
"}";
|
||||
|
||||
UTEST_SETUP;
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHECK_PARSE_LYD(INPUT, PARSE_OPTION, VALIDATE_OPTION, TREE) \
|
||||
CHECK_PARSE_LYD_PARAM(INPUT, LYD_JSON, PARSE_OPTION, VALIDATE_OPTION, LY_SUCCESS, TREE)
|
||||
|
||||
#define PARSER_CHECK_ERROR(INPUT, PARSE_OPTION, VALIDATE_OPTION, MODEL, RET_VAL, ERR_MESSAGE, ERR_PATH, ERR_LINE) \
|
||||
assert_int_equal(RET_VAL, lyd_parse_data_mem(UTEST_LYCTX, INPUT, LYD_JSON, PARSE_OPTION, VALIDATE_OPTION, &MODEL));\
|
||||
CHECK_LOG_CTX(ERR_MESSAGE, ERR_PATH, ERR_LINE);\
|
||||
assert_null(MODEL)
|
||||
|
||||
#define CHECK_LYD_STRING(IN_MODEL, PRINT_OPTION, TEXT) \
|
||||
CHECK_LYD_STRING_PARAM(IN_MODEL, TEXT, LYD_JSON, PRINT_OPTION)
|
||||
|
||||
static void
|
||||
test_leaf(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
struct lyd_node_term *leaf;
|
||||
const char *data;
|
||||
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-with-defaults", "2011-06-01", NULL));
|
||||
|
||||
data = "{\"a:foo\":\"foo value\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "foo", 1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
leaf = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(leaf->value, STRING, "foo value");
|
||||
|
||||
CHECK_LYSC_NODE(tree->next->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_SET_DFLT, 1, "foo2",
|
||||
1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
leaf = (struct lyd_node_term *)tree->next->next;
|
||||
|
||||
CHECK_LYD_VALUE(leaf->value, STRING, "default-val");
|
||||
assert_true(leaf->flags & LYD_DEFAULT);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* make foo2 explicit */
|
||||
data = "{\"a:foo2\":\"default-val\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_SET_DFLT, 1, "foo2",
|
||||
1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
leaf = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(leaf->value, STRING, "default-val");
|
||||
assert_false(leaf->flags & LYD_DEFAULT);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* parse foo2 but make it implicit */
|
||||
data = "{\"a:foo2\":\"default-val\",\"@a:foo2\":{\"ietf-netconf-with-defaults:default\":true}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_SET_DFLT, 1, "foo2",
|
||||
1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
leaf = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(leaf->value, STRING, "default-val");
|
||||
assert_true(leaf->flags & LYD_DEFAULT);
|
||||
|
||||
/* print default values */
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL_TAG, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* skip leaf */
|
||||
data = "{\"a:cp\":{\"x\":\"val\",\"y\":\"valy\",\"z\":5}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{\"a:cp\":{\"y\":\"valy\",\"z\":5}}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* multiple meatadata hint and unknown metadata xxx supposed to be skipped since it is from missing schema */
|
||||
data = "{\"@a:foo\":{\"a:hint\":1,\"a:hint\":2,\"x:xxx\":{\"value\":\"/x:no/x:yes\"}},\"a:foo\":\"xxx\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "foo", 1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
CHECK_LYD_META(tree->meta, 1, "hint", 1, 1, INT8, "1", 1);
|
||||
CHECK_LYD_META(tree->meta->next, 1, "hint", 0, 1, INT8, "2", 2);
|
||||
assert_null(tree->meta->next->next);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
|
||||
"{\"a:foo\":\"xxx\",\"@a:foo\":{\"a:hint\":1,\"a:hint\":2}}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
PARSER_CHECK_ERROR(data, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Unknown (or not implemented) YANG module \"x\" of metadata \"x:xxx\".", "/@a:foo", 1);
|
||||
|
||||
/* missing referenced metadata node */
|
||||
PARSER_CHECK_ERROR("{\"@a:foo\" : { \"a:hint\" : 1 }}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Missing JSON data instance to be coupled with @a:foo metadata.", "/@a:foo", 1);
|
||||
|
||||
/* missing namespace for meatadata*/
|
||||
PARSER_CHECK_ERROR("{\"a:foo\" : \"value\", \"@a:foo\" : { \"hint\" : 1 }}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Metadata in JSON must be namespace-qualified, missing prefix for \"hint\".", "/a:foo", 1);
|
||||
|
||||
/* invalid JSON type */
|
||||
data = "{\"a:l1\" : [{ \"a\" : \"val-a\", \"b\" : \"val-b\", \"c\" : 1, \"cont\" : { \"e\" : \"0\" } }]}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Invalid non-boolean-encoded boolean value \"0\".", "/a:l1[a='val-a'][b='val-b'][c='1']/cont/e", 1);
|
||||
|
||||
/* reverse solidus in JSON object member name */
|
||||
data = "{\"@a:foo\":{\"a:hi\\nt\":1},\"a:foo\":\"xxx\"}";
|
||||
assert_int_equal(LY_EINVAL, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
CHECK_LOG_CTX("Annotation definition for attribute \"a:hi\nt\" not found.", "/@a:foo/@a:hi\nt", 1);
|
||||
|
||||
data = "{\"a:foo\": null}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Invalid non-string-encoded string value \"\".", "/a:foo", 1);
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_leaflist(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
struct lyd_node_term *ll;
|
||||
|
||||
data = "{\"a:ll1\":[10,11]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "10", 10);
|
||||
|
||||
assert_non_null(tree->next);
|
||||
CHECK_LYSC_NODE(tree->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree->next;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "11", 11);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* accept empty */
|
||||
data = "{\"a:ll1\":[]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
|
||||
/* simple metadata */
|
||||
data = "{\"a:ll1\":[10,11],\"@a:ll1\":[null,{\"a:hint\":2}]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "10", 10);
|
||||
|
||||
assert_non_null(tree->next);
|
||||
CHECK_LYSC_NODE(tree->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree->next;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "11", 11);
|
||||
CHECK_LYD_META(ll->meta, 1, "hint", 0, 1, INT8, "2", 2);
|
||||
assert_null(ll->meta->next);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* multiple meatadata hint and unknown metadata xxx supposed to be skipped since it is from missing schema */
|
||||
data = "{\"@a:ll1\" : [{\"a:hint\" : 1, \"x:xxx\" : { \"value\" : \"/x:no/x:yes\" }, "
|
||||
"\"a:hint\" : 10},null,{\"a:hint\" : 3}], \"a:ll1\" : [1,2,3]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "1", 1);
|
||||
CHECK_LYD_META(ll->meta->next, 1, "hint", 1, 1, INT8, "1", 1);
|
||||
CHECK_LYD_META(ll->meta->next->next, 1, "hint", 0, 1, INT8, "10", 10);
|
||||
|
||||
assert_non_null(tree->next);
|
||||
CHECK_LYSC_NODE(tree->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree->next;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "2", 2);
|
||||
assert_null(ll->meta);
|
||||
|
||||
assert_non_null(tree->next->next);
|
||||
CHECK_LYSC_NODE(tree->next->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree->next->next;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "3", 3);
|
||||
CHECK_LYD_META(ll->meta, 1, "hint", 0, 1, INT8, "3", 3);
|
||||
assert_null(ll->meta->next);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
|
||||
"{\"a:ll1\":[1,2,3],\"@a:ll1\":[{\"a:hint\":1,\"a:hint\":10},null,{\"a:hint\":3}]}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* missing referenced metadata node */
|
||||
PARSER_CHECK_ERROR("{\"@a:ll1\":[{\"a:hint\":1}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Missing JSON data instance to be coupled with @a:ll1 metadata.", "/@a:ll1", 1);
|
||||
|
||||
PARSER_CHECK_ERROR("{\"a:ll1\":[1],\"@a:ll1\":[{\"a:hint\":1},{\"a:hint\":2}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Missing JSON data instance #2 of a:ll1 to be coupled with metadata.", "/a:ll1", 1);
|
||||
|
||||
PARSER_CHECK_ERROR("{\"@a:ll1\":[{\"a:hint\":1},{\"a:hint\":2},{\"a:hint\":3}],\"a:ll1\" : [1, 2]}", 0, LYD_VALIDATE_PRESENT,
|
||||
tree, LY_EVALID, "Missing JSON data instance #3 to be coupled with @a:ll1 metadata.", "/@a:ll1", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_anydata(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
data = "{\"a:any\":{\"x:element1\":{\"element2\":\"/a:some/a:path\",\"list\":[{},{\"key\":\"a\"}]}}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_R | LYS_SET_CONFIG, 1, "any",
|
||||
1, LYS_ANYDATA, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:any\":{}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_R | LYS_SET_CONFIG, 1, "any",
|
||||
1, LYS_ANYDATA, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:any\":{\"node\":20}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_R | LYS_SET_CONFIG, 1, "any",
|
||||
1, LYS_ANYDATA, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:any\": null}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Expecting JSON name/object but anydata \"any\" is represented in input data as name/null.", NULL, 1);
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_anyxml(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
data = "{\"a:axml\":\"some-value in string\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":\"\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":55}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":false}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":null}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":[null,true,false]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":[null,true,{\"name\":[25,40, false]}]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* same as anydata tests */
|
||||
data = "{\"a:axml\":{\"x:element1\":{\"element2\":\"/a:some/a:path\",\"list\":[{},{\"key\":\"a\"}]}}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":{}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_list(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree, *iter;
|
||||
struct lyd_node_inner *list;
|
||||
struct lyd_node_term *leaf;
|
||||
|
||||
/* check hashes */
|
||||
data = "{\"a:l1\":[{\"a\":\"one\",\"b\":\"one\",\"c\":1}]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "l1",
|
||||
1, LYS_LIST, 0, 0, NULL, 0);
|
||||
list = (struct lyd_node_inner *)tree;
|
||||
LY_LIST_FOR(list->child, iter) {
|
||||
assert_int_not_equal(0, iter->hash);
|
||||
}
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* accept empty */
|
||||
data = "{\"a:l1\":[]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
|
||||
/* missing keys */
|
||||
PARSER_CHECK_ERROR("{ \"a:l1\": [ {\"c\" : 1, \"b\" : \"b\"}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"List instance is missing its key \"a\".", "/a:l1[b='b'][c='1']", 1);
|
||||
|
||||
PARSER_CHECK_ERROR("{ \"a:l1\": [ {\"a\" : \"a\"}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"List instance is missing its key \"b\".", "/a:l1[a='a']", 1);
|
||||
|
||||
PARSER_CHECK_ERROR("{ \"a:l1\": [ {\"b\" : \"b\", \"a\" : \"a\"}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"List instance is missing its key \"c\".", "/a:l1[a='a'][b='b']", 1);
|
||||
|
||||
/* key duplicate */
|
||||
PARSER_CHECK_ERROR("{ \"a:l1\": [ {\"c\" : 1, \"b\" : \"b\", \"a\" : \"a\", \"c\" : 1}]}", 0, LYD_VALIDATE_PRESENT,
|
||||
tree, LY_EVALID, "Duplicate instance of \"c\".", "/a:l1[a='a'][b='b'][c='1'][c='1']/c", 1);
|
||||
|
||||
/* keys order, in contrast to XML, JSON accepts keys in any order even in strict mode */
|
||||
CHECK_PARSE_LYD("{ \"a:l1\": [ {\"d\" : \"d\", \"a\" : \"a\", \"c\" : 1, \"b\" : \"b\"}]}", 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "l1",
|
||||
1, LYS_LIST, 0, 0, NULL, 0);
|
||||
list = (struct lyd_node_inner *)tree;
|
||||
assert_non_null(leaf = (struct lyd_node_term *)list->child);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "a", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "b", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "c", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "d", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
CHECK_LOG_CTX(NULL, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
|
||||
"{\"a:l1\":[{\"a\":\"a\",\"b\":\"b\",\"c\":1,\"d\":\"d\"}]}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
CHECK_PARSE_LYD("{\"a:l1\":[{\"c\":1,\"b\":\"b\",\"a\":\"a\"}]}", LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "l1",
|
||||
1, LYS_LIST, 0, 0, NULL, 0);
|
||||
list = (struct lyd_node_inner *)tree;
|
||||
assert_non_null(leaf = (struct lyd_node_term *)list->child);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "a",
|
||||
1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "b",
|
||||
1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "c",
|
||||
1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
CHECK_LOG_CTX(NULL, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
|
||||
"{\"a:l1\":[{\"a\":\"a\",\"b\":\"b\",\"c\":1}]}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* skip unknown nested nodes */
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":3,\"counters\":{\"count1\":\"c1\",\"count2\":\"c2\"}}]}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":3}]}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:cp\":{\"@\":{\"a:hint\":1}}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_PRESENCE, 1, "cp",
|
||||
1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
CHECK_LYD_META(tree->meta, 1, "hint", 0, 1, INT8, "1", 1);
|
||||
assert_null(tree->meta->next);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_container(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
struct lyd_node_inner *cont;
|
||||
|
||||
CHECK_PARSE_LYD("{\"a:c\":{}}", 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c",
|
||||
1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
cont = (struct lyd_node_inner *)tree;
|
||||
assert_true(cont->flags & LYD_DEFAULT);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:cp\":{}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_PRESENCE, 1, "cp",
|
||||
1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
cont = (struct lyd_node_inner *)tree;
|
||||
assert_false(cont->flags & LYD_DEFAULT);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* skip container */
|
||||
CHECK_PARSE_LYD("{\"a:unknown\":{\"a\":\"val\",\"b\":5}}", 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:c\": null}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Expecting JSON name/object but container \"c\" is represented in input data as name/null.", NULL, 1);
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_opaq(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
/* invalid value, no flags */
|
||||
data = "{\"a:foo3\":[null]}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Invalid non-number-encoded uint32 value \"\".", "/a:foo3", 1);
|
||||
|
||||
/* opaq flag */
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0, LY_VALUE_JSON, "foo3", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* special chars */
|
||||
data = "{\"a:foo3\":\"ab\\\"\\\\\\r\\t\"}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* wrong encoding */
|
||||
data = "{\"a:foo3\":\"25\"}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0, LY_VALUE_JSON, "foo3", 0, 0, NULL, 0, "25");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:foo4\":25}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0, LY_VALUE_JSON, "foo4", 0, 0, NULL, 0, "25");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* missing key, no flags */
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"d\":\"val_d\"}]}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"List instance is missing its key \"c\".", "/a:l1[a='val_a'][b='val_b']", 1);
|
||||
|
||||
/* opaq flag */
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* invalid key, no flags */
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Invalid non-number-encoded int16 value \"val_c\".", "/a:l1[a='val_a'][b='val_b']/c", 1);
|
||||
|
||||
/* opaq flag */
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":{\"val\":\"val_c\"}}]}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\"}]}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* invalid metadata */
|
||||
data = "{\"@a:foo\":\"str\",\"@a:foo3\":1,\"a:foo3\":2}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Unknown module of node \"@a:foo\".", "/", 0);
|
||||
CHECK_LOG_CTX("Missing JSON data instance to be coupled with @a:foo metadata.", "/@a:foo", 1);
|
||||
|
||||
/* empty name */
|
||||
PARSER_CHECK_ERROR("{\"@a:foo\":{\"\":0}}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"JSON object member name cannot be a zero-length string.", "/@a:foo", 1);
|
||||
|
||||
/* opaque data tree format print */
|
||||
data =
|
||||
"{\n"
|
||||
" \"ietf-netconf-nmda:get-data\": {\n"
|
||||
" \"data\": {\n"
|
||||
" \"ietf-keystore:keystore\": {\n"
|
||||
" \"asymmetric-keys\": {\n"
|
||||
" \"asymmetric-key\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"genkey\",\n"
|
||||
" \"algorithm\": \"rsa2048\"\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" \"ietf-netconf-server:netconf-server\": {\n"
|
||||
" \"listen\": {\n"
|
||||
" \"idle-timeout\": 3600,\n"
|
||||
" \"endpoint\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"default-ssh\",\n"
|
||||
" \"ssh\": {\n"
|
||||
" \"tcp-server-parameters\": {\n"
|
||||
" \"local-address\": \"0.0.0.0\",\n"
|
||||
" \"local-port\": 830\n"
|
||||
" },\n"
|
||||
" \"ssh-server-parameters\": {\n"
|
||||
" \"server-identity\": {\n"
|
||||
" \"host-key\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"default-key\",\n"
|
||||
" \"public-key\": {\n"
|
||||
" \"keystore-reference\": \"genkey\"\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" },\n"
|
||||
" \"client-authentication\": {\n"
|
||||
" \"supported-authentication-methods\": {\n"
|
||||
" \"publickey\": [null],\n"
|
||||
" \"passsword\": [null],\n"
|
||||
" \"other\": [\n"
|
||||
" \"interactive\",\n"
|
||||
" \"gssapi\"\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_rpc(void **state)
|
||||
{
|
||||
const char *data;
|
||||
char *str;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *op;
|
||||
const struct lyd_node *node;
|
||||
const char *dsc = "Edit data in an NMDA datastore.\n"
|
||||
"\n"
|
||||
"If an error condition occurs such that an error severity\n"
|
||||
"<rpc-error> element is generated, the server will stop\n"
|
||||
"processing the <edit-data> operation and restore the\n"
|
||||
"specified configuration to its complete state at\n"
|
||||
"the start of this <edit-data> operation.";
|
||||
|
||||
assert_non_null((ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-nmda", "2019-01-07", NULL)));
|
||||
|
||||
data = "{\"ietf-netconf-nmda:edit-data\":{"
|
||||
"\"datastore\":\"ietf-datastores:running\","
|
||||
"\"config\":{\"a:cp\":{\"z\":[null],\"@z\":{\"ietf-netconf:operation\":\"replace\"}},"
|
||||
"\"a:l1\":[{\"@\":{\"ietf-netconf:operation\":\"replace\"},\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}"
|
||||
"}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_RPC_YANG, &tree, &op));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(op);
|
||||
|
||||
CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, dsc, 0, LYS_STATUS_CURR,
|
||||
1, 0, 0, 1, "edit-data", LYS_RPC,
|
||||
0, 0, 0, 0, 0, NULL, 0);
|
||||
|
||||
node = tree;
|
||||
CHECK_LYSC_ACTION((struct lysc_node_action *)node->schema, dsc, 0, LYS_STATUS_CURR,
|
||||
1, 0, 0, 1, "edit-data", LYS_RPC,
|
||||
0, 0, 0, 0, 0, NULL, 0);
|
||||
node = lyd_child(node)->next;
|
||||
CHECK_LYSC_NODE(node->schema, "Inline config content.", 0, LYS_STATUS_CURR | LYS_IS_INPUT, 1, "config",
|
||||
0, LYS_ANYDATA, 1, 0, NULL, 0);
|
||||
|
||||
node = ((struct lyd_node_any *)node)->value.tree;
|
||||
CHECK_LYSC_NODE(node->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_PRESENCE, 1, "cp",
|
||||
1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
node = lyd_child(node);
|
||||
/* z has no value */
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0, LY_VALUE_JSON, "z", 0, 0, NULL, 0, "");
|
||||
node = node->parent->next;
|
||||
/* l1 key c has invalid value so it is at the end */
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* append to parent */
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(NULL, UTEST_LYCTX, "/a:r1", NULL, 0, &op));
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory("{\"l1\": \"some str\", \"l2\": \"some other str\"}", &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_JSON, LYD_TYPE_RPC_YANG, &tree, NULL));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, op, LYD_JSON, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK));
|
||||
lyd_free_tree(op);
|
||||
assert_string_equal(str, "{\"a:r1\":{\"l1\":\"some str\",\"l2\":\"some other str\"}}");
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void
|
||||
test_action(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *op;
|
||||
|
||||
data = "{\"a:c\":{\"act\":{\"al\":\"value\"}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_RPC_YANG, &tree, &op));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(op);
|
||||
CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
|
||||
1, 0, 0, 1, "act", LYS_ACTION,
|
||||
1, 0, 0, 1, 0, NULL, 0);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* wrong namespace, element name, whatever... */
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void
|
||||
test_notification(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *ntf;
|
||||
|
||||
data = "{\"a:c\":{\"n1\":{\"nl\":\"value\"}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_YANG, &tree, &ntf));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(ntf);
|
||||
CHECK_LYSC_NOTIF((struct lysc_node_notif *)ntf->schema, 1, NULL, 0, 0x4, 1, 0, "n1", 1, 0, NULL, 0);
|
||||
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c", 1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:n2\":{}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_YANG, &tree, &ntf));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(ntf);
|
||||
CHECK_LYSC_NOTIF((struct lysc_node_notif *)ntf->schema, 0, NULL, 0, 0x4, 1, 0, "n2", 0, 0, NULL, 0);
|
||||
|
||||
assert_non_null(tree);
|
||||
assert_ptr_equal(ntf, tree);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* wrong namespace, element name, whatever... */
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void
|
||||
test_reply(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *op;
|
||||
const struct lyd_node *node;
|
||||
|
||||
data = "{\"a:c\":{\"act\":{\"al\":25}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_REPLY_YANG, &tree, &op));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(op);
|
||||
CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
|
||||
1, 0, 0, 1, "act", LYS_ACTION,
|
||||
1, 0, 0, 1, 0, NULL, 0);
|
||||
node = lyd_child(op);
|
||||
CHECK_LYSC_NODE(node->schema, NULL, 0, LYS_STATUS_CURR | LYS_IS_OUTPUT, 1, "al", 0, LYS_LEAF, 1, 0, NULL, 0);
|
||||
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c", 1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
|
||||
/* TODO print only rpc-reply node and then output subtree */
|
||||
CHECK_LYD_STRING(lyd_child(op), LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{\"a:al\":25}");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{\"a:c\":{\"act\":{\"al\":25}}}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* wrong namespace, element name, whatever... */
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void
|
||||
test_restconf_rpc(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *envp;
|
||||
|
||||
assert_non_null((ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-nmda", "2019-01-07", NULL)));
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(NULL, UTEST_LYCTX, "/ietf-netconf-nmda:edit-data", NULL, 0, &tree));
|
||||
|
||||
data = "{\"ietf-netconf-nmda:input\":{"
|
||||
"\"datastore\":\"ietf-datastores:running\","
|
||||
"\"config\":{\"a:cp\":{\"z\":[null],\"@z\":{\"ietf-netconf:operation\":\"replace\"}},"
|
||||
"\"a:l1\":[{\"@\":{\"ietf-netconf:operation\":\"replace\"},\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}"
|
||||
"}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, tree, in, LYD_JSON, LYD_TYPE_RPC_RESTCONF, &envp, NULL));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
/* the same just connected to the edit-data RPC */
|
||||
data = "{\"ietf-netconf-nmda:edit-data\":{"
|
||||
"\"datastore\":\"ietf-datastores:running\","
|
||||
"\"config\":{\"a:cp\":{\"z\":[null],\"@z\":{\"ietf-netconf:operation\":\"replace\"}},"
|
||||
"\"a:l1\":[{\"@\":{\"ietf-netconf:operation\":\"replace\"},\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}"
|
||||
"}}";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
lyd_free_all(envp);
|
||||
}
|
||||
|
||||
static void
|
||||
test_restconf_notification(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *ntf;
|
||||
|
||||
data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2013-12-21T00:01:00Z\",\"a:c\":{\"n1\":{\"nl\":\"value\"}}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, &tree, &ntf));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
/* envelopes separately */
|
||||
data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2013-12-21T00:01:00Z\"}}";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
/* notification with the parent node */
|
||||
data = "{\"a:c\":{\"n1\":{\"nl\":\"value\"}}}";
|
||||
CHECK_LYD_STRING(lyd_parent(ntf), LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
lyd_free_all(tree);
|
||||
lyd_free_all(ntf);
|
||||
|
||||
/* wrong order */
|
||||
data = "{\"ietf-restconf:notification\":{\"a:n2\":{},\"eventTime\":\"2013-12-21T00:01:00Z\"}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, &tree, &ntf));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
lyd_free_all(tree);
|
||||
lyd_free_all(ntf);
|
||||
|
||||
/* unknown notification */
|
||||
data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2013-12-21T00:01:00Z\",\"invalid:n2\":{}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, &tree, &ntf));
|
||||
UTEST_LOG_CTX_CLEAN;
|
||||
ly_in_free(in, 0);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_restconf_reply(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *envp;
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(NULL, UTEST_LYCTX, "/a:c/act", NULL, 0, &tree));
|
||||
|
||||
data = "{\"a:output\":{\"al\":25}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, lyd_child(tree), in, LYD_JSON, LYD_TYPE_REPLY_RESTCONF, &envp, NULL));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
/* connected to the RPC with the parent */
|
||||
data = "{\"a:c\":{\"act\":{\"al\":25}}}";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
lyd_free_all(envp);
|
||||
}
|
||||
|
||||
static void
|
||||
test_metadata(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
/* invalid metadata value */
|
||||
data = "{\"a:c\":{\"x\":\"xval\",\"@x\":{\"a:hint\":\"value\"}}}";
|
||||
assert_int_equal(LY_EVALID, lyd_parse_data_mem(_UC->ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_null(tree);
|
||||
CHECK_LOG_CTX("Invalid non-number-encoded int8 value \"value\".", "/a:c/x/@a:hint", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_leaf, setup),
|
||||
UTEST(test_leaflist, setup),
|
||||
UTEST(test_anydata, setup),
|
||||
UTEST(test_anyxml, setup),
|
||||
UTEST(test_list, setup),
|
||||
UTEST(test_container, setup),
|
||||
UTEST(test_opaq, setup),
|
||||
UTEST(test_rpc, setup),
|
||||
UTEST(test_action, setup),
|
||||
UTEST(test_notification, setup),
|
||||
UTEST(test_reply, setup),
|
||||
UTEST(test_restconf_rpc, setup),
|
||||
UTEST(test_restconf_notification, setup),
|
||||
UTEST(test_restconf_reply, setup),
|
||||
UTEST(test_metadata, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1034
tests/utests/data/test_parser_xml.c
Normal file
1034
tests/utests/data/test_parser_xml.c
Normal file
File diff suppressed because it is too large
Load diff
83
tests/utests/data/test_printer_json.c
Normal file
83
tests/utests/data/test_printer_json.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* @file test_printer_json.c
|
||||
* @author: Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief unit tests for functions from printer_yang.c
|
||||
*
|
||||
* Copyright (c) 2019-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"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
const char *schema1 = "module schema1 {namespace urn:tests:schema1;prefix schema1;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"anydata data;"
|
||||
"}";
|
||||
const char *schema2 = "module schema2 {namespace urn:tests:schema2;prefix s2;yang-version 1.1;"
|
||||
" container a {"
|
||||
" container b {"
|
||||
" leaf c {"
|
||||
" type string;"
|
||||
" default \"dflt\";"
|
||||
" }"
|
||||
" }"
|
||||
" }"
|
||||
"}";
|
||||
|
||||
UTEST_SETUP;
|
||||
UTEST_ADD_MODULE(schema1, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_container_presence(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
char *buffer = NULL;
|
||||
const char *data = "{\"schema1:data\":{\"cont1\":{}}}";
|
||||
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&buffer, tree, LYD_JSON, LYD_PRINT_SHRINK));
|
||||
CHECK_STRING(buffer, data);
|
||||
free(buffer);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_empty_container_wd_trim(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
char *buffer = NULL;
|
||||
const char *data = "{\"schema2:a\":{\"b\":{\"c\":\"dflt\"}}}";
|
||||
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&buffer, tree, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WD_TRIM));
|
||||
CHECK_STRING(buffer, "{}");
|
||||
free(buffer);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&buffer, tree, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WD_TRIM | LYD_PRINT_KEEPEMPTYCONT));
|
||||
CHECK_STRING(buffer, "{\"schema2:a\":{\"b\":{}}}");
|
||||
free(buffer);
|
||||
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_container_presence, setup),
|
||||
UTEST(test_empty_container_wd_trim, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
344
tests/utests/data/test_printer_xml.c
Normal file
344
tests/utests/data/test_printer_xml.c
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* @file test_printer_xml.c
|
||||
* @author: Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief unit tests for functions from printer_yang.c
|
||||
*
|
||||
* Copyright (c) 2019-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 "out.h"
|
||||
#include "parser_data.h"
|
||||
#include "printer_data.h"
|
||||
#include "tests_config.h"
|
||||
#include "tree_schema.h"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
const char *schema_defs = "module defs {namespace urn:tests:defs;prefix d;yang-version 1.1;"
|
||||
"identity crypto-alg; identity interface-type; identity ethernet {base interface-type;} identity fast-ethernet {base ethernet;}}";
|
||||
const char *schema_types = "module types {namespace urn:tests:types;prefix t;yang-version 1.1; import defs {prefix defs;}"
|
||||
"feature f; identity gigabit-ethernet { base defs:ethernet;}"
|
||||
"container cont {leaf leaftarget {type empty;}"
|
||||
" list listtarget {key id; max-elements 5;leaf id {type uint8;} leaf value {type string;}"
|
||||
" action test {input {leaf a {type string;}} output {leaf b {type string;}}}}"
|
||||
" leaf-list leaflisttarget {type uint8; max-elements 5;}}"
|
||||
"list list {key id; leaf id {type string;} leaf value {type string;} leaf-list targets {type string;}}"
|
||||
"list list2 {key \"id value\"; leaf id {type string;} leaf value {type string;}}"
|
||||
"list list_inst {key id; leaf id {type instance-identifier {require-instance true;}} leaf value {type string;}}"
|
||||
"list list_ident {key id; leaf id {type identityref {base defs:interface-type;}} leaf value {type string;}}"
|
||||
"leaf-list leaflisttarget {type string;}"
|
||||
"leaf binary {type binary {length 5 {error-message \"This base64 value must be of length 5.\";}}}"
|
||||
"leaf binary-norestr {type binary;}"
|
||||
"leaf int8 {type int8 {range 10..20;}}"
|
||||
"leaf uint8 {type uint8 {range 150..200;}}"
|
||||
"leaf int16 {type int16 {range -20..-10;}}"
|
||||
"leaf uint16 {type uint16 {range 150..200;}}"
|
||||
"leaf int32 {type int32;}"
|
||||
"leaf uint32 {type uint32;}"
|
||||
"leaf int64 {type int64;}"
|
||||
"leaf uint64 {type uint64;}"
|
||||
"leaf bits {type bits {bit zero; bit one {if-feature f;} bit two;}}"
|
||||
"leaf enums {type enumeration {enum white; enum yellow {if-feature f;}}}"
|
||||
"leaf dec64 {type decimal64 {fraction-digits 1; range 1.5..10;}}"
|
||||
"leaf dec64-norestr {type decimal64 {fraction-digits 18;}}"
|
||||
"leaf str {type string {length 8..10; pattern '[a-z ]*';}}"
|
||||
"leaf str-norestr {type string;}"
|
||||
"leaf bool {type boolean;}"
|
||||
"leaf empty {type empty;}"
|
||||
"leaf ident {type identityref {base defs:interface-type;}}"
|
||||
"leaf inst {type instance-identifier {require-instance true;}}"
|
||||
"leaf inst-noreq {type instance-identifier {require-instance false;}}"
|
||||
"leaf lref {type leafref {path /leaflisttarget; require-instance true;}}"
|
||||
"leaf lref2 {type leafref {path \"../list[id = current()/../str-norestr]/targets\"; require-instance true;}}"
|
||||
"leaf un1 {type union {"
|
||||
" type leafref {path /int8; require-instance true;}"
|
||||
" type union { type identityref {base defs:interface-type;} type instance-identifier {require-instance true;} }"
|
||||
" type string {length 1..20;}}}"
|
||||
"anydata any;"
|
||||
"rpc sum {input {leaf x {type uint8;} leaf y {type uint8;}} output {leaf result {type uint16;}}}}";
|
||||
const char *schema_defaults =
|
||||
"module defaults {\n"
|
||||
" namespace \"urn:defaults\";\n"
|
||||
" prefix d;\n"
|
||||
" leaf a {\n"
|
||||
" type union {\n"
|
||||
" type instance-identifier;\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" default \"/d:b\";\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf c {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
"}";
|
||||
|
||||
UTEST_SETUP;
|
||||
|
||||
UTEST_ADD_MODULE(schema_defs, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema_types, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema_defaults, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHECK_PARSE_LYD(INPUT, PARSE_OPTION, VALIDATE_OPTION, TREE) \
|
||||
CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, PARSE_OPTION, VALIDATE_OPTION, LY_SUCCESS, TREE)
|
||||
|
||||
#define CHECK_LYD_STRING(IN_MODEL, PRINT_OPTION, TEXT) \
|
||||
CHECK_LYD_STRING_PARAM(IN_MODEL, TEXT, LYD_XML, PRINT_OPTION)
|
||||
|
||||
static void
|
||||
test_anydata(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
const char *data;
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\"><somexml xmlns:x=\"url:x\" xmlns=\"example.com\"><x:x/></somexml></any>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
/* canonized */
|
||||
data = "<any xmlns=\"urn:tests:types\"><somexml xmlns=\"example.com\"><x xmlns=\"url:x\"/></somexml></any>";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\"/>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <cont>\n"
|
||||
" <defs:elem1 xmlns:defs=\"urn:tests:defs\">\n"
|
||||
" <elem2 xmlns:defaults=\"urn:defaults\" defs:attr1=\"defaults:val\" attr2=\"/defaults:node/defs:node2\">\n"
|
||||
" </elem2>\n"
|
||||
" </defs:elem1>\n"
|
||||
" </cont>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
/* cont should be normally parsed */
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "any", 0, LYS_ANYDATA, 0, 0, NULL, 0);
|
||||
CHECK_LYD_NODE_ANY((struct lyd_node_any *)tree, 0, 0, 0, LYD_ANYDATA_DATATREE);
|
||||
struct lyd_node *tree_tmp = ((struct lyd_node_any *)tree)->value.tree;
|
||||
|
||||
CHECK_LYSC_NODE(tree_tmp->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "cont", 1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
/* but its children not */
|
||||
assert_null(((struct lyd_node_inner *)tree_tmp)->child->schema);
|
||||
/* canonized */
|
||||
data =
|
||||
"<any xmlns=\"urn:tests:types\">\n"
|
||||
" <cont>\n"
|
||||
" <elem1 xmlns=\"urn:tests:defs\">\n"
|
||||
" <elem2 xmlns=\"urn:tests:types\" xmlns:defs=\"urn:tests:defs\" xmlns:defaults=\"urn:defaults\" "
|
||||
"defs:attr1=\"defaults:val\" attr2=\"/defaults:node/defs:node2\">\n"
|
||||
" </elem2>\n"
|
||||
" </elem1>\n"
|
||||
" </cont>\n"
|
||||
"</any>\n";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <ahoj attr=\"<test\">\n"
|
||||
" ahoj jak se vede < how are you"
|
||||
" </ahoj>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <leaflisttarget> ahoj </leaflisttarget>\n"
|
||||
" <leaflisttarget> nazdar </leaflisttarget>\n"
|
||||
" <leaflisttarget> Čau </leaflisttarget>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <cont2/>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <cont>\n"
|
||||
" < how are you"
|
||||
" </cont>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_defaults(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
const char *data;
|
||||
const char *data_trim;
|
||||
const char *data_all;
|
||||
const char *data_all_tag;
|
||||
const char *data_impl_tag;
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-with-defaults", "2011-06-01", NULL));
|
||||
|
||||
/* standard default value */
|
||||
data = "<c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_TRIM | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
data = "<a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
data = "<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
|
||||
" ncwd:default=\"true\" xmlns:d=\"urn:defaults\">/d:b</a>"
|
||||
"<c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
data = "<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
|
||||
" ncwd:default=\"true\" xmlns:d=\"urn:defaults\">/d:b</a>"
|
||||
"<c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* string value equal to the default but default is an unresolved instance-identifier, so they are not considered equal */
|
||||
data = "<a xmlns=\"urn:defaults\">/d:b</a><c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_TRIM | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* instance-identifier value equal to the default, should be considered equal */
|
||||
data = "<a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b><c xmlns=\"urn:defaults\">aa</c>";
|
||||
data_trim = "<b xmlns=\"urn:defaults\">val</b><c xmlns=\"urn:defaults\">aa</c>";
|
||||
data_all = "<a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b><c xmlns=\"urn:defaults\">aa</c>";
|
||||
data_all_tag = "<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
|
||||
" ncwd:default=\"true\" xmlns:d=\"urn:defaults\">/d:b</a>"
|
||||
"<b xmlns=\"urn:defaults\">val</b>"
|
||||
"<c xmlns=\"urn:defaults\">aa</c>";
|
||||
data_impl_tag = "<a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b><c xmlns=\"urn:defaults\">aa</c>";
|
||||
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_TRIM | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_trim);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_all);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_all_tag);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_impl_tag);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static void
|
||||
test_rpc(void **state)
|
||||
{
|
||||
struct state_s *s = (struct state_s *)(*state);
|
||||
struct lyd_node *tree1;
|
||||
struct lyd_node *tree2;
|
||||
const struct lyd_node **trees;
|
||||
const char *request;
|
||||
const char *reply, *result;
|
||||
char *printed;
|
||||
ssize_t len;
|
||||
struct ly_out *out;
|
||||
|
||||
s->func = test_rpc;
|
||||
assert_non_null(out = ly_out_new_memory(&printed, 0));
|
||||
|
||||
request = "<sum xmlns=\"urn:tests:types\"><x>10</x><y>20</y></sum>";
|
||||
reply = "<result xmlns=\"urn:tests:types\">30</result>";
|
||||
result = "<sum xmlns=\"urn:tests:types\"><result>30</result></sum>";
|
||||
assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
|
||||
assert_true((len = lyd_print_tree(out, tree1, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, request);
|
||||
ly_out_reset(out);
|
||||
assert_non_null(trees = lyd_trees_new(1, tree1));
|
||||
assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
|
||||
assert_true((len = lyd_print_tree(out, tree2, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, result);
|
||||
ly_out_reset(out);
|
||||
lyd_trees_free(trees, 0);
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* no arguments */
|
||||
request = "<sum xmlns=\"urn:tests:types\"/>";
|
||||
reply = "";
|
||||
result = "<sum xmlns=\"urn:tests:types\"/>";
|
||||
assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
|
||||
assert_true((len = lyd_print_tree(out, tree1, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, request);
|
||||
ly_out_reset(out);
|
||||
assert_non_null(trees = lyd_trees_new(1, tree1));
|
||||
assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
|
||||
assert_true((len = lyd_print_tree(out, tree2, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, result);
|
||||
ly_out_reset(out);
|
||||
lyd_trees_free(trees, 0);
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* action
|
||||
* "container cont {leaf leaftarget {type empty;}"
|
||||
"list listtarget {key id; max-elements 5;leaf id {type uint8;} leaf value {type string;}"
|
||||
"action test {input {leaf a {type string;}} output {leaf b {type string;}}}}"
|
||||
"leaf-list leaflisttarget {type uint8; max-elements 5;}}"
|
||||
*/
|
||||
request = "<cont xmlns=\"urn:tests:types\"><listtarget><id>10</id><test><a>test</a></test></listtarget></cont>";
|
||||
reply = "<b xmlns=\"urn:tests:types\">test-reply</b>";
|
||||
result = "<cont xmlns=\"urn:tests:types\"><listtarget><id>10</id><test><b>test-reply</b></test></listtarget></cont>";
|
||||
assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
|
||||
assert_true((len = lyd_print_tree(out, tree1, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, request);
|
||||
ly_out_reset(out);
|
||||
assert_non_null(trees = lyd_trees_new(1, tree1));
|
||||
assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
|
||||
assert_true((len = lyd_print_tree(out, tree2, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, result);
|
||||
ly_out_reset(out);
|
||||
lyd_trees_free(trees, 0);
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
ly_out_free(out, NULL, 1);
|
||||
s->func = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_anydata, setup),
|
||||
UTEST(test_defaults, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
822
tests/utests/data/test_tree_data.c
Normal file
822
tests/utests/data/test_tree_data.c
Normal file
|
@ -0,0 +1,822 @@
|
|||
/**
|
||||
* @file test_tree_data.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief unit tests for functions from tree_data.c
|
||||
*
|
||||
* Copyright (c) 2018-2023 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 "libyang.h"
|
||||
#include "ly_common.h"
|
||||
#include "path.h"
|
||||
#include "xpath.h"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
const char *schema1 = "module a {namespace urn:tests:a;prefix a;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"leaf bar {type string;}"
|
||||
"list l1 { key \"a b\"; leaf a {type string;} leaf b {type string;} leaf c {type string;}}"
|
||||
"leaf foo { type string;}"
|
||||
"leaf-list ll { type string;}"
|
||||
"container c {leaf-list x {type string;}}"
|
||||
"anydata any {config false;}"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;} leaf-list d {type string;}}"
|
||||
"}}";
|
||||
|
||||
const char *schema2 = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}}"
|
||||
"anydata any {config false;}"
|
||||
"}";
|
||||
|
||||
const char *schema3 = "module c {yang-version 1.1; namespace \"http://example.com/main\";prefix m;"
|
||||
"import \"ietf-inet-types\" {prefix inet;}"
|
||||
"typedef optional-ip-address {type union {"
|
||||
" type inet:ip-address;"
|
||||
" type string;"
|
||||
"}}"
|
||||
"container cont {"
|
||||
" list nexthop {min-elements 1; key \"gateway\";"
|
||||
" leaf gateway {type optional-ip-address;}"
|
||||
" }"
|
||||
" leaf-list pref {type inet:ipv6-prefix;}"
|
||||
"}}";
|
||||
|
||||
UTEST_SETUP;
|
||||
|
||||
UTEST_ADD_MODULE(schema1, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema3, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHECK_PARSE_LYD(INPUT, PARSE_OPTION, VALIDATE_OPTION, TREE) \
|
||||
CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, PARSE_OPTION, VALIDATE_OPTION, LY_SUCCESS, TREE)
|
||||
|
||||
#define CHECK_PARSE_LYD_PARAM_CTX(CTX, INPUT, PARSE_OPTION, OUT_NODE) \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(CTX, INPUT, LYD_XML, PARSE_OPTION, LYD_VALIDATE_PRESENT, &OUT_NODE)); \
|
||||
assert_non_null(OUT_NODE);
|
||||
|
||||
#define RECREATE_CTX_WITH_MODULE(CTX, MODULE) \
|
||||
ly_ctx_destroy(CTX); \
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &CTX)); \
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(MODULE, &_UC->in)); \
|
||||
assert_int_equal(LY_SUCCESS, lys_parse(CTX, _UC->in, LYS_IN_YANG, NULL, NULL)); \
|
||||
ly_in_free(_UC->in, 0);
|
||||
|
||||
static void
|
||||
test_compare(void **state)
|
||||
{
|
||||
struct lyd_node *tree1, *tree2;
|
||||
const char *data1;
|
||||
const char *data2;
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(NULL, NULL, 0));
|
||||
|
||||
data1 = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>x</c></l1>";
|
||||
data2 = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>y</c></l1>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(((struct lyd_node_inner *)tree1)->child, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<l2 xmlns=\"urn:tests:a\"><c><x>a</x></c></l2><l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1->next, tree2->next, LYD_COMPARE_FULL_RECURSION));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next->next, tree2->next, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<ll xmlns=\"urn:tests:a\">a</ll><ll xmlns=\"urn:tests:a\">b</ll>";
|
||||
data2 = "<ll xmlns=\"urn:tests:a\">b</ll>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(NULL, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, NULL, 0));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<c xmlns=\"urn:tests:a\"><x>x</x></c>";
|
||||
data2 = "<c xmlns=\"urn:tests:a\"><x>y</x></c>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<c xmlns=\"urn:tests:a\"><x>x</x></c>";
|
||||
data2 = "<c xmlns=\"urn:tests:a\"><x>x</x><x>y</x></c>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<any xmlns=\"urn:tests:a\"><x>x</x></any>";
|
||||
data2 = "<any xmlns=\"urn:tests:a\"><x>x</x><x>y</x></any>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1->next, tree2->next, 0));
|
||||
lyd_free_all(tree1);
|
||||
data1 = "<any xmlns=\"urn:tests:a\"><x>x</x><x>y</x></any>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<c xmlns=\"urn:tests:a\"><x>c</x><x>a</x><x>b</x></c>";
|
||||
data2 = "<c xmlns=\"urn:tests:a\"><x>a</x><x>b</x><x>c</x></c>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_compare_diff_ctx(void **state)
|
||||
{
|
||||
struct lyd_node *tree1, *tree2;
|
||||
const char *data1, *data2;
|
||||
struct ly_ctx *ctx2 = NULL;
|
||||
const char *module;
|
||||
|
||||
/* create second context with the same schema */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with schema that has a different name */
|
||||
module = "module c {namespace urn:tests:c;prefix c;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:c\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with schema that has a different revision */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2015-05-08;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with schema that has no revision */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with schema that has a different parent nodetype */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"container l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(lyd_child(lyd_child(tree1)), lyd_child(lyd_child(tree2)), 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with the same opaq data nodes */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"anydata any {config false;}"
|
||||
"}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<any xmlns=\"urn:tests:b\" xmlns:aa=\"urn:tests:b\"><x>aa:x</x></any>";
|
||||
data2 = "<any xmlns=\"urn:tests:b\" xmlns:bb=\"urn:tests:b\"><x>bb:x</x></any>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, LYD_PARSE_ONLY, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, LYD_PARSE_ONLY, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with the different opaq data node value */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"anydata any {config false;}"
|
||||
"}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<any xmlns=\"urn:tests:b\" xmlns:aa=\"urn:tests:b\"><x>aa:x</x></any>";
|
||||
data2 = "<any xmlns=\"urn:tests:b\" xmlns:bb=\"urn:tests:b\"><x>bb:y</x></any>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, LYD_PARSE_ONLY, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, LYD_PARSE_ONLY, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with the wrong prefix in opaq data node value */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"anydata any {config false;}"
|
||||
"}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<any xmlns=\"urn:tests:b\" xmlns:aa=\"urn:tests:b\"><x>aa:x</x></any>";
|
||||
data2 = "<any xmlns=\"urn:tests:b\" xmlns:bb=\"urn:tests:b\"><x>cc:x</x></any>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, LYD_PARSE_ONLY, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, LYD_PARSE_ONLY, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* clean up */
|
||||
ly_ctx_destroy(ctx2);
|
||||
_UC->in = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_dup(void **state)
|
||||
{
|
||||
struct lyd_node *tree1, *tree2;
|
||||
const char *result;
|
||||
const char *data;
|
||||
|
||||
data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>x</c></l1>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1, NULL, LYD_DUP_RECURSIVE, &tree2));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>x</c></l1>";
|
||||
result = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b></l1>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1, NULL, 0, &tree2));
|
||||
lyd_free_all(tree1);
|
||||
CHECK_PARSE_LYD(result, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l2 xmlns=\"urn:tests:a\"><c><x>a</x></c></l2><l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
result = "<l2 xmlns=\"urn:tests:a\"><c><x>a</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_siblings(tree1, NULL, LYD_DUP_RECURSIVE, &tree2));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, tree2->next, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1->next, NULL, LYD_DUP_RECURSIVE, &tree2));
|
||||
lyd_free_all(tree1);
|
||||
CHECK_PARSE_LYD(result, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree2);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1->next, NULL, 0, &tree2));
|
||||
lyd_free_all(tree1);
|
||||
result = "<l2 xmlns=\"urn:tests:a\"/>";
|
||||
CHECK_PARSE_LYD_PARAM(result, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:a\"><c><a>a</a></c></any>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1, NULL, 0, &tree2));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(lyd_child(lyd_child(tree1->next)), NULL, LYD_DUP_WITH_PARENTS, &tree2));
|
||||
int unsigned flag = LYS_CONFIG_R | LYS_SET_ENUM;
|
||||
|
||||
CHECK_LYSC_NODE(tree2->schema, NULL, 0, flag, 1, "x", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, (struct lyd_node *)tree2->parent->parent,
|
||||
LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>c</c></l1>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(((struct lyd_node_inner *)tree1)->child->prev, NULL,
|
||||
LYD_DUP_WITH_PARENTS, &tree2));
|
||||
flag = LYS_CONFIG_W | LYS_SET_ENUM;
|
||||
CHECK_LYSC_NODE(tree2->schema, NULL, 0, flag, 1, "c", 0, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, (struct lyd_node *)tree2->parent, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1->next, NULL, 0, &tree2));
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(lyd_child(lyd_child(tree1->next)), (struct lyd_node_inner *)tree2,
|
||||
LYD_DUP_WITH_PARENTS, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* invalid */
|
||||
data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>c</c></l1><l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_EINVAL, lyd_dup_single(((struct lyd_node_inner *)tree1)->child->prev,
|
||||
(struct lyd_node_inner *)tree1->next, LYD_DUP_WITH_PARENTS, NULL));
|
||||
CHECK_LOG_CTX("None of the duplicated node \"c\" schema parents match the provided parent \"c\".", NULL, 0);
|
||||
lyd_free_all(tree1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_target(void **state)
|
||||
{
|
||||
const struct lyd_node_term *term;
|
||||
struct lyd_node *tree;
|
||||
struct lyxp_expr *exp;
|
||||
struct ly_path *path;
|
||||
const char *path_str = "/a:l2[2]/c/d[3]";
|
||||
const char *data =
|
||||
"<l2 xmlns=\"urn:tests:a\"><c>"
|
||||
" <d>a</d>"
|
||||
" </c></l2>"
|
||||
"<l2 xmlns=\"urn:tests:a\"><c>"
|
||||
" <d>a</d>"
|
||||
" <d>b</d>"
|
||||
" <d>b</d>"
|
||||
" <d>c</d>"
|
||||
"</c></l2>"
|
||||
"<l2 xmlns=\"urn:tests:a\"><c>"
|
||||
"</c></l2>";
|
||||
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_int_equal(LY_SUCCESS, ly_path_parse(UTEST_LYCTX, NULL, path_str, strlen(path_str), 0, LY_PATH_BEGIN_EITHER,
|
||||
LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp));
|
||||
assert_int_equal(LY_SUCCESS, ly_path_compile(UTEST_LYCTX, NULL, NULL, NULL, exp, LY_PATH_OPER_INPUT,
|
||||
LY_PATH_TARGET_SINGLE, 1, LY_VALUE_JSON, NULL, &path));
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_target(path, tree, (struct lyd_node **)&term));
|
||||
|
||||
const int unsigned flag = LYS_CONFIG_R | LYS_SET_ENUM | LYS_ORDBY_USER;
|
||||
|
||||
CHECK_LYSC_NODE(term->schema, NULL, 0, flag, 1, "d", 0, LYS_LEAFLIST, 1, 0, NULL, 0);
|
||||
assert_string_equal(lyd_get_value(&term->node), "b");
|
||||
assert_string_equal(lyd_get_value(term->prev), "b");
|
||||
|
||||
lyd_free_all(tree);
|
||||
ly_path_free(UTEST_LYCTX, path);
|
||||
lyxp_expr_free(UTEST_LYCTX, exp);
|
||||
}
|
||||
|
||||
static void
|
||||
test_list_pos(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
data = "<bar xmlns=\"urn:tests:a\">test</bar>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>one</a><b>one</b></l1>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>two</a><b>two</b></l1>"
|
||||
"<foo xmlns=\"urn:tests:a\">test</foo>";
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_int_equal(0, lyd_list_pos(tree));
|
||||
assert_int_equal(1, lyd_list_pos(tree->next));
|
||||
assert_int_equal(2, lyd_list_pos(tree->next->next));
|
||||
assert_int_equal(0, lyd_list_pos(tree->next->next->next));
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<ll xmlns=\"urn:tests:a\">one</ll>"
|
||||
"<ll xmlns=\"urn:tests:a\">two</ll>"
|
||||
"<ll xmlns=\"urn:tests:a\">three</ll>";
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_int_equal(1, lyd_list_pos(tree));
|
||||
assert_int_equal(2, lyd_list_pos(tree->next));
|
||||
assert_int_equal(3, lyd_list_pos(tree->next->next));
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<ll xmlns=\"urn:tests:a\">one</ll>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>one</a><b>one</b></l1>"
|
||||
"<ll xmlns=\"urn:tests:a\">two</ll>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>two</a><b>two</b></l1>"
|
||||
"<ll xmlns=\"urn:tests:a\">three</ll>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>three</a><b>three</b></l1>";
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_string_equal("l1", tree->schema->name);
|
||||
assert_int_equal(1, lyd_list_pos(tree));
|
||||
assert_int_equal(2, lyd_list_pos(tree->next));
|
||||
assert_int_equal(3, lyd_list_pos(tree->next->next));
|
||||
assert_string_equal("ll", tree->next->next->next->schema->name);
|
||||
assert_int_equal(1, lyd_list_pos(tree->next->next->next));
|
||||
assert_int_equal(2, lyd_list_pos(tree->next->next->next->next));
|
||||
assert_int_equal(3, lyd_list_pos(tree->next->next->next->next->next));
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_first_sibling(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
struct lyd_node_inner *parent;
|
||||
|
||||
data = "<bar xmlns=\"urn:tests:a\">test</bar>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>one</a><b>one</b><c>one</c></l1>"
|
||||
"<foo xmlns=\"urn:tests:a\">test</foo>";
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_ptr_equal(tree, lyd_first_sibling(tree->next));
|
||||
assert_ptr_equal(tree, lyd_first_sibling(tree));
|
||||
assert_ptr_equal(tree, lyd_first_sibling(tree->prev));
|
||||
parent = (struct lyd_node_inner *)tree->next;
|
||||
assert_int_equal(LYS_LIST, parent->schema->nodetype);
|
||||
assert_ptr_equal(parent->child, lyd_first_sibling(parent->child->next));
|
||||
assert_ptr_equal(parent->child, lyd_first_sibling(parent->child));
|
||||
assert_ptr_equal(parent->child, lyd_first_sibling(parent->child->prev));
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_find_path(void **state)
|
||||
{
|
||||
struct lyd_node *root;
|
||||
const struct lys_module *mod;
|
||||
|
||||
mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "c");
|
||||
assert_non_null(mod);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_inner(NULL, mod, "cont", 0, &root));
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(root, NULL, "/c:cont/nexthop[gateway='10.0.0.1']", NULL, LYD_NEW_PATH_UPDATE, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(root, NULL, "/c:cont/nexthop[gateway='2100::1']", NULL, LYD_NEW_PATH_UPDATE, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(root, NULL, "/c:cont/pref[.='fc00::/64']", NULL, 0, NULL));
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "/c:cont/nexthop[gateway='10.0.0.1']", 0, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "/c:cont/nexthop[gateway='2100::1']", 0, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "/c:cont/pref[.='fc00::/64']", 0, NULL));
|
||||
|
||||
assert_int_equal(LY_EVALID, lyd_find_path(root, "/cont", 0, NULL));
|
||||
CHECK_LOG_CTX("Prefix missing for \"cont\" in path.", "/c:cont", 0);
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "nexthop[gateway='2100::1']", 0, NULL));
|
||||
|
||||
lyd_free_all(root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_hash(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
const char *schema, *data;
|
||||
|
||||
schema =
|
||||
"module test-data-hash {"
|
||||
" yang-version 1.1;"
|
||||
" namespace \"urn:tests:tdh\";"
|
||||
" prefix t;"
|
||||
" container c {"
|
||||
" leaf-list ll {"
|
||||
" type string;"
|
||||
" }"
|
||||
" }"
|
||||
"}";
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* The number of <ll/> must be greater or equal to LYD_HT_MIN_ITEMS
|
||||
* for the correct test run. It should guarantee the creation of a hash table.
|
||||
*/
|
||||
assert_true(LYD_HT_MIN_ITEMS <= 4);
|
||||
data =
|
||||
"<c xmlns='urn:tests:tdh'>"
|
||||
" <ll/>"
|
||||
" <ll/>"
|
||||
" <ll/>"
|
||||
" <ll/>"
|
||||
"</c>";
|
||||
|
||||
/* The run must not crash due to the assert that checks the hash. */
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
|
||||
CHECK_LOG_CTX("Duplicate instance of \"ll\".", "/test-data-hash:c/ll[.='']", 1);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_lyxp_vars(void **UNUSED(state))
|
||||
{
|
||||
struct lyxp_var *vars;
|
||||
|
||||
/* Test free. */
|
||||
vars = NULL;
|
||||
lyxp_vars_free(vars);
|
||||
|
||||
/* Bad arguments for lyxp_vars_add(). */
|
||||
assert_int_equal(LY_EINVAL, lyxp_vars_set(NULL, "var1", "val1"));
|
||||
assert_int_equal(LY_EINVAL, lyxp_vars_set(&vars, NULL, "val1"));
|
||||
assert_int_equal(LY_EINVAL, lyxp_vars_set(&vars, "var1", NULL));
|
||||
lyxp_vars_free(vars);
|
||||
vars = NULL;
|
||||
|
||||
/* Add one item. */
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "val1"));
|
||||
assert_int_equal(LY_ARRAY_COUNT(vars), 1);
|
||||
assert_string_equal(vars[0].name, "var1");
|
||||
assert_string_equal(vars[0].value, "val1");
|
||||
lyxp_vars_free(vars);
|
||||
vars = NULL;
|
||||
|
||||
/* Add three items. */
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "val1"));
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "val2"));
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var3", "val3"));
|
||||
assert_int_equal(LY_ARRAY_COUNT(vars), 3);
|
||||
assert_string_equal(vars[0].name, "var1");
|
||||
assert_string_equal(vars[0].value, "val1");
|
||||
assert_string_equal(vars[1].name, "var2");
|
||||
assert_string_equal(vars[1].value, "val2");
|
||||
assert_string_equal(vars[2].name, "var3");
|
||||
assert_string_equal(vars[2].value, "val3");
|
||||
lyxp_vars_free(vars);
|
||||
vars = NULL;
|
||||
|
||||
/* Change value of a variable. */
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "val1"));
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "val2"));
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "new_value"));
|
||||
assert_string_equal(vars[0].name, "var1");
|
||||
assert_string_equal(vars[0].value, "new_value");
|
||||
assert_string_equal(vars[1].name, "var2");
|
||||
assert_string_equal(vars[1].value, "val2");
|
||||
lyxp_vars_free(vars);
|
||||
vars = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_leafref_nodes(void **state)
|
||||
{
|
||||
struct lyd_node *tree, *iter;
|
||||
struct lyd_node_term *target_node = NULL, *leafref_node;
|
||||
const struct lyd_leafref_links_rec *rec;
|
||||
const char *schema, *data, *value;
|
||||
|
||||
ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_LINKING);
|
||||
|
||||
schema =
|
||||
"module test-data-hash {"
|
||||
" yang-version 1.1;"
|
||||
" namespace \"urn:tests:tdh\";"
|
||||
" prefix t;"
|
||||
" leaf-list ll {"
|
||||
" type string;"
|
||||
" }"
|
||||
" container c1 {"
|
||||
" leaf ref1 {"
|
||||
" type leafref {"
|
||||
" path \"../../ll\";"
|
||||
" }"
|
||||
" }"
|
||||
" }"
|
||||
" leaf ref2 {"
|
||||
" type leafref {"
|
||||
" path \"../ll\";"
|
||||
" }"
|
||||
" }"
|
||||
"}";
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data =
|
||||
"{"
|
||||
" \"test-data-hash:ll\": [\"qwe\", \"asd\"],"
|
||||
" \"test-data-hash:c1\": { \"ref1\": \"qwe\"},"
|
||||
" \"test-data-hash:ref2\": \"asd\""
|
||||
"}";
|
||||
|
||||
/* The run must not crash due to the assert that checks the hash. */
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
LY_LIST_FOR(tree, iter) {
|
||||
if (strcmp(iter->schema->name, "ll") == 0) {
|
||||
value = lyd_get_value(iter);
|
||||
if (strcmp(value, "asd") == 0) {
|
||||
target_node = (struct lyd_node_term *)iter;
|
||||
}
|
||||
}
|
||||
if (strcmp(iter->schema->name, "ref2") == 0) {
|
||||
leafref_node = (struct lyd_node_term *)iter;
|
||||
}
|
||||
}
|
||||
|
||||
/* verify state after leafref plugin validation */
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
assert_ptr_equal(rec->target_nodes[0], target_node);
|
||||
/* value modification of target */
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)target_node, "ASD"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
/* change back to original value */
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)target_node, "asd"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
/* linking the whole tree again */
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_link_node_tree(tree));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
assert_ptr_equal(rec->target_nodes[0], target_node);
|
||||
/* value modification of leafref */
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "qwe"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "asd"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
/* linking the whole tree again */
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_link_node_tree(tree));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
assert_ptr_equal(rec->target_nodes[0], target_node);
|
||||
/* freeing whole tree */
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_leafref_nodes2(void **state)
|
||||
{
|
||||
struct lyd_node *tree, *iter;
|
||||
const char *schema, *data;
|
||||
struct lyd_node_term *leafref_node = NULL;
|
||||
const struct lyd_node_term *target_node1, *target_node2;
|
||||
const struct lyd_leafref_links_rec *rec;
|
||||
|
||||
ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_LINKING);
|
||||
|
||||
schema =
|
||||
"module test-data-hash {"
|
||||
" yang-version 1.1;"
|
||||
" namespace \"urn:tests:tdh\";"
|
||||
" prefix t;"
|
||||
" list l1 {"
|
||||
" key \"l1 l2\";"
|
||||
" leaf l1 {"
|
||||
" type string;"
|
||||
" }"
|
||||
" leaf l2 {"
|
||||
" type string;"
|
||||
" }"
|
||||
" }"
|
||||
" leaf ref1 {"
|
||||
" type leafref {"
|
||||
" path \"../l1/l1\";"
|
||||
" }"
|
||||
" }"
|
||||
" leaf-list ll1 {"
|
||||
" type string;"
|
||||
" config false;"
|
||||
" }"
|
||||
" leaf ref2 {"
|
||||
" type leafref {"
|
||||
" path \"../ll1\";"
|
||||
" }"
|
||||
" config false;"
|
||||
" }"
|
||||
"}";
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data =
|
||||
"{"
|
||||
" \"test-data-hash:l1\": ["
|
||||
" {\"l1\": \"A\", \"l2\": \"B\"},"
|
||||
" {\"l1\": \"A\", \"l2\": \"C\"}"
|
||||
" ],"
|
||||
" \"test-data-hash:ref1\": \"A\","
|
||||
" \"test-data-hash:ll1\": [\"asd\", \"qwe\", \"asd\"],"
|
||||
" \"test-data-hash:ref2\": \"asd\""
|
||||
"}";
|
||||
|
||||
/* The run must not crash due to the assert that checks the hash. */
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
LY_LIST_FOR(tree, iter) {
|
||||
if (strcmp(iter->schema->name, "ref1") == 0) {
|
||||
leafref_node = (struct lyd_node_term *)iter;
|
||||
}
|
||||
}
|
||||
|
||||
/* verify state after leafref plugin validation */
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(2, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
target_node1 = rec->target_nodes[0];
|
||||
target_node2 = rec->target_nodes[1];
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node1, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node2, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
/* value modification of leafref to remove all links*/
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "qwe"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node1, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node2, &rec));
|
||||
/* linking the whole tree again */
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "A"));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_link_node_tree(tree));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(2, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node1, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node2, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
|
||||
/* verify duplicated value in leaf-list */
|
||||
LY_LIST_FOR(tree, iter) {
|
||||
if (strcmp(iter->schema->name, "ref2") == 0) {
|
||||
leafref_node = (struct lyd_node_term *)iter;
|
||||
}
|
||||
}
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(2, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
target_node1 = rec->target_nodes[0];
|
||||
target_node2 = rec->target_nodes[1];
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node1, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node2, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
/* freeing whole tree */
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_compare, setup),
|
||||
UTEST(test_compare_diff_ctx, setup),
|
||||
UTEST(test_dup, setup),
|
||||
UTEST(test_target, setup),
|
||||
UTEST(test_list_pos, setup),
|
||||
UTEST(test_first_sibling, setup),
|
||||
UTEST(test_find_path, setup),
|
||||
UTEST(test_data_hash, setup),
|
||||
UTEST(test_lyxp_vars),
|
||||
UTEST(test_data_leafref_nodes),
|
||||
UTEST(test_data_leafref_nodes2),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1638
tests/utests/data/test_tree_data_sorted.c
Normal file
1638
tests/utests/data/test_tree_data_sorted.c
Normal file
File diff suppressed because it is too large
Load diff
1541
tests/utests/data/test_validation.c
Normal file
1541
tests/utests/data/test_validation.c
Normal file
File diff suppressed because it is too large
Load diff
205
tests/utests/extensions/test_metadata.c
Normal file
205
tests/utests/extensions/test_metadata.c
Normal file
|
@ -0,0 +1,205 @@
|
|||
/**
|
||||
* @file test_metadata.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief unit tests for Metadata extension (annotation) support
|
||||
*
|
||||
* Copyright (c) 2019 - 2022 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 "libyang.h"
|
||||
#include "plugins_exts.h"
|
||||
#include "plugins_exts/metadata.h"
|
||||
|
||||
static void
|
||||
test_yang(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lysc_ext_instance *e;
|
||||
const char *units;
|
||||
|
||||
const char *data = "module a {yang-version 1.1; namespace urn:tests:extensions:metadata:a; prefix a;"
|
||||
"import ietf-yang-metadata {prefix md;}"
|
||||
"feature f;"
|
||||
"md:annotation x {"
|
||||
" description \"test\";"
|
||||
" if-feature f;"
|
||||
" reference \"test\";"
|
||||
" status \"current\";"
|
||||
" type uint8;"
|
||||
" units meters;"
|
||||
"}}";
|
||||
const char *feats[] = {"f", NULL};
|
||||
|
||||
UTEST_ADD_MODULE(data, LYS_IN_YANG, feats, &mod);
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(mod->compiled->exts));
|
||||
e = &mod->compiled->exts[0];
|
||||
assert_non_null(e->compiled);
|
||||
assert_non_null(e->substmts);
|
||||
lyplg_ext_get_storage(e, LY_STMT_UNITS, sizeof units, (const void **)&units);
|
||||
assert_string_equal("meters", units);
|
||||
|
||||
/* invalid */
|
||||
/* missing mandatory type substatement */
|
||||
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
|
||||
"import ietf-yang-metadata {prefix md;}"
|
||||
"md:annotation aa;}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Missing mandatory keyword \"type\" as a child of \"md:annotation aa\".",
|
||||
"/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* not allowed substatement */
|
||||
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
|
||||
"import ietf-yang-metadata {prefix md;}"
|
||||
"md:annotation aa {default x;}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Invalid keyword \"default\" as a child of \"md:annotation aa\" extension instance.",
|
||||
"/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* invalid cardinality of units substatement */
|
||||
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
|
||||
"import ietf-yang-metadata {prefix md;}"
|
||||
"md:annotation aa {type string; units x; units y;}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Duplicate keyword \"units\".", "/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* invalid cardinality of status substatement */
|
||||
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
|
||||
"import ietf-yang-metadata {prefix md;}"
|
||||
"md:annotation aa {type string; status current; status obsolete;}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Duplicate keyword \"status\".", "/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* invalid cardinality of status substatement */
|
||||
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
|
||||
"import ietf-yang-metadata {prefix md;}"
|
||||
"md:annotation aa {type string; type uint8;}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Duplicate keyword \"type\".", "/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* duplication of the same annotation */
|
||||
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
|
||||
"import ietf-yang-metadata {prefix md;}"
|
||||
"md:annotation aa {type string;} md:annotation aa {type uint8;}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Extension md:annotation is instantiated multiple times.",
|
||||
"/aa:{extension='md:annotation'}/aa", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_yin(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lysc_ext_instance *e;
|
||||
const char *data, *units;
|
||||
|
||||
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"a\">\n"
|
||||
"<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:a\"/><prefix value=\"a\"/>\n"
|
||||
"<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
|
||||
"<feature name=\"f\"/>\n"
|
||||
"<md:annotation name=\"x\">\n"
|
||||
" <description><text>test</text></description>\n"
|
||||
" <reference><text>test</text></reference>\n"
|
||||
" <if-feature name=\"f\"/>\n"
|
||||
" <status value=\"current\"/>\n"
|
||||
" <type name=\"uint8\"/>\n"
|
||||
" <units name=\"meters\"/>\n"
|
||||
"</md:annotation></module>";
|
||||
const char *feats[] = {"f", NULL};
|
||||
|
||||
UTEST_ADD_MODULE(data, LYS_IN_YIN, feats, &mod);
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(mod->compiled->exts));
|
||||
e = &mod->compiled->exts[0];
|
||||
assert_non_null(e->compiled);
|
||||
assert_non_null(e->substmts);
|
||||
lyplg_ext_get_storage(e, LY_STMT_UNITS, sizeof units, (const void **)&units);
|
||||
assert_string_equal("meters", units);
|
||||
|
||||
/* invalid */
|
||||
/* missing mandatory type substatement */
|
||||
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
|
||||
"<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
|
||||
"<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
|
||||
"<md:annotation name=\"aa\"/>\n"
|
||||
"</module>";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Missing mandatory keyword \"type\" as a child of \"md:annotation aa\".",
|
||||
"/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* not allowed substatement */
|
||||
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
|
||||
"<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
|
||||
"<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
|
||||
"<md:annotation name=\"aa\">\n"
|
||||
" <default value=\"x\"/>\n"
|
||||
"</md:annotation></module>";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
|
||||
CHECK_LOG_CTX("Invalid keyword \"default\" as a child of \"md:annotation aa\" extension instance.",
|
||||
"/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* invalid cardinality of units substatement */
|
||||
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
|
||||
"<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
|
||||
"<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
|
||||
"<md:annotation name=\"aa\">\n"
|
||||
" <type name=\"string\"/>\n"
|
||||
" <units name=\"x\"/>\n"
|
||||
" <units name=\"y\"/>\n"
|
||||
"</md:annotation></module>";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
|
||||
CHECK_LOG_CTX("Duplicate keyword \"units\".", "/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* invalid cardinality of status substatement */
|
||||
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
|
||||
"<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
|
||||
"<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
|
||||
"<md:annotation name=\"aa\">\n"
|
||||
" <type name=\"string\"/>\n"
|
||||
" <status value=\"current\"/>\n"
|
||||
" <status value=\"obsolete\"/>\n"
|
||||
"</md:annotation></module>";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
|
||||
CHECK_LOG_CTX("Duplicate keyword \"status\".", "/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* invalid cardinality of status substatement */
|
||||
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
|
||||
"<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
|
||||
"<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
|
||||
"<md:annotation name=\"aa\">\n"
|
||||
" <type name=\"string\"/>\n"
|
||||
" <type name=\"uint8\"/>\n"
|
||||
"</md:annotation></module>";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
|
||||
CHECK_LOG_CTX("Duplicate keyword \"type\".", "/aa:{extension='md:annotation'}/aa", 0);
|
||||
|
||||
/* duplication of the same annotation */
|
||||
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
|
||||
"<yang-version value=\"1.1\"/><namespace uri=\"urn:tests:extensions:metadata:aa\"/><prefix value=\"aa\"/>\n"
|
||||
"<import module=\"ietf-yang-metadata\"><prefix value=\"md\"/></import>\n"
|
||||
"<md:annotation name=\"aa\">\n"
|
||||
" <type name=\"string\"/>\n"
|
||||
"</md:annotation><md:annotation name=\"aa\">\n"
|
||||
" <type name=\"uint8\"/>\n"
|
||||
"</md:annotation></module>";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Extension md:annotation is instantiated multiple times.",
|
||||
"/aa:{extension='md:annotation'}/aa", 0);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_yang),
|
||||
UTEST(test_yin),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
124
tests/utests/extensions/test_nacm.c
Normal file
124
tests/utests/extensions/test_nacm.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* @file test_nacm.c
|
||||
* @author: Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief unit tests for NACM extensions support
|
||||
*
|
||||
* Copyright (c) 2019-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 "libyang.h"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
UTEST_SETUP;
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-acm", "2018-02-14", NULL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_deny_all(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lysc_node_container *cont;
|
||||
struct lysc_node_leaf *leaf;
|
||||
struct lysc_ext_instance *e;
|
||||
|
||||
const char *data = "module a {yang-version 1.1; namespace urn:tests:extensions:nacm:a; prefix en;"
|
||||
"import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}"
|
||||
"container a { nacm:default-deny-all; leaf aa {type string;}}"
|
||||
"leaf b {type string;}}";
|
||||
|
||||
/* valid data */
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
|
||||
assert_non_null(cont = (struct lysc_node_container *)mod->compiled->data);
|
||||
assert_non_null(leaf = (struct lysc_node_leaf *)cont->child);
|
||||
assert_non_null(e = &cont->exts[0]);
|
||||
assert_int_equal(LY_ARRAY_COUNT(cont->exts), 1);
|
||||
assert_int_equal(LY_ARRAY_COUNT(leaf->exts), 1); /* NACM extensions inherit */
|
||||
assert_ptr_equal(e->def, leaf->exts[0].def);
|
||||
assert_int_equal(1, *((uint8_t *)e->compiled)); /* plugin's value for default-deny-all */
|
||||
assert_null(cont->next->exts);
|
||||
|
||||
/* ignored - valid with warning */
|
||||
data = "module b {yang-version 1.1; namespace urn:tests:extensions:nacm:b; prefix en;"
|
||||
"import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}"
|
||||
"nacm:default-deny-all;}";
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": "
|
||||
"Extension nacm:default-deny-all is allowed only in a data nodes, but it is placed in \"module\" statement.",
|
||||
"/b:{extension='nacm:default-deny-all'}", 0);
|
||||
|
||||
/* invalid */
|
||||
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:nacm:aa; prefix en;"
|
||||
"import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}"
|
||||
"leaf l { type string; nacm:default-deny-all; nacm:default-deny-write;}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": "
|
||||
"Extension nacm:default-deny-write is mixed with nacm:default-deny-all.",
|
||||
"/aa:l/{extension='nacm:default-deny-all'}", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_deny_write(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lysc_node_container *cont;
|
||||
struct lysc_node_leaf *leaf;
|
||||
struct lysc_ext_instance *e;
|
||||
|
||||
const char *data = "module a {yang-version 1.1; namespace urn:tests:extensions:nacm:a; prefix en;"
|
||||
"import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}"
|
||||
"container a { nacm:default-deny-write; leaf aa {type string;}}"
|
||||
"leaf b {type string;}}";
|
||||
|
||||
/* valid data */
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
|
||||
assert_non_null(cont = (struct lysc_node_container *)mod->compiled->data);
|
||||
assert_non_null(leaf = (struct lysc_node_leaf *)cont->child);
|
||||
assert_non_null(e = &cont->exts[0]);
|
||||
assert_int_equal(LY_ARRAY_COUNT(cont->exts), 1);
|
||||
assert_int_equal(LY_ARRAY_COUNT(leaf->exts), 1); /* NACM extensions inherit */
|
||||
assert_ptr_equal(e->def, leaf->exts[0].def);
|
||||
assert_int_equal(2, *((uint8_t *)e->compiled)); /* plugin's value for default-deny-write */
|
||||
|
||||
/* ignored - valid with warning */
|
||||
data = "module b {yang-version 1.1; namespace urn:tests:extensions:nacm:b; prefix en;"
|
||||
"import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}"
|
||||
"notification notif {nacm:default-deny-write;}}";
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": "
|
||||
"Extension nacm:default-deny-write is not allowed in notification statement.",
|
||||
"/b:notif/{extension='nacm:default-deny-write'}", 0);
|
||||
|
||||
/* invalid */
|
||||
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:nacm:aa; prefix en;"
|
||||
"import ietf-netconf-acm {revision-date 2018-02-14; prefix nacm;}"
|
||||
"leaf l { type string; nacm:default-deny-write; nacm:default-deny-write;}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": "
|
||||
"Extension nacm:default-deny-write is instantiated multiple times.",
|
||||
"/aa:l/{extension='nacm:default-deny-write'}", 0);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_deny_all, setup),
|
||||
UTEST(test_deny_write, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1657
tests/utests/extensions/test_schema_mount.c
Normal file
1657
tests/utests/extensions/test_schema_mount.c
Normal file
File diff suppressed because it is too large
Load diff
255
tests/utests/extensions/test_structure.c
Normal file
255
tests/utests/extensions/test_structure.c
Normal file
|
@ -0,0 +1,255 @@
|
|||
/**
|
||||
* @file test_structure.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief unit tests for structure extensions support
|
||||
*
|
||||
* Copyright (c) 2022 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 "libyang.h"
|
||||
|
||||
static void
|
||||
test_schema(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lysc_ext_instance *e;
|
||||
char *printed = NULL;
|
||||
const char *data, *info;
|
||||
|
||||
/* valid data */
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix a;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"sx:structure struct {"
|
||||
" must \"/n2/l\";"
|
||||
" status deprecated;"
|
||||
" description desc;"
|
||||
" reference no-ref;"
|
||||
" typedef my-type {type string;}"
|
||||
" grouping my-grp {leaf gl {type my-type;}}"
|
||||
" container n1 {leaf l {config false; type uint32;}}"
|
||||
" list n2 {leaf l {type leafref {path /n1/l;}}}"
|
||||
" uses my-grp;"
|
||||
"}}";
|
||||
|
||||
UTEST_ADD_MODULE(data, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(e = mod->compiled->exts);
|
||||
assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
|
||||
|
||||
/* valid augment data */
|
||||
data = "module b {yang-version 1.1; namespace urn:tests:extensions:structure:b; prefix b;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"import a {prefix a;}"
|
||||
"sx:augment-structure \"/a:struct/a:n1\" {"
|
||||
" status obsolete;"
|
||||
" reference none;"
|
||||
" leaf aug-leaf {type string;}"
|
||||
"}}";
|
||||
|
||||
UTEST_ADD_MODULE(data, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(e = mod->compiled->exts);
|
||||
assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
|
||||
|
||||
/* yang compiled print */
|
||||
info = "module a {\n"
|
||||
" namespace \"urn:tests:extensions:structure:a\";\n"
|
||||
" prefix a;\n"
|
||||
"\n"
|
||||
" ietf-yang-structure-ext:structure \"struct\" {\n"
|
||||
" must \"/n2/l\";\n"
|
||||
" status deprecated;\n"
|
||||
" description\n"
|
||||
" \"desc\";\n"
|
||||
" reference\n"
|
||||
" \"no-ref\";\n"
|
||||
" container n1 {\n"
|
||||
" status deprecated;\n"
|
||||
" leaf l {\n"
|
||||
" type uint32;\n"
|
||||
" status deprecated;\n"
|
||||
" }\n"
|
||||
" leaf aug-leaf {\n"
|
||||
" type string;\n"
|
||||
" status obsolete;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" list n2 {\n"
|
||||
" min-elements 0;\n"
|
||||
" max-elements 4294967295;\n"
|
||||
" ordered-by user;\n"
|
||||
" status deprecated;\n"
|
||||
" leaf l {\n"
|
||||
" type leafref {\n"
|
||||
" path \"/n1/l\";\n"
|
||||
" require-instance true;\n"
|
||||
" type uint32;\n"
|
||||
" }\n"
|
||||
" status deprecated;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" leaf gl {\n"
|
||||
" type string;\n"
|
||||
" status deprecated;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
assert_non_null(mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "a"));
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
|
||||
assert_string_equal(printed, info);
|
||||
free(printed);
|
||||
|
||||
info = "module b {\n"
|
||||
" namespace \"urn:tests:extensions:structure:b\";\n"
|
||||
" prefix b;\n"
|
||||
"\n"
|
||||
" ietf-yang-structure-ext:augment-structure \"/a:struct/a:n1\";\n"
|
||||
"}\n";
|
||||
|
||||
assert_non_null(mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "b"));
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
|
||||
assert_string_equal(printed, info);
|
||||
free(printed);
|
||||
|
||||
/* no substatements */
|
||||
data = "module c {yang-version 1.1; namespace urn:tests:extensions:structure:c; prefix c;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"sx:structure struct;}";
|
||||
info = "module c {\n"
|
||||
" namespace \"urn:tests:extensions:structure:c\";\n"
|
||||
" prefix c;\n"
|
||||
"\n"
|
||||
" ietf-yang-structure-ext:structure \"struct\";\n"
|
||||
"}\n";
|
||||
|
||||
UTEST_ADD_MODULE(data, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(e = mod->compiled->exts);
|
||||
assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
|
||||
assert_string_equal(printed, info);
|
||||
free(printed);
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema_invalid(void **state)
|
||||
{
|
||||
const char *data;
|
||||
|
||||
/* structure */
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"sx:structure struct {import yang;}}";
|
||||
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid keyword \"import\" as a child of \"sx:structure struct\" extension instance.",
|
||||
"/a:{extension='sx:structure'}/struct", 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"container b { sx:structure struct { container x { leaf x {type string;}}}}}";
|
||||
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": "
|
||||
"Extension sx:structure must not be used as a non top-level statement in \"container\" statement.",
|
||||
"/a:b/{extension='sx:structure'}/struct", 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"sx:structure { container x { leaf x {type string;}}}}";
|
||||
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
|
||||
CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Extension instance \"sx:structure\" missing argument element \"name\".", NULL, 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"sx:structure struct { container x { leaf x {type string;}}}"
|
||||
"sx:structure struct { container y { leaf y {type string;}}}}";
|
||||
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": Extension sx:structure is instantiated multiple times.",
|
||||
"/a:{extension='sx:structure'}/struct", 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"sx:structure struct { container x { leaf x {type string;}}}"
|
||||
"choice struct { container y { leaf y {type string;}}}}";
|
||||
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": Extension sx:structure collides with a choice with the same identifier.",
|
||||
"/a:{extension='sx:structure'}/struct", 0);
|
||||
|
||||
/* augment-structure */
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix a;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"sx:structure struct {"
|
||||
" container n1 {leaf l {config false; type uint32;}}"
|
||||
" list n2 {leaf l {type string;}}"
|
||||
"}"
|
||||
"container n1 {leaf l2 {type uint8;}}}";
|
||||
UTEST_ADD_MODULE(data, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data = "module b {yang-version 1.1; namespace urn:tests:extensions:structure:b; prefix b;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"import a {prefix a;}"
|
||||
"sx:augment-structure \"/a:n1\" {"
|
||||
" leaf aug-leaf {type string;}"
|
||||
"}}";
|
||||
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("Augment extension target node \"/a:n1\" from module \"b\" was not found.",
|
||||
"/b:{extension='sx:augment-structure'}/{augment='/a:n1'}", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_parse(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lysc_ext_instance *e;
|
||||
struct lyd_node *tree = NULL;
|
||||
const char *yang;
|
||||
const char *xml = "<x xmlns=\"urn:tests:extensions:structure:a\">"
|
||||
"<x>test</x>"
|
||||
"<x2 xmlns=\"urn:tests:extensions:structure:b\">25</x2>"
|
||||
"</x>";
|
||||
const char *json = "{\"a:x\":{\"x\":\"test\",\"b:x2\":25}}";
|
||||
|
||||
yang = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix a;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"sx:structure struct { container x { leaf x { type string;}}}}";
|
||||
UTEST_ADD_MODULE(yang, LYS_IN_YANG, NULL, &mod);
|
||||
|
||||
yang = "module b {yang-version 1.1; namespace urn:tests:extensions:structure:b; prefix b;"
|
||||
"import ietf-yang-structure-ext {prefix sx;}"
|
||||
"import a {prefix a;}"
|
||||
"sx:augment-structure \"/a:struct/a:x\" {"
|
||||
" leaf x2 {type uint32;}"
|
||||
"}}";
|
||||
UTEST_ADD_MODULE(yang, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* get extension after recompilation */
|
||||
assert_non_null(e = mod->compiled->exts);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(xml, &UTEST_IN));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_ext_data(e, NULL, UTEST_IN, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
|
||||
CHECK_LYD_STRING_PARAM(tree, xml, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
lyd_free_all(tree);
|
||||
|
||||
ly_in_memory(UTEST_IN, json);
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_ext_data(e, NULL, UTEST_IN, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
|
||||
CHECK_LYD_STRING_PARAM(tree, json, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_schema),
|
||||
UTEST(test_schema_invalid),
|
||||
UTEST(test_parse),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
267
tests/utests/extensions/test_yangdata.c
Normal file
267
tests/utests/extensions/test_yangdata.c
Normal file
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* @file test_yangdata.c
|
||||
* @author: Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief unit tests for yang-data extensions support
|
||||
*
|
||||
* Copyright (c) 2019-2021 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 "libyang.h"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
UTEST_SETUP;
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-restconf", "2017-01-26", NULL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lysc_ext_instance *e;
|
||||
char *printed = NULL;
|
||||
const char *data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"feature x;"
|
||||
"rc:yang-data template { container x { list l { leaf x { type string;}} leaf y {if-feature x; type string; config false;}}}}";
|
||||
const char *info = "module a {\n"
|
||||
" namespace \"urn:tests:extensions:yangdata:a\";\n"
|
||||
" prefix self;\n\n"
|
||||
" ietf-restconf:yang-data \"template\" {\n"
|
||||
" container x {\n"
|
||||
" status current;\n"
|
||||
" list l {\n" /* no key */
|
||||
" min-elements 0;\n"
|
||||
" max-elements 4294967295;\n"
|
||||
" ordered-by user;\n"
|
||||
" status current;\n"
|
||||
" leaf x {\n"
|
||||
" type string;\n"
|
||||
" status current;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" leaf y {\n" /* config and if-feature are ignored */
|
||||
" type string;\n"
|
||||
" status current;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/* valid data */
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
|
||||
assert_non_null(e = mod->compiled->exts);
|
||||
assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
|
||||
assert_string_equal(printed, info);
|
||||
free(printed);
|
||||
|
||||
data = "module c {yang-version 1.1; namespace urn:tests:extensions:yangdata:c; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"grouping g { choice ch { container a {presence a; config false;} container b {presence b; config true;}}}"
|
||||
"rc:yang-data template { uses g;}}";
|
||||
info = "module c {\n"
|
||||
" namespace \"urn:tests:extensions:yangdata:c\";\n"
|
||||
" prefix self;\n\n"
|
||||
" ietf-restconf:yang-data \"template\" {\n"
|
||||
" choice ch {\n"
|
||||
" status current;\n"
|
||||
" case a {\n"
|
||||
" status current;\n"
|
||||
" container a {\n"
|
||||
" presence \"true\";\n"
|
||||
" status current;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" case b {\n"
|
||||
" status current;\n"
|
||||
" container b {\n"
|
||||
" presence \"true\";\n"
|
||||
" status current;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
|
||||
assert_non_null(e = mod->compiled->exts);
|
||||
assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 1);
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
|
||||
assert_string_equal(printed, info);
|
||||
free(printed);
|
||||
|
||||
/* ignored - valid with warning */
|
||||
data = "module b {yang-version 1.1; namespace urn:tests:extensions:yangdata:b; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"container b { rc:yang-data template { container x { leaf x {type string;}}}}}";
|
||||
info = "module b {\n"
|
||||
" namespace \"urn:tests:extensions:yangdata:b\";\n"
|
||||
" prefix self;\n\n"
|
||||
" container b {\n"
|
||||
" config true;\n"
|
||||
" status current;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
|
||||
assert_null(mod->compiled->exts);
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
|
||||
"Extension rc:yang-data is ignored since it appears as a non top-level statement in \"container\" statement.",
|
||||
"/b:b/{extension='rc:yang-data'}/template", 0);
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
|
||||
assert_string_equal(printed, info);
|
||||
free(printed);
|
||||
|
||||
/* sama data nodes name, but not conflicting */
|
||||
data = "module d {yang-version 1.1; namespace urn:tests:extensions:yangdata:d; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"leaf d { type string;}"
|
||||
"rc:yang-data template1 { container d {presence d;}}"
|
||||
"rc:yang-data template2 { container d {presence d;}}}";
|
||||
info = "module d {\n"
|
||||
" namespace \"urn:tests:extensions:yangdata:d\";\n"
|
||||
" prefix self;\n\n"
|
||||
" ietf-restconf:yang-data \"template1\" {\n"
|
||||
" container d {\n"
|
||||
" presence \"true\";\n"
|
||||
" status current;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" ietf-restconf:yang-data \"template2\" {\n"
|
||||
" container d {\n"
|
||||
" presence \"true\";\n"
|
||||
" status current;\n"
|
||||
" }\n"
|
||||
" }\n\n"
|
||||
" leaf d {\n"
|
||||
" type string;\n"
|
||||
" config true;\n"
|
||||
" status current;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, &mod));
|
||||
assert_non_null(e = mod->compiled->exts);
|
||||
assert_int_equal(LY_ARRAY_COUNT(mod->compiled->exts), 2);
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
|
||||
assert_string_equal(printed, info);
|
||||
free(printed);
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema_invalid(void **state)
|
||||
{
|
||||
const char *data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data template { leaf x {type string;}}}";
|
||||
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Invalid keyword \"leaf\" as a child of \"rc:yang-data template\" extension instance.",
|
||||
"/a:{extension='rc:yang-data'}/template", 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data template { choice x { leaf x {type string;}}}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
|
||||
"Extension rc:yang-data is instantiated with leaf top level data node (inside a choice), "
|
||||
"but only a single container data node is allowed.", "/a:{extension='rc:yang-data'}/template", 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data template { choice x { case x { container z {presence ppp;} leaf x {type string;}}}}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
|
||||
"Extension rc:yang-data is instantiated with multiple top level data nodes (inside a single choice's case), "
|
||||
"but only a single container data node is allowed.", "/a:{extension='rc:yang-data'}/template", 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data template { container x { leaf x {type string;}} container y { leaf y {type string;}}}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
|
||||
"Extension rc:yang-data is instantiated with multiple top level data nodes, "
|
||||
"but only a single container data node is allowed.", "/a:{extension='rc:yang-data'}/template", 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data template;}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
|
||||
"Extension rc:yang-data is instantiated without any top level data node, "
|
||||
"but exactly one container data node is expected.", "/a:{extension='rc:yang-data'}/template", 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data { container x { leaf x {type string;}}}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL, 0);
|
||||
CHECK_LOG_CTX("Extension instance \"rc:yang-data\" missing argument element \"name\".", NULL, 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data template { container x { leaf x {type string;}}}"
|
||||
"rc:yang-data template { container y { leaf y {type string;}}}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
|
||||
"Extension rc:yang-data is instantiated multiple times.", "/a:{extension='rc:yang-data'}/template", 0);
|
||||
|
||||
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"grouping t { leaf-list x {type string;}}"
|
||||
"rc:yang-data template { uses t;}}";
|
||||
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
|
||||
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
|
||||
"Extension rc:yang-data is instantiated with leaf-list top level data node, "
|
||||
"but only a single container data node is allowed.", "/a:{extension='rc:yang-data'}/template", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_parse(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lysc_ext_instance *e;
|
||||
struct lyd_node *tree = NULL;
|
||||
const char *schema = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data template { container x { leaf x { type string;}}}}";
|
||||
const char *xml = "<x xmlns=\"urn:tests:extensions:yangdata:a\"><x>test</x></x>";
|
||||
const char *json = "{\"a:x\":{\"x\":\"test\"}}";
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, &mod));
|
||||
assert_non_null(e = mod->compiled->exts);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(xml, &UTEST_IN));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_ext_data(e, NULL, UTEST_IN, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
CHECK_LYD_STRING_PARAM(tree, xml, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
lyd_free_all(tree);
|
||||
|
||||
ly_in_memory(UTEST_IN, json);
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_ext_data(e, NULL, UTEST_IN, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
CHECK_LYD_STRING_PARAM(tree, json, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_schema, setup),
|
||||
UTEST(test_schema_invalid, setup),
|
||||
UTEST(test_parse, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1625
tests/utests/node/list.c
Normal file
1625
tests/utests/node/list.c
Normal file
File diff suppressed because it is too large
Load diff
394
tests/utests/restriction/test_pattern.c
Normal file
394
tests/utests/restriction/test_pattern.c
Normal file
|
@ -0,0 +1,394 @@
|
|||
/**
|
||||
* @file test_pattern.c
|
||||
* @author Radek Iša <isa@cesnet.cz>
|
||||
* @brief test for int8 values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* GLOBAL INCLUDE HEADERS */
|
||||
#include <ctype.h>
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
|
||||
#define MODULE_CREATE_YIN(MOD_NAME, NODES) \
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
|
||||
"<module name=\"" MOD_NAME "\"\n" \
|
||||
" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" \
|
||||
" xmlns:pref=\"urn:tests:" MOD_NAME "\">\n" \
|
||||
" <yang-version value=\"1.1\"/>\n" \
|
||||
" <namespace uri=\"urn:tests:" MOD_NAME "\"/>\n" \
|
||||
" <prefix value=\"pref\"/>\n" \
|
||||
NODES \
|
||||
"</module>\n"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_JSON(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "{\"" MOD_NAME ":port\":" DATA "}"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_JSON(MOD_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "{\"" MOD_NAME ":port\":" DATA "}"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema_yang(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lysc_node_leaf *lysc_leaf;
|
||||
struct lysp_node_leaf *lysp_leaf;
|
||||
struct lysc_pattern *pattern;
|
||||
|
||||
schema = MODULE_CREATE_YANG("T0", "leaf port {type string {"
|
||||
"pattern \"[A-Za-z]*\"{"
|
||||
"description \"pattern description\";"
|
||||
"error-app-tag \"pattern err-apt-tag\";"
|
||||
"error-message \"pattern error message\";}}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *) mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
|
||||
"pattern error message", "[A-Za-z]*", 0, 0, NULL);
|
||||
lysp_leaf = (void *) mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "string", 0, 1, 1, 0, 0, 0);
|
||||
CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Za-z]*", "pattern description",
|
||||
"pattern err-apt-tag", "pattern error message", 0, NULL);
|
||||
|
||||
/* heredity */
|
||||
schema = MODULE_CREATE_YANG("T1", "typedef my_type {type string {"
|
||||
"pattern \"[A-Za-z]*\"{"
|
||||
"description \"pattern description\";"
|
||||
"error-app-tag \"pattern err-apt-tag\";"
|
||||
"error-message \"pattern error message\";}}}"
|
||||
"leaf port {type my_type;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *) mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
|
||||
"pattern error message", "[A-Za-z]*", 0, 0, NULL);
|
||||
lysp_leaf = (void *) mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
|
||||
|
||||
/* heredity new pattern */
|
||||
schema = MODULE_CREATE_YANG("T2", "typedef my_type {type string {"
|
||||
"pattern \"[A-Za-z]*\"{"
|
||||
"description \"pattern description\";"
|
||||
"error-app-tag \"pattern err-apt-tag\";"
|
||||
"error-message \"pattern error message\";}}}"
|
||||
"leaf port {type my_type{pattern \"[A-Z]*\";}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *) mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
|
||||
"pattern error message", "[A-Za-z]*", 0, 0, NULL);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1];
|
||||
CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[A-Z]*", 0, 0, NULL);
|
||||
lysp_leaf = (void *) mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0);
|
||||
CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Z]*", NULL, NULL, NULL, 0, NULL);
|
||||
|
||||
/* heredity new pattern */
|
||||
schema = MODULE_CREATE_YANG("T3", "typedef my_type {type string {"
|
||||
"pattern \"[A-Za-z]*\"{"
|
||||
" description \"pattern 0 description\";"
|
||||
" error-app-tag \"pattern 0 err-apt-tag\";"
|
||||
" error-message \"pattern 0 error message\";}}}"
|
||||
"leaf port {type my_type{pattern \"[A-Z]*\"{"
|
||||
" description \"pattern 1 description\";"
|
||||
" error-app-tag \"pattern 1 err-apt-tag\";"
|
||||
" error-message \"pattern 1 error message\";"
|
||||
"}}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *) mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern 0 description", "pattern 0 err-apt-tag",
|
||||
"pattern 0 error message", "[A-Za-z]*", 0, 0, NULL);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern 1 description", "pattern 1 err-apt-tag",
|
||||
"pattern 1 error message", "[A-Z]*", 0, 0, NULL);
|
||||
lysp_leaf = (void *) mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0);
|
||||
CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Z]*", "pattern 1 description",
|
||||
"pattern 1 err-apt-tag", "pattern 1 error message", 0, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema_yin(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lysc_node_leaf *lysc_leaf;
|
||||
struct lysp_node_leaf *lysp_leaf;
|
||||
struct lysc_pattern *pattern;
|
||||
|
||||
schema = MODULE_CREATE_YIN("T0", "<leaf name=\"port\"> <type name=\"string\">"
|
||||
"<pattern value=\"[A-Za-z]*\">"
|
||||
" <description><text>pattern description</text></description>"
|
||||
" <error-app-tag value=\"pattern err-apt-tag\"/>"
|
||||
" <error-message> <value>pattern error message</value></error-message>"
|
||||
"</pattern></type></leaf>");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *) mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
|
||||
"pattern error message", "[A-Za-z]*", 0, 0, NULL);
|
||||
lysp_leaf = (void *) mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "string", 0, 1, 1, 0, 0, 0);
|
||||
CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Za-z]*", "pattern description",
|
||||
"pattern err-apt-tag", "pattern error message", 0, NULL);
|
||||
|
||||
/* heredity */
|
||||
schema = MODULE_CREATE_YIN("T1", "<typedef name=\"my_type\"> <type name=\"string\">"
|
||||
"<pattern value=\"[A-Za-z]*\">"
|
||||
" <description><text>pattern description</text></description>"
|
||||
" <error-app-tag value=\"pattern err-apt-tag\"/>"
|
||||
" <error-message><value>pattern error message</value></error-message>"
|
||||
"</pattern></type></typedef>"
|
||||
"<leaf name=\"port\"><type name=\"my_type\"/></leaf>");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *) mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
|
||||
"pattern error message", "[A-Za-z]*", 0, 0, NULL);
|
||||
lysp_leaf = (void *) mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
|
||||
|
||||
/* heredity new pattern */
|
||||
schema = MODULE_CREATE_YIN("T2", "<typedef name=\"my_type\"> <type name=\"string\">"
|
||||
"<pattern value=\"[A-Za-z]*\">"
|
||||
" <description><text>pattern description</text></description>"
|
||||
" <error-app-tag value=\"pattern err-apt-tag\"/>"
|
||||
" <error-message><value>pattern error message</value></error-message>"
|
||||
"</pattern></type></typedef>"
|
||||
"<leaf name=\"port\"> <type name=\"my_type\"><pattern value=\"[A-Z]*\"/>"
|
||||
"</type></leaf>");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *) mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern description", "pattern err-apt-tag",
|
||||
"pattern error message", "[A-Za-z]*", 0, 0, NULL);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1];
|
||||
CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[A-Z]*", 0, 0, NULL);
|
||||
lysp_leaf = (void *) mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0);
|
||||
CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Z]*", NULL, NULL, NULL, 0, NULL);
|
||||
|
||||
/* heredity new pattern */
|
||||
schema = MODULE_CREATE_YIN("T3", "<typedef name=\"my_type\"> <type name=\"string\">"
|
||||
"<pattern value=\"[A-Za-z]*\">"
|
||||
" <description> <text>pattern 0 description</text></description>"
|
||||
" <error-app-tag value=\"pattern 0 err-apt-tag\"/>"
|
||||
" <error-message> <value>pattern 0 error message</value></error-message>"
|
||||
"</pattern></type></typedef>"
|
||||
"<leaf name=\"port\"> <type name=\"my_type\">"
|
||||
"<pattern value=\"[A-Z]*\">"
|
||||
" <description><text>pattern 1 description</text></description>"
|
||||
" <error-app-tag value=\"pattern 1 err-apt-tag\"/>"
|
||||
" <error-message><value>pattern 1 error message</value></error-message>"
|
||||
"</pattern></type></leaf>");
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *) mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern 0 description", "pattern 0 err-apt-tag",
|
||||
"pattern 0 error message", "[A-Za-z]*", 0, 0, NULL);
|
||||
pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1];
|
||||
CHECK_LYSC_PATTERN(pattern, "pattern 1 description", "pattern 1 err-apt-tag",
|
||||
"pattern 1 error message", "[A-Z]*", 0, 0, NULL);
|
||||
lysp_leaf = (void *) mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0);
|
||||
CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[A-Z]*", "pattern 1 description",
|
||||
"pattern 1 err-apt-tag", "pattern 1 error message", 0, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema_print(void **state)
|
||||
{
|
||||
const char *schema_yang, *schema_yin;
|
||||
char *printed;
|
||||
struct lys_module *mod;
|
||||
|
||||
/* test print yang to yin */
|
||||
schema_yang = MODULE_CREATE_YANG("PRINT0", "leaf port {type string {"
|
||||
"pattern \"[A-Z]*\"{"
|
||||
"description \"desc < \";"
|
||||
"error-app-tag \"err-apt-tag <\";"
|
||||
"error-message \"error message <\";}}}");
|
||||
|
||||
schema_yin = MODULE_CREATE_YIN("PRINT0",
|
||||
" <leaf name=\"port\">\n"
|
||||
" <type name=\"string\">\n"
|
||||
" <pattern value=\"[A-Z]*\">\n"
|
||||
" <error-message>\n"
|
||||
" <value>error message <</value>\n"
|
||||
" </error-message>\n"
|
||||
" <error-app-tag value=\"err-apt-tag <\"/>\n"
|
||||
" <description>\n"
|
||||
" <text>desc < </text>\n"
|
||||
" </description>\n"
|
||||
" </pattern>\n"
|
||||
" </type>\n"
|
||||
" </leaf>\n");
|
||||
|
||||
UTEST_ADD_MODULE(schema_yang, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
|
||||
assert_string_equal(printed, schema_yin);
|
||||
free(printed);
|
||||
|
||||
/* test print yin to yang */
|
||||
schema_yang = MODULE_CREATE_YANG("PRINT1",
|
||||
"\n"
|
||||
" leaf port {\n"
|
||||
" type string {\n"
|
||||
" pattern \"[A-Z]*\" {\n"
|
||||
" error-message\n"
|
||||
" \"error message <\";\n"
|
||||
" error-app-tag \"err-apt-tag <\";\n"
|
||||
" description\n"
|
||||
" \"desc < \";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n");
|
||||
|
||||
schema_yin = MODULE_CREATE_YIN("PRINT1",
|
||||
" <leaf name=\"port\">\n"
|
||||
" <type name=\"string\">\n"
|
||||
" <pattern value=\"[A-Z]*\">\n"
|
||||
" <error-message>\n"
|
||||
" <value>error message <</value>\n"
|
||||
" </error-message>\n"
|
||||
" <error-app-tag value=\"err-apt-tag <\"/>\n"
|
||||
" <description>\n"
|
||||
" <text>desc < </text>\n"
|
||||
" </description>\n"
|
||||
" </pattern>\n"
|
||||
" </type>\n"
|
||||
" </leaf>\n");
|
||||
|
||||
UTEST_ADD_MODULE(schema_yin, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
|
||||
assert_string_equal(printed, schema_yang);
|
||||
free(printed);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("TPATTERN_0", "typedef my_type {type string {"
|
||||
"pattern \"[A-Za-z]*\"{"
|
||||
" description \"pattern 0 description\";"
|
||||
" error-app-tag \"pattern 0 err-apt-tag\";"
|
||||
" error-message \"pattern 0 error message\";}}}"
|
||||
"leaf port {type my_type{pattern \"[A-Z]*\"{"
|
||||
" description \"pattern 1 description\";"
|
||||
" error-app-tag \"pattern 1 err-apt-tag\";"
|
||||
" error-message \"pattern 1 error message\";"
|
||||
"}}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* test success */
|
||||
TEST_SUCCESS_XML("TPATTERN_0", "AHOJ", STRING, "AHOJ");
|
||||
/* test print error */
|
||||
TEST_ERROR_XML("TPATTERN_0", "T128");
|
||||
CHECK_LOG_CTX("pattern 0 error message", "/TPATTERN_0:port", 1);
|
||||
TEST_ERROR_XML("TPATTERN_0", "ahoj");
|
||||
CHECK_LOG_CTX("pattern 1 error message", "/TPATTERN_0:port", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_schema_yang),
|
||||
UTEST(test_schema_yin),
|
||||
UTEST(test_schema_print),
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
424
tests/utests/restriction/test_range.c
Normal file
424
tests/utests/restriction/test_range.c
Normal file
|
@ -0,0 +1,424 @@
|
|||
/**
|
||||
* @file test_range.c
|
||||
* @author Radek Iša <isa@cesnet.cz>
|
||||
* @brief test for int8 values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* GLOBAL INCLUDE HEADERS */
|
||||
#include <ctype.h>
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
|
||||
#define MODULE_CREATE_YIN(MOD_NAME, NODES) \
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
|
||||
"<module name=\"" MOD_NAME "\"\n" \
|
||||
" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" \
|
||||
" xmlns:pref=\"urn:tests:" MOD_NAME "\">\n" \
|
||||
" <yang-version value=\"1.1\"/>\n" \
|
||||
" <namespace uri=\"urn:tests:" MOD_NAME "\"/>\n" \
|
||||
" <prefix value=\"pref\"/>\n" \
|
||||
NODES \
|
||||
"</module>\n"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_JSON(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "{\"" MOD_NAME ":port\":" DATA "}"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_JSON(MOD_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "{\"" MOD_NAME ":port\":" DATA "}"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema_yang(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lysc_node_leaf *lysc_leaf;
|
||||
struct lysp_node_leaf *lysp_leaf;
|
||||
struct lysc_range *range;
|
||||
|
||||
schema = MODULE_CREATE_YANG("T0", "leaf port {type int8 {"
|
||||
"range \"0 .. 50 | 127\"{"
|
||||
"description \"description test\";"
|
||||
"error-app-tag \"err-apt-tag\";"
|
||||
"error-message \"error message\";}}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *)mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1);
|
||||
range = ((struct lysc_type_num *)lysc_leaf->type)->range;
|
||||
CHECK_LYSC_RANGE(range, "description test", "err-apt-tag", "error message", 0, 2, NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0);
|
||||
CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 50 | 127", "description test", "err-apt-tag", "error message", 0, NULL);
|
||||
|
||||
/* heredity */
|
||||
schema = MODULE_CREATE_YANG("T1", "typedef my_type {type uint16 {"
|
||||
"range \"0 .. 100\"{"
|
||||
"description \"percentage\";"
|
||||
"error-app-tag \"err-apt-tag\";"
|
||||
"error-message \"error message\";}}}"
|
||||
"leaf port {type my_type;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *)mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_UINT16, 0, 1);
|
||||
range = ((struct lysc_type_num *)lysc_leaf->type)->range;
|
||||
CHECK_LYSC_RANGE(range, "percentage", "err-apt-tag", "error message", 0, 1, NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
|
||||
|
||||
/* heredity new range */
|
||||
schema = MODULE_CREATE_YANG("T2", "typedef my_type {type uint16 {"
|
||||
"range \"0 .. 100\"{"
|
||||
"description \"percentage\";"
|
||||
"error-app-tag \"err-apt-tag\";"
|
||||
"error-message \"error message\";}}}"
|
||||
"leaf port {type my_type{range \"0 .. 20\";}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *)mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_UINT16, 0, 1);
|
||||
range = ((struct lysc_type_num *)lysc_leaf->type)->range;
|
||||
CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "my_type", 0, 0, 1, 1, 0, 0);
|
||||
|
||||
/* change */
|
||||
schema = MODULE_CREATE_YANG("T3", "typedef my_type {type uint16 {"
|
||||
"range \"0 .. 100\"{"
|
||||
"description \"percentage\";"
|
||||
"error-app-tag \"err-apt-tag\";"
|
||||
"error-message \"error message\";}}}"
|
||||
"leaf port {type my_type{"
|
||||
" range \"0 .. 50\"{"
|
||||
" description \"description 0-50\";"
|
||||
" error-app-tag \"err-apt-tag 0-50\";"
|
||||
" error-message \"error message 0-50\";}}"
|
||||
"}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *)mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_UINT16, 0, 1);
|
||||
range = ((struct lysc_type_num *)lysc_leaf->type)->range;
|
||||
CHECK_LYSC_RANGE(range, "description 0-50", "err-apt-tag 0-50", "error message 0-50", 0, 1, NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "my_type", 0, 0, 1, 1, 0, 0);
|
||||
CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 50", "description 0-50", "err-apt-tag 0-50", "error message 0-50", 0, NULL);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema_yin(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lysc_node_leaf *lysc_leaf;
|
||||
struct lysp_node_leaf *lysp_leaf;
|
||||
struct lysc_range *range;
|
||||
|
||||
schema = MODULE_CREATE_YIN("T0", "<leaf name=\"port\">"
|
||||
"<type name=\"int64\">"
|
||||
"<range value = \"0 .. 50 | 256\">"
|
||||
" <description>"
|
||||
" <text>desc</text>\n"
|
||||
" </description>\n"
|
||||
"<error-app-tag value=\"text < tag\"/>"
|
||||
" <error-message>"
|
||||
" <value>yin error message <</value>\n"
|
||||
" </error-message>\n"
|
||||
"</range>"
|
||||
"</type>"
|
||||
"</leaf>");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *)mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT64, 0, 1);
|
||||
range = ((struct lysc_type_num *)lysc_leaf->type)->range;
|
||||
CHECK_LYSC_RANGE(range, "desc", "text < tag", "yin error message <", 0, 2, NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "int64", 0, 0, 1, 1, 0, 0);
|
||||
CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 50 | 256", "desc", "text < tag", "yin error message <", 0, NULL);
|
||||
|
||||
/* heredity */
|
||||
schema = MODULE_CREATE_YIN("T1", "<typedef name=\"my_type\">"
|
||||
"<type name=\"int16\">"
|
||||
"<range value = \"0 .. 50\">"
|
||||
" <description>"
|
||||
" <text>percentage</text>\n"
|
||||
" </description>\n"
|
||||
"<error-app-tag value=\"text < tag\"/>"
|
||||
" <error-message>"
|
||||
" <value>yin error message <</value>\n"
|
||||
" </error-message>\n"
|
||||
"</range>"
|
||||
"</type>"
|
||||
"</typedef>"
|
||||
"<leaf name=\"port\"> <type name=\"my_type\"/> </leaf>");
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *)mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT16, 0, 1);
|
||||
range = ((struct lysc_type_num *)lysc_leaf->type)->range;
|
||||
CHECK_LYSC_RANGE(range, "percentage", "text < tag", "yin error message <", 0, 1, NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0);
|
||||
|
||||
/* heredity new range */
|
||||
schema = MODULE_CREATE_YIN("T2", "<typedef name=\"my_type\">"
|
||||
"<type name=\"int32\">"
|
||||
"<range value = \"0 .. 100\">"
|
||||
" <description>"
|
||||
" <text>percentage</text>\n"
|
||||
" </description>\n"
|
||||
" <error-app-tag value=\"text < tag\"/>"
|
||||
" <error-message>"
|
||||
" <value>yin error message <</value>\n"
|
||||
" </error-message>\n"
|
||||
" </range>"
|
||||
" </type>"
|
||||
"</typedef>"
|
||||
"<leaf name=\"port\"> <type name=\"my_type\">"
|
||||
" <range value = \"0 .. 50\"/>"
|
||||
"</type></leaf>");
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *)mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT32, 0, 1);
|
||||
range = ((struct lysc_type_num *)lysc_leaf->type)->range;
|
||||
CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "my_type", 0, 0, 1, 1, 0, 0);
|
||||
|
||||
/* change */
|
||||
schema = MODULE_CREATE_YIN("T3", "<typedef name=\"my_type\">"
|
||||
"<type name=\"int32\">"
|
||||
"<range value = \"0 .. 100\">"
|
||||
" <description>"
|
||||
" <text>percentage</text>\n"
|
||||
" </description>\n"
|
||||
" <error-app-tag value=\"text < tag\"/>"
|
||||
" <error-message>"
|
||||
" <value>yin error message <</value>\n"
|
||||
" </error-message>\n"
|
||||
" </range>"
|
||||
" </type>"
|
||||
"</typedef>"
|
||||
"<leaf name=\"port\"> <type name=\"my_type\">"
|
||||
" <range value = \"0 .. 50\">"
|
||||
" <description>"
|
||||
" <text>percentage 0-50</text>\n"
|
||||
" </description>\n"
|
||||
" <error-app-tag value=\"text tag 0-50\"/>"
|
||||
" <error-message>"
|
||||
" <value>yin error message 0-50</value>\n"
|
||||
" </error-message>\n"
|
||||
" </range>"
|
||||
"</type></leaf>");
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
lysc_leaf = (void *)mod->compiled->data;
|
||||
CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT32, 0, 1);
|
||||
range = ((struct lysc_type_num *)lysc_leaf->type)->range;
|
||||
CHECK_LYSC_RANGE(range, "percentage 0-50", "text tag 0-50", "yin error message 0-50", 0, 1, NULL);
|
||||
lysp_leaf = (void *)mod->parsed->data;
|
||||
CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL);
|
||||
CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "my_type", 0, 0, 1, 1, 0, 0);
|
||||
CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 50", "percentage 0-50", "text tag 0-50", "yin error message 0-50", 0, NULL);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_schema_print(void **state)
|
||||
{
|
||||
const char *schema_yang, *schema_yin;
|
||||
char *printed;
|
||||
struct lys_module *mod;
|
||||
|
||||
/* test print yang to yin */
|
||||
schema_yang = MODULE_CREATE_YANG("PRINT0", "leaf port {type int32 {"
|
||||
"range \"0 .. 50\"{"
|
||||
"description \"desc < \";"
|
||||
"error-app-tag \"err-apt-tag <\";"
|
||||
"error-message \"error message <\";}}}");
|
||||
|
||||
schema_yin = MODULE_CREATE_YIN("PRINT0",
|
||||
" <leaf name=\"port\">\n"
|
||||
" <type name=\"int32\">\n"
|
||||
" <range value=\"0 .. 50\">\n"
|
||||
" <error-message>\n"
|
||||
" <value>error message <</value>\n"
|
||||
" </error-message>\n"
|
||||
" <error-app-tag value=\"err-apt-tag <\"/>\n"
|
||||
" <description>\n"
|
||||
" <text>desc < </text>\n"
|
||||
" </description>\n"
|
||||
" </range>\n"
|
||||
" </type>\n"
|
||||
" </leaf>\n");
|
||||
|
||||
UTEST_ADD_MODULE(schema_yang, LYS_IN_YANG, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
|
||||
assert_string_equal(printed, schema_yin);
|
||||
free(printed);
|
||||
|
||||
/* test print yin to yang */
|
||||
schema_yang = MODULE_CREATE_YANG("PRINT1",
|
||||
"\n"
|
||||
" leaf port {\n"
|
||||
" type int32 {\n"
|
||||
" range \"0 .. 50\" {\n"
|
||||
" error-message\n"
|
||||
" \"error message <\";\n"
|
||||
" error-app-tag \"err-apt-tag <\";\n"
|
||||
" description\n"
|
||||
" \"desc < \";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n");
|
||||
|
||||
schema_yin = MODULE_CREATE_YIN("PRINT1",
|
||||
" <leaf name=\"port\">\n"
|
||||
" <type name=\"int32\">\n"
|
||||
" <range value=\"0 .. 50\">\n"
|
||||
" <error-message>\n"
|
||||
" <value>error message <</value>\n"
|
||||
" </error-message>\n"
|
||||
" <error-app-tag value=\"err-apt-tag <\"/>\n"
|
||||
" <description>\n"
|
||||
" <text>desc < </text>\n"
|
||||
" </description>\n"
|
||||
" </range>\n"
|
||||
" </type>\n"
|
||||
" </leaf>\n");
|
||||
|
||||
UTEST_ADD_MODULE(schema_yin, LYS_IN_YIN, NULL, &mod);
|
||||
assert_non_null(mod);
|
||||
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
|
||||
assert_string_equal(printed, schema_yang);
|
||||
free(printed);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("TRANGE_0", "leaf port {type int8 {"
|
||||
"range \"0 .. 50 | 126\"{"
|
||||
"description \"description test\";"
|
||||
"error-app-tag \"err-apt-tag\";"
|
||||
"error-message \"error message\";}}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* test success */
|
||||
TEST_SUCCESS_XML("TRANGE_0", "126", INT8, "126", 126);
|
||||
/* test print error */
|
||||
TEST_ERROR_XML("TRANGE_0", "-1");
|
||||
CHECK_LOG_CTX("error message", "/TRANGE_0:port", 1);
|
||||
TEST_ERROR_XML("TRANGE_0", "51");
|
||||
CHECK_LOG_CTX("error message", "/TRANGE_0:port", 1);
|
||||
TEST_ERROR_XML("TRANGE_0", "127");
|
||||
CHECK_LOG_CTX("error message", "/TRANGE_0:port", 1);
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("TRANGE_1", "leaf port {type uint8 {"
|
||||
"range \"30 .. 50 | 126\"{"
|
||||
"description \"description test\";"
|
||||
"error-app-tag \"err-apt-tag\";"
|
||||
"error-message \"error message\";}}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* test success */
|
||||
TEST_SUCCESS_XML("TRANGE_1", "126", UINT8, "126", 126);
|
||||
/* test print error */
|
||||
TEST_ERROR_XML("TRANGE_1", "0");
|
||||
CHECK_LOG_CTX("error message", "/TRANGE_1:port", 1);
|
||||
TEST_ERROR_XML("TRANGE_1", "51");
|
||||
CHECK_LOG_CTX("error message", "/TRANGE_1:port", 1);
|
||||
TEST_ERROR_XML("TRANGE_1", "127");
|
||||
CHECK_LOG_CTX("error message", "/TRANGE_1:port", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_schema_yang),
|
||||
UTEST(test_schema_yin),
|
||||
UTEST(test_schema_print),
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
2522
tests/utests/schema/test_printer_tree.c
Normal file
2522
tests/utests/schema/test_printer_tree.c
Normal file
File diff suppressed because it is too large
Load diff
1915
tests/utests/schema/test_schema.c
Normal file
1915
tests/utests/schema/test_schema.c
Normal file
File diff suppressed because it is too large
Load diff
4110
tests/utests/schema/test_tree_schema_compile.c
Normal file
4110
tests/utests/schema/test_tree_schema_compile.c
Normal file
File diff suppressed because it is too large
Load diff
1758
tests/utests/schema/test_yang.c
Normal file
1758
tests/utests/schema/test_yang.c
Normal file
File diff suppressed because it is too large
Load diff
3589
tests/utests/schema/test_yin.c
Normal file
3589
tests/utests/schema/test_yin.c
Normal file
File diff suppressed because it is too large
Load diff
359
tests/utests/types/binary.c
Normal file
359
tests/utests/types/binary.c
Normal file
|
@ -0,0 +1,359 @@
|
|||
/**
|
||||
* @file binary.c
|
||||
* @author Michal Vaško <mvasko@cesnet.cz>
|
||||
* @brief test for built-in binary type
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_store(void **state)
|
||||
{
|
||||
const char *val, *dec_val;
|
||||
unsigned char bin_val[2];
|
||||
struct ly_err_item *err = NULL;
|
||||
struct lys_module *mod;
|
||||
struct lyd_value value = {0};
|
||||
struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY]);
|
||||
struct lysc_type *lysc_type, *lysc_type2;
|
||||
LY_ERR ly_ret;
|
||||
const char *schema;
|
||||
|
||||
/* create schema. Prepare common used variables */
|
||||
schema = MODULE_CREATE_YANG("a", "leaf l {type binary;} leaf k {type binary {length 4..8;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
|
||||
lysc_type2 = ((struct lysc_node_leaf *)mod->compiled->data->next)->type;
|
||||
|
||||
/* check proper type */
|
||||
assert_string_equal("libyang 2 - binary, version 1", type->id);
|
||||
|
||||
/* check store XML double pad */
|
||||
val = "YWhveQ==";
|
||||
dec_val = "ahoy";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, dec_val, strlen(dec_val),
|
||||
0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
/* single pad */
|
||||
val = "YWhveWo=";
|
||||
dec_val = "ahoyj";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, dec_val, strlen(dec_val),
|
||||
0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
/* no pad */
|
||||
val = "YWhveWoy";
|
||||
dec_val = "ahoyj2";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, dec_val, strlen(dec_val),
|
||||
0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
/* binary data */
|
||||
val = "q80=";
|
||||
bin_val[0] = 0xab;
|
||||
bin_val[1] = 0xcd;
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, bin_val, 2);
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, bin_val, 2,
|
||||
0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, bin_val, 2);
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
/* newlines after every 64 chars */
|
||||
val = "MIIEAzCCAuugAwIBAgIURc4sipHvJSlNrQIhRhZilBvV4RowDQYJKoZIhvcNAQEL\n"
|
||||
"BQAwgZAxCzAJBgNVBAYTAkNaMRYwFAYDVQQIDA1Tb3V0aCBNb3JhdmlhMQ0wCwYD\n"
|
||||
"VQQHDARCcm5vMRgwFgYDVQQKDA9DRVNORVQgei5zLnAuby4xDDAKBgNVBAsMA1RN\n"
|
||||
"QzETMBEGA1UEAwwKZXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBs\n"
|
||||
"ZS5vcmcwHhcNMjEwOTAzMTAyMTAxWhcNMzEwOTAxMTAyMTAxWjCBkDELMAkGA1UE\n"
|
||||
"BhMCQ1oxFjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xGDAW\n"
|
||||
"BgNVBAoMD0NFU05FVCB6LnMucC5vLjEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApl\n"
|
||||
"eGFtcGxlIENBMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLm9yZzCCASIwDQYJ\n"
|
||||
"KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN4Ld3JDDocyy9KXNJhEUPeZpQW3UdUN\n"
|
||||
"Xloeh5n/bxasgThkBuQ7oF/nKyVUe517U1CJA993ZIc0jhIWThAnqXkz70DX5EZ7\n"
|
||||
"ancPd01MidA6T8k1RYYJWr+vyIRYYBYzK7LSnU6wMWqPTgzZB+KMWwb065ooLEB5\n"
|
||||
"XwqAeTIMPLRqM1Galewl4ZSuRJnrXxRjfF3AWNyC9dZw6wIg8cppvoLdBGQiFJQf\n"
|
||||
"9SgiVy+HyedAytFEixqKAAIgQUJwhCgbEd6jGFbeaL8HT4MFp1VmaaUBQMkZj/Gn\n"
|
||||
"KBwCk5BEMu76EN1pzHc4Dd6DabQNGCnsqOPe31yhQGmNFy9R6zNnWZMCAwEAAaNT\n"
|
||||
"MFEwHQYDVR0OBBYEFM7w/pO8vk5oowvWPoCKo0RW/JcnMB8GA1UdIwQYMBaAFM7w\n"
|
||||
"/pO8vk5oowvWPoCKo0RW/JcnMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\n"
|
||||
"BQADggEBAG/xfYuRKnCyiwYC/K7kAjHmCNnLCr1mx8P1ECsSJPme3OThDTNeGf8i\n"
|
||||
"N2952tGmMFDa+DaAwPc6Gt3cWTb/NYMTLWlt2yj5rJAcLXxIU0SMafBf+F7E/R8A\n"
|
||||
"b/HDDjs0pQaJ0EJhQJVkMdfj3Wq9l0dJT5iEBUrUQflDufiMdEJEIGKZh86MgzEL\n"
|
||||
"bcn1QX8dlLc91M2OifWStqLzXPicG+jjuoPUceC0flMQDb2qx03sxvJKfYfS5ArA\n"
|
||||
"CqvdWyXLoP7DI9THJrMI/vBHJKpl4Wtmsh2OLn9VHauFMzPSGke5GwjXCpbXGepj\n"
|
||||
"9qWN8Gd/FWgSDH2OBvZ6aHdB1pPjN9k=";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
/* empty value */
|
||||
val = "";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, "", "", 0);
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
/* short value */
|
||||
val = "YQ==";
|
||||
dec_val = "a";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, dec_val, strlen(dec_val),
|
||||
0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
/* length check */
|
||||
val = "Zm91cg==";
|
||||
dec_val = "four";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type2, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type2);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type2, dec_val, strlen(dec_val),
|
||||
0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type2);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
val = "ZWlnaHQwMTI=";
|
||||
dec_val = "eight012";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type2, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type2);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type2, dec_val, strlen(dec_val),
|
||||
0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err));
|
||||
CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
|
||||
assert_ptr_equal(value.realtype, lysc_type2);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
|
||||
/*
|
||||
* ERROR TESTS
|
||||
*/
|
||||
val = "q80.";
|
||||
err = NULL;
|
||||
ly_ret = type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err);
|
||||
assert_int_equal(LY_EVALID, ly_ret);
|
||||
assert_string_equal(err->msg, "Invalid Base64 character '.'.");
|
||||
ly_err_free(err);
|
||||
|
||||
val = "q80";
|
||||
err = NULL;
|
||||
ly_ret = type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err);
|
||||
assert_int_equal(LY_EVALID, ly_ret);
|
||||
assert_string_equal(err->msg, "Base64 encoded value length must be divisible by 4.");
|
||||
ly_err_free(err);
|
||||
|
||||
val = "MTIz";
|
||||
err = NULL;
|
||||
ly_ret = type->store(UTEST_LYCTX, lysc_type2, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err);
|
||||
assert_int_equal(LY_EVALID, ly_ret);
|
||||
assert_string_equal(err->msg, "Unsatisfied length - string \"MTIz\" length is not allowed.");
|
||||
ly_err_free(err);
|
||||
|
||||
/* LYPLG_TYPE_STORE_ONLY test */
|
||||
val = "MTIz";
|
||||
err = NULL;
|
||||
ly_ret = type->store(UTEST_LYCTX, lysc_type2, val, strlen(val),
|
||||
LYPLG_TYPE_STORE_ONLY, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err);
|
||||
assert_int_equal(LY_SUCCESS, ly_ret);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
ly_err_free(err);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_print(void **state)
|
||||
{
|
||||
const char *schema, *val;
|
||||
struct lyd_value value = {0};
|
||||
struct lys_module *mod;
|
||||
struct lysc_type *lysc_type;
|
||||
struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY]);
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
/* create schema. Prepare common used variables */
|
||||
schema = MODULE_CREATE_YANG("a", "leaf l {type binary;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
|
||||
|
||||
/* Testing empty value. */
|
||||
val = "";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
assert_string_equal("", value.realtype->plugin->print(UTEST_LYCTX, &(value), LY_VALUE_CANON, NULL, NULL, NULL));
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_duplicate(void **state)
|
||||
{
|
||||
const char *schema, *val;
|
||||
struct lyd_value value = {0}, dup;
|
||||
struct lys_module *mod;
|
||||
struct lysc_type *lysc_type;
|
||||
struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY]);
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
/* create schema. Prepare common used variables */
|
||||
schema = MODULE_CREATE_YANG("a", "leaf l {type binary;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
|
||||
|
||||
/* Testing empty value. */
|
||||
val = "";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
|
||||
assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &value, &dup));
|
||||
CHECK_LYD_VALUE(dup, BINARY, "", "", 0);
|
||||
type->free(UTEST_LYCTX, &value);
|
||||
type->free(UTEST_LYCTX, &dup);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_sort(void **state)
|
||||
{
|
||||
const char *v1, *v2;
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lyd_value val1 = {0}, val2 = {0};
|
||||
struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_BINARY]);
|
||||
struct lysc_type *lysc_type;
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
/* create schema. Prepare common used variables */
|
||||
schema = MODULE_CREATE_YANG("a", "leaf-list ll {type binary;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data)->type;
|
||||
|
||||
/* v1 < v2, v2 > v1, v1 == v1 */
|
||||
v1 = "YWhveQ=="; /* ahoy */
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "YWhveg=="; /* ahoz */
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* v2 is shorter */
|
||||
v1 = "YWhveQ=="; /* ahoj */
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "YWhv"; /* aho */
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb", "leaf port {type binary;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB("lyb", "port", "");
|
||||
TEST_SUCCESS_LYB("lyb", "port", "YWhveQ==");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_plugin_store),
|
||||
UTEST(test_plugin_print),
|
||||
UTEST(test_plugin_duplicate),
|
||||
UTEST(test_plugin_sort),
|
||||
UTEST(test_data_lyb),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1121
tests/utests/types/bits.c
Normal file
1121
tests/utests/types/bits.c
Normal file
File diff suppressed because it is too large
Load diff
109
tests/utests/types/boolean.c
Normal file
109
tests/utests/types/boolean.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* @file boolean.c
|
||||
* @author Adam Piecek <piecek@cesnet.cz>
|
||||
* @brief test for built-in enumeration type
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "typedef tboolean {type boolean;}"
|
||||
"leaf l1 {type boolean;}"
|
||||
"leaf l2 {type tboolean;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_XML("defs", "l1", "true", BOOL, "true", 1);
|
||||
|
||||
TEST_SUCCESS_XML("defs", "l1", "false", BOOL, "false", 0);
|
||||
|
||||
TEST_SUCCESS_XML("defs", "l2", "false", BOOL, "false", 0);
|
||||
|
||||
/* invalid value */
|
||||
TEST_ERROR_XML("defs", "l1", "unsure");
|
||||
CHECK_LOG_CTX("Invalid boolean value \"unsure\".", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", " true");
|
||||
CHECK_LOG_CTX("Invalid boolean value \" true\".", "/defs:l1", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb",
|
||||
"leaf bool {type boolean;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB("lyb", "bool", "true");
|
||||
TEST_SUCCESS_LYB("lyb", "bool", "false");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_plugin_lyb),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
130
tests/utests/types/decimal64.c
Normal file
130
tests/utests/types/decimal64.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* @file decimal64.c
|
||||
* @author Adam Piecek <piecek@cesnet.cz>
|
||||
* @brief test for built-in enumeration type
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_PARSE_STORE_ONLY_XML(MOD_NAME, NODE_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STORE_ONLY, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf l1 {type decimal64 {fraction-digits 1; range 1.5..10;}}"
|
||||
"leaf l2 {type decimal64 {fraction-digits 18;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_XML("defs", "l1", "\n +8 \t\n ", DEC64, "8.0", 80);
|
||||
TEST_SUCCESS_XML("defs", "l1", "8.00", DEC64, "8.0", 80);
|
||||
|
||||
TEST_SUCCESS_XML("defs", "l2", "-9.223372036854775808", DEC64, "-9.223372036854775808",
|
||||
INT64_C(-9223372036854775807) - INT64_C(1));
|
||||
TEST_SUCCESS_XML("defs", "l2", "9.223372036854775807", DEC64, "9.223372036854775807", INT64_C(9223372036854775807));
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "\n 15 \t\n ");
|
||||
CHECK_LOG_CTX("Unsatisfied range - value \"15.0\" is out of the allowed range.", "/defs:l1", 3);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "\n 0 \t\n ");
|
||||
CHECK_LOG_CTX("Unsatisfied range - value \"0.0\" is out of the allowed range.", "/defs:l1", 3);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "xxx");
|
||||
CHECK_LOG_CTX("Invalid 1. character of decimal64 value \"xxx\".", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "");
|
||||
CHECK_LOG_CTX("Invalid empty decimal64 value.", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "8.5 xxx");
|
||||
CHECK_LOG_CTX("Invalid 6. character of decimal64 value \"8.5 xxx\".", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "8.55 xxx");
|
||||
CHECK_LOG_CTX("Value \"8.55\" of decimal64 type exceeds defined number (1) of fraction digits.", "/defs:l1", 1);
|
||||
|
||||
/* LYPLG_TYPE_STORE_ONLY test */
|
||||
TEST_SUCCESS_PARSE_STORE_ONLY_XML("defs", "l1", "\n 15 \t\n ");
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb",
|
||||
"leaf dec64 {type decimal64 {fraction-digits 1; range 1.5..10;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB("lyb", "dec64", "8.00");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_plugin_lyb),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
106
tests/utests/types/empty.c
Normal file
106
tests/utests/types/empty.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* @file empty.c
|
||||
* @author Adam Piecek <piecek@cesnet.cz>
|
||||
* @brief test for built-in enumeration type
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "typedef tempty {type empty;}"
|
||||
"leaf l1 {type empty;}"
|
||||
"leaf l2 {type tempty;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_XML("defs", "l1", "", EMPTY, "");
|
||||
|
||||
TEST_SUCCESS_XML("defs", "l2", "", EMPTY, "");
|
||||
|
||||
/* invalid value */
|
||||
TEST_ERROR_XML("defs", "l1", "x");
|
||||
CHECK_LOG_CTX("Invalid empty value length 1.", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", " ");
|
||||
CHECK_LOG_CTX("Invalid empty value length 1.", "/defs:l1", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb",
|
||||
"leaf empty {type empty;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB("lyb", "empty", "");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_plugin_lyb),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
140
tests/utests/types/enumeration.c
Normal file
140
tests/utests/types/enumeration.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* @file enumeration.c
|
||||
* @author Adam Piecek <piecek@cesnet.cz>
|
||||
* @brief test for built-in enumeration type
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "feature f; leaf l1 {type enumeration {enum white; enum yellow {if-feature f;}}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_XML("defs", "l1", "white", ENUM, "white", "white");
|
||||
|
||||
/* disabled feature */
|
||||
TEST_ERROR_XML("defs", "l1", "yellow");
|
||||
CHECK_LOG_CTX("Invalid enumeration value \"yellow\".", "/defs:l1", 1);
|
||||
|
||||
/* leading/trailing whitespaces */
|
||||
TEST_ERROR_XML("defs", "l1", " white");
|
||||
CHECK_LOG_CTX("Invalid enumeration value \" white\".", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "white\n");
|
||||
CHECK_LOG_CTX("Invalid enumeration value \"white\n\".", "/defs:l1", 2);
|
||||
|
||||
/* invalid value */
|
||||
TEST_ERROR_XML("defs", "l1", "black");
|
||||
CHECK_LOG_CTX("Invalid enumeration value \"black\".", "/defs:l1", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_sort(void **state)
|
||||
{
|
||||
const char *v1, *v2;
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lyd_value val1 = {0}, val2 = {0};
|
||||
struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_ENUM]);
|
||||
struct lysc_type *lysc_type;
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
schema = MODULE_CREATE_YANG("sort", "leaf l1 {type enumeration {enum white; enum yellow; enum black;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
|
||||
|
||||
v1 = "white";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "black";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb", "leaf l1 {type enumeration {enum white; enum yellow; enum black;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB("lyb", "l1", "white");
|
||||
TEST_SUCCESS_LYB("lyb", "l1", "black");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_plugin_sort),
|
||||
UTEST(test_plugin_lyb),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
134
tests/utests/types/identityref.c
Normal file
134
tests/utests/types/identityref.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
* @file identityref.c
|
||||
* @author Adam Piecek <piecek@cesnet.cz>
|
||||
* @brief test for built-in enumeration type
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, NAMESPACES, NODE_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema, *schema2;
|
||||
struct lyd_node *tree;
|
||||
const char *data;
|
||||
|
||||
/* xml test */
|
||||
schema = "module ident-base {"
|
||||
" yang-version 1.1;"
|
||||
" namespace \"urn:tests:ident-base\";"
|
||||
" prefix ib;"
|
||||
" identity ident-base;"
|
||||
" identity ident-imp {base ident-base;}"
|
||||
"}";
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
schema2 = "module defs {"
|
||||
" yang-version 1.1;"
|
||||
" namespace \"urn:tests:defs\";"
|
||||
" prefix d;"
|
||||
" import ident-base {prefix ib;}"
|
||||
" identity ident1 {base ib:ident-base;}"
|
||||
" leaf l1 {type identityref {base ib:ident-base;}}"
|
||||
"}";
|
||||
UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* local ident, XML/JSON print */
|
||||
data = "<l1 xmlns=\"urn:tests:defs\">ident1</l1>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, IDENT, "defs:ident1", "ident1");
|
||||
CHECK_LYD_STRING_PARAM(tree, data, LYD_XML, LYD_PRINT_SHRINK);
|
||||
CHECK_LYD_STRING_PARAM(tree, "{\"defs:l1\":\"ident1\"}", LYD_JSON, LYD_PRINT_SHRINK);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* foreign ident, XML/JSON print */
|
||||
data = "<l1 xmlns=\"urn:tests:defs\" xmlns:ib=\"urn:tests:ident-base\">ib:ident-imp</l1>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, IDENT, "ident-base:ident-imp", "ident-imp");
|
||||
CHECK_LYD_STRING_PARAM(tree, data, LYD_XML, LYD_PRINT_SHRINK);
|
||||
CHECK_LYD_STRING_PARAM(tree, "{\"defs:l1\":\"ident-base:ident-imp\"}", LYD_JSON, LYD_PRINT_SHRINK);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* invalid value */
|
||||
TEST_ERROR_XML("defs", "", "l1", "fast-ethernet");
|
||||
CHECK_LOG_CTX("Invalid identityref \"fast-ethernet\" value - identity not found in module \"defs\".", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "xmlns:x=\"urn:tests:defs\"", "l1", "x:slow-ethernet");
|
||||
CHECK_LOG_CTX("Invalid identityref \"x:slow-ethernet\" value - identity not found in module \"defs\".", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "xmlns:x=\"urn:tests:ident-base\"", "l1", "x:ident-base");
|
||||
CHECK_LOG_CTX("Invalid identityref \"x:ident-base\" value - identity not derived from the base \"ident-base:ident-base\".",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "xmlns:x=\"urn:tests:unknown\"", "l1", "x:ident-base");
|
||||
CHECK_LOG_CTX("Invalid identityref \"x:ident-base\" value - unable to map prefix to YANG schema.", "/defs:l1", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb",
|
||||
"identity idbase;"
|
||||
"identity ident {base idbase;}"
|
||||
"leaf lf {type identityref {base idbase;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB("lyb", "lf", "ident");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_plugin_lyb),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
337
tests/utests/types/inet_types.c
Normal file
337
tests/utests/types/inet_types.c
Normal file
|
@ -0,0 +1,337 @@
|
|||
/**
|
||||
* @file inet_types.c
|
||||
* @author Michal Vaško <mvasko@cesnet.cz>
|
||||
* @brief test for ietf-inet-types values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YIN(MOD_NAME, NODES) \
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
|
||||
"<module name=\"" MOD_NAME "\"\n" \
|
||||
" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" \
|
||||
" xmlns:pref=\"urn:tests:" MOD_NAME "\">\n" \
|
||||
" <yang-version value=\"1.1\"/>\n" \
|
||||
" <namespace uri=\"urn:tests:" MOD_NAME "\"/>\n" \
|
||||
" <prefix value=\"pref\"/>\n" \
|
||||
NODES \
|
||||
"</module>\n"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
" import ietf-inet-types {\n" \
|
||||
" prefix inet;\n" \
|
||||
" }\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_PARSE_STORE_ONLY_XML(MOD_NAME, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STORE_ONLY, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 4, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_PARSE_STORE_ONLY_XML(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STORE_ONLY, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("a",
|
||||
"leaf l {type inet:ip-address;}"
|
||||
"leaf l2 {type inet:ipv6-address;}"
|
||||
"leaf l3 {type inet:ip-address-no-zone;}"
|
||||
"leaf l4 {type inet:ipv6-address-no-zone;}"
|
||||
"leaf l5 {type inet:ip-prefix;}"
|
||||
"leaf l6 {type inet:ipv4-prefix;}"
|
||||
"leaf l7 {type inet:ipv6-prefix;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* ip-address */
|
||||
TEST_SUCCESS_XML("a", "l", "192.168.0.1", UNION, "192.168.0.1", STRING, "192.168.0.1");
|
||||
TEST_SUCCESS_XML("a", "l", "192.168.0.1%12", UNION, "192.168.0.1%12", STRING, "192.168.0.1%12");
|
||||
TEST_SUCCESS_XML("a", "l", "2008:15:0:0:0:0:feAC:1", UNION, "2008:15::feac:1", STRING, "2008:15::feac:1");
|
||||
|
||||
/* ipv6-address */
|
||||
TEST_SUCCESS_XML("a", "l2", "FAAC:21:011:Da85::87:daaF%1", STRING, "faac:21:11:da85::87:daaf%1");
|
||||
|
||||
/* ip-address-no-zone */
|
||||
TEST_SUCCESS_XML("a", "l3", "127.0.0.1", UNION, "127.0.0.1", STRING, "127.0.0.1");
|
||||
TEST_SUCCESS_XML("a", "l3", "0:00:000:0000:000:00:0:1", UNION, "::1", STRING, "::1");
|
||||
|
||||
/* ipv6-address-no-zone */
|
||||
TEST_SUCCESS_XML("a", "l4", "A:B:c:D:e:f:1:0", STRING, "a:b:c:d:e:f:1:0");
|
||||
|
||||
/* ip-prefix */
|
||||
TEST_SUCCESS_XML("a", "l5", "158.1.58.4/1", UNION, "128.0.0.0/1", STRING, "128.0.0.0/1");
|
||||
TEST_SUCCESS_XML("a", "l5", "158.1.58.4/24", UNION, "158.1.58.0/24", STRING, "158.1.58.0/24");
|
||||
TEST_SUCCESS_XML("a", "l5", "2000:A:B:C:D:E:f:a/16", UNION, "2000::/16", STRING, "2000::/16");
|
||||
|
||||
/* ipv4-prefix */
|
||||
TEST_SUCCESS_XML("a", "l6", "0.1.58.4/32", STRING, "0.1.58.4/32");
|
||||
TEST_SUCCESS_XML("a", "l6", "12.1.58.4/8", STRING, "12.0.0.0/8");
|
||||
|
||||
/* ipv6-prefix */
|
||||
TEST_SUCCESS_XML("a", "l7", "::C:D:E:f:a/112", STRING, "::c:d:e:f:0/112");
|
||||
TEST_SUCCESS_XML("a", "l7", "::C:D:E:f:a/110", STRING, "::c:d:e:c:0/110");
|
||||
TEST_SUCCESS_XML("a", "l7", "::C:D:E:f:a/96", STRING, "::c:d:e:0:0/96");
|
||||
TEST_SUCCESS_XML("a", "l7", "::C:D:E:f:a/55", STRING, "::/55");
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_basic_plugins_only_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("a", "leaf l {type inet:ipv4-address;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* Stored via ipv4-address plugin */
|
||||
TEST_SUCCESS_XML("a", "l", "192.168.0.1", STRING, "192.168.0.1");
|
||||
TEST_ERROR_XML("a", "l", "192.168.0.333");
|
||||
TEST_ERROR_PARSE_STORE_ONLY_XML("a", "l", "192.168.0.333");
|
||||
|
||||
/* Recreate context to get rid of all plugins */
|
||||
ly_ctx_destroy(UTEST_LYCTX);
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_BUILTIN_PLUGINS_ONLY, &UTEST_LYCTX));
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* Stored via string plugin */
|
||||
TEST_SUCCESS_XML("a", "l", "192.168.0.1", STRING, "192.168.0.1");
|
||||
TEST_ERROR_XML("a", "l", "192.168.0.333");
|
||||
CHECK_LOG_CTX("Unsatisfied pattern - \"192.168.0.333\" does not conform to \""
|
||||
"(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9]"
|
||||
"[0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(%[\\p{N}\\p{L}]+)?\".", "/a:l", 1);
|
||||
TEST_SUCCESS_PARSE_STORE_ONLY_XML("a", "l", "192.168.0.333", STRING, "192.168.0.333");
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb",
|
||||
"leaf l {type inet:ip-address;}"
|
||||
"leaf l2 {type inet:ipv6-address;}"
|
||||
"leaf l3 {type inet:ip-address-no-zone;}"
|
||||
"leaf l4 {type inet:ipv6-address-no-zone;}"
|
||||
"leaf l5 {type inet:ip-prefix;}"
|
||||
"leaf l6 {type inet:ipv4-prefix;}"
|
||||
"leaf l7 {type inet:ipv6-prefix;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_LYB("lyb", "l", "192.168.0.1");
|
||||
TEST_SUCCESS_LYB("lyb", "l2", "FAAC:21:011:Da85::87:daaF%1");
|
||||
TEST_SUCCESS_LYB("lyb", "l3", "127.0.0.1");
|
||||
TEST_SUCCESS_LYB("lyb", "l4", "A:B:c:D:e:f:1:0");
|
||||
TEST_SUCCESS_LYB("lyb", "l5", "158.1.58.4/1");
|
||||
TEST_SUCCESS_LYB("lyb", "l6", "12.1.58.4/8");
|
||||
TEST_SUCCESS_LYB("lyb", "l7", "::C:D:E:f:a/112");
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_sort(void **state)
|
||||
{
|
||||
const char *v1, *v2;
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lyd_value val1 = {0}, val2 = {0};
|
||||
struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION]);
|
||||
struct lysc_type *lysc_type;
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
schema = MODULE_CREATE_YANG("a",
|
||||
"leaf l {type inet:ip-address;}"
|
||||
"leaf l2 {type inet:ipv6-address;}"
|
||||
"leaf l3 {type inet:ip-address-no-zone;}"
|
||||
"leaf l4 {type inet:ipv6-address-no-zone;}"
|
||||
"leaf l5 {type inet:ipv4-prefix;}"
|
||||
"leaf l6 {type inet:ipv6-prefix;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
|
||||
/* ipv4-address */
|
||||
lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
|
||||
|
||||
v1 = "192.168.0.1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "192.168.0.2";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
v1 = "192.168.0.1%1A";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "192.168.0.1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* ipv6-address */
|
||||
lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next)->type;
|
||||
type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING]);
|
||||
|
||||
v1 = "2008:15:0:0:0:0:feAC:1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "2008:15::feac:2";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
v1 = "FAAC:21:011:Da85::87:daaF%1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "FAAC:21:011:Da85::87:daaF%14";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* ipv4-address-no-zone */
|
||||
lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next)->type;
|
||||
type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION]);
|
||||
v1 = "127.0.0.1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "127.0.1.1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* ipv6-address-no-zone */
|
||||
lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next->next)->type;
|
||||
type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_STRING]);
|
||||
v1 = "A:B:c:D:e:f:1:1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "A:B:c:D:e:f:1:0";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* ipv4-prefix */
|
||||
lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next->next->next)->type;
|
||||
v1 = "0.1.58.4/32";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "0.1.58.4/16";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* ipv6-prefix */
|
||||
lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data->next->next->next->next->next)->type;
|
||||
v1 = "::C:D:E:f:a/96";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "::C:D:E:f:a/112";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_data_lyb),
|
||||
UTEST(test_plugin_sort),
|
||||
UTEST(test_data_basic_plugins_only_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
292
tests/utests/types/instanceid.c
Normal file
292
tests/utests/types/instanceid.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
/**
|
||||
* @file instanceid.c
|
||||
* @author Adam Piecek <piecek@cesnet.cz>
|
||||
* @brief test for built-in enumeration type
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 1, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, RET) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, RET, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define LYB_CHECK_START \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data;
|
||||
|
||||
#define LYB_CHECK_END \
|
||||
{ \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME1, DATA1, NODE_NAME2, DATA2) \
|
||||
LYB_CHECK_START \
|
||||
data = "<" NODE_NAME1 " xmlns=\"urn:tests:" MOD_NAME "\">" DATA1 "</" NODE_NAME1 ">" \
|
||||
"<xdf:" NODE_NAME2 " xmlns:xdf=\"urn:tests:" MOD_NAME "\">/xdf:" DATA2 "</xdf:" NODE_NAME2 ">"; \
|
||||
LYB_CHECK_END \
|
||||
|
||||
#define TEST_SUCCESS_LYB2(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
LYB_CHECK_START \
|
||||
data = "<" NODE_NAME " xmlns:aa=\"urn:tests:lyb2\" xmlns=\"urn:tests:" MOD_NAME "\">/aa:" DATA "</" NODE_NAME ">"; \
|
||||
LYB_CHECK_END \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema, *schema2;
|
||||
const enum ly_path_pred_type val1[] = {0, 0};
|
||||
const enum ly_path_pred_type val2[] = {LY_PATH_PREDTYPE_LIST, 0};
|
||||
const enum ly_path_pred_type val3[] = {LY_PATH_PREDTYPE_LEAFLIST};
|
||||
const enum ly_path_pred_type val4[] = {LY_PATH_PREDTYPE_LIST, 0};
|
||||
const enum ly_path_pred_type val5[] = {LY_PATH_PREDTYPE_LIST, 0};
|
||||
const enum ly_path_pred_type val6[] = {LY_PATH_PREDTYPE_LIST, 0};
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("mod", "container cont {leaf l2 {type empty;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
schema2 = MODULE_CREATE_YANG("defs", "identity ident; identity ident-der1 {base ident;} identity ident-der2 {base ident;}"
|
||||
"leaf l1 {type instance-identifier {require-instance true;}}"
|
||||
"leaf l2 {type instance-identifier {require-instance false;}}"
|
||||
"container cont {leaf l {type empty;}}"
|
||||
"list list {key \"id\"; leaf id {type string;} leaf value {type string;}}"
|
||||
"leaf-list llist {type uint32;}"
|
||||
"list list-inst {key \"id\"; leaf id {type instance-identifier;} leaf value {type string;}}"
|
||||
"list list-ident {key \"id\"; leaf id {type identityref {base ident;}} leaf value {type string;}}"
|
||||
"list list2 {key \"id id2\"; leaf id {type string;} leaf id2 {type string;}}"
|
||||
"list list-keyless {config false; leaf value {type string;}}");
|
||||
UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_XML2("<cont xmlns=\"urn:tests:defs\"><l/></cont>", "defs", "xmlns:xdf=\"urn:tests:defs\"", "l1",
|
||||
"/xdf:cont/xdf:l", INST, "/defs:cont/l", val1);
|
||||
|
||||
TEST_SUCCESS_XML2("<list xmlns=\"urn:tests:defs\"><id>a</id></list><list xmlns=\"urn:tests:defs\"><id>b</id></list>",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:list[xdf:id='b']/xdf:id", INST,
|
||||
"/defs:list[id='b']/id", val2);
|
||||
|
||||
TEST_SUCCESS_XML2("<llist xmlns=\"urn:tests:defs\">1</llist><llist xmlns=\"urn:tests:defs\">2</llist>",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:llist[.='1']", INST, "/defs:llist[.='1']", val3);
|
||||
|
||||
TEST_SUCCESS_XML2("<list-inst xmlns=\"urn:tests:defs\"><id xmlns:b=\"urn:tests:defs\">/b:llist[.='1']</id>"
|
||||
"<value>x</value></list-inst>"
|
||||
"<list-inst xmlns=\"urn:tests:defs\"><id xmlns:b=\"urn:tests:defs\">/b:llist[.='2']</id>"
|
||||
"<value>y</value></list-inst>"
|
||||
"<llist xmlns=\"urn:tests:defs\">1</llist><llist xmlns=\"urn:tests:defs\">2</llist>",
|
||||
"defs", "xmlns:a=\"urn:tests:defs\"", "a:l1", "/a:list-inst[a:id=\"/a:llist[.='1']\"]/a:value",
|
||||
INST, "/defs:list-inst[id=\"/defs:llist[.='1']\"]/value", val4);
|
||||
|
||||
TEST_SUCCESS_XML2("<list-ident xmlns=\"urn:tests:defs\"><id xmlns:b=\"urn:tests:defs\">b:ident-der1</id>"
|
||||
"<value>x</value></list-ident>"
|
||||
"<list-ident xmlns=\"urn:tests:defs\"><id xmlns:b=\"urn:tests:defs\">b:ident-der2</id>"
|
||||
"<value>y</value></list-ident>",
|
||||
"defs", "xmlns:a=\"urn:tests:defs\"", "a:l1", "/a:list-ident[a:id='a:ident-der1']/a:value",
|
||||
INST, "/defs:list-ident[id='defs:ident-der1']/value", val5);
|
||||
|
||||
TEST_SUCCESS_XML2("<list2 xmlns=\"urn:tests:defs\"><id>defs:xxx</id><id2>x</id2></list2>"
|
||||
"<list2 xmlns=\"urn:tests:defs\"><id>a:xxx</id><id2>y</id2></list2>",
|
||||
"defs", "xmlns:a=\"urn:tests:defs\"", "a:l1", "/a:list2[a:id='a:xxx'][a:id2='y']/a:id2",
|
||||
INST, "/defs:list2[id='a:xxx'][id2='y']/id2", val6);
|
||||
|
||||
/* syntax/semantic errors */
|
||||
TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>a</id></list>"
|
||||
"<list xmlns=\"urn:tests:defs\"><id>b</id><value>x</value></list>",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:list[2]/xdf:value", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[2]/xdf:value\" value - semantic error: "
|
||||
"Positional predicate defined for configuration list \"list\" in path.", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/t:cont/t:1l", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/t:cont/t:1l\" value - syntax error: Invalid character 't'[9] of expression '/t:cont/t:1l'.",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/t:cont:t:1l", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/t:cont:t:1l\" value - syntax error: Invalid character ':'[8] of expression '/t:cont:t:1l'.",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:cont/xdf:invalid/xdf:path", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:cont/xdf:invalid/xdf:path\" value - semantic error: Not found node \"invalid\" in path.",
|
||||
"/defs:l1", 1);
|
||||
|
||||
/* non-existing instances, instance-identifier is here in JSON format because it is already in internal
|
||||
* representation without canonical prefixes */
|
||||
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"/>",
|
||||
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont/m:l2", LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/mod:cont/l2\" value - required instance not found.",
|
||||
"/defs:l1", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">1</llist>",
|
||||
"defs", "xmlns:a=\"urn:tests:defs\"", "l1", "/a:llist[.='2']", LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/defs:llist[.='2']\" value - required instance not found.",
|
||||
"/defs:l1", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("<list2 xmlns=\"urn:tests:defs\"><id>a</id><id2>a</id2></list2>"
|
||||
"<list2 xmlns=\"urn:tests:defs\"><id>c</id><id2>b</id2></list2>"
|
||||
"<llist xmlns=\"urn:tests:defs\">a</llist>"
|
||||
"<llist xmlns=\"urn:tests:defs\">b</llist>",
|
||||
"defs", "xmlns:a=\"urn:tests:defs\"", "l1", "/a:list2[a:id='a'][a:id2='a']/a:id", LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/defs:list2[id='a'][id2='a']/id\" value - required instance not found.",
|
||||
"/defs:l1", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("<list2 xmlns=\"urn:tests:defs\"><id>a</id><id2>a</id2></list2>"
|
||||
"<list2 xmlns=\"urn:tests:defs\"><id>c</id><id2>b</id2></list2>"
|
||||
"<llist xmlns=\"urn:tests:defs\">1</llist>"
|
||||
"<llist xmlns=\"urn:tests:defs\">2</llist>",
|
||||
"defs", "xmlns:a=\"urn:tests:defs\"", "l1", "/a:llist[.='3']", LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/defs:llist[.='3']\" value - required instance not found.",
|
||||
"/defs:l1", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "xmlns:a=\"urn:tests:defs\"", "l1", "/a:list-keyless[3]", LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/defs:list-keyless[3]\" value - required instance not found.",
|
||||
"/defs:l1", 0, "instance-required");
|
||||
|
||||
/* more errors */
|
||||
TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">x</llist>",
|
||||
"defs", "xmlns:t=\"urn:tests:defs\"", "t:l1", "/t:llist[1", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[1\" value - syntax error: Unexpected XPath expression end.",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"/>",
|
||||
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont[1]", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont[1]\" value - semantic error: Positional predicate defined for container \"cont\" in path.",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"/>",
|
||||
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "[1]", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"[1]\" value - syntax error: Unexpected XPath token \"[\" (\"[1]\"), expected \"Operator(Path)\".",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"><l2/></cont>",
|
||||
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont/m:l2[l2='1']", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont/m:l2[l2='1']\" value - syntax error: Prefix missing for \"l2\" in path.",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"><l2/></cont>",
|
||||
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont/m:l2[m:l2='1']", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont/m:l2[m:l2='1']\" value - semantic error: List predicate defined for leaf \"l2\" in path.",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">1</llist><llist xmlns=\"urn:tests:defs\">2</llist>",
|
||||
"defs", "xmlns:t=\"urn:tests:defs\"", "t:l1", "/t:llist[4]", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[4]\" value - semantic error: Positional predicate defined for configuration leaf-list \"llist\" in path.",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/t:llist[6]", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[6]\" value - semantic error: No module connected with the prefix \"t\" found (prefix format XML prefixes).",
|
||||
"/defs:l2", 1);
|
||||
|
||||
TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>1</id><value>x</value></list>",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list[xdf:value='x']", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[xdf:value='x']\" value - semantic error: Key expected instead of leaf \"value\" in path.",
|
||||
"/defs:l2", 1);
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list[.='x']", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[.='x']\" value - semantic error: Leaf-list predicate defined for list \"list\" in path.",
|
||||
"/defs:l2", 1);
|
||||
|
||||
TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">1</llist>",
|
||||
"defs", "xmlns:t=\"urn:tests:defs\"", "t:l1", "/t:llist[.='x']", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[.='x']\" value - semantic error: Invalid type uint32 value \"x\".",
|
||||
"/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/t:llist[1][2]", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[1][2]\" value - syntax error: Unparsed characters \"[2]\" left at the end of path.",
|
||||
"/defs:l2", 1);
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/t:llist[.='a'][.='b']", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[.='a'][.='b']\" value - syntax error: Unparsed characters \"[.='b']\" left at the end of path.",
|
||||
"/defs:l2", 1);
|
||||
|
||||
TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>1</id><value>x</value></list>",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list[xdf:id='1'][xdf:id='2']/xdf:value", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[xdf:id='1'][xdf:id='2']/xdf:value\" value - syntax error: Duplicate predicate key \"id\" in path.",
|
||||
"/defs:l2", 1);
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list2[xdf:id='1']/xdf:value", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list2[xdf:id='1']/xdf:value\" value - semantic error: Predicate missing for a key of list \"list2\" in path.",
|
||||
"/defs:l2", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb",
|
||||
"leaf-list leaflisttarget {type string;}"
|
||||
"leaf inst {type instance-identifier {require-instance true;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB("lyb", "leaflisttarget", "1", "inst", "leaflisttarget[.='1']");
|
||||
|
||||
/* ietf-netconf-acm node-instance-identifier type */
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
schema = MODULE_CREATE_YANG("lyb2",
|
||||
"import ietf-netconf-acm {prefix acm;}"
|
||||
"leaf-list ll {type string;}"
|
||||
"leaf nii {type acm:node-instance-identifier;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB2("lyb2", "nii", "ll[. = 'some_string']");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_plugin_lyb),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
76
tests/utests/types/instanceid_keys.c
Normal file
76
tests/utests/types/instanceid_keys.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* @file instanceid_keys.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief test for yang instance-identifier-keys type
|
||||
*
|
||||
* Copyright (c) 2022 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML_NS1(MOD_NAME, NODE_NAME, PREFIX, NS, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" xmlns:" PREFIX "=\"" NS "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "import yang {prefix y;} leaf l1 {type y:instance-identifier-keys;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_XML_NS1("defs", "l1", "px", "urn:tests:defs", "[px:key='val']", STRING, "[defs:key='val']");
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "black");
|
||||
CHECK_LOG_CTX("Invalid first character 'b', list key predicates expected.", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "[this is not a valid xpath]");
|
||||
CHECK_LOG_CTX("Invalid character 0x69 ('i'), perhaps \"this\" is supposed to be a function call.", "/defs:l1", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "l1", "[px:key='val']");
|
||||
CHECK_LOG_CTX("Failed to resolve prefix \"px\".", "/defs:l1", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
74
tests/utests/types/int16.c
Normal file
74
tests/utests/types/int16.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file int16.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief test for int16 values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* GLOBAL INCLUDE HEADERS */
|
||||
#include <ctype.h>
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
#include "plugins_internal.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, ## __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf port {type int16 {range -20..-10;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_ERROR_XML("defs", "100");
|
||||
CHECK_LOG_CTX("Unsatisfied range - value \"100\" is out of the allowed range.", "/defs:port", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
74
tests/utests/types/int32.c
Normal file
74
tests/utests/types/int32.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file int32.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief test for int32 values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* GLOBAL INCLUDE HEADERS */
|
||||
#include <ctype.h>
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
#include "plugins_internal.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, ## __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf port {type int32;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_ERROR_XML("defs", "0x01");
|
||||
CHECK_LOG_CTX("Invalid type int32 value \"0x01\".", "/defs:port", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
80
tests/utests/types/int64.c
Normal file
80
tests/utests/types/int64.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* @file int64.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief test for int32 values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* GLOBAL INCLUDE HEADERS */
|
||||
#include <ctype.h>
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
#include "plugins_internal.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, ## __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf port {type int64;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_ERROR_XML("defs", "");
|
||||
CHECK_LOG_CTX("Invalid type int64 empty value.", "/defs:port", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", " ");
|
||||
CHECK_LOG_CTX("Invalid type int64 empty value.", "/defs:port", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "-10 xxx");
|
||||
CHECK_LOG_CTX("Invalid type int64 value \"-10 xxx\".", "/defs:port", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1762
tests/utests/types/int8.c
Normal file
1762
tests/utests/types/int8.c
Normal file
File diff suppressed because it is too large
Load diff
326
tests/utests/types/leafref.c
Normal file
326
tests/utests/types/leafref.c
Normal file
|
@ -0,0 +1,326 @@
|
|||
/**
|
||||
* @file leafref.c
|
||||
* @author Adam Piecek <piecek@cesnet.cz>
|
||||
* @brief test for built-in enumeration type
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 1, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, RET) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, RET, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME1, DATA1, NODE_NAME2, DATA2) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME1 " xmlns=\"urn:tests:" MOD_NAME "\"><name>" DATA1 "</name></" NODE_NAME1 ">" \
|
||||
"<" NODE_NAME2 " xmlns=\"urn:tests:" MOD_NAME "\">" DATA2 "</" NODE_NAME2 ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema, *schema2, *schema3, *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf lref {type leafref {path /leaflisttarget; require-instance true;}}"
|
||||
"leaf lref2 {type leafref {path \"../list[id = current()/../str-norestr]/targets\"; require-instance true;}}"
|
||||
"leaf str-norestr {type string;}"
|
||||
"list list {key id; leaf id {type string;} leaf value {type string;} leaf-list targets {type string;}}"
|
||||
"container cont {leaf leaftarget {type empty;}"
|
||||
" list listtarget {key id; max-elements 5;leaf id {type uint8;} leaf value {type string;}}"
|
||||
" leaf-list leaflisttarget {type uint8; max-elements 5;}}"
|
||||
"leaf-list leaflisttarget {type string;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
schema2 = MODULE_CREATE_YANG("leafrefs", "import defs {prefix t;}"
|
||||
"container c { container x {leaf x {type string;}} list l {"
|
||||
" key \"id value\"; leaf id {type string;} leaf value {type string;}"
|
||||
" leaf lr1 {type leafref {path \"../../../t:str-norestr\"; require-instance true;}}"
|
||||
" leaf lr2 {type leafref {path \"../../l[id=current()/../../../t:str-norestr]\" +"
|
||||
" \"[value=current()/../../../t:str-norestr]/value\"; require-instance true;}}"
|
||||
" leaf lr3 {type leafref {path \"/t:list[t:id=current ( )/../../x/x]/t:targets\";}}"
|
||||
"}}");
|
||||
UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_XML2("<leaflisttarget xmlns=\"urn:tests:defs\">x</leaflisttarget>"
|
||||
"<leaflisttarget xmlns=\"urn:tests:defs\">y</leaflisttarget>",
|
||||
"defs", "xmlns:a=\"urn:tests:defs\"", "a:lref", "y", STRING, "y");
|
||||
|
||||
TEST_SUCCESS_XML2("<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>"
|
||||
"<list xmlns=\"urn:tests:defs\"><id>y</id><targets>x</targets><targets>y</targets></list>"
|
||||
"<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>",
|
||||
"defs", "xmlns:a=\"urn:tests:defs\"", "a:lref2", "y", STRING, "y");
|
||||
|
||||
data = "<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>"
|
||||
"<c xmlns=\"urn:tests:leafrefs\"><l><id>x</id><value>x</value><lr1>y</lr1></l></c>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)lyd_child(lyd_child(tree->next->next)->next)->next->next,
|
||||
0, 0, 0, 1, 1, STRING, "y");
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>"
|
||||
"<list xmlns=\"urn:tests:defs\"><id>y</id><targets>c</targets><targets>d</targets></list>"
|
||||
"<c xmlns=\"urn:tests:leafrefs\"><x><x>y</x></x>"
|
||||
"<l><id>x</id><value>x</value><lr3>c</lr3></l></c>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)lyd_child(lyd_child(tree->next->next->next)->next)->next->next,
|
||||
0, 0, 0, 1, 1, STRING, "c");
|
||||
lyd_free_all(tree);
|
||||
|
||||
schema3 = MODULE_CREATE_YANG("simple", "leaf l1 {type leafref {path \"../target\";}}"
|
||||
"leaf target {type string;}");
|
||||
UTEST_ADD_MODULE(schema3, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data = "<l1 xmlns=\"urn:tests:simple\">"*"'</l1>"
|
||||
"<target xmlns=\"urn:tests:simple\">"*"'</target>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<l1 xmlns=\"urn:tests:simple\">"*'"</l1>"
|
||||
"<target xmlns=\"urn:tests:simple\">"*'"</target>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* invalid value */
|
||||
TEST_ERROR_XML2("<leaflisttarget xmlns=\"urn:tests:defs\">x</leaflisttarget>",
|
||||
"defs", "", "lref", "y", LY_EVALID);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid leafref value \"y\" - no target instance \"/leaflisttarget\" with the same value.",
|
||||
"/defs:lref", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>"
|
||||
"<list xmlns=\"urn:tests:defs\"><id>y</id><targets>x</targets><targets>y</targets></list>"
|
||||
"<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>",
|
||||
"defs", "", "lref2", "b", LY_EVALID);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid leafref value \"b\" - "
|
||||
"no target instance \"../list[id = current()/../str-norestr]/targets\" with the same value.",
|
||||
"/defs:lref2", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>"
|
||||
"<list xmlns=\"urn:tests:defs\"><id>y</id><targets>x</targets><targets>y</targets></list>",
|
||||
"defs", "", "lref2", "b", LY_EVALID);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid leafref value \"b\" - "
|
||||
"no target instance \"../list[id = current()/../str-norestr]/targets\" with the same value.",
|
||||
"/defs:lref2", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>",
|
||||
"defs", "", "lref2", "b", LY_EVALID);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid leafref value \"b\" - "
|
||||
"no target instance \"../list[id = current()/../str-norestr]/targets\" with the same value.",
|
||||
"/defs:lref2", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>",
|
||||
"leafrefs", "", "c", "<l><id>x</id><value>x</value><lr1>a</lr1></l>", LY_EVALID);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid leafref value \"a\" - no target instance \"../../../t:str-norestr\" with the same value.",
|
||||
"/leafrefs:c/l[id='x'][value='x']/lr1", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("<str-norestr xmlns=\"urn:tests:defs\">z</str-norestr>",
|
||||
"leafrefs", "", "c", "<l><id>y</id><value>y</value></l><l><id>x</id><value>x</value><lr2>z</lr2></l>", LY_EVALID);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid leafref value \"z\" - no target instance \"../../l[id=current()/../../../t:str-norestr]"
|
||||
"[value=current()/../../../t:str-norestr]/value\" with the same value.",
|
||||
"/leafrefs:c/l[id='x'][value='x']/lr2", 0, "instance-required");
|
||||
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "", "lref", "%n", LY_EVALID);
|
||||
CHECK_LOG_CTX_APPTAG("Invalid leafref value \"%n\" - no target instance \"/leaflisttarget\" with the same value.",
|
||||
"/defs:lref", 0, "instance-required");
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_json(void **state)
|
||||
{
|
||||
const char *schema, *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
/* json test */
|
||||
schema = MODULE_CREATE_YANG("simple", "leaf l1 {type leafref {path \"../target\";}}"
|
||||
"leaf target {type string;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data = "{"
|
||||
" \"simple:l1\":\"\\\"*\\\"'\","
|
||||
" \"simple:target\":\"\\\"*\\\"'\""
|
||||
"}";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{"
|
||||
" \"simple:l1\":\"\\\"*'\\\"\","
|
||||
" \"simple:target\":\"\\\"*'\\\"\""
|
||||
"}";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb",
|
||||
"list lst {key \"name\"; leaf name {type string;}}"
|
||||
"leaf lref {type leafref {path \"../lst/name\";}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB("lyb", "lst", "key_str", "lref", "key_str");
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_sort(void **state)
|
||||
{
|
||||
const char *v1, *v2;
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lyd_value val1 = {0}, val2 = {0};
|
||||
struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_LEAFREF]);
|
||||
struct lysc_type *lysc_type;
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
schema = MODULE_CREATE_YANG("simple",
|
||||
"leaf l1 {"
|
||||
" type leafref {"
|
||||
" require-instance false;"
|
||||
" path \"../target\";"
|
||||
" }"
|
||||
"}"
|
||||
"leaf target {"
|
||||
" type string;"
|
||||
"}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
|
||||
|
||||
v1 = "str1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "str2";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xpath_json(void **state)
|
||||
{
|
||||
const char *schema, *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_EXTENDED);
|
||||
|
||||
/* json xpath test */
|
||||
schema = MODULE_CREATE_YANG("xp_test",
|
||||
"list l1 {key t1;"
|
||||
"leaf t1 {type uint8;}"
|
||||
"list l2 {key t2;"
|
||||
"leaf t2 {type uint8;}"
|
||||
"leaf-list l3 {type uint8;}"
|
||||
"}}"
|
||||
"leaf r1 {type leafref {path \"../l1/t1\";}}"
|
||||
"leaf r2 {type leafref {path \"deref(../r1)/../l2/t2\";}}"
|
||||
"leaf r3 {type leafref {path \"deref(../r2)/../l3\";}}");
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data = "{"
|
||||
" \"xp_test:l1\":[{\"t1\": 1,\"l2\":[{\"t2\": 2,\"l3\":[3]}]}],"
|
||||
" \"xp_test:r1\": 1,"
|
||||
" \"xp_test:r2\": 2,"
|
||||
" \"xp_test:r3\": 3"
|
||||
"}";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_xpath_invalid_schema(void **state)
|
||||
{
|
||||
const char *schema1, *schema2;
|
||||
|
||||
ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_EXTENDED);
|
||||
schema1 = MODULE_CREATE_YANG("xp_test",
|
||||
"list l1 {key t1;"
|
||||
"leaf t1 {type uint8;}"
|
||||
"list l2 {key t2;"
|
||||
"leaf t2 {type uint8;}"
|
||||
"leaf-list l3 {type uint8;}"
|
||||
"}}"
|
||||
"leaf r1 {type leafref {path \"deref(../l1)/../l2/t2\";}}");
|
||||
|
||||
UTEST_INVALID_MODULE(schema1, LYS_IN_YANG, NULL, LY_EVALID)
|
||||
CHECK_LOG_CTX("The deref function target node \"l1\" is not leaf nor leaflist", "/xp_test:r1", 0);
|
||||
|
||||
schema2 = MODULE_CREATE_YANG("xp_test",
|
||||
"list l1 {key t1;"
|
||||
"leaf t1 {type uint8;}"
|
||||
"list l2 {key t2;"
|
||||
"leaf t2 {type uint8;}"
|
||||
"leaf-list l3 {type uint8;}"
|
||||
"}}"
|
||||
"leaf r1 {type uint8;}"
|
||||
"leaf r2 {type leafref {path \"deref(../r1)/../l2/t2\";}}");
|
||||
|
||||
UTEST_INVALID_MODULE(schema2, LYS_IN_YANG, NULL, LY_EVALID)
|
||||
CHECK_LOG_CTX("The deref function target node \"r1\" is not leafref", "/xp_test:r2", 0);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_data_json),
|
||||
UTEST(test_plugin_lyb),
|
||||
UTEST(test_plugin_sort),
|
||||
UTEST(test_data_xpath_json),
|
||||
UTEST(test_xpath_invalid_schema)
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1379
tests/utests/types/string.c
Normal file
1379
tests/utests/types/string.c
Normal file
File diff suppressed because it is too large
Load diff
74
tests/utests/types/uint16.c
Normal file
74
tests/utests/types/uint16.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file uint16.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief test for uint16 values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* GLOBAL INCLUDE HEADERS */
|
||||
#include <ctype.h>
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
#include "plugins_internal.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, ## __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf port {type uint16 {range 150..200;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_ERROR_XML("defs", "\n 1500 \t\n ");
|
||||
CHECK_LOG_CTX("Unsatisfied range - value \"1500\" is out of the allowed range.", "/defs:port", 3);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
74
tests/utests/types/uint32.c
Normal file
74
tests/utests/types/uint32.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file uint32.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief test for uint32 values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* GLOBAL INCLUDE HEADERS */
|
||||
#include <ctype.h>
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
#include "plugins_internal.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, ## __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf port {type uint32;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_ERROR_XML("defs", "-10");
|
||||
CHECK_LOG_CTX("Value \"-10\" is out of type uint32 min/max bounds.", "/defs:port", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
80
tests/utests/types/uint64.c
Normal file
80
tests/utests/types/uint64.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* @file uint64.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief test for uint64 values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* GLOBAL INCLUDE HEADERS */
|
||||
#include <ctype.h>
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
#include "plugins_internal.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, ## __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf port {type uint64;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_ERROR_XML("defs", "");
|
||||
CHECK_LOG_CTX("Invalid type uint64 empty value.", "/defs:port", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", " ");
|
||||
CHECK_LOG_CTX("Invalid type uint64 empty value.", "/defs:port", 1);
|
||||
|
||||
TEST_ERROR_XML("defs", "10 xxx");
|
||||
CHECK_LOG_CTX("Invalid type uint64 value \"10 xxx\".", "/defs:port", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
87
tests/utests/types/uint8.c
Normal file
87
tests/utests/types/uint8.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* @file uint8.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief test for uint8 values
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* GLOBAL INCLUDE HEADERS */
|
||||
#include <ctype.h>
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
#include "plugins_internal.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_PARSE_STORE_ONLY_XML(MOD_NAME, DATA) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STORE_ONLY, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf port {type uint8 {range 150..200;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_XML("defs", "\n 150 \t\n ", UINT8, "150", 150);
|
||||
|
||||
TEST_ERROR_XML("defs", "\n 15 \t\n ");
|
||||
CHECK_LOG_CTX("Unsatisfied range - value \"15\" is out of the allowed range.", "/defs:port", 3);
|
||||
|
||||
/* LYPLG_TYPE_STORE_ONLY test */
|
||||
TEST_SUCCESS_PARSE_STORE_ONLY_XML("defs", "\n 15 \t\n ");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
315
tests/utests/types/union.c
Normal file
315
tests/utests/types/union.c
Normal file
|
@ -0,0 +1,315 @@
|
|||
/**
|
||||
* @file union.c
|
||||
* @author Adam Piecek <piecek@cesnet.cz>
|
||||
* @brief test for built-in enumeration type
|
||||
*
|
||||
* Copyright (c) 2021 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
/* LOCAL INCLUDE HEADERS */
|
||||
#include "libyang.h"
|
||||
#include "path.h"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 1, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, RET) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, RET, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
const enum ly_path_pred_type val1[] = {LY_PATH_PREDTYPE_LEAFLIST};
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "identity ident1; identity ident2 {base ident1;}"
|
||||
"leaf un1 {type union {"
|
||||
" type leafref {path /int8; require-instance true;}"
|
||||
" type leafref {path /int64; require-instance true;}"
|
||||
" type union { type identityref {base ident1;} type instance-identifier {require-instance true;} }"
|
||||
" type string {length 1..20;}}}"
|
||||
"leaf int8 {type int8 {range 10..20;}}"
|
||||
"leaf int64 {type int64;}"
|
||||
"leaf-list llist {type string;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
TEST_SUCCESS_XML2("<int8 xmlns=\"urn:tests:defs\">12</int8>",
|
||||
"defs", "", "un1", "12", UNION, "12", INT8, "12", 12);
|
||||
|
||||
TEST_SUCCESS_XML2("<int8 xmlns=\"urn:tests:defs\">12</int8>",
|
||||
"defs", "", "un1", "2", UNION, "2", STRING, "2");
|
||||
|
||||
TEST_SUCCESS_XML2("<int8 xmlns=\"urn:tests:defs\">10</int8>",
|
||||
"defs", "xmlns:x=\"urn:tests:defs\"", "un1", "x:ident2", UNION, "defs:ident2", IDENT, "defs:ident2", "ident2");
|
||||
|
||||
TEST_SUCCESS_XML2("<int8 xmlns=\"urn:tests:defs\">10</int8>",
|
||||
"defs", "xmlns:x=\"urn:tests:defs\"", "un1", "x:ident55", UNION, "x:ident55", STRING, "x:ident55");
|
||||
|
||||
TEST_SUCCESS_XML2("<llist xmlns=\"urn:tests:defs\">x</llist>"
|
||||
"<llist xmlns=\"urn:tests:defs\">y</llist>",
|
||||
"defs", "xmlns:x=\"urn:tests:defs\"", "un1", "/x:llist[.='y']", UNION, "/defs:llist[.='y']",
|
||||
INST, "/defs:llist[.='y']", val1);
|
||||
|
||||
TEST_SUCCESS_XML2("<llist xmlns=\"urn:tests:defs\">x</llist>"
|
||||
"<llist xmlns=\"urn:tests:defs\">y</llist>",
|
||||
"defs", "xmlns:x=\"urn:tests:defs\"", "un1", "/x:llist[3]", UNION, "/x:llist[3]",
|
||||
STRING, "/x:llist[3]");
|
||||
|
||||
/* invalid value */
|
||||
TEST_ERROR_XML2("",
|
||||
"defs", "", "un1", "123456789012345678901", LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid union value \"123456789012345678901\" - no matching subtype found:\n"
|
||||
" libyang 2 - leafref, version 1: Invalid type int8 value \"123456789012345678901\".\n"
|
||||
" libyang 2 - leafref, version 1: Invalid type int64 value \"123456789012345678901\".\n"
|
||||
" libyang 2 - identityref, version 1: Invalid identityref \"123456789012345678901\" value - identity not found in module \"defs\".\n"
|
||||
" libyang 2 - instance-identifier, version 1: Invalid instance-identifier \"123456789012345678901\" value - syntax error.\n"
|
||||
" libyang 2 - string, version 1: Unsatisfied length - string \"123456789012345678901\" length is not allowed.\n",
|
||||
"/defs:un1", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_json(void **state)
|
||||
{
|
||||
const char *schema, *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("defs", "leaf un21 {type union {type uint8; type string;}}"
|
||||
"leaf un22 {type union {type uint16; type string;}}"
|
||||
"leaf un2 {type union {type leafref {path /un21; require-instance false;} type leafref {path /un22; require-instance false;}}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data = "{\"defs:un2\":\"str\"}";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
CHECK_LYD_STRING_PARAM(tree, data, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
schema = MODULE_CREATE_YANG("lyb",
|
||||
"leaf int8 {type int8 {range 10..20;}}"
|
||||
"leaf un1 {type union {"
|
||||
" type leafref {path /int8; require-instance true;}"
|
||||
" type string;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
TEST_SUCCESS_LYB("lyb", "un1", "12");
|
||||
TEST_SUCCESS_LYB("lyb", "un1", "some_string");
|
||||
TEST_SUCCESS_LYB("lyb", "un1", "");
|
||||
}
|
||||
|
||||
static void
|
||||
test_plugin_sort(void **state)
|
||||
{
|
||||
const char *v1, *v2;
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lyd_value val1 = {0}, val2 = {0};
|
||||
struct lyplg_type *type = lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION]);
|
||||
struct lysc_type *lysc_type;
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
schema = MODULE_CREATE_YANG("sort", "leaf-list ll {type union {type uint16; type int16;}}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data)->type;
|
||||
|
||||
v1 = "1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_DECNUM, NULL, &val1, NULL, &err));
|
||||
v2 = "-1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_DECNUM, NULL, &val2, NULL, &err));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
v1 = "-1";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_DECNUM, NULL, &val1, NULL, &err));
|
||||
v2 = "-2";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_JSON, NULL, LYD_VALHINT_DECNUM, NULL, &val2, NULL, &err));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_validation(void **state)
|
||||
{
|
||||
const char *schema, *data;
|
||||
struct lyd_node *tree;
|
||||
char *out;
|
||||
uint32_t uint_val;
|
||||
|
||||
schema = MODULE_CREATE_YANG("val",
|
||||
"leaf l1 {\n"
|
||||
" type union {\n"
|
||||
" type uint32 {\n"
|
||||
" range \"0..1048575\";\n"
|
||||
" }\n"
|
||||
" type enumeration {\n"
|
||||
" enum auto;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"leaf int8 {type int8 {range 10..20;}}\n"
|
||||
"leaf l2 {\n"
|
||||
" type union {\n"
|
||||
" type leafref {path /int8; require-instance true;}\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* parse from LYB */
|
||||
data = "<l1 xmlns=\"urn:tests:val\">auto</l1><int8 xmlns=\"urn:tests:val\">15</int8><l2 xmlns=\"urn:tests:val\">15</l2>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS));
|
||||
lyd_free_all(tree);
|
||||
CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
free(out);
|
||||
|
||||
/* validate */
|
||||
assert_int_equal(LY_SUCCESS, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT, NULL));
|
||||
|
||||
/* print and compare */
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS));
|
||||
assert_string_equal(out, data);
|
||||
|
||||
free(out);
|
||||
lyd_free_all(tree);
|
||||
|
||||
schema = MODULE_CREATE_YANG("lref",
|
||||
"container test {\n"
|
||||
" list a {\n"
|
||||
" key \"name\";\n"
|
||||
" leaf name {\n"
|
||||
" type enumeration {\n"
|
||||
" enum zero;\n"
|
||||
" enum one;\n"
|
||||
" enum two;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" list b {\n"
|
||||
" key \"name\";\n"
|
||||
" leaf name {\n"
|
||||
" type uint32;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" list community {\n"
|
||||
" key \"name\";\n"
|
||||
" leaf name {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf view {\n"
|
||||
" type union {\n"
|
||||
" type leafref {\n"
|
||||
" path \"../../a/name\";\n"
|
||||
" }\n"
|
||||
" type leafref {\n"
|
||||
" path \"../../b/name\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* parse from LYB #1 */
|
||||
data = "<test xmlns=\"urn:tests:lref\"><b><name>2</name></b><community><name>test</name><view>2</view></community></test>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS));
|
||||
lyd_free_all(tree);
|
||||
CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
free(out);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* parse from LYB #2 */
|
||||
data = "<test xmlns=\"urn:tests:lref\"><a><name>one</name></a><community><name>test</name><view>one</view></community></test>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS));
|
||||
lyd_free_all(tree);
|
||||
CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
free(out);
|
||||
|
||||
/* remove the target and create another, which is represented the same way in LYB */
|
||||
lyd_free_tree(lyd_child(tree));
|
||||
uint_val = 1;
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_list(tree, NULL, "b", LYD_NEW_VAL_BIN, NULL, &uint_val, sizeof uint_val));
|
||||
assert_int_equal(LY_EVALID, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT, NULL));
|
||||
CHECK_LOG_CTX("Invalid LYB union value - no matching subtype found:\n"
|
||||
" libyang 2 - leafref, version 1: Invalid leafref value \"one\" - no target instance \"../../a/name\" with the same value.\n"
|
||||
" libyang 2 - leafref, version 1: Invalid type uint32 value \"one\".\n", "/lref:test/community[name='test']/view", 0);
|
||||
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_data_json),
|
||||
UTEST(test_plugin_lyb),
|
||||
UTEST(test_plugin_sort),
|
||||
UTEST(test_validation),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
323
tests/utests/types/yang_types.c
Normal file
323
tests/utests/types/yang_types.c
Normal file
|
@ -0,0 +1,323 @@
|
|||
/**
|
||||
* @file yang_types.c
|
||||
* @author Michal Vaško <mvasko@cesnet.cz>
|
||||
* @brief test for ietf-yang-types values
|
||||
*
|
||||
* Copyright (c) 2021 - 2023 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
|
||||
*/
|
||||
|
||||
/* INCLUDE UTEST HEADER */
|
||||
#define _UTEST_MAIN_
|
||||
#include "../utests.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "libyang.h"
|
||||
|
||||
#define MODULE_CREATE_YIN(MOD_NAME, NODES) \
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
|
||||
"<module name=\"" MOD_NAME "\"\n" \
|
||||
" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" \
|
||||
" xmlns:pref=\"urn:tests:" MOD_NAME "\">\n" \
|
||||
" <yang-version value=\"1.1\"/>\n" \
|
||||
" <namespace uri=\"urn:tests:" MOD_NAME "\"/>\n" \
|
||||
" <prefix value=\"pref\"/>\n" \
|
||||
NODES \
|
||||
"</module>\n"
|
||||
|
||||
#define MODULE_CREATE_YANG(MOD_NAME, NODES) \
|
||||
"module " MOD_NAME " {\n" \
|
||||
" yang-version 1.1;\n" \
|
||||
" namespace \"urn:tests:" MOD_NAME "\";\n" \
|
||||
" prefix pref;\n" \
|
||||
" import ietf-yang-types {\n" \
|
||||
" prefix yang;\n" \
|
||||
" }\n" \
|
||||
NODES \
|
||||
"}\n"
|
||||
|
||||
#define TEST_SUCCESS_XML(MOD_NAME, NODE_NAME, DATA, TYPE, ...) \
|
||||
{ \
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
|
||||
CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
|
||||
lyd_free_all(tree); \
|
||||
}
|
||||
|
||||
#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA, RET) \
|
||||
{\
|
||||
struct lyd_node *tree; \
|
||||
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, RET, tree); \
|
||||
assert_null(tree); \
|
||||
}
|
||||
|
||||
#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \
|
||||
{ \
|
||||
struct lyd_node *tree_1; \
|
||||
struct lyd_node *tree_2; \
|
||||
char *xml_out, *data; \
|
||||
data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \
|
||||
assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \
|
||||
assert_non_null(tree_2); \
|
||||
CHECK_LYD(tree_1, tree_2); \
|
||||
free(xml_out); \
|
||||
lyd_free_all(tree_1); \
|
||||
lyd_free_all(tree_2); \
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_xml(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("a",
|
||||
"leaf l {type yang:date-and-time;}"
|
||||
"leaf l21 {type yang:hex-string;}"
|
||||
"leaf l22 {type yang:uuid;}"
|
||||
"leaf l3 {type yang:xpath1.0;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
schema = MODULE_CREATE_YANG("b",
|
||||
"");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* date-and-time */
|
||||
TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888Z", STRING, "2005-05-25T21:15:15.88888-02:00");
|
||||
TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-08:59", STRING, "2005-06-01T06:14:15-02:00");
|
||||
TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-23:00", STRING, "2005-06-01T20:15:15-02:00");
|
||||
|
||||
/* test 1 second before epoch (mktime returns -1, but it is a correct value), with and without DST */
|
||||
TEST_SUCCESS_XML("a", "l", "1970-01-01T00:59:59-02:00", STRING, "1970-01-01T00:59:59-02:00");
|
||||
TEST_SUCCESS_XML("a", "l", "1969-12-31T23:59:59-02:00", STRING, "1969-12-31T23:59:59-02:00");
|
||||
|
||||
/* canonize */
|
||||
TEST_SUCCESS_XML("a", "l", "2005-02-29T23:15:15-02:00", STRING, "2005-03-01T23:15:15-02:00");
|
||||
|
||||
/* fractional hours */
|
||||
TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888+04:30", STRING, "2005-05-25T16:45:15.88888-02:00");
|
||||
|
||||
/* unknown timezone -- timezone conversion MUST NOT happen */
|
||||
TEST_SUCCESS_XML("a", "l", "2017-02-01T00:00:00-00:00", STRING, "2017-02-01T00:00:00-00:00");
|
||||
TEST_SUCCESS_XML("a", "l", "2021-02-29T00:00:00-00:00", STRING, "2021-03-01T00:00:00-00:00");
|
||||
|
||||
TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00", LY_EVALID);
|
||||
CHECK_LOG_CTX("Unsatisfied pattern - \"2005-05-31T23:15:15.-08:00\" does not conform to "
|
||||
"\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[\\+\\-]\\d{2}:\\d{2})\".",
|
||||
"/a:l", 1);
|
||||
|
||||
TEST_ERROR_XML("a", "l", "2023-16-15T20:13:01+01:00", LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid date-and-time month \"15\".", "/a:l", 1);
|
||||
|
||||
TEST_ERROR_XML("a", "l", "2023-10-15T20:13:01+95:00", LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid date-and-time timezone hour \"95\".", "/a:l", 1);
|
||||
|
||||
/* hex-string */
|
||||
TEST_SUCCESS_XML("a", "l21", "DB:BA:12:54:fa", STRING, "db:ba:12:54:fa");
|
||||
TEST_SUCCESS_XML("a", "l22", "f81D4fAE-7dec-11d0-A765-00a0c91E6BF6", STRING, "f81d4fae-7dec-11d0-a765-00a0c91e6bf6");
|
||||
|
||||
/* xpath1.0 */
|
||||
TEST_SUCCESS_XML("a\" xmlns:aa=\"urn:tests:a", "l3", "/aa:l3[. = '4']", STRING, "/a:l3[.='4']");
|
||||
TEST_SUCCESS_XML("a\" xmlns:yl=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\" "
|
||||
"xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores", "l3",
|
||||
"/yl:yang-library/yl:datastore/yl:name = 'ds:running'", STRING,
|
||||
"/ietf-yang-library:yang-library/datastore/name='ietf-datastores:running'");
|
||||
TEST_SUCCESS_XML("a\" xmlns:a1=\"urn:tests:a\" xmlns:a2=\"urn:tests:a\" xmlns:bb=\"urn:tests:b", "l3",
|
||||
"/a1:node1/a2:node2[a1:node3/bb:node4]/bb:node5 | bb:node6 and (bb:node7)", STRING,
|
||||
"/a:node1/node2[node3/b:node4]/b:node5 | b:node6 and (b:node7)");
|
||||
TEST_SUCCESS_XML("a", "l3", "/l3[. = '4']", STRING, "/l3[.='4']");
|
||||
|
||||
TEST_ERROR_XML("a", "l3", "/a:l3[. = '4']", LY_EVALID);
|
||||
CHECK_LOG_CTX("Failed to resolve prefix \"a\".", "/a:l3", 1);
|
||||
TEST_ERROR_XML("a\" xmlns:yl=\"urn:ietf:params:xml:ns:yang:ietf-yang-library", "l3",
|
||||
"/yl:yang-library/yl:datastore/yl::name", LY_EVALID);
|
||||
CHECK_LOG_CTX("Storing value failed.", "/a:l3", 1);
|
||||
CHECK_LOG_CTX("Invalid character 'y'[31] of expression '/yl:yang-library/yl:datastore/yl::name'.", "/a:l3", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_print(void **state)
|
||||
{
|
||||
const char *schema = MODULE_CREATE_YANG("a", "leaf l {type yang:xpath1.0;}");
|
||||
const char *data, *expected;
|
||||
struct lyd_node *tree;
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* XML data */
|
||||
data = "<l xmlns=\"urn:tests:a\" xmlns:aa=\"urn:tests:a\">/aa:l[. = '/aa:l']</l>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
|
||||
/* XML print */
|
||||
expected = "<l xmlns=\"urn:tests:a\" xmlns:pref=\"urn:tests:a\">/pref:l[.='/pref:l']</l>";
|
||||
CHECK_LYD_STRING_PARAM(tree, expected, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
|
||||
/* JSON print */
|
||||
expected = "{\"a:l\":\"/a:l[.='/a:l']\"}";
|
||||
CHECK_LYD_STRING_PARAM(tree, expected, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
|
||||
lyd_free_tree(tree);
|
||||
|
||||
/* JSON data */
|
||||
data = "{\"a:l\":\"/a:l/k/m[. = '/a:l']\"}";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
|
||||
/* XML print */
|
||||
expected = "<l xmlns=\"urn:tests:a\" xmlns:pref=\"urn:tests:a\">/pref:l/pref:k/pref:m[.='/pref:l']</l>";
|
||||
CHECK_LYD_STRING_PARAM(tree, expected, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
|
||||
/* JSON print */
|
||||
expected = "{\"a:l\":\"/a:l/k/m[. = '/a:l']\"}";
|
||||
CHECK_LYD_STRING_PARAM(tree, expected, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
|
||||
lyd_free_tree(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_duplicate(void **state)
|
||||
{
|
||||
const char *schema = MODULE_CREATE_YANG("a", "leaf l1 {type yang:date-and-time;} leaf l2 {type yang:xpath1.0;}");
|
||||
const char *data, *expected;
|
||||
struct lyd_node *tree, *dup;
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data = "<l1 xmlns=\"urn:tests:a\">2005-05-25T23:15:15.88888+04:30</l1>"
|
||||
"<l2 xmlns=\"urn:tests:a\" xmlns:aa=\"urn:tests:a\">/aa:l2[. = '/aa:l2']</l2>";
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
|
||||
/* duplicate */
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_siblings(tree, NULL, 0, &dup));
|
||||
|
||||
/* print */
|
||||
expected = "<l1 xmlns=\"urn:tests:a\">2005-05-25T16:45:15.88888-02:00</l1>"
|
||||
"<l2 xmlns=\"urn:tests:a\" xmlns:pref=\"urn:tests:a\">/pref:l2[.='/pref:l2']</l2>";
|
||||
CHECK_LYD_STRING_PARAM(dup, expected, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
|
||||
|
||||
lyd_free_siblings(tree);
|
||||
lyd_free_siblings(dup);
|
||||
}
|
||||
|
||||
static void
|
||||
test_lyb(void **state)
|
||||
{
|
||||
const char *schema;
|
||||
|
||||
/* xml test */
|
||||
schema = MODULE_CREATE_YANG("a",
|
||||
"leaf l {type yang:date-and-time;}"
|
||||
"leaf l2 {type yang:xpath1.0;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* date-and-time */
|
||||
TEST_SUCCESS_LYB("a", "l", "2005-05-25T23:15:15.88888Z");
|
||||
TEST_SUCCESS_LYB("a", "l", "2005-05-31T23:15:15-08:59");
|
||||
TEST_SUCCESS_LYB("a", "l", "2005-05-01T20:15:15-00:00");
|
||||
|
||||
/* xpath1.0 */
|
||||
TEST_SUCCESS_LYB("a\" xmlns:aa=\"urn:tests:a", "l2", "/aa:l2[. = '4']");
|
||||
}
|
||||
|
||||
static void
|
||||
test_sort(void **state)
|
||||
{
|
||||
const char *v1, *v2;
|
||||
const char *schema;
|
||||
struct lys_module *mod;
|
||||
struct lyd_value val1 = {0}, val2 = {0};
|
||||
struct lyplg_type *type = lyplg_type_plugin_find(NULL, "ietf-yang-types", "2013-07-15", "date-and-time");
|
||||
struct lysc_type *lysc_type;
|
||||
struct ly_err_item *err = NULL;
|
||||
|
||||
/* create schema. Prepare common used variables */
|
||||
schema = MODULE_CREATE_YANG("a",
|
||||
"leaf-list ll {type yang:date-and-time;}");
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
|
||||
lysc_type = ((struct lysc_node_leaflist *)mod->compiled->data)->type;
|
||||
|
||||
/* v1 > v2, v2 < v1, v1 == v1 */
|
||||
v1 = "2005-05-25T23:15:15Z";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "2005-05-25T23:15:14Z";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* unknown timezone */
|
||||
v1 = "2005-05-25T23:15:15Z";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "2005-05-25T23:15:15-00:00";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* fractions of a second */
|
||||
v1 = "2005-05-25T23:15:15.88888Z";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "2005-05-25T23:15:15.88889Z";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* zero fractions of a second */
|
||||
v1 = "2005-05-25T23:15:15.00Z";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "2005-05-25T23:15:15Z";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
|
||||
/* zero fractions of a second and non-zero */
|
||||
v1 = "2005-05-25T23:15:15.00Z";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v1, strlen(v1),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val1, NULL, &err));
|
||||
v2 = "2005-05-25T23:15:15.0001Z";
|
||||
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, v2, strlen(v2),
|
||||
0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &val2, NULL, &err));
|
||||
assert_true(0 > type->sort(UTEST_LYCTX, &val1, &val2));
|
||||
assert_true(0 < type->sort(UTEST_LYCTX, &val2, &val1));
|
||||
assert_int_equal(0, type->sort(UTEST_LYCTX, &val1, &val1));
|
||||
type->free(UTEST_LYCTX, &val1);
|
||||
type->free(UTEST_LYCTX, &val2);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_data_xml),
|
||||
UTEST(test_print),
|
||||
UTEST(test_duplicate),
|
||||
UTEST(test_lyb),
|
||||
UTEST(test_sort),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1414
tests/utests/utests.h
Normal file
1414
tests/utests/utests.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue