blob: 22b6f4eef9c36ecff112cb1db3148829112d7f28 [file] [log] [blame]
/**
* @file test_context.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from context.c
*
* Copyright (c) 2018 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _UTEST_MAIN_
#include "utests.h"
#include "context.h"
#include "in.h"
#include "ly_common.h"
#include "schema_compile.h"
#include "tests_config.h"
#include "tree_schema_internal.h"
#ifdef _WIN32
static void
slashes_to_backslashes(char *path)
{
while ((path = strchr(path, '/'))) {
*path++ = '\\';
}
}
static void
test_searchdirs(void **state)
{
const char * const *list;
char *path1 = strdup(TESTS_BIN "/utests");
char *path2 = strdup(TESTS_SRC);
slashes_to_backslashes(path1);
slashes_to_backslashes(path2);
assert_int_equal(LY_EINVAL, ly_ctx_set_searchdir(NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_set_searchdir()).");
assert_null(ly_ctx_get_searchdirs(NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_get_searchdirs()).");
assert_int_equal(LY_EINVAL, ly_ctx_unset_searchdir(NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_unset_searchdir()).");
/* correct path */
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, path1));
assert_int_equal(1, UTEST_LYCTX->search_paths.count);
assert_string_equal(path1, UTEST_LYCTX->search_paths.objs[0]);
/* duplicated paths */
assert_int_equal(LY_EEXIST, ly_ctx_set_searchdir(UTEST_LYCTX, path1));
assert_int_equal(1, UTEST_LYCTX->search_paths.count);
assert_string_equal(path1, UTEST_LYCTX->search_paths.objs[0]);
/* another path */
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, path2));
assert_int_equal(2, UTEST_LYCTX->search_paths.count);
assert_string_equal(path2, UTEST_LYCTX->search_paths.objs[1]);
/* get searchpaths */
list = ly_ctx_get_searchdirs(UTEST_LYCTX);
assert_non_null(list);
assert_string_equal(path1, list[0]);
assert_string_equal(path2, list[1]);
assert_null(list[2]);
/* removing searchpaths */
/* nonexisting */
assert_int_equal(LY_EINVAL, ly_ctx_unset_searchdir(UTEST_LYCTX, "/nonexistingfile"));
CHECK_LOG_CTX("Invalid argument value (ly_ctx_unset_searchdir()).", NULL, 0);
/* first */
assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdir(UTEST_LYCTX, path1));
assert_int_equal(1, UTEST_LYCTX->search_paths.count);
assert_string_not_equal(path1, list[0]);
/* second */
assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdir(UTEST_LYCTX, path2));
assert_int_equal(0, UTEST_LYCTX->search_paths.count);
free(path1);
free(path2);
}
#else
static void
test_searchdirs(void **state)
{
const char * const *list;
/* invalid arguments */
assert_int_equal(LY_EINVAL, ly_ctx_set_searchdir(NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_set_searchdir()).");
assert_null(ly_ctx_get_searchdirs(NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_get_searchdirs()).");
assert_int_equal(LY_EINVAL, ly_ctx_unset_searchdir(NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_unset_searchdir()).");
/* readable and executable, but not a directory */
assert_int_equal(LY_EINVAL, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_BIN "/utest_context"));
CHECK_LOG_CTX("Given search directory \""TESTS_BIN "/utest_context\" is not a directory.", NULL, 0);
/* not existing */
assert_int_equal(LY_EINVAL, ly_ctx_set_searchdir(UTEST_LYCTX, "/nonexistingfile"));
CHECK_LOG_CTX("Unable to use search directory \"/nonexistingfile\" (No such file or directory).", NULL, 0);
/* ly_set_add() fails */
/* no change */
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, NULL));
/* correct path */
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_BIN "/utests"));
assert_int_equal(1, UTEST_LYCTX->search_paths.count);
assert_string_equal(TESTS_BIN "/utests", UTEST_LYCTX->search_paths.objs[0]);
/* duplicated paths */
assert_int_equal(LY_EEXIST, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_BIN "/utests"));
assert_int_equal(1, UTEST_LYCTX->search_paths.count);
assert_string_equal(TESTS_BIN "/utests", UTEST_LYCTX->search_paths.objs[0]);
/* another paths - add 8 to fill the initial buffer of the searchpaths list */
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_BIN "/CMakeFiles"));
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_SRC "/../src"));
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_SRC "/../CMakeModules"));
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_SRC "/../doc"));
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_SRC));
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_BIN));
assert_int_equal(7, UTEST_LYCTX->search_paths.count);
/* get searchpaths */
list = ly_ctx_get_searchdirs(UTEST_LYCTX);
assert_non_null(list);
assert_string_equal(TESTS_BIN "/utests", list[0]);
assert_string_equal(TESTS_BIN "/CMakeFiles", list[1]);
assert_string_equal(TESTS_SRC, list[5]);
assert_string_equal(TESTS_BIN, list[6]);
assert_null(list[7]);
/* removing searchpaths */
/* nonexisting */
assert_int_equal(LY_EINVAL, ly_ctx_unset_searchdir(UTEST_LYCTX, "/nonexistingfile"));
CHECK_LOG_CTX("Invalid argument value (ly_ctx_unset_searchdir()).", NULL, 0);
/* first */
assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdir(UTEST_LYCTX, TESTS_BIN "/utests"));
assert_string_not_equal(TESTS_BIN "/utests", list[0]);
assert_int_equal(6, UTEST_LYCTX->search_paths.count);
/* middle */
assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdir(UTEST_LYCTX, TESTS_SRC));
assert_int_equal(5, UTEST_LYCTX->search_paths.count);
/* last */
assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdir(UTEST_LYCTX, TESTS_BIN));
assert_int_equal(4, UTEST_LYCTX->search_paths.count);
/* all */
assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdir(UTEST_LYCTX, NULL));
assert_int_equal(0, UTEST_LYCTX->search_paths.count);
/* again - no change */
assert_int_equal(LY_SUCCESS, ly_ctx_unset_searchdir(UTEST_LYCTX, NULL));
/* cleanup */
ly_ctx_destroy(UTEST_LYCTX);
/* test searchdir list in ly_ctx_new() */
assert_int_equal(LY_EINVAL, ly_ctx_new("/nonexistingfile", 0, &UTEST_LYCTX));
CHECK_LOG_LASTMSG("Unable to use search directory \"/nonexistingfile\" (No such file or directory).");
assert_int_equal(LY_SUCCESS,
ly_ctx_new(TESTS_SRC PATH_SEPARATOR TESTS_BIN PATH_SEPARATOR TESTS_BIN PATH_SEPARATOR TESTS_SRC,
LY_CTX_DISABLE_SEARCHDIRS, &UTEST_LYCTX));
assert_int_equal(2, UTEST_LYCTX->search_paths.count);
assert_string_equal(TESTS_SRC, UTEST_LYCTX->search_paths.objs[0]);
assert_string_equal(TESTS_BIN, UTEST_LYCTX->search_paths.objs[1]);
}
#endif
static void
test_options(void **state)
{
/* use own context with extra flags */
ly_ctx_destroy(UTEST_LYCTX);
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0xffff, &UTEST_LYCTX));
/* invalid arguments */
assert_int_equal(0, ly_ctx_get_options(NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_get_options()).");
assert_int_equal(LY_EINVAL, ly_ctx_set_options(NULL, 0));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_set_options()).");
assert_int_equal(LY_EINVAL, ly_ctx_unset_options(NULL, 0));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_unset_options()).");
/* unset */
/* LY_CTX_ALL_IMPLEMENTED */
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_ALL_IMPLEMENTED);
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_ALL_IMPLEMENTED));
assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_ALL_IMPLEMENTED);
/* LY_CTX_REF_IMPLEMENTED */
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_REF_IMPLEMENTED);
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED));
assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_REF_IMPLEMENTED);
/* LY_CTX_DISABLE_SEARCHDIRS */
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIRS);
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_DISABLE_SEARCHDIRS));
assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIRS);
/* LY_CTX_DISABLE_SEARCHDIR_CWD */
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIR_CWD);
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_DISABLE_SEARCHDIR_CWD));
assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIR_CWD);
/* LY_CTX_PREFER_SEARCHDIRS */
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_PREFER_SEARCHDIRS);
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_PREFER_SEARCHDIRS));
assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_PREFER_SEARCHDIRS);
/* LY_CTX_LEAFREF_EXTENDED */
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_EXTENDED);
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_LEAFREF_EXTENDED));
assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_EXTENDED);
/* LY_CTX_LEAFREF_LINKING */
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_LINKING);
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_LEAFREF_LINKING));
assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_LINKING);
/* LY_CTX_BUILTIN_PLUGINS_ONLY */
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_BUILTIN_PLUGINS_ONLY);
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_BUILTIN_PLUGINS_ONLY));
assert_int_equal(0, UTEST_LYCTX->flags & LY_CTX_BUILTIN_PLUGINS_ONLY);
assert_int_equal(UTEST_LYCTX->flags, ly_ctx_get_options(UTEST_LYCTX));
/* set back */
/* LY_CTX_ALL_IMPLEMENTED */
assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_ALL_IMPLEMENTED));
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_ALL_IMPLEMENTED);
/* LY_CTX_REF_IMPLEMENTED */
assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED));
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_REF_IMPLEMENTED);
/* LY_CTX_DISABLE_SEARCHDIRS */
assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_DISABLE_SEARCHDIRS));
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIRS);
/* LY_CTX_DISABLE_SEARCHDIR_CWD */
assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_DISABLE_SEARCHDIR_CWD));
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_DISABLE_SEARCHDIR_CWD);
/* LY_CTX_PREFER_SEARCHDIRS */
assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_PREFER_SEARCHDIRS));
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_PREFER_SEARCHDIRS);
/* LY_CTX_LEAFREF_EXTENDED */
assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_EXTENDED));
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_EXTENDED);
/* LY_CTX_LEAFREF_LINKING */
assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_LINKING));
assert_int_not_equal(0, UTEST_LYCTX->flags & LY_CTX_LEAFREF_LINKING);
/* LY_CTX_BUILTIN_PLUGINS_ONLY */
assert_int_equal(LY_EINVAL, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_BUILTIN_PLUGINS_ONLY));
CHECK_LOG_CTX("Invalid argument option (LY_CTX_BUILTIN_PLUGINS_ONLY can be set only when creating a new context) (ly_ctx_set_options()).", NULL, 0);
assert_int_equal(UTEST_LYCTX->flags, ly_ctx_get_options(UTEST_LYCTX));
}
static LY_ERR
test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
{
*module_data = user_data;
*format = LYS_IN_YANG;
*free_module_data = NULL;
return LY_SUCCESS;
}
static void
test_models(void **state)
{
struct ly_in *in;
const char *str;
struct lys_module *mod1, *mod2;
struct lys_glob_unres unres = {0};
/* use own context with extra flags */
ly_ctx_destroy(UTEST_LYCTX);
/* invalid arguments */
assert_int_equal(0, ly_ctx_get_change_count(NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_get_change_count()).");
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &UTEST_LYCTX));
assert_int_equal(UTEST_LYCTX->change_count, ly_ctx_get_change_count(UTEST_LYCTX));
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module x {namespace urn:x;prefix x;}", &in));
assert_int_equal(LY_EINVAL, lys_parse_in(UTEST_LYCTX, in, 4, NULL, NULL, &unres.creating, &mod1));
lys_unres_glob_erase(&unres);
ly_in_free(in, 0);
CHECK_LOG_CTX("Invalid schema input format.", NULL, 0);
/* import callback */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)(str = "test"));
assert_ptr_equal(test_imp_clb, UTEST_LYCTX->imp_clb);
assert_ptr_equal(str, UTEST_LYCTX->imp_clb_data);
assert_ptr_equal(test_imp_clb, ly_ctx_get_module_imp_clb(UTEST_LYCTX, (void **)&str));
assert_string_equal("test", str);
ly_ctx_set_module_imp_clb(UTEST_LYCTX, NULL, NULL);
assert_null(UTEST_LYCTX->imp_clb);
assert_null(UTEST_LYCTX->imp_clb_data);
/* name collision of module and submodule */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule y {belongs-to a {prefix a;} revision 2018-10-30;}");
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module y {namespace urn:y;prefix y;include y;}", &in));
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
lys_unres_glob_erase(&unres);
ly_in_free(in, 0);
CHECK_LOG_CTX("Parsing module \"y\" failed.", NULL, 0);
CHECK_LOG_CTX("Name collision between module and submodule of name \"y\".", NULL, 1);
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module a {namespace urn:a;prefix a;include y;revision 2018-10-30; }", &in));
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
ly_in_free(in, 0);
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module y {namespace urn:y;prefix y;}", &in));
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
lys_unres_glob_erase(&unres);
ly_in_free(in, 0);
CHECK_LOG_CTX("Parsing module \"y\" failed.", NULL, 0);
CHECK_LOG_CTX("Name collision between module and submodule of name \"y\".", NULL, 1);
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule y {belongs-to b {prefix b;}}");
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module b {namespace urn:b;prefix b;include y;}", &in));
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
lys_unres_glob_revert(UTEST_LYCTX, &unres);
lys_unres_glob_erase(&unres);
ly_in_free(in, 0);
CHECK_LOG_CTX("Parsing module \"b\" failed.", NULL, 0);
CHECK_LOG_CTX("Including \"y\" submodule into \"b\" failed.", NULL, 0);
CHECK_LOG_CTX("Parsing submodule failed.", NULL, 0);
CHECK_LOG_CTX("Name collision between submodules of name \"y\".", NULL, 1);
/* selecting correct revision of the submodules */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule y {belongs-to a {prefix a;} revision 2018-10-31;}");
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module a {namespace urn:a;prefix a;include y; revision 2018-10-31;}", &in));
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod2));
lys_unres_glob_erase(&unres);
ly_in_free(in, 0);
assert_string_equal("2018-10-31", mod2->parsed->includes[0].submodule->revs[0].date);
/* reloading module in case only the compiled module resists in the context */
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module w {namespace urn:w;prefix w;revision 2018-10-24;}", &in));
assert_int_equal(LY_SUCCESS, lys_parse(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &mod1));
ly_in_free(in, 0);
assert_non_null(mod1->compiled);
assert_non_null(mod1->parsed);
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module z {namespace urn:z;prefix z;import w {prefix w;revision-date 2018-10-24;}}", &in));
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module w {namespace urn:w;prefix w;revision 2018-10-24;}");
assert_int_equal(LY_SUCCESS, lys_parse(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &mod2));
ly_in_free(in, 0);
assert_non_null(mod2);
assert_non_null(mod1->parsed);
assert_string_equal("w", mod1->name);
}
static void
test_imports(void **state)
{
struct lys_module *mod1, *mod2, *mod3, *import;
char *str;
uint16_t ctx_options;
/* use own context with extra flags */
ly_ctx_destroy(UTEST_LYCTX);
ctx_options = LY_CTX_DISABLE_SEARCHDIRS | LY_CTX_NO_YANGLIBRARY;
/* Import callback provides newer revision of module 'a',
* however the older revision is implemented soon and therefore it is preferred. */
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, ctx_options, &UTEST_LYCTX));
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module a {namespace urn:a; prefix a; revision 2019-09-17;}");
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;revision 2019-09-16;}",
LYS_IN_YANG, &mod1));
assert_true(LYS_MOD_LATEST_REV & mod1->latest_revision);
assert_int_equal(1, mod1->implemented);
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b {namespace urn:b;prefix b;import a {prefix a;}}",
LYS_IN_YANG, &mod2));
assert_ptr_equal(mod1, mod2->parsed->imports[0].module);
assert_true((LYS_MOD_LATEST_REV | LYS_MOD_IMPORTED_REV) & mod1->latest_revision);
assert_string_equal("2019-09-16", mod1->revision);
assert_int_equal(1, mod1->implemented);
assert_non_null(ly_ctx_get_module(UTEST_LYCTX, "a", "2019-09-16"));
ly_ctx_destroy(UTEST_LYCTX);
/* Import callback provides older revision of module 'a' and it is
* imported by another module, so it is preferred even if newer
* revision is implemented later. */
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, ctx_options, &UTEST_LYCTX));
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module a {namespace urn:a; prefix a; revision 2019-09-16;}");
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b {namespace urn:b;prefix b;import a {prefix a;}}",
LYS_IN_YANG, &mod2));
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;revision 2019-09-17;}",
LYS_IN_YANG, &mod1));
ly_log_level(LY_LLVRB);
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module c {namespace urn:c;prefix c;import a {prefix a;}}",
LYS_IN_YANG, &mod3));
CHECK_LOG_LASTMSG("Implemented module \"a@2019-09-17\" is not used for import, revision \"2019-09-16\" is imported instead.");
ly_log_level(LY_LLWRN);
assert_true(LYS_MOD_LATEST_SEARCHDIRS & mod1->latest_revision);
assert_int_equal(1, mod1->implemented);
import = mod2->parsed->imports[0].module;
assert_true(LYS_MOD_IMPORTED_REV & import->latest_revision);
assert_string_equal("2019-09-16", import->revision);
assert_int_equal(0, import->implemented);
import = mod3->parsed->imports[0].module;
assert_string_equal("2019-09-16", import->revision);
assert_non_null(ly_ctx_get_module(UTEST_LYCTX, "a", "2019-09-16"));
assert_non_null(ly_ctx_get_module(UTEST_LYCTX, "a", "2019-09-17"));
assert_string_equal("2019-09-17", ly_ctx_get_module_implemented(UTEST_LYCTX, "a")->revision);
ly_ctx_destroy(UTEST_LYCTX);
/* check of circular dependency */
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, ctx_options, &UTEST_LYCTX));
str = "module a {namespace urn:a; prefix a;"
"import b {prefix b;}"
"}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, str);
str = "module b { yang-version 1.1; namespace urn:b; prefix b;"
"import a {prefix a;}"
"}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
ly_err_clean(UTEST_LYCTX, NULL);
}
static void
test_get_models(void **state)
{
struct lys_module *mod, *mod2;
const char *str0 = "module a {namespace urn:a;prefix a;}";
const char *str1 = "module a {namespace urn:a;prefix a;revision 2018-10-23;}";
const char *str2 = "module a {namespace urn:a;prefix a;revision 2018-10-23;revision 2018-10-24;}";
struct ly_in *in0, *in1, *in2;
struct lys_glob_unres unres = {0};
unsigned int index = 0;
const char *names[] = {
"ietf-yang-metadata", "yang", "ietf-inet-types", "ietf-yang-types", "ietf-yang-schema-mount",
"ietf-yang-structure-ext", "ietf-datastores", "ietf-yang-library", "a", "a", "a"
};
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str0, &in0));
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str1, &in1));
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str2, &in2));
/* invalid arguments */
assert_ptr_equal(NULL, ly_ctx_get_module(NULL, NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_get_module()).");
assert_ptr_equal(NULL, ly_ctx_get_module(UTEST_LYCTX, NULL, NULL));
CHECK_LOG_CTX("Invalid argument name (ly_ctx_get_module()).", NULL, 0);
assert_ptr_equal(NULL, ly_ctx_get_module_ns(NULL, NULL, NULL));
CHECK_LOG_LASTMSG("Invalid argument ctx (ly_ctx_get_module_ns()).");
assert_ptr_equal(NULL, ly_ctx_get_module_ns(UTEST_LYCTX, NULL, NULL));
CHECK_LOG_CTX("Invalid argument ns (ly_ctx_get_module_ns()).", NULL, 0);
assert_null(ly_ctx_get_module(UTEST_LYCTX, "nonsence", NULL));
/* internal modules */
assert_null(ly_ctx_get_module_implemented(UTEST_LYCTX, "ietf-yang-types"));
mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "yang");
assert_non_null(mod);
assert_non_null(mod->parsed);
assert_string_equal("yang", mod->name);
mod2 = ly_ctx_get_module_implemented_ns(UTEST_LYCTX, mod->ns);
assert_ptr_equal(mod, mod2);
assert_non_null(ly_ctx_get_module(UTEST_LYCTX, "ietf-yang-metadata", "2016-08-05"));
assert_non_null(ly_ctx_get_module(UTEST_LYCTX, "ietf-yang-types", "2013-07-15"));
assert_non_null(ly_ctx_get_module(UTEST_LYCTX, "ietf-inet-types", "2013-07-15"));
assert_non_null(ly_ctx_get_module_ns(UTEST_LYCTX, "urn:ietf:params:xml:ns:yang:ietf-datastores", "2018-02-14"));
/* select module by revision */
assert_int_equal(LY_SUCCESS, lys_parse(UTEST_LYCTX, in1, LYS_IN_YANG, NULL, &mod));
/* invalid attempts - implementing module of the same name and inserting the same module */
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in2, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod2));
assert_int_equal(LY_EDENIED, lys_implement(mod2, NULL, &unres));
CHECK_LOG_CTX("Module \"a@2018-10-24\" is already implemented in revision \"2018-10-23\".", NULL, 0);
lys_unres_glob_erase(&unres);
ly_in_reset(in1);
/* it is already there, fine */
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in1, LYS_IN_YANG, NULL, NULL, &unres.creating, NULL));
/* insert the second module only as imported, not implemented */
lys_unres_glob_erase(&unres);
ly_in_reset(in2);
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in2, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod2));
lys_unres_glob_erase(&unres);
assert_non_null(mod2);
assert_ptr_not_equal(mod, mod2);
mod = ly_ctx_get_module_latest(UTEST_LYCTX, "a");
assert_ptr_equal(mod, mod2);
mod2 = ly_ctx_get_module_latest_ns(UTEST_LYCTX, mod->ns);
assert_ptr_equal(mod, mod2);
/* work with module with no revision */
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in0, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod));
lys_unres_glob_erase(&unres);
assert_ptr_equal(mod, ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
assert_ptr_not_equal(mod, ly_ctx_get_module_latest(UTEST_LYCTX, "a"));
str1 = "submodule b {belongs-to a {prefix a;}}";
ly_in_free(in1, 0);
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str1, &in1));
assert_int_equal(LY_EINVAL, lys_parse_in(UTEST_LYCTX, in1, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod));
CHECK_LOG_CTX("Input data contains submodule which cannot be parsed directly without its main module.", NULL, 0);
lys_unres_glob_erase(&unres);
while ((mod = (struct lys_module *)ly_ctx_get_module_iter(UTEST_LYCTX, &index))) {
assert_string_equal(names[index - 1], mod->name);
}
assert_int_equal(11, index);
/* cleanup */
ly_in_free(in0, 0);
ly_in_free(in1, 0);
ly_in_free(in2, 0);
}
static void
test_ylmem(void **state)
{
#define DATA_YANG_LIBRARY_START "<yang-library xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"\
" <module-set>\n"\
" <name>complete</name>\n"\
" <module>\n"\
" <name>yang</name>\n"\
" <revision>2022-06-16</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"\
" </module>\n"\
" <module>\n"\
" <name>ietf-yang-library</name>\n"\
" <revision>2019-01-04</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>\n"\
" </module>\n"
#define DATA_YANG_BASE_IMPORTS " <import-only-module>\n"\
" <name>ietf-yang-metadata</name>\n"\
" <revision>2016-08-05</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-metadata</namespace>\n"\
" </import-only-module>\n"\
" <import-only-module>\n"\
" <name>ietf-inet-types</name>\n"\
" <revision>2013-07-15</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</namespace>\n"\
" </import-only-module>\n"\
" <import-only-module>\n"\
" <name>ietf-yang-types</name>\n"\
" <revision>2013-07-15</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</namespace>\n"\
" </import-only-module>\n"\
" <import-only-module>\n"\
" <name>ietf-datastores</name>\n"\
" <revision>2018-02-14</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-datastores</namespace>\n"\
" </import-only-module>\n"
#define DATA_YANG_SCHEMA_MODULE_STATE " </module-set>\n"\
" <schema>\n"\
" <name>complete</name>\n"\
" <module-set>complete</module-set>\n"\
" </schema>\n"\
" <content-id>9</content-id>\n"\
"</yang-library>\n"\
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"\
" <module-set-id>12</module-set-id>\n"\
" <module>\n"\
" <name>ietf-yang-metadata</name>\n"\
" <revision>2016-08-05</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-metadata</namespace>\n"\
" <conformance-type>import</conformance-type>\n"\
" </module>\n"\
" <module>\n"\
" <name>yang</name>\n"\
" <revision>2022-06-16</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"\
" <conformance-type>implement</conformance-type>\n"\
" </module>\n"\
" <module>\n"\
" <name>ietf-inet-types</name>\n"\
" <revision>2013-07-15</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</namespace>\n"\
" <conformance-type>import</conformance-type>\n"\
" </module>\n"\
" <module>\n"\
" <name>ietf-yang-types</name>\n"\
" <revision>2013-07-15</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</namespace>\n"\
" <conformance-type>import</conformance-type>\n"\
" </module>\n"\
" <module>\n"\
" <name>ietf-yang-library</name>\n"\
" <revision>2019-01-04</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>\n"\
" <conformance-type>implement</conformance-type>\n"\
" </module>\n"\
" <module>\n"\
" <name>ietf-datastores</name>\n"\
" <revision>2018-02-14</revision>\n"\
" <namespace>urn:ietf:params:xml:ns:yang:ietf-datastores</namespace>\n"\
" <conformance-type>import</conformance-type>\n"\
" </module>\n"
const char *yanglibrary_only =
DATA_YANG_LIBRARY_START
DATA_YANG_BASE_IMPORTS
DATA_YANG_SCHEMA_MODULE_STATE
"</modules-state>\n";
const char *with_netconf =
DATA_YANG_LIBRARY_START
" <module>\n"
" <name>ietf-netconf</name>\n"
" <revision>2011-06-01</revision>\n"
" <namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace>\n"
" </module>\n"
DATA_YANG_BASE_IMPORTS
" <import-only-module>\n"
" <name>ietf-netconf-acm</name>\n"
" <revision>2018-02-14</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-acm</namespace>\n"
" </import-only-module>\n"
DATA_YANG_SCHEMA_MODULE_STATE
" <module>\n"
" <name>ietf-netconf</name>\n"
" <revision>2011-06-01</revision>\n"
" <namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace>\n"
" <conformance-type>implement</conformance-type>\n"
" </module>\n"
" <module>\n"
" <name>ietf-netconf-acm</name>\n"
" <revision>2018-02-14</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-acm</namespace>\n"
" <conformance-type>import</conformance-type>\n"
" </module>\n"
"</modules-state>";
char *with_netconf_features = malloc(8096);
strcpy(with_netconf_features,
DATA_YANG_LIBRARY_START
" <module>\n"
" <name>ietf-netconf</name>\n"
" <revision>2011-06-01</revision>\n"
" <namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace>\n"
" <feature>writable-running</feature>\n"
" <feature>candidate</feature>\n"
" <feature>confirmed-commit</feature>\n"
" <feature>rollback-on-error</feature>\n"
" <feature>validate</feature>\n"
" <feature>startup</feature>\n"
" <feature>url</feature>\n"
" <feature>xpath</feature>\n"
" </module>\n"
" <import-only-module>\n"
" <name>ietf-yang-metadata</name>\n"
" <revision>2016-08-05</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-metadata</namespace>\n"
" </import-only-module>\n"
" <import-only-module>\n"
" <name>ietf-inet-types</name>\n"
" <revision>2013-07-15</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</namespace>\n"
" </import-only-module>\n"
" <import-only-module>\n"
" <name>ietf-yang-types</name>\n"
" <revision>2013-07-15</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</namespace>\n"
" </import-only-module>\n"
" <import-only-module>\n"
" <name>ietf-datastores</name>\n"
" <revision>2018-02-14</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:ietf-datastores</namespace>\n"
" </import-only-module>\n"
" <import-only-module>\n"
" <name>ietf-netconf-acm</name>\n"
" <revision>2018-02-14</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-acm</namespace>\n"
" </import-only-module>\n");
strcpy(with_netconf_features + strlen(with_netconf_features),
DATA_YANG_SCHEMA_MODULE_STATE
" <module>\n"
" <name>ietf-netconf</name>\n"
" <revision>2011-06-01</revision>\n"
" <namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace>\n"
" <feature>writable-running</feature>\n"
" <feature>candidate</feature>\n"
" <feature>confirmed-commit</feature>\n"
" <feature>rollback-on-error</feature>\n"
" <feature>validate</feature>\n"
" <feature>startup</feature>\n"
" <feature>url</feature>\n"
" <feature>xpath</feature>\n"
" <conformance-type>implement</conformance-type>\n"
" </module>\n"
" <module>\n"
" <name>ietf-netconf-acm</name>\n"
" <revision>2018-02-14</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-acm</namespace>\n"
" <conformance-type>import</conformance-type>\n"
" </module>\n"
"</modules-state>");
const char *garbage_revision =
"<yang-library xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
" <module-set>\n"
" <name>complete</name>\n"
" <module>\n"
" <name>yang</name>\n"
" <revision>2022-06-16</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"
" </module>\n"
" <module>\n"
" <name>ietf-yang-library</name>\n"
" <revision>2019-01-01</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>\n"
" </module>\n"
DATA_YANG_BASE_IMPORTS
DATA_YANG_SCHEMA_MODULE_STATE
"</modules-state>\n";
const char *no_yanglibrary =
"<yang-library xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
" <module-set>\n"
" <name>complete</name>\n"
" <module>\n"
" <name>yang</name>\n"
" <revision>2022-06-16</revision>\n"
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"
" </module>\n"
DATA_YANG_BASE_IMPORTS
DATA_YANG_SCHEMA_MODULE_STATE
"</modules-state>\n";
(void) state;
/* seperate context to avoid double free during teadown */
struct ly_ctx *ctx_test = NULL;
/* test invalid parameters */
assert_int_equal(LY_EINVAL, ly_ctx_new_ylpath(NULL, NULL, LYD_XML, 0, &ctx_test));
assert_int_equal(LY_EINVAL, ly_ctx_new_ylpath(NULL, TESTS_SRC, LYD_XML, 0, NULL));
assert_int_equal(LY_ESYS, ly_ctx_new_ylpath(NULL, TESTS_SRC "garbage", LYD_XML, 0, &ctx_test));
/* basic test with ietf-yang-library-only */
assert_int_equal(LY_SUCCESS, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", yanglibrary_only, LYD_XML, 0, &ctx_test));
assert_non_null(ly_ctx_get_module(ctx_test, "ietf-yang-library", "2019-01-04"));
assert_null(ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01"));
ly_ctx_destroy(ctx_test);
ctx_test = NULL;
/* test loading module, should also import other module */
assert_int_equal(LY_SUCCESS, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", with_netconf, LYD_XML, 0, &ctx_test));
assert_non_null(ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01"));
assert_int_equal(1, ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01")->implemented);
assert_non_null(ly_ctx_get_module(ctx_test, "ietf-netconf-acm", "2018-02-14"));
assert_int_equal(0, ly_ctx_get_module(ctx_test, "ietf-netconf-acm", "2018-02-14")->implemented);
assert_int_equal(LY_ENOT, lys_feature_value(ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01"), "url"));
ly_ctx_destroy(ctx_test);
ctx_test = NULL;
/* test loading module with feature if they are present */
assert_int_equal(LY_SUCCESS, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", with_netconf_features, LYD_XML, 0, &ctx_test));
assert_non_null(ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01"));
assert_non_null(ly_ctx_get_module(ctx_test, "ietf-netconf-acm", "2018-02-14"));
assert_int_equal(LY_SUCCESS, lys_feature_value(ly_ctx_get_module(ctx_test, "ietf-netconf", "2011-06-01"), "url"));
ly_ctx_destroy(ctx_test);
ctx_test = NULL;
/* test with not matching revision */
assert_int_equal(LY_EINVAL, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", garbage_revision, LYD_XML, 0, &ctx_test));
/* test data containing ietf-yang-library which conflicts with the option */
assert_int_equal(LY_EINVAL, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", with_netconf_features, LYD_XML, LY_CTX_NO_YANGLIBRARY, &ctx_test));
/* test creating without ietf-yang-library */
assert_int_equal(LY_SUCCESS, ly_ctx_new_ylmem(TESTS_SRC "/modules/yang/", no_yanglibrary, LYD_XML, LY_CTX_NO_YANGLIBRARY, &ctx_test));
assert_int_equal(NULL, ly_ctx_get_module(ctx_test, "ietf-yang-library", "2019-01-04"));
ly_ctx_destroy(ctx_test);
free(with_netconf_features);
}
static LY_ERR
check_node_priv_parsed_is_set(struct lysc_node *node, void *data, ly_bool *UNUSED(dfs_continue))
{
const struct lysp_node *pnode;
const char ***iter;
pnode = (const struct lysp_node *)node->priv;
CHECK_POINTER(pnode, 1);
iter = (const char ***)data;
CHECK_POINTER(**iter, 1);
CHECK_STRING(pnode->name, **iter);
(*iter)++;
return LY_SUCCESS;
}
static LY_ERR
check_node_priv_parsed_not_set(struct lysc_node *node, void *UNUSED(data), ly_bool *UNUSED(dfs_continue))
{
CHECK_POINTER(node->priv, 0);
return LY_SUCCESS;
}
static void
check_ext_instance_priv_parsed_is_set(struct lysc_ext_instance *ext)
{
LY_ARRAY_COUNT_TYPE u, v;
struct lysc_ext_substmt *substmts;
struct lysc_node *cnode;
const char **iter;
const char *check[] = {
"tmp_cont", "lf", NULL
};
LY_ARRAY_FOR(ext, u) {
substmts = ext[u].substmts;
LY_ARRAY_FOR(substmts, v) {
if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
cnode = *(struct lysc_node **)substmts[v].storage_p;
iter = check;
assert_int_equal(LY_SUCCESS, lysc_tree_dfs_full(cnode, check_node_priv_parsed_is_set, &iter));
}
}
}
}
static void
check_ext_instance_priv_parsed_not_set(struct lysc_ext_instance *ext)
{
LY_ARRAY_COUNT_TYPE u, v;
struct lysc_ext_substmt *substmts;
struct lysc_node *cnode;
LY_ARRAY_FOR(ext, u) {
substmts = ext[u].substmts;
LY_ARRAY_FOR(substmts, v) {
if (substmts && substmts[v].storage_p && (substmts[v].stmt & LY_STMT_DATA_NODE_MASK)) {
cnode = *(struct lysc_node **)substmts[v].storage_p;
if (cnode) {
CHECK_POINTER((struct lysp_node *)cnode->priv, 0);
}
}
}
}
}
/**
* @brief Testing of LY_CTX_SET_PRIV_PARSED.
*/
static void
test_set_priv_parsed(void **state)
{
struct lys_module *mod;
const char *schema_a;
const char **iter;
const char *check[] = {
"cont", "contnotif", "contx", "grpleaf", "augleaf", "l1",
"l1a", "l1b", "l1c", "foo1", "ll", "any", "l2",
"l2c", "l2cx", "ch", "cas", "casx", "oper",
"input", "inparam", "output", "outparam", "n1", NULL
};
/* each node must have a unique name. */
schema_a = "module a {\n"
" namespace urn:tests:a;\n"
" prefix a;yang-version 1.1;\n"
"\n"
" import ietf-restconf {\n"
" prefix rc;\n"
" revision-date 2017-01-26;\n"
" }\n"
"\n"
" rc:yang-data \"tmp\" {\n"
" container tmp_cont {\n"
" leaf lf {\n"
" type string;\n"
" }\n"
" }\n"
" }\n"
" container cont {\n"
" notification contnotif;\n"
" leaf-list contx {\n"
" type string;\n"
" }\n"
" uses grp;\n"
" }\n"
" list l1 {\n"
" key \"l1a l1b\";\n"
" leaf l1a {\n"
" type string;\n"
" }\n"
" leaf l1b {\n"
" type string;\n"
" }\n"
" leaf l1c {\n"
" type string;\n"
" }\n"
" }\n"
" feature f1;\n"
" feature f2;\n"
" leaf foo1 {\n"
" type uint16;\n"
" if-feature f1;\n"
" }\n"
" leaf foo2 {\n"
" type uint16;\n"
" }\n"
" leaf foo3 {\n"
" type uint16;\n"
" if-feature f2;\n"
" }\n"
" leaf-list ll {\n"
" type string;\n"
" }\n"
" anydata any {\n"
" config false;\n"
" }\n"
" list l2 {\n"
" config false;\n"
" container l2c {\n"
" leaf l2cx {\n"
" type string;\n"
" }\n"
" }\n"
" }\n"
" choice ch {\n"
" case cas {\n"
" leaf casx {\n"
" type string;\n"
" }\n"
" }\n"
" }\n"
" rpc oper {\n"
" input {\n"
" leaf inparam {\n"
" type string;\n"
" }\n"
" }\n"
" output {\n"
" leaf outparam {\n"
" type int8;\n"
" }\n"
" }\n"
" }\n"
" notification n1;\n"
" grouping grp {\n"
" leaf grpleaf {\n"
" type uint16;\n"
" }\n"
" }\n"
" augment /cont {\n"
" leaf augleaf {\n"
" type uint16;\n"
" }\n"
" }\n"
" deviation /a:foo2 {\n"
" deviate not-supported;\n"
" }\n"
"}\n";
/* use own context with extra flags */
ly_ctx_destroy(UTEST_LYCTX);
const char *feats[] = {"f1", NULL};
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_SET_PRIV_PARSED, &UTEST_LYCTX));
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-restconf", "2017-01-26", NULL));
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, feats, NULL);
mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL);
iter = check;
assert_int_equal(LY_SUCCESS, lysc_module_dfs_full(mod, check_node_priv_parsed_is_set, &iter));
check_ext_instance_priv_parsed_is_set(mod->compiled->exts);
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_SET_PRIV_PARSED));
mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL);
iter = check;
assert_int_equal(LY_SUCCESS, lysc_module_dfs_full(mod, check_node_priv_parsed_not_set, &iter));
check_ext_instance_priv_parsed_not_set(mod->compiled->exts);
assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_SET_PRIV_PARSED));
mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL);
iter = check;
assert_int_equal(LY_SUCCESS, lysc_module_dfs_full(mod, check_node_priv_parsed_is_set, &iter));
check_ext_instance_priv_parsed_is_set(mod->compiled->exts);
}
static void
test_explicit_compile(void **state)
{
uint32_t i;
struct lys_module *mod;
const char *schema_a = "module a {\n"
" namespace urn:tests:a;\n"
" prefix a;yang-version 1.1;\n"
" feature f1;\n"
" feature f2;\n"
" leaf foo1 {\n"
" type uint16;\n"
" if-feature f1;\n"
" }\n"
" leaf foo2 {\n"
" type uint16;\n"
" }\n"
" container cont {\n"
" leaf foo3 {\n"
" type string;\n"
" }\n"
" }\n"
"}\n";
const char *schema_b = "module b {\n"
" namespace urn:tests:b;\n"
" prefix b;yang-version 1.1;\n"
" import a {\n"
" prefix a;\n"
" }\n"
" augment /a:cont {\n"
" leaf augleaf {\n"
" type uint16;\n"
" }\n"
" }\n"
"}\n";
const char *schema_c = "module c {\n"
" namespace urn:tests:c;\n"
" prefix c;yang-version 1.1;\n"
" import a {\n"
" prefix a;\n"
" }\n"
" deviation /a:foo2 {\n"
" deviate not-supported;\n"
" }\n"
"}\n";
/* use own context with extra flags */
ly_ctx_destroy(UTEST_LYCTX);
const char *feats[] = {"f1", NULL};
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_EXPLICIT_COMPILE, &UTEST_LYCTX));
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, &mod);
UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
UTEST_ADD_MODULE(schema_c, LYS_IN_YANG, NULL, NULL);
assert_int_equal(LY_SUCCESS, lys_set_implemented((struct lys_module *)mod, feats));
/* none of the modules should be compiled */
i = 0;
while ((mod = ly_ctx_get_module_iter(UTEST_LYCTX, &i))) {
assert_null(mod->compiled);
}
assert_int_equal(LY_SUCCESS, ly_ctx_compile(UTEST_LYCTX));
/* check internal modules */
mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "yang");
assert_non_null(mod);
mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "ietf-datastores");
assert_non_null(mod);
mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "ietf-yang-library");
assert_non_null(mod);
/* check test modules */
mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "a");
assert_non_null(mod);
mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "b");
assert_non_null(mod);
mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "c");
assert_non_null(mod);
}
static void
test_free_parsed(void **state)
{
ly_ctx_free_parsed(UTEST_LYCTX);
ly_ctx_destroy(UTEST_LYCTX);
UTEST_LYCTX = NULL;
}
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_searchdirs),
UTEST(test_options),
UTEST(test_models),
UTEST(test_imports),
UTEST(test_get_models),
UTEST(test_ylmem),
UTEST(test_set_priv_parsed),
UTEST(test_explicit_compile),
UTEST(test_free_parsed),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}