From cd07912073c951b4bbb871ed2653af1be2cfc714 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:55:11 +0200 Subject: Adding upstream version 2.1.30. Signed-off-by: Daniel Baumann --- tests/utests/data/test_merge.c | 756 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 756 insertions(+) create mode 100644 tests/utests/data/test_merge.c (limited to 'tests/utests/data/test_merge.c') diff --git a/tests/utests/data/test_merge.c b/tests/utests/data/test_merge.c new file mode 100644 index 0000000..3e7b772 --- /dev/null +++ b/tests/utests/data/test_merge.c @@ -0,0 +1,756 @@ +/** + * @file test_merge.c + * @author Michal Vasko + * @brief tests for complex data merges. + * + * Copyright (c) 2020 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 "libyang.h" + +#define LYD_TREE_CREATE(INPUT, MODEL) \ + CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, MODEL) + +#define CONTEXT_CREATE \ + CONTEXT_CREATE_PATH(NULL) + +#define LYD_TREE_CHECK_CHAR(MODEL, TEXT, PARAMS) \ + CHECK_LYD_STRING_PARAM(MODEL, TEXT, LYD_XML, LYD_PRINT_WITHSIBLINGS | PARAMS) + +static void +test_batch(void **state) +{ + const char *start = + "\n" + " \n" + " yang\n" + " 2016-02-11\n" + " implement\n" + " \n" + "\n"; + const char *data[] = { + "\n" + " \n" + " ietf-yang-library\n" + " 2016-02-01\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " ietf-netconf-acm\n" + " 2012-02-22\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " ietf-netconf\n" + " 2011-06-01\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " ietf-netconf-monitoring\n" + " 2010-10-04\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " ietf-netconf-with-defaults\n" + " 2011-06-01\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " yang\n" + " 2016-02-11\n" + " urn:ietf:params:xml:ns:yang:1\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " ietf-yang-library\n" + " 2016-02-01\n" + " urn:ietf:params:xml:ns:yang:ietf-yang-library\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " ietf-netconf-acm\n" + " 2012-02-22\n" + " urn:ietf:params:xml:ns:yang:ietf-netconf-acm\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " ietf-netconf\n" + " 2011-06-01\n" + " urn:ietf:params:xml:ns:netconf:base:1.0\n" + " writable-running\n" + " candidate\n" + " rollback-on-error\n" + " validate\n" + " startup\n" + " xpath\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " ietf-netconf-monitoring\n" + " 2010-10-04\n" + " urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\n" + " implement\n" + " \n" + "\n", + "\n" + " \n" + " ietf-netconf-with-defaults\n" + " 2011-06-01\n" + " urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\n" + " implement\n" + " \n" + "\n" + }; + const char *output_template = + "\n" + " \n" + " yang\n" + " 2016-02-11\n" + " urn:ietf:params:xml:ns:yang:1\n" + " implement\n" + " \n" + " \n" + " ietf-yang-library\n" + " 2016-02-01\n" + " urn:ietf:params:xml:ns:yang:ietf-yang-library\n" + " implement\n" + " \n" + " \n" + " ietf-netconf-acm\n" + " 2012-02-22\n" + " urn:ietf:params:xml:ns:yang:ietf-netconf-acm\n" + " implement\n" + " \n" + " \n" + " ietf-netconf\n" + " 2011-06-01\n" + " urn:ietf:params:xml:ns:netconf:base:1.0\n" + " writable-running\n" + " candidate\n" + " rollback-on-error\n" + " validate\n" + " startup\n" + " xpath\n" + " implement\n" + " \n" + " \n" + " ietf-netconf-monitoring\n" + " 2010-10-04\n" + " urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\n" + " implement\n" + " \n" + " \n" + " ietf-netconf-with-defaults\n" + " 2011-06-01\n" + " urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\n" + " implement\n" + " \n" + "\n"; + + struct lyd_node *target; + + CHECK_PARSE_LYD_PARAM(start, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, target); + + for (int32_t i = 0; i < 11; ++i) { + struct lyd_node *source; + + CHECK_PARSE_LYD_PARAM(data[i], LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, source); + assert_int_equal(LY_SUCCESS, lyd_merge_siblings(&target, source, LYD_MERGE_DESTRUCT)); + } + + LYD_TREE_CHECK_CHAR(target, output_template, 0); + + lyd_free_all(target); +} + +static void +test_leaf(void **state) +{ + const char *sch = "module x {" + " namespace urn:x;" + " prefix x;" + " container A {" + " leaf f1 {type string;}" + " container B {" + " leaf f2 {type string;}" + " }" + " }" + " }"; + const char *trg = " block "; + const char *src = " aa bb "; + const char *result = "aabb"; + struct lyd_node *source, *target; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + LYD_TREE_CREATE(src, source); + LYD_TREE_CREATE(trg, target); + + /* merge them */ + assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + /* check the result */ + LYD_TREE_CHECK_CHAR(target, result, LYD_PRINT_SHRINK); + + lyd_free_all(target); + lyd_free_all(source); +} + +static void +test_container(void **state) +{ + const char *sch = + "module A {\n" + " namespace \"aa:A\";\n" + " prefix A;\n" + " container A {\n" + " leaf f1 {type string;}\n" + " container B {\n" + " leaf f2 {type string;}\n" + " }\n" + " container C {\n" + " leaf f3 {type string;}\n" + " }\n" + " }\n" + "}\n"; + + const char *trg = " aaa "; + const char *src = " bbb "; + const char *result = "aaabbb"; + struct lyd_node *source, *target; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + LYD_TREE_CREATE(src, source); + LYD_TREE_CREATE(trg, target); + + /* merge them */ + assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + /* check the result */ + LYD_TREE_CHECK_CHAR(target, result, LYD_PRINT_SHRINK); + + /* destroy */ + lyd_free_all(source); + lyd_free_all(target); +} + +static void +test_list(void **state) +{ + const char *sch = + "module merge {\n" + " namespace \"http://test/merge\";\n" + " prefix merge;\n" + "\n" + " container inner1 {\n" + " list b-list1 {\n" + " key p1;\n" + " leaf p1 {\n" + " type uint8;\n" + " }\n" + " leaf p2 {\n" + " type string;\n" + " }\n" + " leaf p3 {\n" + " type boolean;\n" + " default false;\n" + " }\n" + " }\n" + " }\n" + "}\n"; + + const char *trg = + "\n" + " \n" + " 1\n" + " a\n" + " true\n" + " \n" + "\n"; + const char *src = + "\n" + " \n" + " 1\n" + " b\n" + " \n" + "\n"; + const char *result = + "\n" + " \n" + " 1\n" + " b\n" + " true\n" + " \n" + "\n"; + struct lyd_node *source, *target; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + LYD_TREE_CREATE(src, source); + LYD_TREE_CREATE(trg, target); + + /* merge them */ + assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + /* check the result */ + LYD_TREE_CHECK_CHAR(target, result, 0); + + lyd_free_all(target); + lyd_free_all(source); +} + +static void +test_list2(void **state) +{ + const char *sch = + "module merge {\n" + " namespace \"http://test/merge\";\n" + " prefix merge;\n" + "\n" + " container inner1 {\n" + " list b-list1 {\n" + " key p1;\n" + " leaf p1 {\n" + " type uint8;\n" + " }\n" + " leaf p2 {\n" + " type string;\n" + " }\n" + " container inner2 {\n" + " leaf p3 {\n" + " type boolean;\n" + " default false;\n" + " }\n" + " leaf p4 {\n" + " type string;\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}\n"; + + const char *trg = + "\n" + " \n" + " 1\n" + " a\n" + " \n" + " val\n" + " \n" + " \n" + "\n"; + const char *src = + "\n" + " \n" + " 1\n" + " b\n" + " \n" + "\n"; + const char *result = + "\n" + " \n" + " 1\n" + " b\n" + " \n" + " val\n" + " \n" + " \n" + "\n"; + struct lyd_node *source, *target; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + LYD_TREE_CREATE(src, source); + LYD_TREE_CREATE(trg, target); + + /* merge them */ + assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + /* check the result */ + LYD_TREE_CHECK_CHAR(target, result, 0); + + lyd_free_all(source); + lyd_free_all(target); +} + +static void +test_dup_inst_list(void **state) +{ + const char *sch = + "module merge {\n" + " namespace \"http://test/merge\";\n" + " prefix merge;\n" + "\n" + " container inner1 {\n" + " config false;\n" + " list b-list1 {\n" + " leaf p1 {\n" + " type uint8;\n" + " }\n" + " leaf p2 {\n" + " type string;\n" + " }\n" + " container inner2 {\n" + " leaf p4 {\n" + " type string;\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}\n"; + + const char *trg = + "\n" + " \n" + " 1\n" + " b\n" + " \n" + " \n" + " 1\n" + " a\n" + " \n" + " val\n" + " \n" + " \n" + "\n"; + const char *src = + "\n" + " \n" + " 1\n" + " b\n" + " \n" + " \n" + " 2\n" + " a\n" + " \n" + "\n"; + const char *result = + "\n" + " \n" + " 1\n" + " b\n" + " \n" + " \n" + " 1\n" + " a\n" + " \n" + " val\n" + " \n" + " \n" + " \n" + " 2\n" + " a\n" + " \n" + "\n"; + struct lyd_node *source, *target; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + LYD_TREE_CREATE(src, source); + LYD_TREE_CREATE(trg, target); + + /* merge them */ + assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + /* check the result */ + LYD_TREE_CHECK_CHAR(target, result, 0); + + lyd_free_all(source); + lyd_free_all(target); +} + +static void +test_dup_inst_llist(void **state) +{ + const char *sch = + "module merge {\n" + " namespace \"http://test/merge\";\n" + " prefix merge;\n" + "\n" + " container inner1 {\n" + " config false;\n" + " leaf-list b-llist1 {\n" + " type string;\n" + " }\n" + " }\n" + "}\n"; + + const char *trg = + "\n" + " a\n" + " b\n" + " c\n" + " d\n" + " a\n" + " b\n" + " c\n" + " d\n" + "\n"; + const char *src = + "\n" + " d\n" + " c\n" + " b\n" + " a\n" + " a\n" + " a\n" + " a\n" + " f\n" + " f\n" + "\n"; + const char *result = + "\n" + " a\n" + " b\n" + " c\n" + " d\n" + " a\n" + " b\n" + " c\n" + " d\n" + " a\n" + " a\n" + " f\n" + " f\n" + "\n"; + struct lyd_node *source, *target; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + LYD_TREE_CREATE(src, source); + LYD_TREE_CREATE(trg, target); + + /* merge them */ + assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + /* check the result */ + LYD_TREE_CHECK_CHAR(target, result, 0); + + lyd_free_all(source); + lyd_free_all(target); +} + +static void +test_case(void **state) +{ + const char *sch = + "module merge {\n" + " namespace \"http://test/merge\";\n" + " prefix merge;\n" + " container cont {\n" + " choice ch {\n" + " container inner {\n" + " leaf p1 {\n" + " type string;\n" + " }\n" + " }\n" + " case c2 {\n" + " leaf p1 {\n" + " type string;\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}\n"; + + const char *trg = + "\n" + " \n" + " 1\n" + " \n" + "\n"; + const char *src = + "\n" + " 1\n" + "\n"; + const char *result = + "\n" + " 1\n" + "\n"; + struct lyd_node *source, *target; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + LYD_TREE_CREATE(src, source); + LYD_TREE_CREATE(trg, target); + + /* merge them */ + assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + /* check the result */ + LYD_TREE_CHECK_CHAR(target, result, 0); + + lyd_free_all(source); + lyd_free_all(target); +} + +static void +test_dflt(void **state) +{ + const char *sch = + "module merge-dflt {\n" + " namespace \"urn:merge-dflt\";\n" + " prefix md;\n" + " container top {\n" + " leaf a {\n" + " type string;\n" + " }\n" + " leaf b {\n" + " type string;\n" + " }\n" + " leaf c {\n" + " type string;\n" + " default \"c_dflt\";\n" + " }\n" + " }\n" + "}\n"; + struct lyd_node *target = NULL; + struct lyd_node *source = NULL; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/c", "c_dflt", 0, &target), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/a", "a_val", 0, &source), LY_SUCCESS); + assert_int_equal(lyd_new_path(source, UTEST_LYCTX, "/merge-dflt:top/b", "b_val", 0, NULL), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&source, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + assert_int_equal(lyd_merge_siblings(&target, source, LYD_MERGE_DESTRUCT | LYD_MERGE_DEFAULTS), LY_SUCCESS); + source = NULL; + + /* c should be replaced and now be default */ + assert_string_equal(lyd_child(target)->prev->schema->name, "c"); + assert_true(lyd_child(target)->prev->flags & LYD_DEFAULT); + + lyd_free_all(target); + lyd_free_all(source); +} + +static void +test_dflt2(void **state) +{ + const char *sch = + "module merge-dflt {\n" + " namespace \"urn:merge-dflt\";\n" + " prefix md;\n" + " container top {\n" + " leaf a {\n" + " type string;\n" + " }\n" + " leaf b {\n" + " type string;\n" + " }\n" + " leaf c {\n" + " type string;\n" + " default \"c_dflt\";\n" + " }\n" + " }\n" + "}\n"; + struct lyd_node *target; + struct lyd_node *source; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/c", "c_dflt", 0, &target), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/a", "a_val", 0, &source), LY_SUCCESS); + assert_int_equal(lyd_new_path(source, UTEST_LYCTX, "/merge-dflt:top/b", "b_val", 0, NULL), LY_SUCCESS); + assert_int_equal(lyd_validate_all(&source, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS); + + assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS); + + /* c should not be replaced, so c remains not default */ + assert_false(lyd_child(target)->flags & LYD_DEFAULT); + + lyd_free_all(target); + lyd_free_all(source); +} + +static void +test_leafrefs(void **state) +{ + const char *sch = "module x {" + " namespace urn:x;" + " prefix x;" + " list l {" + " key n;" + " leaf n { type string; }" + " leaf t { type string; }" + " leaf r { type leafref { path '/l/n'; } }}}"; + const char *trg = "a" + "ba"; + const char *src = "ca" + "a*"; + const char *res = "a*" + "ba" + "ca"; + struct lyd_node *source, *target; + + UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL); + + LYD_TREE_CREATE(src, source); + LYD_TREE_CREATE(trg, target); + + assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS); + + LYD_TREE_CHECK_CHAR(target, res, LYD_PRINT_SHRINK); + + lyd_free_all(source); + lyd_free_all(target); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_batch), + UTEST(test_leaf), + UTEST(test_container), + UTEST(test_list), + UTEST(test_list2), + UTEST(test_dup_inst_list), + UTEST(test_dup_inst_llist), + UTEST(test_case), + UTEST(test_dflt), + UTEST(test_dflt2), + UTEST(test_leafrefs), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} -- cgit v1.2.3