1
0
Fork 0

Adding upstream version 3.1.0+dfsg.

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

359
tests/utests/types/binary.c Normal file
View 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

File diff suppressed because it is too large Load diff

View 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);
}

View 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
View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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

File diff suppressed because it is too large Load diff

View 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\">&quot;*&quot;&#39;</l1>"
"<target xmlns=\"urn:tests:simple\">&quot;*&quot;&#39;</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\">&quot;*&#39;&quot;</l1>"
"<target xmlns=\"urn:tests:simple\">&quot;*&#39;&quot;</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

File diff suppressed because it is too large Load diff

View 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);
}

View 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);
}

View 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);
}

View 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
View 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);
}

View 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);
}