| /* |
| * @file test_printer_yin.c |
| * @author: Fred Gan <ganshaolong@vip.qq.com> |
| * @brief unit tests for functions from printer_yin.c |
| * |
| * Copyright (c) 2019-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 "common.h" |
| #include "context.h" |
| #include "out.h" |
| #include "printer_schema.h" |
| #include "tree_schema.h" |
| |
| static void |
| test_module(void **state) |
| { |
| const struct lys_module *mod; |
| |
| const char *orig = |
| "module all {\n" |
| " yang-version 1.1;\n" |
| " namespace \"urn:all\";\n" |
| " prefix all_mod;\n\n" |
| " import ietf-yang-types {\n" |
| " prefix yt;\n" |
| " revision-date 2013-07-15;\n" |
| " description\n" |
| " \"YANG types\";\n" |
| " reference\n" |
| " \"RFC reference\";\n" |
| " }\n\n" |
| " feature feat1 {\n" |
| " if-feature \"feat2\";\n" |
| " status obsolete;\n" |
| " }\n\n" |
| " feature feat2;\n" |
| " feature feat3;\n\n" |
| " identity ident2 {\n" |
| " base ident1;\n" |
| " }\n\n" |
| " identity ident1;\n\n" |
| " typedef tdef1 {\n" |
| " type tdef2 {\n" |
| " length \"3..9 | 30..40\";\n" |
| " pattern \"[ac]*\";\n" |
| " }\n" |
| " units \"none\";\n" |
| " default \"aaa\";\n" |
| " }\n\n" |
| " typedef tdef2 {\n" |
| " type string {\n" |
| " length \"2..10 | 20..50\";\n" |
| " pattern \"[ab]*\";\n" |
| " }\n" |
| " }\n\n" |
| " grouping group1 {\n" |
| " leaf leaf1 {\n" |
| " type int8;\n" |
| " }\n" |
| " }\n\n" |
| " container cont1 {\n" |
| " leaf leaf2 {\n" |
| " if-feature \"feat1\";\n" |
| " type int16;\n" |
| " status obsolete;\n" |
| " }\n\n" |
| " uses group1 {\n" |
| " if-feature \"feat2\";\n" |
| " refine \"leaf1\" {\n" |
| " if-feature \"feat3\";\n" |
| " must \"24 - 4 = number('20')\";\n" |
| " default \"25\";\n" |
| " config true;\n" |
| " mandatory false;\n" |
| " description\n" |
| " \"dsc\";\n" |
| " reference\n" |
| " \"none\";\n" |
| " }\n" |
| " }\n\n" |
| " leaf leaf3 {\n" |
| " type int32;\n" |
| " }\n\n" |
| " leaf leaf4 {\n" |
| " type int64 {\n" |
| " range \"1000 .. 50000\" {\n" |
| " error-message\n" |
| " \"Special error message.\";\n" |
| " error-app-tag \"special-tag\";\n" |
| " }\n" |
| " }\n" |
| " }\n\n" |
| " leaf leaf5 {\n" |
| " type uint8;\n" |
| " }\n\n" |
| " leaf leaf6 {\n" |
| " type uint16;\n" |
| " }\n\n" |
| " leaf leaf7 {\n" |
| " type uint32;\n" |
| " }\n\n" |
| " leaf leaf8 {\n" |
| " type uint64;\n" |
| " }\n\n" |
| " choice choic1 {\n" |
| " default \"leaf9b\";\n" |
| " leaf leaf9a {\n" |
| " type decimal64 {\n" |
| " fraction-digits 9;\n" |
| " }\n" |
| " }\n\n" |
| " leaf leaf9b {\n" |
| " type boolean;\n" |
| " default \"false\";\n" |
| " }\n" |
| " }\n\n" |
| " leaf leaf10 {\n" |
| " type boolean;\n" |
| " }\n\n" |
| " leaf leaf11 {\n" |
| " type enumeration {\n" |
| " enum \"one\";\n" |
| " enum \"two\";\n" |
| " enum \"five\" {\n" |
| " value 5;\n" |
| " }\n" |
| " }\n" |
| " }\n\n" |
| " leaf leaf12 {\n" |
| " type bits {\n" |
| " bit flag0 {\n" |
| " position 0;\n" |
| " }\n" |
| " bit flag1;\n" |
| " bit flag2 {\n" |
| " position 2;\n" |
| " }\n" |
| " bit flag3 {\n" |
| " position 3;\n" |
| " }\n" |
| " }\n" |
| " default \"flag0 flag3\";\n" |
| " }\n\n" |
| " leaf leaf13 {\n" |
| " type binary;\n" |
| " }\n\n" |
| " leaf leaf14 {\n" |
| " type leafref {\n" |
| " path \"/cont1/leaf17\";\n" |
| " }\n" |
| " }\n\n" |
| " leaf leaf15 {\n" |
| " type empty;\n" |
| " }\n\n" |
| " leaf leaf16 {\n" |
| " type union {\n" |
| " type instance-identifier {\n" |
| " require-instance true;\n" |
| " }\n" |
| " type int8;\n" |
| " }\n" |
| " }\n\n" |
| " list list1 {\n" |
| " key \"leaf18\";\n" |
| " unique \"leaf19\";\n" |
| " min-elements 1;\n" |
| " max-elements 20;\n" |
| " leaf leaf18 {\n" |
| " type string;\n" |
| " }\n\n" |
| " leaf leaf19 {\n" |
| " type uint32;\n" |
| " }\n\n" |
| " anyxml axml1;\n" |
| " anydata adata1;\n\n" |
| " action act1 {\n" |
| " input {\n" |
| " leaf leaf24 {\n" |
| " type string;\n" |
| " }\n" |
| " }\n\n" |
| " output {\n" |
| " leaf leaf25 {\n" |
| " type string;\n" |
| " }\n" |
| " }\n" |
| " }\n\n" |
| " notification notif1 {\n" |
| " leaf leaf26 {\n" |
| " type string;\n" |
| " }\n" |
| " }\n" |
| " }\n\n" |
| " leaf-list llist1 {\n" |
| " type tdef1;\n" |
| " ordered-by user;\n" |
| " }\n\n" |
| " list list2 {\n" |
| " key \"leaf27 leaf28\";\n" |
| " leaf leaf27 {\n" |
| " type uint8;\n" |
| " }\n\n" |
| " leaf leaf28 {\n" |
| " type uint8;\n" |
| " }\n" |
| " }\n\n" |
| " leaf leaf29 {\n" |
| " type instance-identifier;\n" |
| " }\n\n" |
| " container must-deviations-container {\n" |
| " presence \"Allows deviations on the leaf\";\n" |
| " leaf leaf30 {\n" |
| " type string;\n" |
| " }\n" |
| " }\n\n" |
| " leaf leaf23 {\n" |
| " type empty;\n" |
| " }\n" |
| " }\n\n" |
| " augment \"/cont1\" {\n" |
| " leaf leaf17 {\n" |
| " type string;\n" |
| " }\n" |
| " }\n\n" |
| " rpc rpc1 {\n" |
| " input {\n" |
| " leaf leaf20 {\n" |
| " type tdef1;\n" |
| " }\n" |
| " }\n\n" |
| " output {\n" |
| " container cont2 {\n" |
| " leaf leaf21 {\n" |
| " type empty;\n" |
| " }\n" |
| " }\n" |
| " }\n" |
| " }\n\n" |
| " container test-when {\n" |
| " leaf when-check {\n" |
| " type boolean;\n" |
| " }\n\n" |
| " leaf gated-data {\n" |
| " when \"../when-check = 'true'\";\n" |
| " type uint16;\n" |
| " }\n" |
| " }\n\n" |
| " extension c-define {\n" |
| " description\n" |
| " \"Takes as an argument a name string.\n" |
| " Makes the code generator use the given name\n" |
| " in the #define.\";\n" |
| " argument \"name\";\n" |
| " }\n" |
| "}\n"; |
| |
| const char *ori_res = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"all\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:all_mod=\"urn:all\"\n" |
| " xmlns:yt=\"urn:ietf:params:xml:ns:yang:ietf-yang-types\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:all\"/>\n" |
| " <prefix value=\"all_mod\"/>\n" |
| " <import module=\"ietf-yang-types\">\n" |
| " <prefix value=\"yt\"/>\n" |
| " <revision-date date=\"2013-07-15\"/>\n" |
| " <description>\n" |
| " <text>YANG types</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <text>RFC reference</text>\n" |
| " </reference>\n" |
| " </import>\n\n" |
| " <extension name=\"c-define\">\n" |
| " <argument name=\"name\"/>\n" |
| " <description>\n" |
| " <text>Takes as an argument a name string.\n" |
| "Makes the code generator use the given name\n" |
| "in the #define.</text>\n" |
| " </description>\n" |
| " </extension>\n" |
| " <feature name=\"feat1\">\n" |
| " <if-feature name=\"feat2\"/>\n" |
| " <status value=\"obsolete\"/>\n" |
| " </feature>\n" |
| " <feature name=\"feat2\"/>\n" |
| " <feature name=\"feat3\"/>\n" |
| " <identity name=\"ident2\">\n" |
| " <base name=\"ident1\"/>\n" |
| " </identity>\n" |
| " <identity name=\"ident1\"/>\n" |
| " <typedef name=\"tdef1\">\n" |
| " <type name=\"tdef2\">\n" |
| " <length value=\"3..9 | 30..40\"/>\n" |
| " <pattern value=\"[ac]*\"/>\n" |
| " </type>\n" |
| " <units name=\"none\"/>\n" |
| " <default value=\"aaa\"/>\n" |
| " </typedef>\n" |
| " <typedef name=\"tdef2\">\n" |
| " <type name=\"string\">\n" |
| " <length value=\"2..10 | 20..50\"/>\n" |
| " <pattern value=\"[ab]*\"/>\n" |
| " </type>\n" |
| " </typedef>\n" |
| " <grouping name=\"group1\">\n" |
| " <leaf name=\"leaf1\">\n" |
| " <type name=\"int8\"/>\n" |
| " </leaf>\n" |
| " </grouping>\n" |
| " <container name=\"cont1\">\n" |
| " <leaf name=\"leaf2\">\n" |
| " <if-feature name=\"feat1\"/>\n" |
| " <type name=\"int16\"/>\n" |
| " <status value=\"obsolete\"/>\n" |
| " </leaf>\n" |
| " <uses name=\"group1\">\n" |
| " <if-feature name=\"feat2\"/>\n" |
| " <refine target-node=\"leaf1\">\n" |
| " <if-feature name=\"feat3\"/>\n" |
| " <must condition=\"24 - 4 = number('20')\"/>\n" |
| " <default value=\"25\"/>\n" |
| " <config value=\"true\"/>\n" |
| " <mandatory value=\"false\"/>\n" |
| " <description>\n" |
| " <text>dsc</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <text>none</text>\n" |
| " </reference>\n" |
| " </refine>\n" |
| " </uses>\n" |
| " <leaf name=\"leaf3\">\n" |
| " <type name=\"int32\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf4\">\n" |
| " <type name=\"int64\">\n" |
| " <range value=\"1000 .. 50000\">\n" |
| " <error-message>\n" |
| " <value>Special error message.</value>\n" |
| " </error-message>\n" |
| " <error-app-tag value=\"special-tag\"/>\n" |
| " </range>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf5\">\n" |
| " <type name=\"uint8\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf6\">\n" |
| " <type name=\"uint16\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf7\">\n" |
| " <type name=\"uint32\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf8\">\n" |
| " <type name=\"uint64\"/>\n" |
| " </leaf>\n" |
| " <choice name=\"choic1\">\n" |
| " <default value=\"leaf9b\"/>\n" |
| " <leaf name=\"leaf9a\">\n" |
| " <type name=\"decimal64\">\n" |
| " <fraction-digits value=\"9\"/>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf9b\">\n" |
| " <type name=\"boolean\"/>\n" |
| " <default value=\"false\"/>\n" |
| " </leaf>\n" |
| " </choice>\n" |
| " <leaf name=\"leaf10\">\n" |
| " <type name=\"boolean\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf11\">\n" |
| " <type name=\"enumeration\">\n" |
| " <enum name=\"one\"/>\n" |
| " <enum name=\"two\"/>\n" |
| " <enum name=\"five\">\n" |
| " <value value=\"5\"/>\n" |
| " </enum>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf12\">\n" |
| " <type name=\"bits\">\n" |
| " <bit name=\"flag0\">\n" |
| " <position value=\"0\"/>\n" |
| " </bit>\n" |
| " <bit name=\"flag1\"/>\n" |
| " <bit name=\"flag2\">\n" |
| " <position value=\"2\"/>\n" |
| " </bit>\n" |
| " <bit name=\"flag3\">\n" |
| " <position value=\"3\"/>\n" |
| " </bit>\n" |
| " </type>\n" |
| " <default value=\"flag0 flag3\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf13\">\n" |
| " <type name=\"binary\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf14\">\n" |
| " <type name=\"leafref\">\n" |
| " <path value=\"/cont1/leaf17\"/>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf15\">\n" |
| " <type name=\"empty\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf16\">\n" |
| " <type name=\"union\">\n" |
| " <type name=\"instance-identifier\">\n" |
| " <require-instance value=\"true\"/>\n" |
| " </type>\n" |
| " <type name=\"int8\"/>\n" |
| " </type>\n" |
| " </leaf>\n" |
| " <list name=\"list1\">\n" |
| " <key value=\"leaf18\"/>\n" |
| " <unique tag=\"leaf19\"/>\n" |
| " <min-elements value=\"1\"/>\n" |
| " <max-elements value=\"20\"/>\n" |
| " <leaf name=\"leaf18\">\n" |
| " <type name=\"string\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf19\">\n" |
| " <type name=\"uint32\"/>\n" |
| " </leaf>\n" |
| " <anyxml name=\"axml1\"/>\n" |
| " <anydata name=\"adata1\"/>\n" |
| " <action name=\"act1\">\n" |
| " <input>\n" |
| " <leaf name=\"leaf24\">\n" |
| " <type name=\"string\"/>\n" |
| " </leaf>\n" |
| " </input>\n" |
| " <output>\n" |
| " <leaf name=\"leaf25\">\n" |
| " <type name=\"string\"/>\n" |
| " </leaf>\n" |
| " </output>\n" |
| " </action>\n" |
| " <notification name=\"notif1\">\n" |
| " <leaf name=\"leaf26\">\n" |
| " <type name=\"string\"/>\n" |
| " </leaf>\n" |
| " </notification>\n" |
| " </list>\n" |
| " <leaf-list name=\"llist1\">\n" |
| " <type name=\"tdef1\"/>\n" |
| " <ordered-by value=\"user\"/>\n" |
| " </leaf-list>\n" |
| " <list name=\"list2\">\n" |
| " <key value=\"leaf27 leaf28\"/>\n" |
| " <leaf name=\"leaf27\">\n" |
| " <type name=\"uint8\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"leaf28\">\n" |
| " <type name=\"uint8\"/>\n" |
| " </leaf>\n" |
| " </list>\n" |
| " <leaf name=\"leaf29\">\n" |
| " <type name=\"instance-identifier\"/>\n" |
| " </leaf>\n" |
| " <container name=\"must-deviations-container\">\n" |
| " <presence value=\"Allows deviations on the leaf\"/>\n" |
| " <leaf name=\"leaf30\">\n" |
| " <type name=\"string\"/>\n" |
| " </leaf>\n" |
| " </container>\n" |
| " <leaf name=\"leaf23\">\n" |
| " <type name=\"empty\"/>\n" |
| " </leaf>\n" |
| " </container>\n" |
| " <container name=\"test-when\">\n" |
| " <leaf name=\"when-check\">\n" |
| " <type name=\"boolean\"/>\n" |
| " </leaf>\n" |
| " <leaf name=\"gated-data\">\n" |
| " <when condition=\"../when-check = 'true'\"/>\n" |
| " <type name=\"uint16\"/>\n" |
| " </leaf>\n" |
| " </container>\n" |
| " <augment target-node=\"/cont1\">\n" |
| " <leaf name=\"leaf17\">\n" |
| " <type name=\"string\"/>\n" |
| " </leaf>\n" |
| " </augment>\n" |
| " <rpc name=\"rpc1\">\n" |
| " <input>\n" |
| " <leaf name=\"leaf20\">\n" |
| " <type name=\"tdef1\"/>\n" |
| " </leaf>\n" |
| " </input>\n" |
| " <output>\n" |
| " <container name=\"cont2\">\n" |
| " <leaf name=\"leaf21\">\n" |
| " <type name=\"empty\"/>\n" |
| " </leaf>\n" |
| " </container>\n" |
| " </output>\n" |
| " </rpc>\n" |
| "</module>\n"; |
| |
| char *printed; |
| struct ly_out *out; |
| |
| assert_int_equal(LY_SUCCESS, ly_out_new_memory(&printed, 0, &out)); |
| |
| UTEST_ADD_MODULE(orig, LYS_IN_YANG, NULL, &mod); |
| assert_int_equal(LY_SUCCESS, lys_print_module(out, mod, LYS_OUT_YIN, 0, 0)); |
| assert_int_equal(strlen(ori_res), ly_out_printed(out)); |
| assert_string_equal(printed, ori_res); |
| |
| ly_out_free(out, NULL, 1); |
| } |
| |
| static LY_ERR |
| test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name), |
| const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format, |
| const char **module_data, void (**free_module_data)(void *model_data, void *user_data)) |
| { |
| *module_data = user_data; |
| *format = LYS_IN_YIN; |
| *free_module_data = NULL; |
| return LY_SUCCESS; |
| } |
| |
| static void |
| test_submodule(void **state) |
| { |
| const struct lys_module *mod; |
| |
| const char *mod_yin = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<module name=\"a\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:a_mod=\"urn:a\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <namespace uri=\"urn:a\"/>\n" |
| " <prefix value=\"a_mod\"/>\n" |
| " <include module=\"a-sub\"/>\n" |
| "</module>\n"; |
| |
| char *submod_yin = |
| "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| "<submodule name=\"a-sub\"\n" |
| " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" |
| " xmlns:a_mod=\"urn:a\"\n" |
| " xmlns:yt=\"urn:ietf:params:xml:ns:yang:ietf-yang-types\">\n" |
| " <yang-version value=\"1.1\"/>\n" |
| " <belongs-to module=\"a\">\n" |
| " <prefix value=\"a_mod\"/>\n" |
| " </belongs-to>\n" |
| " <import module=\"ietf-yang-types\">\n" |
| " <prefix value=\"yt\"/>\n" |
| " <revision-date date=\"2013-07-15\"/>\n" |
| " </import>\n\n" |
| " <description>\n" |
| " <text>YANG types</text>\n" |
| " </description>\n" |
| " <reference>\n" |
| " <text>RFC reference</text>\n" |
| " </reference>\n" |
| "</submodule>\n"; |
| |
| char *printed; |
| struct ly_out *out; |
| |
| assert_int_equal(LY_SUCCESS, ly_out_new_memory(&printed, 0, &out)); |
| |
| ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod_yin); |
| |
| UTEST_ADD_MODULE(mod_yin, LYS_IN_YIN, NULL, &mod); |
| assert_int_equal(LY_SUCCESS, lys_print_submodule(out, mod->parsed->includes[0].submodule, LYS_OUT_YIN, 0, 0)); |
| assert_int_equal(strlen(submod_yin), ly_out_printed(out)); |
| assert_string_equal(printed, submod_yin); |
| |
| ly_out_free(out, NULL, 1); |
| } |
| |
| int |
| main(void) |
| { |
| const struct CMUnitTest tests[] = { |
| UTEST(test_module), |
| UTEST(test_submodule), |
| }; |
| |
| return cmocka_run_group_tests(tests, NULL, NULL); |
| } |