/* * @file test_libyang.c * @author: Mislav Novakovic * @brief unit tests for functions from libyang.h header * * Copyright (C) 2016 Deutsche Telekom AG. * * Author: Mislav Novakovic * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include "tests/config.h" #include "libyang.h" /* include private header to be able to check internal values */ #include "../../src/context.h" struct ly_ctx *ctx = NULL; struct lyd_node *root = NULL; const struct lys_module *module = NULL; static int setup_f(void **state) { (void) state; /* unused */ char *config_file = TESTS_DIR"/api/files/a.xml"; char *yin_file = TESTS_DIR"/api/files/a.yin"; char *yang_file = TESTS_DIR"/api/files/b.yang"; char *yang_dev_file = TESTS_DIR"/api/files/b-dev.yang"; char *yang_folder = TESTS_DIR"/api/files"; ctx = ly_ctx_new(yang_folder, 0); if (!ctx) { return -1; } if (!lys_parse_path(ctx, yin_file, LYS_IN_YIN)) { return -1; } if (!(module = lys_parse_path(ctx, yang_file, LYS_IN_YANG))) { return -1; } if (!lys_parse_path(ctx, yang_dev_file, LYS_IN_YANG)) { return -1; } root = lyd_parse_path(ctx, config_file, LYD_XML, LYD_OPT_CONFIG | LYD_OPT_STRICT); if (!root) { return -1; } return 0; } static int teardown_f(void **state) { (void) state; /* unused */ if (root) { lyd_free_withsiblings(root); } if (ctx) { ly_ctx_destroy(ctx, NULL); } root = NULL; ctx = NULL; return 0; } static void test_ly_ctx_new(void **state) { char *yang_folder1 = TESTS_DIR"/data/files"; char *yang_folder2 = TESTS_DIR"/data:"TESTS_DIR"/data/files"; const char * const *list = NULL; (void) state; /* unused */ ctx = ly_ctx_new(yang_folder1, 0); assert_ptr_not_equal(NULL, ctx); list = ly_ctx_get_searchdirs(ctx); assert_ptr_not_equal(NULL, list); assert_ptr_not_equal(NULL, list[0]); assert_ptr_equal(NULL, list[1]); ly_ctx_destroy(ctx, NULL); ctx = ly_ctx_new(yang_folder2, 0); assert_ptr_not_equal(NULL, ctx); list = ly_ctx_get_searchdirs(ctx); assert_ptr_not_equal(NULL, list); assert_ptr_not_equal(NULL, list[0]); assert_ptr_not_equal(NULL, list[1]); assert_ptr_equal(NULL, list[2]); ly_ctx_destroy(ctx, NULL); } static void test_ly_ctx_new_invalid(void **state) { char *yang_folder = "INVALID_PATH"; (void) state; /* unused */ ctx = ly_ctx_new(yang_folder, 0); if (ctx) { fail(); } } static void test_ly_ctx_get_searchdirs(void **state) { const char * const *result; char yang_folder[PATH_MAX]; (void) state; /* unused */ assert_ptr_not_equal(realpath(TESTS_DIR"/data/files", yang_folder), NULL); ctx = ly_ctx_new(yang_folder, 0); if (!ctx) { fail(); } result = ly_ctx_get_searchdirs(ctx); if (!result) { fail(); } assert_string_equal(yang_folder, result[0]); assert_ptr_equal(NULL, result[1]); ly_ctx_destroy(ctx, NULL); } static void test_ly_ctx_set_searchdir(void **state) { const char * const *result; char yang_folder[PATH_MAX]; char new_yang_folder[PATH_MAX]; (void) state; /* unused */ assert_ptr_not_equal(realpath(TESTS_DIR"/data/files", yang_folder), NULL); assert_ptr_not_equal(realpath(TESTS_DIR"/schema/yin", new_yang_folder), NULL); ctx = ly_ctx_new(yang_folder, 0); if (!ctx) { fail(); } ly_ctx_set_searchdir(ctx, new_yang_folder); result = ly_ctx_get_searchdirs(ctx); if (!result) { fail(); } assert_string_equal(yang_folder, result[0]); assert_string_equal(new_yang_folder, result[1]); assert_ptr_equal(NULL, result[2]); ly_ctx_unset_searchdirs(ctx, 0); assert_string_equal(new_yang_folder, result[0]); assert_ptr_equal(NULL, result[1]); ly_ctx_destroy(ctx, NULL); } static void test_ly_ctx_set_searchdir_invalid(void **state) { const char * const *result; char yang_folder[PATH_MAX]; char *new_yang_folder = "INVALID_PATH"; (void) state; /* unused */ assert_ptr_not_equal(realpath(TESTS_DIR"/data/files", yang_folder), NULL); ctx = ly_ctx_new(yang_folder, 0); if (!ctx) { fail(); } /* adding duplicity - the path is not duplicated */ ly_ctx_set_searchdir(NULL, yang_folder); result = ly_ctx_get_searchdirs(ctx); if (!result) { fail(); } assert_string_equal(yang_folder, result[0]); assert_ptr_equal(NULL, result[1]); /* adding invalid path, previous is kept */ ly_ctx_set_searchdir(ctx, new_yang_folder); result = ly_ctx_get_searchdirs(ctx); if (!result) { fail(); } assert_string_equal(yang_folder, result[0]); assert_ptr_equal(NULL, result[1]); ly_ctx_unset_searchdirs(ctx, -1); result = ly_ctx_get_searchdirs(ctx); if (result) { fail(); } ly_ctx_destroy(ctx, NULL); } static void test_ly_ctx_info(void **state) { struct lyd_node *node; (void) state; /* unused */ node = ly_ctx_info(NULL); if (node) { fail(); } node = ly_ctx_info(ctx); if (!node) { fail(); } assert_int_equal(LYD_VAL_OK, node->validity); lyd_free_withsiblings(node); } static void test_ly_ctx_new_ylmem(void **state) { struct lyd_node *node; char *mem; struct ly_ctx *new_ctx; (void) state; /* unused */ node = ly_ctx_info(ctx); if (!node) { fail(); } if (lyd_print_mem(&mem, node, LYD_XML, LYP_WITHSIBLINGS)) { fail(); } new_ctx = ly_ctx_new_ylmem(TESTS_DIR"/api/files", mem, LYD_XML, 0); if (!new_ctx) { fail(); } lyd_free_withsiblings(node); free(mem); ly_ctx_destroy(new_ctx, NULL); } static void test_ly_ctx_module_clb(void **state) { (void) state; void *clb, *data; assert_ptr_equal(clb = ly_ctx_get_module_imp_clb(ctx, &data), NULL); assert_ptr_equal(data, NULL); clb = (intptr_t *)64; data = (intptr_t *)128; ly_ctx_set_module_imp_clb(ctx, clb, data); assert_ptr_equal(ly_ctx_get_module_imp_clb(ctx, &data), clb); assert_ptr_equal(data, (intptr_t *)128); ly_ctx_set_module_imp_clb(ctx, NULL, NULL); assert_ptr_equal(clb = ly_ctx_get_module_data_clb(ctx, &data), NULL); assert_ptr_equal(data, NULL); clb = (intptr_t *)64; data = (intptr_t *)128; ly_ctx_set_module_data_clb(ctx, clb, data); assert_ptr_equal(ly_ctx_get_module_data_clb(ctx, &data), clb); assert_ptr_equal(data, (intptr_t *)128); ly_ctx_set_module_data_clb(ctx, NULL, NULL); } static void test_ly_ctx_get_module(void **state) { (void) state; /* unused */ const struct lys_module *module; const char *name1 = "a"; const char *name2 = "b"; const char *revision = "2016-03-01"; module = ly_ctx_get_module(NULL, name1, NULL, 0); if (module) { fail(); } module = ly_ctx_get_module(ctx, NULL, NULL, 0); if (module) { fail(); } module = ly_ctx_get_module(ctx, "invalid", NULL, 0); if (module) { fail(); } module = ly_ctx_get_module(ctx, name1, NULL, 0); if (!module) { fail(); } assert_string_equal("a", module->name); module = ly_ctx_get_module(ctx, name1, "invalid", 0); if (module) { fail(); } module = ly_ctx_get_module(ctx, name1, revision, 0); if (!module) { fail(); } assert_string_equal(revision, module->rev->date); module = ly_ctx_get_module(ctx, name2, NULL, 0); if (!module) { fail(); } assert_string_equal("b", module->name); module = ly_ctx_get_module(ctx, name2, "invalid", 0); if (module) { fail(); } module = ly_ctx_get_module(ctx, name2, revision, 0); if (!module) { fail(); } assert_string_equal(revision, module->rev->date); } static void test_ly_ctx_get_module_older(void **state) { (void) state; /* unused */ const struct lys_module *module = NULL; const struct lys_module *module_older = NULL; const char *name = "a"; const char *revision = "2016-03-01"; const char *revision_older = "2015-01-01"; module_older = ly_ctx_get_module_older(NULL, module); if (module_older) { fail(); } module_older = ly_ctx_get_module_older(ctx, NULL); if (module_older) { fail(); } module = ly_ctx_load_module(ctx, "c", NULL); if (!module) { fail(); } module = ly_ctx_load_module(ctx, name, revision); if (!module) { fail(); } module_older = ly_ctx_get_module_older(ctx, module); if (!module_older) { fail(); } assert_string_equal(revision_older, module_older->rev->date); } static void test_ly_ctx_load_module(void **state) { (void) state; /* unused */ const struct lys_module *module; const char *name = "a"; const char *revision = "2015-01-01"; module = ly_ctx_load_module(NULL, name, revision); if (module) { fail(); } module = ly_ctx_load_module(ctx, NULL, revision); if (module) { fail(); } module = ly_ctx_load_module(ctx, "INVALID_NAME", revision); if (module) { fail(); } module = ly_ctx_load_module(ctx, "c", NULL); if (!module) { fail(); } assert_string_equal("c", module->name); module = ly_ctx_get_module(ctx, "a", revision, 0); if (!module) { fail(); } assert_string_equal("a", module->name); module = ly_ctx_get_module(ctx, "b", revision, 0); if (!module) { fail(); } assert_string_equal("b", module->name); } static void test_ly_ctx_clean(void **state) { (void) state; /* unused */ const struct lys_module *mod; struct ly_ctx *ctx; uint32_t dict_used; uint16_t setid; int modules_count; ctx = ly_ctx_new(TESTS_DIR"/api/files/", 0); /* remember starting values */ setid = ctx->models.module_set_id; modules_count = ctx->models.used; dict_used = ctx->dict.hash_tab->used; /* add a module */ mod = ly_ctx_load_module(ctx, "x", NULL); assert_ptr_not_equal(mod, NULL); assert_int_equal(modules_count + 1, ctx->models.used); assert_int_not_equal(dict_used, ctx->dict.hash_tab->used); /* clean the context */ ly_ctx_clean(ctx, NULL); assert_int_equal(setid + 2, ctx->models.module_set_id); assert_int_equal(modules_count, ctx->models.used); assert_int_equal(dict_used, ctx->dict.hash_tab->used); /* add a module again ... */ mod = ly_ctx_load_module(ctx, "x", NULL); assert_ptr_not_equal(mod, NULL); assert_int_equal(modules_count + 1, ctx->models.used); assert_int_not_equal(dict_used, ctx->dict.hash_tab->used); /* .. and add some string into dictionary */ assert_ptr_not_equal(lydict_insert(ctx, "qwertyuiop", 0), NULL); ++dict_used; /* clean the context */ ly_ctx_clean(ctx, NULL); assert_int_equal(setid + 4, ctx->models.module_set_id); assert_int_equal(modules_count, ctx->models.used); assert_int_equal(dict_used, ctx->dict.hash_tab->used); /* cleanup */ lydict_remove(ctx, "qwertyuiop"); ly_ctx_destroy(ctx, NULL); } static void test_ly_ctx_clean2(void **state) { (void) state; /* unused */ const char *yang_dep = "module x {" " namespace uri:x;" " prefix x;" " import ietf-yang-library { prefix yl; }" " leaf x { config false; type leafref { path /yl:modules-state/yl:module/yl:name; } } }"; struct ly_ctx *ctx; const struct lys_module *mod; struct lys_node_leaf *leaf; ctx = ly_ctx_new(NULL, 0); assert_ptr_not_equal(ctx, NULL); /* load module depending by leafref on internal ietf-yang-library */ assert_ptr_not_equal(lys_parse_mem(ctx, yang_dep, LYS_IN_YANG), NULL); /* get the target leaf in ietf-yang-library */ mod = ctx->models.list[ctx->internal_module_count - 1]; /* magic: leaf = /yl:modules-state/yl:module/yl:name */ leaf = (struct lys_node_leaf *)mod->data->prev->prev->child->next->child->prev->child->child; assert_true(leaf->backlinks && leaf->backlinks->number == 1); /* clean the context ... */ ly_ctx_clean(ctx, NULL); /* ... and check that the leafref backlinks are removed */ assert_true(!leaf->backlinks || !leaf->backlinks->number); /* cleanup */ ly_ctx_destroy(ctx, NULL); } static void test_ly_ctx_remove_module(void **state) { (void) state; /* unused */ const struct lys_module *mod; uint32_t dict_used; uint16_t setid; int modules_count; ctx = ly_ctx_new(TESTS_DIR"/api/files/", 0); /* remember starting values */ setid = ctx->models.module_set_id; modules_count = ctx->models.used; dict_used = ctx->dict.hash_tab->used; mod = ly_ctx_load_module(ctx, "x", NULL); ly_ctx_remove_module(mod, NULL); /* add a module */ mod = ly_ctx_load_module(ctx, "y", NULL); assert_ptr_not_equal(mod, NULL); assert_true(setid < ctx->models.module_set_id); setid = ctx->models.module_set_id; assert_int_equal(modules_count + 2, ctx->models.used); assert_int_not_equal(dict_used, ctx->dict.hash_tab->used); /* remove the imported module (x), that should cause removing also the loaded module (y) */ mod = ly_ctx_get_module(ctx, "x", NULL, 0); assert_ptr_not_equal(mod, NULL); ly_ctx_remove_module(mod, NULL); assert_true(setid < ctx->models.module_set_id); setid = ctx->models.module_set_id; assert_int_equal(modules_count, ctx->models.used); assert_int_equal(dict_used, ctx->dict.hash_tab->used); /* add a module again ... */ mod = ly_ctx_load_module(ctx, "y", NULL); assert_ptr_not_equal(mod, NULL); assert_true(setid < ctx->models.module_set_id); setid = ctx->models.module_set_id; assert_int_equal(modules_count + 2, ctx->models.used); assert_int_not_equal(dict_used, ctx->dict.hash_tab->used); /* ... now remove the loaded module, the imported module is supposed to be removed because it is not * used in any other module */ ly_ctx_remove_module(mod, NULL); assert_true(setid < ctx->models.module_set_id); setid = ctx->models.module_set_id; assert_int_equal(modules_count, ctx->models.used); assert_int_equal(dict_used, ctx->dict.hash_tab->used); /* add a module again ... */ mod = ly_ctx_load_module(ctx, "y", NULL); assert_ptr_not_equal(mod, NULL); assert_true(setid < ctx->models.module_set_id); setid = ctx->models.module_set_id; assert_int_equal(modules_count + 2, ctx->models.used); assert_int_not_equal(dict_used, ctx->dict.hash_tab->used); /* and mark even the imported module 'x' as implemented ... */ assert_int_equal(lys_set_implemented(mod->imp[0].module), EXIT_SUCCESS); /* ... now remove the loaded module, the imported module is supposed to be kept because it is implemented */ ly_ctx_remove_module(mod, NULL); assert_true(setid < ctx->models.module_set_id); setid = ctx->models.module_set_id; assert_int_equal(modules_count + 1, ctx->models.used); assert_int_not_equal(dict_used, ctx->dict.hash_tab->used); mod = ly_ctx_get_module(ctx, "y", NULL, 0); assert_ptr_equal(mod, NULL); mod = ly_ctx_get_module(ctx, "x", NULL, 0); assert_ptr_not_equal(mod, NULL); ly_ctx_clean(ctx, NULL); /* add a module again ... */ mod = ly_ctx_load_module(ctx, "y", NULL); assert_true(setid < ctx->models.module_set_id); setid = ctx->models.module_set_id; assert_int_equal(modules_count + 2, ctx->models.used); assert_int_not_equal(dict_used, ctx->dict.hash_tab->used); /* and add another one also importing module 'x' ... */ assert_ptr_not_equal(ly_ctx_load_module(ctx, "z", NULL), NULL); assert_true(setid < ctx->models.module_set_id); setid = ctx->models.module_set_id; assert_int_equal(modules_count + 3, ctx->models.used); /* ... now remove the first loaded module, the imported module is supposed to be kept because it is used * by the second loaded module */ ly_ctx_remove_module(mod, NULL); assert_true(setid < ctx->models.module_set_id); setid = ctx->models.module_set_id; assert_int_equal(modules_count + 2, ctx->models.used); assert_int_not_equal(dict_used, ctx->dict.hash_tab->used); mod = ly_ctx_get_module(ctx, "y", NULL, 0); assert_ptr_equal(mod, NULL); mod = ly_ctx_get_module(ctx, "x", NULL, 0); assert_ptr_not_equal(mod, NULL); mod = ly_ctx_get_module(ctx, "z", NULL, 0); assert_ptr_not_equal(mod, NULL); } static void test_ly_ctx_remove_module2(void **state) { (void) state; /* unused */ const char *yang_main = "module x {" " namespace uri:x;" " prefix x;" " feature x;" " identity basex;" " leaf x { type string; } }"; const char *yang_dep = "module y {" " namespace uri:y;" " prefix y;" " import x { prefix x; }" " feature y { if-feature x:x; }" " identity y { base x:basex; }" " leaf y { type leafref { path /x:x; } } }"; const struct lys_module *mod; struct lys_node_leaf *leaf; ctx = ly_ctx_new(NULL, 0); assert_ptr_not_equal(ctx, NULL); /* load both modules, y depends on x and x will contain several backlinks to y */ assert_ptr_not_equal((mod = lys_parse_mem(ctx, yang_main, LYS_IN_YANG)), NULL); assert_ptr_not_equal(lys_parse_mem(ctx, yang_dep, LYS_IN_YANG), NULL); /* check that there are the expected backlinks */ leaf = (struct lys_node_leaf *)mod->data; assert_true(mod->features[0].depfeatures && mod->features[0].depfeatures->number); assert_true(mod->ident[0].der && mod->ident[0].der->number); assert_true(leaf->backlinks && leaf->backlinks->number); /* remove y ... */ mod = ly_ctx_get_module(ctx, "y", NULL, 0); assert_ptr_not_equal(mod, NULL); assert_int_equal(ly_ctx_remove_module(mod, NULL), 0); /* ... make sure that x is still present ... */ mod = ly_ctx_get_module(ctx, "x", NULL, 0); assert_ptr_not_equal(mod, NULL); leaf = (struct lys_node_leaf *)mod->data; /* ... and check that the backlinks in it were removed */ assert_true(!mod->features[0].depfeatures || !mod->features[0].depfeatures->number); assert_true(!mod->ident[0].der || !mod->ident[0].der->number); assert_true(!leaf->backlinks || !leaf->backlinks->number); } static void test_lys_set_enabled(void **state) { (void) state; /* unused */ const struct lys_module *mod; ctx = ly_ctx_new(NULL, 0); assert_ptr_not_equal(ctx, NULL); /* test failures - invalid input */ assert_int_not_equal(lys_set_enabled(NULL), 0); /* test success - enabled module */ mod = ly_ctx_get_module(ctx, "ietf-yang-library", NULL, 0); assert_ptr_not_equal(mod, NULL); assert_int_equal(lys_set_enabled(mod), 0); } /* include also some test for lys_set_enabled() */ static void test_lys_set_disabled(void **state) { (void) state; /* unused */ uint32_t idx; const struct lys_module *mod, *modx, *mody; const char *yang_x = "module x {" " namespace uri:x;" " prefix x;" " container x { presence yes; }}"; const char *yang_y = "module y {" " namespace uri:y;" " prefix y;" " import x { prefix x;}" " augment /x:x {" " leaf y { type string;}}}"; ctx = ly_ctx_new(NULL, 0); assert_ptr_not_equal(ctx, NULL); /* test failures - invalid input */ assert_int_not_equal(lys_set_disabled(NULL), 0); /* test failures - internal module */ mod = ly_ctx_get_module(ctx, "ietf-yang-library", NULL, 0); assert_ptr_not_equal(mod, NULL); assert_int_not_equal(lys_set_disabled(mod), 0); /* test success - disabling y extending x */ modx = lys_parse_mem(ctx, yang_x, LYS_IN_YANG); assert_ptr_not_equal(modx, NULL); mody = lys_parse_mem(ctx, yang_y, LYS_IN_YANG); assert_ptr_not_equal(mody, NULL); /* all the modules are enabled ... */ assert_int_equal(mody->disabled, 0); assert_int_equal(modx->disabled, 0); /* ... and the y's augment is applied */ assert_ptr_not_equal(modx->data->child, NULL); /* by disabling y ... */ assert_int_equal(lys_set_disabled(mody), 0); /* ... y is disabled while x stays enabled (it is implemented) ...*/ assert_int_equal(mody->disabled, 1); assert_int_equal(modx->disabled, 0); /* ... and y's augment disappeared from x */ assert_ptr_equal(modx->data->child, NULL); /* by enabling it, everything goes back */ assert_int_equal(lys_set_enabled(mody), 0); assert_int_equal(mody->disabled, 0); assert_int_equal(modx->disabled, 0); assert_ptr_not_equal(modx->data->child, NULL); /* by disabling x ... */ assert_int_equal(lys_set_disabled(modx), 0); /* ... both x and y are disabled (y depends on x) ...*/ assert_int_equal(mody->disabled, 1); assert_int_equal(modx->disabled, 1); /* ... and y's augment disappeared from x */ assert_ptr_equal(modx->data->child, NULL); /* iterate through all disabled modules */ idx = 0; mod = ly_ctx_get_disabled_module_iter(ctx, &idx); assert_ptr_not_equal(mod, NULL); assert_int_equal(mod->disabled, 1); assert_string_equal(mod->name, "x"); /* by enabling it, everything goes back */ assert_int_equal(lys_set_enabled(modx), 0); assert_int_equal(mody->disabled, 0); assert_int_equal(modx->disabled, 0); assert_ptr_not_equal(modx->data->child, NULL); } static void test_ly_ctx_get_module_by_ns(void **state) { (void) state; /* unused */ const struct lys_module *module; const char *ns = "urn:a"; const char *revision = NULL; module = ly_ctx_get_module_by_ns(NULL, ns, revision, 0); if (module) { fail(); } module = ly_ctx_get_module_by_ns(ctx, NULL, revision, 0); if (module) { fail(); } module = ly_ctx_get_module_by_ns(ctx, ns, revision, 0); if (!module) { fail(); } assert_string_equal("a", module->name); module = ly_ctx_get_module_by_ns(ctx, "urn:b", revision, 0); if (!module) { fail(); } assert_string_equal("b", module->name); } static void test_ly_ctx_get_submodule(void **state) { (void) state; /* unused */ const struct lys_submodule *submodule; const char *mod_name = "a"; const char *sub_name = "asub"; const char *revision = NULL; submodule = ly_ctx_get_submodule(NULL, mod_name, revision, sub_name, NULL); if (submodule) { fail(); } submodule = ly_ctx_get_submodule(ctx, NULL, revision, sub_name, "2010-02-08"); if (submodule) { fail(); } submodule = ly_ctx_get_submodule(ctx, mod_name, revision, NULL, NULL); if (submodule) { fail(); } submodule = ly_ctx_get_submodule(ctx, mod_name, revision, sub_name, NULL); if (!submodule) { fail(); } assert_string_equal("asub", submodule->name); submodule = ly_ctx_get_submodule(ctx, "b", revision, "bsub", NULL); if (!submodule) { fail(); } assert_string_equal("bsub", submodule->name); } static void test_ly_ctx_get_submodule2(void **state) { (void) state; /* unused */ const struct lys_submodule *submodule; const char *sub_name1 = "asub"; const char *sub_name2 = "bsub"; submodule = ly_ctx_get_submodule2(NULL, sub_name1); if (submodule) { fail(); } submodule = ly_ctx_get_submodule2(root->schema->module, NULL); if (submodule) { fail(); } submodule = ly_ctx_get_submodule2(root->schema->module, sub_name1); if (!submodule) { fail(); } assert_string_equal("asub", submodule->name); submodule = ly_ctx_get_submodule2(module, sub_name2); if (!submodule) { fail(); } assert_string_equal("bsub", submodule->name); } static void test_lys_find_path(void **state) { (void) state; /* unused */ struct ly_set *set; const char *nodeid1 = "/x/bubba"; const char *nodeid2 = "/b:x/b:bubba"; const char *nodeid3 = "/x/choic/con/con/lef"; set = lys_find_path(NULL, root->schema, nodeid1); if (!set || (set->number != 1)) { fail(); } ly_set_free(set); set = lys_find_path(NULL, root->schema, NULL); if (set) { fail(); } set = lys_find_path(root->schema->module, root->schema, nodeid1); if (!set || (set->number != 1)) { fail(); } assert_string_equal("bubba", set->set.s[0]->name); ly_set_free(set); set = lys_find_path(root->schema->module, root->schema, nodeid2); if (!set || (set->number != 1)) { fail(); } assert_string_equal("bubba", set->set.s[0]->name); ly_set_free(set); set = lys_find_path(root->schema->module, root->schema, nodeid3); if (!set || (set->number != 1)) { fail(); } assert_string_equal("lef", set->set.s[0]->name); ly_set_free(set); } static void test_ly_set_new(void **state) { (void) state; /* unused */ struct ly_set *set; set = ly_set_new(); if (!set) { fail(); } free(set); } static void test_ly_set_add(void **state) { (void) state; /* unused */ struct ly_set *set; int rc; set = ly_set_new(); if (!set) { fail(); } rc = ly_set_add(NULL, root->child->schema, 0); if(rc != -1) { fail(); } rc = ly_set_add(set, NULL, 0); if(rc != -1) { fail(); } rc = ly_set_add(set, root->child->schema, 0); if(rc == -1) { fail(); } ly_set_free(set); } static void test_ly_set_rm(void **state) { (void) state; /* unused */ struct ly_set *set; int rc; set = ly_set_new(); if (!set) { fail(); } rc = ly_set_rm(NULL, root->child->schema); if(!rc) { fail(); } rc = ly_set_rm(set, NULL); if(!rc) { fail(); } rc = ly_set_add(set, root->child->schema, 0); if(rc) { fail(); } rc = ly_set_rm(set, root->child->schema); if(rc) { fail(); } ly_set_free(set); } static void test_ly_set_rm_index(void **state) { (void) state; /* unused */ struct ly_set *set; int rc; set = ly_set_new(); if (!set) { fail(); } rc = ly_set_rm_index(NULL, 0); if(!rc) { fail(); } rc = ly_set_add(set, root->child->schema, 0); if(rc) { fail(); } rc = ly_set_rm_index(set, 0); if(rc) { fail(); } ly_set_free(set); } static void test_ly_set_free(void **state) { (void) state; /* unused */ struct ly_set *set; set = ly_set_new(); if (!set) { fail(); } ly_set_free(set); if (!set) { fail(); } } static void test_ly_verb(void **state) { (void) state; /* unused */ ly_verb(LY_LLERR); } void clb_custom(LY_LOG_LEVEL level, const char *msg, const char *path ) { (void) level; /* unused */ (void) msg; /* unused */ (void) path; /* unused */ } static void test_ly_get_log_clb(void **state) { (void) state; /* unused */ void *clb = NULL; clb = ly_get_log_clb(); assert_ptr_equal(clb, NULL); } static void test_ly_set_log_clb(void **state) { (void) state; /* unused */ void *clb = NULL; void *clb_new = NULL; clb = ly_get_log_clb(); ly_set_log_clb(clb_custom,0); clb_new = ly_get_log_clb(); assert_ptr_not_equal(clb, clb_new); } static void test_ly_log_options(void **state) { (void)state; const struct ly_err_item *i; const struct lys_module *mod; char *path; /* reset logging with path */ ly_set_log_clb(NULL, 1); assert_int_equal(ly_log_options(LY_LOLOG | LY_LOSTORE_LAST), LY_LOLOG | LY_LOSTORE_LAST); i = ly_err_first(ctx); assert_null(i); mod = ly_ctx_load_module(ctx, "INVALID_NAME", NULL); assert_null(mod); assert_int_equal(ly_errno, LY_ESYS); i = ly_err_first(ctx); assert_non_null(i); i = i->prev; assert_int_equal(i->no, LY_ESYS); assert_string_equal(i->msg, "Data model \"INVALID_NAME\" not found."); assert_null(i->next); mod = ly_ctx_load_module(ctx, "INVALID_NAME2", NULL); assert_null(mod); assert_int_equal(ly_errno, LY_ESYS); i = ly_err_first(ctx); assert_non_null(i); i = i->prev; assert_int_equal(i->no, LY_ESYS); assert_string_equal(i->msg, "Data model \"INVALID_NAME2\" not found."); assert_null(i->next); ly_log_options(LY_LOSTORE); path = ly_path_data2schema(ctx, "/a:f/g/h"); assert_null(path); assert_int_equal(ly_errno, LY_EVALID); i = ly_err_first(ctx); assert_non_null(i); i = i->prev; assert_int_equal(i->no, LY_EVALID); assert_int_equal(i->vecode, LYVE_PATH_INNODE); assert_string_equal(i->msg, "Schema node not found."); assert_string_equal(i->path, "f"); assert_null(i->next); path = ly_path_data2schema(ctx, "/fgh:f/g/h"); assert_null(path); assert_int_equal(ly_errno, LY_EVALID); i = ly_err_first(ctx); assert_non_null(i); i = i->prev; assert_int_equal(i->no, LY_EVALID); assert_int_equal(i->vecode, LYVE_PATH_INMOD); assert_string_equal(i->msg, "Module not found or not implemented."); assert_string_equal(i->path, "fgh"); assert_null(i->next); assert_non_null(i->prev->next); assert_non_null(i->prev->prev->next); ly_log_options(LY_LOLOG | LY_LOSTORE_LAST); ly_err_clean(ctx, NULL); assert_int_equal(ly_errno, LY_SUCCESS); i = ly_err_first(ctx); assert_null(i); } static void test_ly_path_data2schema(void **state) { (void) state; /* unused */ char *schema_path; schema_path = ly_path_data2schema(ctx, "/a:x/con/lef"); assert_string_equal(schema_path, "/a:x/choic/con/con/lef"); free(schema_path); schema_path = ly_path_data2schema(ctx, "/a:*"); assert_string_equal(schema_path, "/a:*"); free(schema_path); schema_path = ly_path_data2schema(ctx, "/a:*//*"); assert_string_equal(schema_path, "/a:*//*"); free(schema_path); schema_path = ly_path_data2schema(ctx, "/a:x//."); assert_string_equal(schema_path, "/a:x//."); free(schema_path); schema_path = ly_path_data2schema(ctx, "/a:x[bar-leaf='aa']//."); assert_string_equal(schema_path, "/a:x[bar-leaf='aa']//."); free(schema_path); schema_path = ly_path_data2schema(ctx, "/a:x/bar-gggg"); assert_string_equal(schema_path, "/a:x/bar-gggg"); free(schema_path); schema_path = ly_path_data2schema(ctx, "/a:x/bar-gggg | /a:x"); assert_string_equal(schema_path, "/a:x/bar-gggg | /a:x"); free(schema_path); schema_path = ly_path_data2schema(ctx, "/a:x/bar-gggg and ( /a:x/bar-gggg or /a:x)"); assert_string_equal(schema_path, "/a:x/bar-gggg and ( /a:x/bar-gggg or /a:x)"); free(schema_path); } static void test_ly_get_loaded_plugins(void **state) { (void) state; int i; const char * const *plugins; for (i = 0, plugins = ly_get_loaded_plugins(); plugins && plugins[i]; ++i) { fail(); } ly_load_plugins(); plugins = ly_get_loaded_plugins(); assert_non_null(plugins); for (i = 0; plugins[i]; ++i) { if (!strcmp(plugins[i], "metadata")) { break; } } assert_non_null(plugins[i]); for (i = 0; plugins[i]; ++i) { if (!strcmp(plugins[i], "yangdata")) { break; } } assert_non_null(plugins[i]); for (i = 0; plugins[i]; ++i) { if (!strcmp(plugins[i], "nacm")) { break; } } assert_non_null(plugins[i]); for (i = 0; plugins[i]; ++i) { if (!strcmp(plugins[i], "user_date_and_time")) { break; } } assert_non_null(plugins[i]); ly_clean_plugins(); for (i = 0, plugins = ly_get_loaded_plugins(); plugins && plugins[i]; ++i) { fail(); } } static void test_ly_ctx_internal_modules_count(void **state) { (void) state; unsigned int internal_modules_count; struct ly_ctx *new_ctx; const char *yang_folder = TESTS_DIR"/api/files"; new_ctx = ly_ctx_new(yang_folder, 0); internal_modules_count = ly_ctx_internal_modules_count(new_ctx); if (internal_modules_count == 0) { fail(); } ly_ctx_clean(new_ctx, NULL); ly_ctx_destroy(new_ctx, NULL); new_ctx = ly_ctx_new("INVALID PATH", 0); internal_modules_count = ly_ctx_internal_modules_count(new_ctx); if (internal_modules_count != 0) { fail(); } ly_ctx_clean(new_ctx, NULL); ly_ctx_destroy(new_ctx, NULL); } void test_ly_ctx_set_allimplemented(void **state) { (void) state; /* unused */ const struct lys_module *module = NULL; /* standard setup */ module = ly_ctx_load_module(ctx, "y", NULL); /* implemented flag should be 0 */ if (module->imp->module->implemented == 1) { fail(); } ly_ctx_remove_module(module, NULL); /* setup with set_allimplement */ ly_ctx_set_allimplemented(ctx); module = ly_ctx_load_module(ctx, "y", NULL); /* implemented flag should be 1 */ if (module->imp->module->implemented != 1) { fail(); } ly_ctx_remove_module(module, NULL); } void test_ly_ctx_get_module_set_id(void **state) { (void) state; uint16_t set_id = ctx->models.module_set_id; if (set_id != ly_ctx_get_module_set_id(ctx)) { fail(); } } void test_ly_ctx_get_module_iter(void **state) { (void) state; const struct lys_module *first_module = NULL; const struct lys_module *second_module = NULL; const struct lys_module *iteration = NULL; uint32_t iter_num = 0; uint8_t first_found = 0; uint8_t second_found = 0; struct ly_ctx *ctx; ctx = ly_ctx_new(TESTS_DIR"/api/files/", 0); first_module = ly_ctx_load_module(ctx, "x", NULL); second_module = ly_ctx_load_module(ctx, "y", NULL); /* enabled modules */ do { iteration = ly_ctx_get_module_iter(ctx, &iter_num); if (iteration == first_module) { first_found = 1; } if (iteration == second_module) { second_found = 1; } } while (iteration != NULL); if (!second_found) { fail(); } if (!first_found) { fail(); } /* disabled modules */ iter_num = 0; lys_set_disabled(first_module); lys_set_disabled(second_module); first_found = 0; second_found = 0; do { iteration = ly_ctx_get_disabled_module_iter(ctx, &iter_num); if (iteration == first_module) { first_found = 1; } if (iteration == second_module) { second_found = 1; } } while (iteration != NULL); if (!second_found) { fail(); } if (!first_found) { fail(); } ly_ctx_clean(ctx, NULL); ly_ctx_destroy(ctx, NULL); } void test_ly_ctx_set_trusted(void **state) { (void) state; int flags = ctx->models.flags; /* raising flag for trusted */ ly_ctx_set_trusted(ctx); /* Checking for changes in context */ if (ctx->models.flags == flags) { fail(); } /* lowering the flag for trusted */ ly_ctx_unset_trusted(ctx); /* Checking whether the the context has returned to previous state */ if (ctx->models.flags != flags) { fail(); } } void test_ly_ctx_get_node(void **state) { (void) state; const struct lys_node *node = NULL; module = ly_ctx_load_module(ctx, "y", NULL); /* Test with a valid path */ node = ly_ctx_get_node(ctx, NULL, "/b:x/b:bubba", 0); if (!node) { fail(); } /* Test with an invalid path */ node = ly_ctx_get_node(ctx, NULL, "INVALID PATH", 0); if (node) { fail(); } } void test_ly_ctx_find_path(void **state) { (void) state; struct ly_set *set = NULL; set = ly_ctx_find_path(ctx, "/b:*"); /* Test with a valid path */ if (!set) { fail(); } ly_set_free(set); set = ly_ctx_find_path(ctx, "INVALID PATH"); /* Test with an invalid path */ if (set) { fail(); } ly_set_free(set); } void test_ly_ctx_destroy(void **state) { (void) state; /* unused */ struct ly_ctx *new_ctx = NULL; if (new_ctx) { fail(); } new_ctx = ly_ctx_new(TESTS_DIR "/api/files", 0); /* Making sure that the context has internal modules */ if (!new_ctx->internal_module_count) { fail(); } ly_ctx_clean(new_ctx, NULL); ly_ctx_destroy(new_ctx, NULL); /* Checking if the funcion has cleared the internal structure */ } void test_ly_path_xml2json(void **state) { (void) state; struct lyxml_elem *xml = NULL; char *xml_path; char *mem; struct lyd_node *node; node = ly_ctx_info(ctx); if (!node) { fail(); } if (lyd_print_mem(&mem, node, LYD_XML, LYP_WITHSIBLINGS)) { fail(); } xml = lyxml_parse_mem(ctx, mem, LYXML_PARSE_NOMIXEDCONTENT); if (!mem) { fail(); } /* Check for the xml element */ if (!xml) { fail(); } xml_path = ly_path_xml2json(ctx, "/c", xml); /* Check for xml path */ if (!xml_path) { fail(); } free(xml_path); xml_path = ly_path_xml2json(ctx, "INVALID PATH", xml); /* Check for xml invalid path */ if (xml_path) { fail(); } /* Freeing the elements */ lyxml_free_withsiblings(ctx, xml); lyd_free_withsiblings(node); free(mem); } void test_ly_set_dup(void **state) { (void) state; struct ly_set *first_set = NULL; struct ly_set *second_set = NULL; /* Creating the first set */ first_set = ly_set_new(); if (!first_set) { fail(); } /* Duplicating the first set onto the second */ second_set = ly_set_dup(first_set); if (!second_set) { fail(); } ly_set_free(first_set); ly_set_free(second_set); } void test_ly_set_merge(void **state) { (void) state; struct ly_set *first_set = NULL; struct ly_set *second_set = NULL; first_set = ly_set_new(); second_set = ly_set_new(); /* Adding a node to the second set to later see whether the merge was successful*/ ly_set_add(second_set, root->child->schema, 0); /* Check if both sets are set */ if (!first_set || !second_set) { fail(); } /* Check if the merge is successful */ if (ly_set_merge(first_set, second_set, LY_SET_OPT_USEASLIST)) { fail(); } /* Check if the first set got the node from the second set */ if (ly_set_contains(first_set, root->child->schema) != -1) { fail(); } /* Check that the second set is clear */ if (ly_set_contains(second_set, root->child->schema) == -1) { fail(); } } void test_ly_set_contains(void **state) { (void) state; struct ly_set *set = NULL; struct lys_node *node = NULL; node = (struct lys_node *) ly_ctx_get_node(ctx, NULL, "/b:x/b:bubba", 0); /* Check if the set contains the node before we add it to the set */ if (ly_set_contains(set, node)) { fail(); } ly_set_add(set, node, 0); /* Check if the set contains the node after we add it to the set */ if (!ly_set_contains(set, node)) { fail(); } } void test_ly_vecode(void **state) { (void) state; ly_log_options(LY_LOLOG | LY_LOSTORE_LAST); /* Make an error */ ly_ctx_load_module(ctx, "y", NULL); ly_set_log_clb(NULL, 1); ly_ctx_find_path(ctx, "g"); /* Check if the vecode coresponds to the error made */ if (LYVE_PATH_INMOD == ly_vecode(ctx)) { fail(); } } void test_ly_errmsg(void **state) { (void) state; const char *errmsg = "invalid module name (path)"; ly_log_options(LY_LOLOG | LY_LOSTORE_LAST); /* Make an error */ ly_ctx_load_module(ctx, "y", NULL); ly_set_log_clb(NULL, 1); ly_ctx_find_path(ctx, "g"); /* Check if the error message coresponds to the error made */ if (errmsg == ly_errmsg(ctx)) { fail(); } } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_ly_ctx_new), cmocka_unit_test(test_ly_ctx_new_invalid), cmocka_unit_test(test_ly_ctx_get_searchdirs), cmocka_unit_test(test_ly_ctx_set_searchdir), cmocka_unit_test(test_ly_ctx_set_searchdir_invalid), cmocka_unit_test_setup_teardown(test_ly_ctx_info, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_new_ylmem, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_module_clb, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_get_module, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_get_module_older, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_load_module, setup_f, teardown_f), cmocka_unit_test_teardown(test_ly_ctx_remove_module, teardown_f), cmocka_unit_test_teardown(test_ly_ctx_remove_module2, teardown_f), cmocka_unit_test_teardown(test_lys_set_enabled, teardown_f), cmocka_unit_test_teardown(test_lys_set_disabled, teardown_f), cmocka_unit_test(test_ly_ctx_clean), cmocka_unit_test(test_ly_ctx_clean2), cmocka_unit_test_setup_teardown(test_ly_ctx_get_module_by_ns, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_get_submodule, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_get_submodule2, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_lys_find_path, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_set_new, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_set_add, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_set_rm, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_set_rm_index, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_set_free, setup_f, teardown_f), cmocka_unit_test(test_ly_verb), cmocka_unit_test(test_ly_get_log_clb), cmocka_unit_test(test_ly_set_log_clb), cmocka_unit_test_setup_teardown(test_ly_log_options, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_path_data2schema, setup_f, teardown_f), cmocka_unit_test(test_ly_get_loaded_plugins), cmocka_unit_test(test_ly_ctx_internal_modules_count), cmocka_unit_test_setup_teardown(test_ly_ctx_set_allimplemented, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_get_module_set_id, setup_f, teardown_f), cmocka_unit_test(test_ly_ctx_get_module_iter), cmocka_unit_test_setup_teardown(test_ly_ctx_set_trusted, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_get_node, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_ctx_find_path, setup_f, teardown_f), cmocka_unit_test(test_ly_ctx_destroy), cmocka_unit_test_setup_teardown(test_ly_path_xml2json, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_set_dup, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_vecode, setup_f, teardown_f), cmocka_unit_test_setup_teardown(test_ly_errmsg, setup_f, teardown_f), }; return cmocka_run_group_tests(tests, NULL, NULL); }