Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions src/plugins_exts.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,15 +559,17 @@ lyplg_ext_get_storage(const struct lysc_ext_instance *ext, int stmt, uint32_t st
LIBYANG_API_DEF LY_ERR
lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint32_t storage_size, const void **storage)
{
LY_ARRAY_COUNT_TYPE u;
LY_ARRAY_COUNT_TYPE u, v;
const struct lysp_ext_instance *extp = NULL;
const struct lysp_submodule *submod;
const char *extp_name;
enum ly_stmt match = 0;
void **s_p = NULL;

LY_CHECK_ARG_RET(NULL, ext, ext->module->parsed, LY_EINVAL);

/* find the parsed ext instance */
/* find the parsed ext instance, it may be a top-level extension instance of the module or
* any of its submodules */
LY_ARRAY_FOR(ext->module->parsed->exts, u) {
extp = &ext->module->parsed->exts[u];
extp_name = strchr(extp->name, ':') + 1;
Expand All @@ -577,6 +579,21 @@ lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint
}
extp = NULL;
}
for (v = 0; !extp && (v < LY_ARRAY_COUNT(ext->module->parsed->includes)); ++v) {
submod = ext->module->parsed->includes[v].submodule;
if (!submod) {
continue;
}
LY_ARRAY_FOR(submod->exts, u) {
extp = &submod->exts[u];
extp_name = strchr(extp->name, ':') + 1;

if (!strcmp(ext->def->name, extp_name)) {
break;
}
extp = NULL;
}
}
assert(extp);

if (!(stmt & LY_STMT_NODE_MASK)) {
Expand Down
49 changes: 49 additions & 0 deletions tests/utests/extensions/test_structure.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,54 @@ test_xpath(void **state)
lyd_free_all(tree);
}

static LY_ERR
submod_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *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))
{
if (!submod_name || strcmp(submod_name, "c_sub")) {
return LY_ENOTFOUND;
}

*module_data = user_data;
*format = LYS_IN_YANG;
*free_module_data = NULL;
return LY_SUCCESS;
}

static void
test_submod(void **state)
{
struct lys_module *mod;
char *printed = NULL;
const char *data, *submod;

/* top-level extension instances of a submodule are compiled into the module
* but their parsed instances are stored in the submodule */
submod = "submodule c_sub {yang-version 1.1; belongs-to c {prefix c;}"
"import ietf-yang-structure-ext {prefix sx;}"
"sx:augment-structure \"/c:basetop/c:x\" {leaf z {type string;}}"
"}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, submod_imp_clb, (void *)submod);

data = "module c {yang-version 1.1; namespace urn:tests:extensions:structure:c; prefix c;"
"include c_sub;"
"import ietf-yang-structure-ext {prefix sx;}"
"sx:structure basetop {container x {leaf l {type string;}}}"
"}";
UTEST_ADD_MODULE(data, LYS_IN_YANG, NULL, &mod);

ly_ctx_set_module_imp_clb(UTEST_LYCTX, NULL, NULL);

/* tree print with compiled nodes iterates compiled extension instances, the parsed one
* of a submodule extension instance used not to be found and asserted on */
assert_int_equal(LY_SUCCESS, ly_ctx_set_options(UTEST_LYCTX, LY_CTX_SET_PRIV_PARSED));
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_TREE, 0));
assert_int_equal(LY_SUCCESS, ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_SET_PRIV_PARSED));
assert_non_null(strstr(printed, "augment-structure /c:basetop/c:x:"));
free(printed);
}

int
main(void)
{
Expand All @@ -456,6 +504,7 @@ main(void)
UTEST(test_schema_invalid),
UTEST(test_parse),
UTEST(test_xpath),
UTEST(test_submod),
};

return cmocka_run_group_tests(tests, NULL, NULL);
Expand Down