| /** |
| * \file test_extensions.c |
| * \author Radek Krejci <rkrejci@cesnet.cz> |
| * \brief libyang tests - extensions |
| * |
| * Copyright (c) 2016 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 <errno.h> |
| #include <fcntl.h> |
| #include <pthread.h> |
| #include <setjmp.h> |
| #include <stdarg.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| #include <cmocka.h> |
| |
| #include "../../src/libyang.h" |
| #include "../config.h" |
| |
| #define SCHEMA_FOLDER_YIN TESTS_DIR"/schema/yin/files" |
| #define SCHEMA_FOLDER_YANG TESTS_DIR"/schema/yang/files" |
| |
| struct state { |
| struct ly_ctx *ctx; |
| int fd; |
| char *str1; |
| char *str2; |
| }; |
| |
| static int |
| setup_ctx(void **state, const char *searchdir) |
| { |
| struct state *st; |
| |
| (*state) = st = calloc(1, sizeof *st); |
| if (!st) { |
| fprintf(stderr, "Memory allocation error"); |
| return -1; |
| } |
| |
| /* libyang context */ |
| st->ctx = ly_ctx_new(searchdir); |
| if (!st->ctx) { |
| fprintf(stderr, "Failed to create context.\n"); |
| goto error; |
| } |
| |
| st->fd = -1; |
| |
| return 0; |
| |
| error: |
| ly_ctx_destroy(st->ctx, NULL); |
| free(st); |
| (*state) = NULL; |
| |
| return -1; |
| } |
| |
| static int |
| setup_ctx_yin(void **state) |
| { |
| return setup_ctx(state, SCHEMA_FOLDER_YIN); |
| } |
| |
| static int |
| setup_ctx_yang(void **state) |
| { |
| return setup_ctx(state, SCHEMA_FOLDER_YANG); |
| } |
| |
| static int |
| teardown_ctx(void **state) |
| { |
| struct state *st = (*state); |
| |
| ly_ctx_destroy(st->ctx, NULL); |
| if (st->fd >= 0) { |
| close(st->fd); |
| } |
| free(st->str1); |
| free(st->str2); |
| free(st); |
| (*state) = NULL; |
| |
| return 0; |
| } |
| |
| static void |
| test_module_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </yang-version>\n <namespace uri=\"urn:ext\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </namespace>\n <prefix value=\"x\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </prefix>\n" |
| " <import module=\"ext-def\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <prefix value=\"e\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </prefix>\n <revision-date date=\"2017-01-18\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </revision-date>\n <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </import>\n" |
| " <include module=\"ext-inc\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <revision-date date=\"2017-01-18\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </revision-date>\n <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </include>\n" |
| " <revision date=\"2017-01-20\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </revision>\n <revision date=\"2017-01-18\">\n" |
| " <e:a/>\n" |
| " </revision>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| "</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_module_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n namespace \"urn:ext\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n prefix x {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n\n" |
| " import ext-def {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " prefix e {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n revision-date 2017-01-18 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " include ext-inc {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " revision-date 2017-01-18 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " revision \"2017-01-20\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n" |
| " revision \"2017-01-18\" {\n" |
| " e:a;\n" |
| " }\n\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_container_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <container name=\"c\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <presence value=\"test\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </presence>\n" |
| " <config value=\"false\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </config>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </container>\n</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_container_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " namespace \"urn:ext\";\n prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " container c {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " presence \"test\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n config false {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_leaf_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <typedef name=\"length\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <type name=\"int32\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </type>\n" |
| " <units name=\"meter\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </units>\n" |
| " <default value=\"10\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </default>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </typedef>\n" |
| " <leaf name=\"l\">\n" |
| " <type name=\"string\">\n" |
| " <pattern value=\"[a-z]\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <modifier value=\"invert-match\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </modifier>\n <error-message>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <value>emsg</value>\n" |
| " </error-message>\n <error-app-tag value=\"eapptag\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </error-app-tag>\n <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </pattern>\n" |
| " </type>\n" |
| " <units name=\"petipivo\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </units>\n" |
| " <must condition=\"true()\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <error-message>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <value>emsg</value>\n" |
| " </error-message>\n <error-app-tag value=\"eapptag\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </error-app-tag>\n <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </must>\n" |
| " <config value=\"false\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </config>\n" |
| " <mandatory value=\"true\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </mandatory>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </leaf>\n <leaf name=\"d\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <type name=\"length\"/>\n" |
| " <default value=\"1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </default>\n" |
| " </leaf>\n</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_leaf_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " typedef length {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " type int32 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n units \"meter\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n default \"10\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " leaf l {\n type string {\n" |
| " pattern \"[a-z]\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " modifier invert-match {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n error-message\n \"emsg\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n error-app-tag \"eapptag\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n }\n" |
| " units \"petipivo\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n must \"true()\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " error-message\n \"emsg\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n error-app-tag \"eapptag\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " }\n config false {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n mandatory true {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " leaf d {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " type int8;\n default \"1\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_leaflist_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <feature name=\"f1\"/>\n <feature name=\"f\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <if-feature name=\"f1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </if-feature>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </feature>\n" |
| " <leaf-list name=\"l1\">\n" |
| " <when condition=\"true()\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </when>\n <if-feature name=\"f\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </if-feature>\n <type name=\"string\">\n" |
| " <length value=\"5\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <error-message>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <value>emsg</value>\n" |
| " </error-message>\n <error-app-tag value=\"eapptag\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </error-app-tag>\n <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </length>\n" |
| " </type>\n" |
| " <units name=\"petipivo\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </units>\n" |
| " <must condition=\"true()\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <error-message>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <value>emsg</value>\n" |
| " </error-message>\n <error-app-tag value=\"eapptag\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </error-app-tag>\n <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </must>\n" |
| " <config value=\"true\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </config>\n" |
| " <min-elements value=\"1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </min-elements>\n" |
| " <max-elements value=\"1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </max-elements>\n" |
| " <ordered-by value=\"user\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </ordered-by>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </leaf-list>\n" |
| " <leaf-list name=\"l2\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <type name=\"int8\">\n" |
| " <range value=\"1..10\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <error-message>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <value>emsg</value>\n" |
| " </error-message>\n <error-app-tag value=\"eapptag\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </error-app-tag>\n <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </range>\n" |
| " </type>\n" |
| " <default value=\"1\"/>\n <default value=\"2\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </default>\n" |
| " </leaf-list>\n</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_leaflist_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " feature f1;\n\n feature f {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " if-feature \"f1\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " leaf-list l1 {\n" |
| " when \"true()\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " }\n if-feature \"f\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n type string {\n length \"5\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " error-message\n \"emsg\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n error-app-tag \"eapptag\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n }\n" |
| " units \"petipivo\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n must \"true()\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " error-message\n \"emsg\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n error-app-tag \"eapptag\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " }\n config true {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n min-elements 1 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n max-elements 1 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n ordered-by user {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " leaf-list l2 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " type int8 {\n range \"1..10\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " error-message\n \"emsg\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n error-app-tag \"eapptag\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n }\n" |
| " default \"1\";\n" |
| " default \"2\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_list_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <list name=\"l\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <key value=\"id\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </key>\n" |
| " <unique tag=\"val1\"/>\n <unique tag=\"val2\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </unique>\n" |
| " <config value=\"true\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </config>\n" |
| " <min-elements value=\"1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </min-elements>\n" |
| " <max-elements value=\"1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </max-elements>\n" |
| " <ordered-by value=\"user\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </ordered-by>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <leaf name=\"id\">\n" |
| " <type name=\"instance-identifier\">\n" |
| " <e:a/>\n" |
| " <require-instance value=\"true\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </require-instance>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " <leaf name=\"val1\">\n" |
| " <type name=\"decimal64\">\n" |
| " <e:a/>\n" |
| " <fraction-digits value=\"2\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </fraction-digits>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " <leaf name=\"val2\">\n" |
| " <type name=\"leafref\">\n" |
| " <e:a/>\n" |
| " <path value=\"../val1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </path>\n" |
| " <require-instance value=\"true\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </require-instance>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " </list>\n</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_list_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " list l {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " key \"id\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n unique \"val1\";\n unique \"val2\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n config true {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n min-elements 1 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n max-elements 1 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n ordered-by user {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n leaf id {\n" |
| " type instance-identifier {\n" |
| " e:a;\n" |
| " require-instance true {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n" |
| " }\n\n leaf val1 {\n" |
| " type decimal64 {\n" |
| " e:a;\n" |
| " fraction-digits 2 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n" |
| " }\n\n leaf val2 {\n" |
| " type leafref {\n" |
| " e:a;\n" |
| " path \"../val1\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n require-instance true {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n" |
| " }\n }\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_anydata_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <feature name=\"f\"/>\n" |
| " <anyxml name=\"a\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <when condition=\"true()\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </when>\n <if-feature name=\"f\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </if-feature>\n" |
| " <must condition=\"true()\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <error-message>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <value>emsg</value>\n" |
| " </error-message>\n <error-app-tag value=\"eapptag\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </error-app-tag>\n <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </must>\n" |
| " <config value=\"true\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </config>\n" |
| " <mandatory value=\"true\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </mandatory>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </anyxml>\n</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_anydata_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " feature f;\n\n" |
| " anyxml l {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " when \"true()\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " }\n if-feature \"f\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n must \"true()\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " error-message\n \"emsg\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n error-app-tag \"eapptag\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " }\n config true {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n mandatory true {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_choice_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <choice name=\"ch\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <default value=\"a\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </default>\n" |
| " <config value=\"true\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </config>\n" |
| " <mandatory value=\"false\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </mandatory>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <case name=\"a\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <leaf name=\"c\">\n" |
| " <type name=\"bits\">\n" |
| " <bit name=\"zero\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <position value=\"0\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </position>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </bit>\n" |
| " <bit name=\"one\">\n <e:a/>\n </bit>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " </case>\n" |
| " <leaf name=\"b\">\n" |
| " <type name=\"enumeration\">\n" |
| " <enum name=\"one\">\n <e:a/>\n </enum>\n" |
| " <enum name=\"two\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <value value=\"2\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </value>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </enum>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " </choice>\n</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_choice_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " choice ch {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " default \"a\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n config true {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n mandatory false {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n case a {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n leaf c {\n" |
| " type bits {\n" |
| " bit zero {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " position 0 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n" |
| " bit one {\n" |
| " e:a;\n" |
| " }\n" |
| " }\n" |
| " }\n\n leaf b {\n" |
| " type enumeration {\n" |
| " enum \"one\" {\n" |
| " e:a;\n" |
| " }\n" |
| " enum \"two\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " value 2 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n }\n }\n }\n }\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_uses_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <identity name=\"zero\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </identity>\n" |
| " <identity name=\"one\">\n" |
| " <base name=\"zero\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </base>\n" |
| " </identity>\n" |
| " <identity name=\"two\">\n" |
| " <base name=\"zero\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </base>\n" |
| " <base name=\"one\">\n" |
| " <e:a/>\n" |
| " </base>\n" |
| " </identity>\n" |
| " <grouping name=\"grp\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <container name=\"c\">\n <e:a/>\n </container>\n" |
| " <leaf name=\"l\">\n" |
| " <type name=\"identityref\">\n" |
| " <base name=\"two\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </base>\n" |
| " </type>\n" |
| " <mandatory value=\"true\">\n <e:a/>\n </mandatory>\n" |
| " </leaf>\n" |
| " <leaf-list name=\"ll1\">\n" |
| " <type name=\"int8\"/>\n" |
| " <min-elements value=\"2\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </min-elements>\n" |
| " </leaf-list>\n" |
| " <leaf-list name=\"ll2\">\n" |
| " <type name=\"int8\"/>\n" |
| " </leaf-list>\n" |
| " </grouping>\n" |
| " <uses name=\"grp\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <refine target-node=\"c\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <presence value=\"true\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </presence>\n" |
| " <config value=\"false\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </config>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </refine>\n" |
| " <refine target-node=\"l\">\n" |
| " <mandatory value=\"false\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </mandatory>\n" |
| " </refine>\n" |
| " <refine target-node=\"ll1\">\n" |
| " <min-elements value=\"1\">\n" |
| " <e:a/>\n" |
| " </min-elements>\n" |
| " <max-elements value=\"2\">\n" |
| " <e:b x=\"one\"/>\n" |
| " </max-elements>\n" |
| " </refine>\n" |
| " <refine target-node=\"ll2\">\n" |
| " <e:a/>\n" |
| " <default value=\"1\"/>\n" |
| " <default value=\"2\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </default>\n" |
| " </refine>\n" |
| " <augment target-node=\"c\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <leaf name=\"a\">\n" |
| " <type name=\"int8\"/>\n" |
| " </leaf>\n" |
| " </augment>\n" |
| " </uses>\n" |
| "</module>\n"; |
| struct lys_node *uses; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| |
| /* check applied refine's substatements' extensions */ |
| uses = mod->data->prev; |
| assert_int_equal(uses->nodetype, LYS_USES); |
| |
| assert_int_equal(uses->child->ext_size, 15); /* number of extensions in c */ |
| assert_int_equal(uses->child->next->ext_size, 3); /* number of extensions in l */ |
| assert_int_equal(uses->child->next->next->ext_size, 2); /* number of extensions in ll1 */ |
| assert_int_equal(uses->child->prev->ext_size, 4); /* number of extensions in ll2 */ |
| } |
| |
| static void |
| test_uses_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " identity zero {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " identity one {\n" |
| " base zero {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " identity two {\n" |
| " base zero {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n base one {\n" |
| " e:a;\n" |
| " }\n }\n\n" |
| " grouping grp {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n container c;\n\n" |
| " leaf l {\n" |
| " type identityref {\n" |
| " base two {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n" |
| " mandatory true {\n" |
| " e:a;\n" |
| " }\n }\n\n" |
| " leaf-list ll1 {\n" |
| " type int8;\n" |
| " }\n\n" |
| " leaf-list ll2 {\n" |
| " type int8;\n" |
| " }\n }\n\n" |
| " uses grp {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n refine \"c\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " presence \"true\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n config false {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " }\n refine \"l\" {\n" |
| " mandatory false {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " }\n refine \"ll1\" {\n" |
| " min-elements 1 {\n" |
| " e:a;\n" |
| " }\n max-elements 2 {\n" |
| " e:b \"one\";\n" |
| " }\n" |
| " }\n refine \"ll2\" {\n" |
| " e:a;\n" |
| " default \"1\";\n" |
| " default \"2\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n" |
| " }\n augment \"c\" {\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n leaf a {\n" |
| " type int8;\n" |
| " }\n }\n }\n}\n"; |
| struct lys_node *uses; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| |
| /* check applied refine's substatements' extensions */ |
| uses = mod->data->prev; |
| assert_int_equal(uses->nodetype, LYS_USES); |
| |
| assert_int_equal(uses->child->ext_size, 15); /* number of extensions in c */ |
| assert_int_equal(uses->child->next->ext_size, 3); /* number of extensions in l */ |
| assert_int_equal(uses->child->next->next->ext_size, 2); /* number of extensions in ll1 */ |
| assert_int_equal(uses->child->prev->ext_size, 4); /* number of extensions in ll2 */ |
| } |
| |
| static void |
| test_extension_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <extension name=\"x\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <argument name=\"y\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <yin-element value=\"false\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </yin-element>\n" |
| " </argument>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " </extension>\n" |
| " <e:a>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </e:a>\n</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_extension_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " extension x {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " argument y {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " yin-element false {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " e:a {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_rpc_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <container name=\"c\">\n" |
| " <action name=\"a\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <input>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <leaf name=\"in\">\n" |
| " <type name=\"int8\"/>\n" |
| " </leaf>\n" |
| " </input>\n" |
| " <output>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <leaf name=\"in\">\n" |
| " <type name=\"int8\"/>\n" |
| " </leaf>\n" |
| " </output>\n" |
| " </action>\n" |
| " </container>\n" |
| " <rpc name=\"r\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <input>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <leaf name=\"in\">\n" |
| " <type name=\"int8\"/>\n" |
| " </leaf>\n" |
| " </input>\n" |
| " <output>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <leaf name=\"in\">\n" |
| " <type name=\"int8\"/>\n" |
| " </leaf>\n" |
| " </output>\n" |
| " </rpc>\n</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_rpc_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " container c {\n" |
| " action a {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n input {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " leaf in {\n" |
| " type int8;\n" |
| " }\n }\n\n" |
| " output {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " leaf out {\n" |
| " type int8;\n" |
| " }\n }\n }\n }\n\n" |
| " rpc r {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n input {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " leaf in {\n" |
| " type int8;\n" |
| " }\n }\n\n" |
| " output {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " leaf out {\n" |
| " type int8;\n" |
| " }\n }\n }\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_notif_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <container name=\"c\">\n" |
| " <notification name=\"n-in-c\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <leaf name=\"info\">\n" |
| " <type name=\"int8\"/>\n" |
| " </leaf>\n" |
| " </notification>\n" |
| " </container>\n" |
| " <notification name=\"n\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <status value=\"current\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </status>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <leaf name=\"info\">\n" |
| " <type name=\"int8\"/>\n" |
| " </leaf>\n" |
| " </notification>\n</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_notif_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " container c {\n" |
| " notification n-in-c {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n leaf out {\n" |
| " type int8;\n" |
| " }\n }\n }\n\n" |
| " notification n {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " status current {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n leaf in {\n" |
| " type int8;\n" |
| " }\n }\n}\n"; |
| |
| mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| } |
| |
| static void |
| test_deviation_sub_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod, *dev; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <deviation target-node=\"/e:l1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <description>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>desc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <text>ref</text>\n" |
| " </reference>\n" |
| " <deviate value=\"not-supported\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </deviate>\n" |
| " </deviation>\n" |
| " <deviation target-node=\"/e:ll1\">\n" |
| " <deviate value=\"add\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " <units name=\"meter\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </units>\n" |
| " <default value=\"1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </default>\n" |
| " <default value=\"2\">\n" |
| " <e:a/>\n" |
| " </default>\n" |
| " <config value=\"false\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </config>\n" |
| " </deviate>\n" |
| " </deviation>\n" |
| " <deviation target-node=\"/e:lst1\">\n" |
| " <deviate value=\"add\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n" |
| " <unique tag=\"val1\"/>\n <unique tag=\"val2\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </unique>\n" |
| " <min-elements value=\"1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </min-elements>\n" |
| " <max-elements value=\"1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </max-elements>\n" |
| " </deviate>\n" |
| " </deviation>\n" |
| " <deviation target-node=\"/e:l2\">\n" |
| " <deviate value=\"replace\">\n" |
| " <e:b x=\"ten\"/>\n" |
| " <mandatory value=\"false\">\n" |
| " <e:a/>\n" |
| " </mandatory>\n" |
| " </deviate>\n" |
| " </deviation>\n" |
| " <deviation target-node=\"/e:lst1/e:val2\">\n" |
| " <deviate value=\"delete\">\n" |
| " <e:a/>\n" |
| " <units name=\"meter\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </units>\n" |
| " <default value=\"1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </default>\n" |
| " </deviate>\n" |
| " </deviation>\n" |
| " <deviation target-node=\"/e:lst2\">\n" |
| " <deviate value=\"delete\">\n" |
| " <e:a/>\n <e:b x=\"two\"/>\n" |
| " <unique tag=\"val1\">\n" |
| " <e:a/>\n <e:b x=\"one\"/>\n <e:c>\n <e:y>one</e:y>\n </e:c>\n" |
| " </unique>\n" |
| " </deviate>\n" |
| " </deviation>\n" |
| "</module>\n"; |
| struct lys_node *node; |
| |
| mod = ly_ctx_load_module(st->ctx, "ext-def", NULL); |
| assert_ptr_not_equal(mod, NULL); |
| |
| dev = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(dev, NULL); |
| |
| lys_print_mem(&st->str1, dev, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| |
| /* check extensions in the deviated data */ |
| /* l1 is removed */ |
| assert_string_not_equal(mod->data->name, "l1"); |
| assert_string_not_equal(mod->data->prev->name, "l1"); |
| assert_string_not_equal(mod->data->next->name, "l1"); |
| |
| /* l2 is now first and instead of 5 extensions it now has only 3 */ |
| node = mod->data; |
| assert_string_equal(node->name, "l2"); |
| assert_int_equal(node->flags & LYS_MAND_MASK, LYS_MAND_FALSE); |
| assert_int_equal(node->ext_size, 3); |
| |
| /* ll1 has 13 extensions (10 from substatements) */ |
| node = mod->data->next; |
| assert_string_equal(node->name, "ll1"); |
| assert_int_equal(node->ext_size, 13); |
| |
| /* lst1 has 12 extensions (2 added, 9 added from substatements) */ |
| node = mod->data->next->next; |
| assert_string_equal(node->name, "lst1"); |
| assert_int_equal(node->ext_size, 12); |
| |
| /* lst2 has 1 ext, since the deviation removes unique with all its extensions and 3 of the 4 node's extensions */ |
| node = mod->data->prev; |
| assert_string_equal(node->name, "lst2"); |
| assert_int_equal(node->ext_size, 1); |
| |
| /* val2 has no extension, all were deleted */ |
| node = mod->data->next->next->child->prev; |
| assert_string_equal(node->name, "val2"); |
| assert_string_equal(node->parent->name, "lst1"); |
| assert_int_equal(node->ext_size, 0); |
| |
| /* revert deviations */ |
| ly_ctx_remove_module(dev, NULL); |
| |
| /* l1 is reconnected at the end of data nodes */ |
| assert_string_equal(mod->data->prev->name, "l1"); |
| |
| /* l2 is back true and contains again the 5 extensions */ |
| node = mod->data; |
| assert_string_equal(node->name, "l2"); |
| assert_int_equal(node->flags & LYS_MAND_MASK, LYS_MAND_TRUE); |
| assert_int_equal(node->ext_size, 5); |
| |
| /* ll1 has no extension again */ |
| node = mod->data->next; |
| assert_string_equal(node->name, "ll1"); |
| assert_int_equal(node->ext_size, 0); |
| |
| /* lst1 has back 1 extension */ |
| node = mod->data->next->next; |
| assert_string_equal(node->name, "lst1"); |
| assert_int_equal(node->ext_size, 1); |
| |
| /* lst2 has back all the 5 original extensions */ |
| node = mod->data->prev->prev; /* lst2 is not last, there is added l1 */ |
| assert_string_equal(node->name, "lst2"); |
| assert_int_equal(node->ext_size, 5); |
| |
| /* val2 has back all its 2 extensions */ |
| node = mod->data->next->next->child->prev; |
| assert_string_equal(node->name, "val2"); |
| assert_string_equal(node->parent->name, "lst1"); |
| assert_int_equal(node->ext_size, 2); |
| } |
| |
| static void |
| test_deviation_sub_yang(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod, *dev; |
| const char *yang = "module ext {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:ext\";\n" |
| " prefix x;\n\n" |
| " import ext-def {\n prefix e;\n }\n\n" |
| " deviation \"/e:l1\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " description\n \"desc\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n reference\n \"ref\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n deviate not-supported {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n\n" |
| " deviation \"/e:ll1\" {\n" |
| " deviate add {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " units \"meter\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n default \"1\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n default \"2\" {\n" |
| " e:a;\n" |
| " }\n config false {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n }\n\n" |
| " deviation \"/e:lst1\" {\n" |
| " deviate add {\n" |
| " e:a;\n e:b \"one\";\n" |
| " unique \"val1\";\n" |
| " unique \"val2\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n min-elements 1 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n max-elements 2 {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n }\n\n" |
| " deviation \"/e:l2\" {\n" |
| " deviate replace {\n" |
| " e:b \"ten\";\n" |
| " mandatory false {\n" |
| " e:a;\n" |
| " }\n }\n }\n\n" |
| " deviation \"/e:lst1/e:val2\" {\n" |
| " deviate delete {\n" |
| " e:a;\n" |
| " units \"meter\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n default \"1\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n }\n\n" |
| " deviation \"/e:lst2\" {\n" |
| " deviate delete {\n" |
| " e:a;\n e:b \"two\";\n" |
| " unique \"val1\" {\n" |
| " e:a;\n e:b \"one\";\n e:c \"one\";\n" |
| " }\n }\n }\n}\n"; |
| struct lys_node *node; |
| |
| mod = ly_ctx_load_module(st->ctx, "ext-def", NULL); |
| assert_ptr_not_equal(mod, NULL); |
| |
| dev = lys_parse_mem(st->ctx, yang, LYS_IN_YANG); |
| assert_ptr_not_equal(dev, NULL); |
| |
| lys_print_mem(&st->str1, dev, LYS_OUT_YANG, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yang); |
| |
| /* check extensions in the deviated data */ |
| /* l1 is removed */ |
| assert_string_not_equal(mod->data->name, "l1"); |
| assert_string_not_equal(mod->data->prev->name, "l1"); |
| assert_string_not_equal(mod->data->next->name, "l1"); |
| |
| /* l2 is now first and instead of 5 extensions it now has only 3 */ |
| node = mod->data; |
| assert_string_equal(node->name, "l2"); |
| assert_int_equal(node->flags & LYS_MAND_MASK, LYS_MAND_FALSE); |
| assert_int_equal(node->ext_size, 3); |
| |
| /* ll1 has 13 extensions (10 from substatements) */ |
| node = mod->data->next; |
| assert_string_equal(node->name, "ll1"); |
| assert_int_equal(node->ext_size, 13); |
| |
| /* lst1 has 12 extensions (2 added, 9 added from substatements) */ |
| node = mod->data->next->next; |
| assert_string_equal(node->name, "lst1"); |
| assert_int_equal(node->ext_size, 12); |
| |
| /* lst2 has 1 ext, since the deviation removes unique with all its extensions and 3 of the 4 node's extensions */ |
| node = mod->data->prev; |
| assert_string_equal(node->name, "lst2"); |
| assert_int_equal(node->ext_size, 1); |
| |
| /* val2 has no extension, all were deleted */ |
| node = mod->data->next->next->child->prev; |
| assert_string_equal(node->name, "val2"); |
| assert_string_equal(node->parent->name, "lst1"); |
| assert_int_equal(node->ext_size, 0); |
| |
| /* revert deviations */ |
| ly_ctx_remove_module(dev, NULL); |
| |
| /* l1 is reconnected at the end of data nodes */ |
| assert_string_equal(mod->data->prev->name, "l1"); |
| |
| /* l2 is back true and contains again the 5 extensions */ |
| node = mod->data; |
| assert_string_equal(node->name, "l2"); |
| assert_int_equal(node->flags & LYS_MAND_MASK, LYS_MAND_TRUE); |
| assert_int_equal(node->ext_size, 5); |
| |
| /* ll1 has no extension again */ |
| node = mod->data->next; |
| assert_string_equal(node->name, "ll1"); |
| assert_int_equal(node->ext_size, 0); |
| |
| /* lst1 has back 1 extension */ |
| node = mod->data->next->next; |
| assert_string_equal(node->name, "lst1"); |
| assert_int_equal(node->ext_size, 1); |
| |
| /* lst2 has back all the 5 original extensions */ |
| node = mod->data->prev->prev; /* lst2 is not last, there is added l1 */ |
| assert_string_equal(node->name, "lst2"); |
| assert_int_equal(node->ext_size, 5); |
| |
| /* val2 has back all its 2 extensions */ |
| node = mod->data->next->next->child->prev; |
| assert_string_equal(node->name, "val2"); |
| assert_string_equal(node->parent->name, "lst1"); |
| assert_int_equal(node->ext_size, 2); |
| } |
| |
| static void |
| test_complex_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <e:complex>\n" |
| " <argument name=\"a\"/>\n" |
| " <base name=\"b\"/>\n" |
| " <belongs-to module=\"test\">\n <prefix value=\"t\"/>\n </belongs-to>\n" |
| " <contact>\n <text>contact</text>\n </contact>\n" |
| " <default value=\"c\"/>\n" |
| " <description>\n <text>description</text>\n </description>\n" |
| " <error-app-tag value=\"d\"/>\n" |
| " <error-message>\n <value>errmsg</value>\n </error-message>\n" |
| " <key value=\"e\"/>\n" |
| " <namespace uri=\"urn\"/>\n" |
| " <organization>\n <text>org</text>\n </organization>\n" |
| " <path value=\"f\"/>\n" |
| " <prefix value=\"g\"/>\n" |
| " <presence value=\"h\"/>\n" |
| " <reference>\n <text>reference</text>\n </reference>\n" |
| " <revision-date date=\"i\"/>\n" |
| " <units name=\"j\"/>\n" |
| " <modifier value=\"invert-match\"/>\n" |
| " <require-instance value=\"true\"/>\n" |
| " <config value=\"true\"/>\n" |
| " <mandatory value=\"true\"/>\n" |
| " <ordered-by value=\"user\"/>\n" |
| " <status value=\"obsolete\"/>\n" |
| " <fraction-digits value=\"5\"/>\n" |
| " <max-elements value=\"2\"/>\n" |
| " <min-elements value=\"4\"/>\n" |
| " <position value=\"11\"/>\n" |
| " <value value=\"355\"/>\n" |
| " <unique tag=\"e\"/>\n" |
| " <module name=\"inmod\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:i=\"urn:inmod\">\n" |
| " <namespace uri=\"urn:inmod\"/>\n" |
| " <prefix value=\"i\"/>\n" |
| " </module>\n" |
| " <action name=\"action\"/>\n" |
| " <anydata name=\"anydata\"/>\n" |
| " <anyxml name=\"anyxml\"/>\n" |
| " <case name=\"case\"/>\n" |
| " <choice name=\"choice\">\n" |
| " <anydata name=\"a\"/>\n" |
| " <anydata name=\"b\"/>\n" |
| " </choice>\n" |
| " <container name=\"container\">\n" |
| " <presence value=\"presence\"/>\n" |
| " </container>\n" |
| " <grouping name=\"grp\">\n" |
| " <anydata name=\"c\"/>\n" |
| " </grouping>\n" |
| " <input>\n" |
| " <anydata name=\"d\"/>\n" |
| " </input>\n" |
| " <leaf name=\"e\">\n" |
| " <type name=\"string\"/>\n" |
| " </leaf>\n" |
| " <leaf-list name=\"f\">\n" |
| " <type name=\"string\"/>\n" |
| " </leaf-list>\n" |
| " <list name=\"g\">\n" |
| " <key value=\"k\"/>\n" |
| " <leaf name=\"k\">\n" |
| " <type name=\"string\"/>\n" |
| " </leaf>\n" |
| " </list>\n" |
| " <notification name=\"h\">\n" |
| " <anydata name=\"i\"/>\n" |
| " </notification>\n" |
| " <output>\n" |
| " <anydata name=\"i\"/>\n" |
| " </output>\n" |
| " <uses name=\"grp\"/>\n" |
| " <typedef name=\"mytype\">\n <type name=\"string\"/>\n </typedef>\n" |
| " <type name=\"string\"/>\n" |
| " <if-feature name=\"f\"/>\n" |
| " <length value=\"10..20\"/>\n" |
| " <must condition=\"1\"/>\n" |
| " <pattern value=\"[a-z]*\"/>\n" |
| " <range value=\"0..10\"/>\n" |
| " <when condition=\"1\"/>\n" |
| " <revision date=\"2016-02-16\"/>\n" |
| " </e:complex>\n" |
| " <feature name=\"f\"/>\n" |
| "</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| static void |
| test_complex_arrays_yin(void **state) |
| { |
| struct state *st = (*state); |
| const struct lys_module *mod; |
| const char *yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"ext\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:x=\"urn:ext\"\n" |
| " xmlns:e=\"urn:ext-def\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:ext\"/>\n" |
| " <prefix value=\"x\"/>\n" |
| " <import module=\"ext-def\">\n <prefix value=\"e\"/>\n </import>\n" |
| " <e:complex-arrays>\n" |
| " <argument name=\"a\"/>\n" |
| " <argument name=\"b\"/>\n" |
| " <base name=\"a\"/>\n" |
| " <base name=\"b\"/>\n" |
| " <belongs-to module=\"test1\">\n <prefix value=\"t1\"/>\n </belongs-to>\n" |
| " <belongs-to module=\"test2\">\n <prefix value=\"t2\"/>\n </belongs-to>\n" |
| " <contact>\n <text>contact1</text>\n </contact>\n" |
| " <contact>\n <text>contact2</text>\n </contact>\n" |
| " <default value=\"a\"/>\n" |
| " <default value=\"b\"/>\n" |
| " <description>\n <text>description1</text>\n </description>\n" |
| " <description>\n <text>description2</text>\n </description>\n" |
| " <error-app-tag value=\"a\"/>\n" |
| " <error-app-tag value=\"b\"/>\n" |
| " <error-message>\n <value>errmsg1</value>\n </error-message>\n" |
| " <error-message>\n <value>errmsg2</value>\n </error-message>\n" |
| " <key value=\"a\"/>\n" |
| " <key value=\"b\"/>\n" |
| " <namespace uri=\"urn1\"/>\n" |
| " <namespace uri=\"urn2\"/>\n" |
| " <organization>\n <text>org1</text>\n </organization>\n" |
| " <organization>\n <text>org2</text>\n </organization>\n" |
| " <path value=\"a\"/>\n" |
| " <path value=\"b\"/>\n" |
| " <prefix value=\"a\"/>\n" |
| " <prefix value=\"b\"/>\n" |
| " <presence value=\"a\"/>\n" |
| " <presence value=\"b\"/>\n" |
| " <reference>\n <text>reference1</text>\n </reference>\n" |
| " <reference>\n <text>reference2</text>\n </reference>\n" |
| " <units name=\"a\"/>\n" |
| " <units name=\"b\"/>\n" |
| " <fraction-digits value=\"5\"/>\n" |
| " <fraction-digits value=\"10\"/>\n" |
| " <max-elements value=\"2\"/>\n" |
| " <max-elements value=\"3\"/>\n" |
| " <min-elements value=\"4\"/>\n" |
| " <min-elements value=\"5\"/>\n" |
| " <position value=\"11\"/>\n" |
| " <position value=\"12\"/>\n" |
| " <value value=\"42\"/>\n" |
| " <value value=\"-55\"/>\n" |
| " <unique tag=\"l1 l2\"/>\n" |
| " <unique tag=\"l2\"/>\n" |
| " <module name=\"inmod1\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:i=\"urn:inmod1\">\n" |
| " <namespace uri=\"urn:inmod1\"/>\n" |
| " <prefix value=\"i\"/>\n" |
| " </module>\n" |
| " <module name=\"inmod2\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:i=\"urn:inmod2\">\n" |
| " <namespace uri=\"urn:inmod2\"/>\n" |
| " <prefix value=\"i\"/>\n" |
| " </module>\n" |
| " <anydata name=\"anydata1\"/>\n" |
| " <anydata name=\"anydata2\"/>\n" |
| " <anyxml name=\"anyxml1\"/>\n" |
| " <anyxml name=\"anyxml2\"/>\n" |
| " <leaf name=\"l1\">\n <type name=\"string\"/>\n </leaf>\n" |
| " <leaf name=\"l2\">\n <type name=\"string\"/>\n </leaf>\n" |
| " <typedef name=\"mytype1\">\n <type name=\"string\"/>\n </typedef>\n" |
| " <typedef name=\"mytype2\">\n <type name=\"string\"/>\n </typedef>\n" |
| " <type name=\"string\"/>\n" |
| " <type name=\"uint8\"/>\n" |
| " <if-feature name=\"f1\"/>\n" |
| " <if-feature name=\"f2\"/>\n" |
| " <length value=\"10\"/>\n" |
| " <length value=\"20\"/>\n" |
| " <must condition=\"1\"/>\n" |
| " <must condition=\"2\"/>\n" |
| " <pattern value=\"[a-z]*\"/>\n" |
| " <pattern value=\"[A-Z]*\"/>\n" |
| " <range value=\"0..10\"/>\n" |
| " <range value=\"100..110\"/>\n" |
| " <when condition=\"1\"/>\n" |
| " <when condition=\"2\"/>\n" |
| " <revision date=\"2016-02-16\"/>\n" |
| " <revision date=\"2016-02-17\"/>\n" |
| " </e:complex-arrays>\n" |
| " <feature name=\"f1\"/>\n" |
| " <feature name=\"f2\"/>\n" |
| "</module>\n"; |
| |
| mod = lys_parse_mem(st->ctx, yin, LYS_IN_YIN); |
| assert_ptr_not_equal(mod, NULL); |
| |
| lys_print_mem(&st->str1, mod, LYS_OUT_YIN, NULL); |
| assert_ptr_not_equal(st->str1, NULL); |
| assert_string_equal(st->str1, yin); |
| } |
| |
| int |
| main(void) |
| { |
| const struct CMUnitTest cmut[] = { |
| cmocka_unit_test_setup_teardown(test_module_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_container_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_leaf_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_leaflist_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_list_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_anydata_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_choice_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_uses_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_extension_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_rpc_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_notif_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_deviation_sub_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_complex_yin, setup_ctx_yin, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_complex_arrays_yin, setup_ctx_yin, teardown_ctx), |
| |
| cmocka_unit_test_setup_teardown(test_module_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_container_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_leaf_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_leaflist_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_list_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_anydata_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_choice_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_uses_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_extension_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_rpc_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_notif_sub_yang, setup_ctx_yang, teardown_ctx), |
| cmocka_unit_test_setup_teardown(test_deviation_sub_yang, setup_ctx_yang, teardown_ctx), |
| }; |
| |
| return cmocka_run_group_tests(cmut, NULL, NULL); |
| } |