| /** |
| * @file test_yang_data.c |
| * @author Pavol Vican <vican.pavol@gmail.com> |
| * @brief Cmocka tests for YANG data template. |
| * |
| * 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 |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <setjmp.h> |
| #include <stdarg.h> |
| #include <cmocka.h> |
| |
| #include "tests/config.h" |
| #include "libyang.h" |
| |
| struct state { |
| struct ly_ctx *ctx; |
| const struct lys_module *mod; |
| struct lyd_node *dt; |
| char * str1, *str2; |
| }; |
| |
| static int |
| setup_f(void **state) |
| { |
| struct state *st; |
| const char *yang = "module yang-data {\n" |
| " prefix yang;\n" |
| " namespace \"urn:cesnet:yang-data\";\n" |
| " import ietf-restconf {\n" |
| " prefix rc;\n" |
| " }\n" |
| " rc:yang-data data {\n" |
| " uses rc:errors;\n" |
| " }\n" |
| " rc:yang-data node {\n" |
| " choice select {\n" |
| " container test {\n" |
| " leaf num {\n" |
| " type uint8; \n" |
| " }\n" |
| " }\n" |
| " container test1 {\n" |
| " leaf first {\n" |
| " type uint8; \n" |
| " }\n" |
| " leaf second {\n" |
| " type string; \n" |
| " }\n" |
| " leaf third {\n" |
| " type boolean; \n" |
| " }\n" |
| " }\n" |
| " }\n" |
| " }\n" |
| "}"; |
| |
| (*state) = st = calloc(1, sizeof *st); |
| if (!st) { |
| fprintf(stderr, "Memory allocation error"); |
| return -1; |
| } |
| |
| /* libyang context */ |
| st->ctx = ly_ctx_new(TESTS_DIR"/data/files/", 0); |
| if (!st->ctx) { |
| fprintf(stderr, "Failed to create context.\n"); |
| return -1; |
| } |
| |
| st->mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| if (!st->mod){ |
| fprintf(stderr, "Failed to load module.\n"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| static int |
| teardown_f(void **state) |
| { |
| struct state *st = (*state); |
| |
| lyd_free_withsiblings(st->dt); |
| ly_ctx_destroy(st->ctx, NULL); |
| free(st->str1); |
| free(st->str2); |
| free(st); |
| (*state) = NULL; |
| |
| return 0; |
| } |
| |
| static void |
| test_new_path(void **state) |
| { |
| struct state *st = (*state); |
| |
| st->dt = lyd_new_path(NULL, st->ctx, "/yang-data:#node/test1/first", "test", 0 ,0); |
| assert_ptr_equal(st->dt, NULL); |
| st->dt = lyd_new_path(NULL, st->ctx, "/yang-data:#node/test1/first", "50", 0 ,0); |
| assert_ptr_not_equal(st->dt, NULL); |
| assert_ptr_not_equal(lyd_new_path(st->dt, st->ctx, "/yang-data:#node/test1/second", "test-second", 0 ,0), NULL); |
| assert_ptr_equal(lyd_new_path(st->dt, st->ctx, "/yang-data:test1/third", "true", 0 ,0), NULL); |
| } |
| |
| static void |
| test_new_yangdata(void **state) |
| { |
| struct state *st = (*state); |
| |
| st->dt = lyd_new_yangdata(st->mod, "node", "test"); |
| assert_ptr_not_equal(st->dt, NULL); |
| lyd_new_leaf(st->dt, st->mod, "num", "25"); |
| assert_ptr_not_equal(st->dt->child, NULL); |
| st->str1 = lyd_path(st->dt->child); |
| assert_string_equal(st->str1, "/yang-data:#node/test/num"); |
| } |
| |
| static void |
| test_mem_yangdata(void **state) |
| { |
| struct state *st = (*state); |
| char *str; |
| |
| char *xml_file = "<errors xmlns=\"urn:cesnet:yang-data\">\n" |
| " <error>\n" |
| " <error-type>protocol</error-type>\n" |
| " <error-tag>Bad packet</error-tag>\n" |
| " </error>\n" |
| "</errors>\n" |
| "<node xmlns=\"urn:cesnet:yang-data\">\n" |
| " <test>\n" |
| " <num>50</num>\n" |
| " </test>\n" |
| "</node>\n"; |
| char *json_file1 = "{\n" |
| " \"yang-data:errors\" : {\n" |
| " \"error\" : [\n" |
| " {\n" |
| " \"error-type\" : \"protocol\",\n" |
| " \"error-tag\" : \"Bad packet\"\n" |
| " }\n" |
| " ]\n" |
| " }\n" |
| " \"yang-data:node\" : {\n" |
| " \"test\" : {\n" |
| " \"num\" : 50\n" |
| " }\n" |
| " }\n" |
| "}\n"; |
| char *json_file2 = "{\n" |
| " \"yang-data:errors\" : {\n" |
| " \"error\" : [\n" |
| " {\n" |
| " \"error-type\" : \"protocol\",\n" |
| " \"error-tag\" : \"Bad packet\"\n" |
| " }\n" |
| " ]\n" |
| " }\n" |
| "}\n"; |
| st->dt = lyd_parse_mem(st->ctx, json_file1, LYD_JSON, LYD_OPT_DATA_TEMPLATE, "data"); |
| assert_ptr_equal(st->dt, NULL); |
| st->dt = lyd_parse_mem(st->ctx, json_file2, LYD_JSON, LYD_OPT_DATA_TEMPLATE, "data"); |
| assert_ptr_not_equal(st->dt, NULL); |
| |
| lyd_print_mem(&str, st->dt, LYD_LYB, 0); |
| lyd_free(st->dt); |
| st->dt = lyd_parse_mem(st->ctx, str, LYD_LYB, LYD_OPT_DATA_TEMPLATE, "data"); |
| free(str); |
| assert_ptr_not_equal(st->dt, NULL); |
| lyd_free(st->dt); |
| |
| st->dt = lyd_parse_mem(st->ctx, xml_file, LYD_XML, LYD_OPT_DATA_TEMPLATE | LYD_OPT_STRICT, "data"); |
| assert_ptr_equal(st->dt, NULL); |
| st->dt = lyd_parse_mem(st->ctx, xml_file, LYD_XML, LYD_OPT_DATA_TEMPLATE, "data"); |
| assert_ptr_not_equal(st->dt, NULL); |
| } |
| |
| static void |
| test_validate_yangdata(void **state) |
| { |
| struct state *st = (*state); |
| |
| st->dt = lyd_new_path(NULL, st->ctx, "/yang-data:#data/errors/error[1]/error-type", "transport", 0 ,0); |
| assert_return_code(lyd_validate(&st->dt, LYD_OPT_DATA_TEMPLATE, NULL), EXIT_FAILURE); |
| assert_ptr_not_equal(lyd_new_leaf(st->dt->child, st->mod, "error-tag", "Error"), NULL); |
| assert_return_code(lyd_validate(&st->dt, LYD_OPT_DATA_TEMPLATE, NULL), EXIT_SUCCESS); |
| } |
| |
| static void |
| test_path_yangdata(void **state) |
| { |
| struct state *st = (*state); |
| struct ly_set *set; |
| const struct lys_node *node; |
| char *str; |
| |
| st->dt = lyd_new_path(st->dt, st->ctx, "/yang-data:#node/test1/second", "test-second", 0 ,0); |
| set = lyd_find_path(st->dt,"/yang-data:#node/test1/second"); |
| assert_ptr_not_equal(set, NULL); |
| assert_int_equal(set->number, 1); |
| |
| st->str1 = lys_data_path(st->dt->child->schema); |
| st->str2 = lyd_path(st->dt->child); |
| assert_string_equal(st->str1, st->str2); |
| assert_string_equal(st->str1, "/yang-data:#node/test1/second"); |
| |
| str = st->str2; |
| free(st->str1); |
| st->str1 = lys_path(st->dt->child->schema, LYS_PATH_FIRST_PREFIX); |
| st->str2 = ly_path_data2schema(st->ctx,str); |
| free(str); |
| assert_string_equal(st->str1, st->str2); |
| assert_string_equal(st->str1, "/yang-data:#node/select/test1/test1/second"); |
| |
| ly_set_free(set); |
| set = lys_find_path(st->mod, NULL, st->str1); |
| assert_ptr_not_equal(set, NULL); |
| assert_int_equal(set->number, 1); |
| |
| ly_set_free(set); |
| free(st->str1); |
| st->str1 = lys_path(st->dt->child->schema, 0); |
| set = ly_ctx_find_path(st->ctx, st->str1); |
| assert_ptr_not_equal(set, NULL); |
| assert_int_equal(set->number, 1); |
| ly_set_free(set); |
| |
| free(st->str2); |
| st->str2 = lyd_path(st->dt->child); |
| node = ly_ctx_get_node(st->ctx, NULL, st->str2, 0); |
| assert_ptr_not_equal(node, NULL); |
| } |
| |
| int main(void) |
| { |
| const struct CMUnitTest tests[] = { |
| cmocka_unit_test_setup_teardown(test_new_path, setup_f, teardown_f), |
| cmocka_unit_test_setup_teardown(test_new_yangdata, setup_f, teardown_f), |
| cmocka_unit_test_setup_teardown(test_path_yangdata, setup_f, teardown_f), |
| cmocka_unit_test_setup_teardown(test_validate_yangdata, setup_f, teardown_f), |
| cmocka_unit_test_setup_teardown(test_mem_yangdata, setup_f, teardown_f), |
| }; |
| |
| return cmocka_run_group_tests(tests, NULL, NULL); |
| } |