/** * \file test_augment.c * \author Michal Vasko * \brief libyang tests - augment targets * * Copyright (c) 2015 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 #include #include #include #include #include #include #include #include #include #include #include "libyang.h" #include "context.h" #include "tests/config.h" #define SCHEMA_FOLDER_YIN TESTS_DIR"/schema/yin/files" #define SCHEMA_FOLDER_YANG TESTS_DIR"/schema/yang/files" #define MOD_COUNT 7 #define YANG_MOD_IDX(idx) (idx) #define YIN_MOD_IDX(idx) (MOD_COUNT + idx) struct ly_ctx *ctx; char *yang_modules[2 * MOD_COUNT] = {0}; char *yin_modules[2 * MOD_COUNT] = {0}; static int setup_ctx_yin(void **state) { *state = malloc(strlen(TESTS_DIR) + 64); assert_non_null(*state); memcpy(*state, SCHEMA_FOLDER_YIN, strlen(SCHEMA_FOLDER_YIN) + 1); ctx = ly_ctx_new(NULL, 0); if (!ctx) { return -1; } return 0; } static int setup_ctx_yang(void **state) { *state = malloc(strlen(TESTS_DIR) + 64); assert_non_null(*state); memcpy(*state, SCHEMA_FOLDER_YANG, strlen(SCHEMA_FOLDER_YANG) + 1); ctx = ly_ctx_new(NULL, 0); if (!ctx) { return -1; } return 0; } static int teardown_ctx(void **state) { free(*state); ly_ctx_destroy(ctx, NULL); return 0; } static void test_target_include_submodule(void **state) { int length; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/a.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } lys_print_mem(&yin_modules[YANG_MOD_IDX(0)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yin_modules[YIN_MOD_IDX(0)], module, LYS_OUT_YIN, NULL, 0, 0); } else { strcpy(path + length, "/a.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } lys_print_mem(&yang_modules[YANG_MOD_IDX(0)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yang_modules[YIN_MOD_IDX(0)], module, LYS_OUT_YIN, NULL, 0, 0); } } static void test_leafref(void **state) { int length; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/b1.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } lys_print_mem(&yin_modules[YANG_MOD_IDX(1)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yin_modules[YIN_MOD_IDX(1)], module, LYS_OUT_YIN, NULL, 0, 0); strcpy(path + length, "/b2.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } lys_print_mem(&yin_modules[YANG_MOD_IDX(2)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yin_modules[YIN_MOD_IDX(2)], module, LYS_OUT_YIN, NULL, 0, 0); } else { strcpy(path + length, "/b1.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } lys_print_mem(&yang_modules[YANG_MOD_IDX(1)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yang_modules[YIN_MOD_IDX(1)], module, LYS_OUT_YIN, NULL, 0, 0); strcpy(path + length, "/b2.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } lys_print_mem(&yang_modules[YANG_MOD_IDX(2)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yang_modules[YIN_MOD_IDX(2)], module, LYS_OUT_YIN, NULL, 0, 0); } } /* Test case to verify the solution for an augment resolution issue: The iffeature consistency check for leafrefs failed because some of the imported augments have not yet been applied. */ static void test_leafref_w_feature1(void **state) { int length, i; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/leafref_w_feature1-mod3.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } } else { strcpy(path + length, "/leafref_w_feature1-mod3.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } } for (i = 0; i < ctx->models.used; i++) { if (strncmp("leafref_w_feature1-mod",ctx->models.list[i]->name,strlen("leafref_w_feature1-mod")) == 0) { assert_non_null(ctx->models.list[i]->implemented); } } } /* Test case to verify the solution for an augment resolution issue: The iffeature consistency check for leafrefs failed because some of the augments have not yet been applied, due to an ordering problem in resolution (similar as in test_leafref_w_feature1()) */ static void test_leafref_w_feature2(void **state) { int length, i; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/leafref_w_feature2-mod1.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } } else { strcpy(path + length, "/leafref_w_feature2-mod1.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } } for (i = 0; i < ctx->models.used; i++) { if (strncmp("leafref_w_feature2-mod",ctx->models.list[i]->name,strlen("leafref_w_feature2-mod")) == 0) { assert_non_null(ctx->models.list[i]->implemented); } } } /* Test case to verify the solution for an augment resolution issue: The iffeature consistency check for leafrefs failed for augments which are in imported modules and which are not going to be implemented/applied. This prevented the module to be installed from being installed */ static void test_leafref_w_feature3(void **state) { int length, i; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/leafref_w_feature1-mod4.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } } else { strcpy(path + length, "/leafref_w_feature1-mod4.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } } for (i = 0; i < ctx->models.used; i++) { if (strcmp("leafref_w_feature1-mod4",ctx->models.list[i]->name) == 0) { assert_non_null(ctx->models.list[i]->implemented); } else if (strncmp("leafref_w_feature1-mod",ctx->models.list[i]->name,strlen("leafref_w_feature1-mod")) == 0) { assert_null(ctx->models.list[i]->implemented); } } } /* Test case to verify the solution for an augment resolution issue: An augment having a relative nodeid couldn't be resolved, if a grouping which is declared in a submodule uses a grouping of an imported module and augments it. Please have a look at all imp_aug_m* schema files. */ static void test_imp_aug(void **state) { int length; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/imp_aug_m1.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } } else { strcpy(path + length, "/imp_aug_m1.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } } } static void test_target_augment(void **state) { int length; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/c1.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } lys_print_mem(&yin_modules[YANG_MOD_IDX(3)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yin_modules[YIN_MOD_IDX(3)], module, LYS_OUT_YIN, NULL, 0, 0); strcpy(path + length, "/c2.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } lys_print_mem(&yin_modules[YANG_MOD_IDX(4)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yin_modules[YIN_MOD_IDX(4)], module, LYS_OUT_YIN, NULL, 0, 0); strcpy(path + length, "/c3.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } lys_print_mem(&yin_modules[YANG_MOD_IDX(5)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yin_modules[YIN_MOD_IDX(5)], module, LYS_OUT_YIN, NULL, 0, 0); } else { strcpy(path + length, "/c1.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } lys_print_mem(&yang_modules[YANG_MOD_IDX(3)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yang_modules[YIN_MOD_IDX(3)], module, LYS_OUT_YIN, NULL, 0, 0); strcpy(path + length, "/c2.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } lys_print_mem(&yang_modules[YANG_MOD_IDX(4)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yang_modules[YIN_MOD_IDX(4)], module, LYS_OUT_YIN, NULL, 0, 0); strcpy(path + length, "/c3.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } lys_print_mem(&yang_modules[YANG_MOD_IDX(5)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yang_modules[YIN_MOD_IDX(5)], module, LYS_OUT_YIN, NULL, 0, 0); } } static void test_unres_augment(void **state) { int length; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/emod.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } lys_print_mem(&yin_modules[YANG_MOD_IDX(6)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yin_modules[YIN_MOD_IDX(6)], module, LYS_OUT_YIN, NULL, 0, 0); } else { strcpy(path + length, "/emod.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } lys_print_mem(&yang_modules[YANG_MOD_IDX(6)], module, LYS_OUT_YANG, NULL, 0, 0); lys_print_mem(&yang_modules[YIN_MOD_IDX(6)], module, LYS_OUT_YIN, NULL, 0, 0); } } static void test_import_augment_target(void **state) { int length; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/g1.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } /*lys_print_mem(&yin_modules[7], module, LYS_OUT_YANG, NULL); lys_print_mem(&yin_modules[14], module, LYS_OUT_YIN, NULL);*/ } else { strcpy(path + length, "/g1.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } /*lys_print_mem(&yin_modules[7], module, LYS_OUT_YANG, NULL); lys_print_mem(&yin_modules[14], module, LYS_OUT_YIN, NULL);*/ } } static void test_import_augment_leafref_implemented(void **state) { int length; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/mainmodule.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } } else { strcpy(path + length, "/mainmodule.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } } module = ly_ctx_get_module(ctx, "mainmodule", NULL, 0); assert_true(module && module->implemented); module = ly_ctx_get_module(ctx, "augmentbase", NULL, 0); assert_true(module && module->implemented); module = ly_ctx_get_module(ctx, "augmentone", NULL, 0); assert_true(module && module->implemented); module = ly_ctx_get_module(ctx, "augmenttwo", NULL, 0); assert_true(module && module->implemented); } static void test_import_augment_leafref_imported(void **state) { int length; char *path = *state; const struct lys_module *module; ly_ctx_set_searchdir(ctx, path); length = strlen(path); if (!strcmp(path, SCHEMA_FOLDER_YIN)) { strcpy(path + length, "/installme.yin"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YIN))) { fail(); } } else { strcpy(path + length, "/installme.yang"); if (!(module = lys_parse_path(ctx, path, LYS_IN_YANG))) { fail(); } } module = ly_ctx_get_module(ctx, "installme", NULL, 0); assert_true(module && module->implemented); module = ly_ctx_get_module(ctx, "aug", NULL, 0); assert_true(module && !module->implemented); module = ly_ctx_get_module(ctx, "base", NULL, 0); assert_true(module && !module->implemented); } static void compare_output(void **state) { int i; char *name[] = {"a", "b1", "b2", "c1", "c2", "c3", "emod"}; (void) state; /* unused state*/ for (i = 0; i < 14; ++i) { fprintf(stdout, "Compare \"%s\" modules print by %s ... ", name[i % 7], (i / 7) ? "yin_print" : "yang_print"); assert_non_null(yang_modules[i]); assert_non_null(yin_modules[i]); if (strcmp(yang_modules[i], yin_modules[i])) { fprintf(stderr, "failed.\n"); fail(); } fprintf(stdout, "ok.\n"); } } static int teardown_output(void **state) { int i; (void)state; /* unused state*/ for (i = 0; i < 14; ++i) { free(yang_modules[i]); free(yin_modules[i]); } return 0; } int main(void) { ly_verb(LY_LLWRN); const struct CMUnitTest cmut[] = { cmocka_unit_test_setup_teardown(test_target_include_submodule, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_leafref, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_target_augment, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_unres_augment, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_import_augment_target, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_leafref_w_feature1, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_leafref_w_feature2, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_leafref_w_feature3, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_imp_aug, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_import_augment_leafref_implemented, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_import_augment_leafref_imported, setup_ctx_yin, teardown_ctx), cmocka_unit_test_setup_teardown(test_target_include_submodule, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_leafref, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_target_augment, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_unres_augment, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_import_augment_target, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_leafref_w_feature1, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_leafref_w_feature2, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_leafref_w_feature3, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_imp_aug, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_import_augment_leafref_implemented, setup_ctx_yang, teardown_ctx), cmocka_unit_test_setup_teardown(test_import_augment_leafref_imported, setup_ctx_yang, teardown_ctx), cmocka_unit_test_teardown(compare_output, teardown_output), }; return cmocka_run_group_tests(cmut, NULL, NULL); }