diff --git a/modules/ietf-yang-schema-comparison@2025-10-20.yang b/modules/ietf-yang-schema-comparison@2025-10-20.yang index 05f602bf2..8332b6016 100644 --- a/modules/ietf-yang-schema-comparison@2025-10-20.yang +++ b/modules/ietf-yang-schema-comparison@2025-10-20.yang @@ -304,6 +304,10 @@ module ietf-yang-schema-comparison { description "YANG statement 'when'."; } + enum "yang-version" { + description + "YANG statement 'yang-version'."; + } } description "Type of the statement that a change affects."; @@ -914,6 +918,11 @@ module ietf-yang-schema-comparison { grouping module-substmts { description "All non-data-definition substatements of a module."; + leaf yang-version { + type string; + description + "YANG version substatement value."; + } leaf prefix { if-feature parsed-schema; type string; diff --git a/src/schema_diff.c b/src/schema_diff.c index 94f13d7d6..24abff23b 100644 --- a/src/schema_diff.c +++ b/src/schema_diff.c @@ -89,7 +89,6 @@ schema_diff_stmt2changed(enum ly_stmt stmt) case LY_STMT_SYNTAX_LEFT_BRACE: case LY_STMT_SYNTAX_RIGHT_BRACE: case LY_STMT_SYNTAX_SEMICOLON: - case LY_STMT_YANG_VERSION: case LY_STMT_YIN_ELEMENT: /* invalid */ LOGINT(NULL); @@ -194,6 +193,8 @@ schema_diff_stmt2changed(enum ly_stmt stmt) return LYS_CHANGED_VALUE; case LY_STMT_WHEN: return LYS_CHANGED_WHEN; + case LY_STMT_YANG_VERSION: + return LYS_CHANGED_YANG_VERSION; } return LYS_CHANGED_NONE; @@ -219,6 +220,30 @@ schema_diff_find_module(const struct ly_ctx *ctx, const char *nodeid, LY_VALUE_F *name = nam; } +/** + * @brief Check changes of a 'yang-version'. + * + * @param[in] yvsn1 First yang-version. + * @param[in] yvsn2 Second yang-version. + * @param[in] parent_changed Parent statement of the change. + * @param[in] changed Changed statement. + * @param[in,out] changes Changes to add to. + * @return LY_ERR value. + */ +static LY_ERR +schema_diff_yangversion_change(uint8_t yvsn1, uint8_t yvsn2, + enum lys_diff_changed_e parent_changed, enum lys_diff_changed_e changed, + struct lys_diff_changes_s *changes) +{ + if (yvsn1 != yvsn2) { + /* modified */ + LY_CHECK_RET(schema_diff_add_change(LYS_CHANGE_MODIFIED, parent_changed, + changed, 1, changes)); + } + + return LY_SUCCESS; +} + LY_ERR schema_diff_text_bc(const char *text1, const char *text2, enum lys_diff_changed_e parent_changed, enum lys_diff_changed_e changed, struct lys_diff_changes_s *changes) @@ -587,6 +612,10 @@ schema_diff_module_identities_change(const struct lysc_ident *idents1, const str static LY_ERR schema_diff_module_change(const struct lys_module *mod1, const struct lys_module *mod2, struct lys_diff_s *diff) { + /* yang-version */ + LY_CHECK_RET(schema_diff_yangversion_change(mod1->version, mod2->version, + LYS_CHANGED_NONE, LYS_CHANGED_YANG_VERSION, &diff->module_changes)); + /* organization */ LY_CHECK_RET(schema_diff_text_bc(mod1->org, mod2->org, LYS_CHANGED_NONE, LYS_CHANGED_ORGANIZATION, &diff->module_changes)); diff --git a/src/schema_diff.h b/src/schema_diff.h index b4bca0e11..28602a5a4 100644 --- a/src/schema_diff.h +++ b/src/schema_diff.h @@ -92,7 +92,8 @@ enum lys_diff_changed_e { LYS_CHANGED_UNIQUE, LYS_CHANGED_UNITS, LYS_CHANGED_VALUE, - LYS_CHANGED_WHEN + LYS_CHANGED_WHEN, + LYS_CHANGED_YANG_VERSION }; /** diff --git a/src/schema_diff_tree.c b/src/schema_diff_tree.c index 82c1ca41c..991dc3a63 100644 --- a/src/schema_diff_tree.c +++ b/src/schema_diff_tree.c @@ -144,6 +144,8 @@ schema_diff_changed2str(enum lys_diff_changed_e ch) return "unique"; case LYS_CHANGED_WHEN: return "when"; + case LYS_CHANGED_YANG_VERSION: + return "yang-version"; } return NULL; @@ -1556,7 +1558,7 @@ schema_diff_imports(const struct lys_module *mod, const struct lysc_node *schema } /** - * @brief Create cmp YANG data from direct text substatement of 'module'. + * @brief Create cmp YANG data from direct 'module' substatement. * * @param[in] change Change to use. * @param[in] mod1 Old module. @@ -1566,7 +1568,7 @@ schema_diff_imports(const struct lys_module *mod, const struct lysc_node *schema * @return LY_ERR value. */ static LY_ERR -schema_diff_module_text(const struct lys_diff_change_s *change, const struct lys_module *mod1, +schema_diff_module_substmt(const struct lys_diff_change_s *change, const struct lys_module *mod1, const struct lys_module *mod2, ly_bool with_parsed, struct lyd_node *diff_list) { LY_ERR rc = LY_SUCCESS; @@ -1605,6 +1607,9 @@ schema_diff_module_text(const struct lys_diff_change_s *change, const struct lys text_old = mod1->ref; text_new = mod2->ref; break; + case LYS_CHANGED_YANG_VERSION: + node_name = "yang-version"; + break; default: LOGINT(mod1->ctx); rc = LY_EINT; @@ -1617,16 +1622,32 @@ schema_diff_module_text(const struct lys_diff_change_s *change, const struct lys /* change info */ LY_CHECK_GOTO(rc = schema_diff_change_info(change, mod_cmp_list), cleanup); - if (text_old) { - /* old */ - LY_CHECK_GOTO(rc = lyd_new_inner(mod_cmp_list, NULL, "old", 0, &cont), cleanup); - LY_CHECK_GOTO(rc = lyd_new_term(cont, NULL, node_name, text_old, 0, NULL), cleanup); - } + if (change->changed != LYS_CHANGED_YANG_VERSION) { + /* text substatement */ + if (text_old) { + /* old */ + LY_CHECK_GOTO(rc = lyd_new_inner(mod_cmp_list, NULL, "old", 0, &cont), cleanup); + LY_CHECK_GOTO(rc = lyd_new_term(cont, NULL, node_name, text_old, 0, NULL), cleanup); + } - if (text_new) { - /* new */ - LY_CHECK_GOTO(rc = lyd_new_inner(mod_cmp_list, NULL, "new", 0, &cont), cleanup); - LY_CHECK_GOTO(rc = lyd_new_term(cont, NULL, node_name, text_new, 0, NULL), cleanup); + if (text_new) { + /* new */ + LY_CHECK_GOTO(rc = lyd_new_inner(mod_cmp_list, NULL, "new", 0, &cont), cleanup); + LY_CHECK_GOTO(rc = lyd_new_term(cont, NULL, node_name, text_new, 0, NULL), cleanup); + } + } else { + /* yang-version substatement */ + if (mod1->version) { + LY_CHECK_GOTO(rc = lyd_new_inner(mod_cmp_list, NULL, "old", 0, &cont), cleanup); + LY_CHECK_GOTO(rc = lyd_new_term(cont, NULL, node_name, + mod1->version == LYS_VERSION_1_1 ? "1.1" : "1", 0, NULL), cleanup); + } + + if (mod2->version) { + LY_CHECK_GOTO(rc = lyd_new_inner(mod_cmp_list, NULL, "new", 0, &cont), cleanup); + LY_CHECK_GOTO(rc = lyd_new_term(cont, NULL, node_name, + mod2->version == LYS_VERSION_1_1 ? "1.1" : "1", 0, NULL), cleanup); + } } cleanup: @@ -3024,9 +3045,9 @@ schema_diff_module(const struct lys_diff_s *diff, const struct lys_module *mod1, LY_ERR rc = LY_SUCCESS; uint32_t i; - /* text substmts */ + /* yang-version and text substmts */ for (i = 0; i < diff->module_changes.count; ++i) { - LY_CHECK_GOTO(rc = schema_diff_module_text(&diff->module_changes.changes[i], mod1, mod2, diff->with_parsed, + LY_CHECK_GOTO(rc = schema_diff_module_substmt(&diff->module_changes.changes[i], mod1, mod2, diff->with_parsed, diff_list), cleanup); } diff --git a/tests/utests/schema_comparison/nbc/x yang-version/yang-version@2000-01-01.yang b/tests/utests/schema_comparison/nbc/x yang-version/yang-version@2000-01-01.yang new file mode 100644 index 000000000..d8a7f1ba6 --- /dev/null +++ b/tests/utests/schema_comparison/nbc/x yang-version/yang-version@2000-01-01.yang @@ -0,0 +1,7 @@ +module yang-version { + yang-version 1; + namespace "urn:test:yang-version"; + prefix yvsn; + + revision 2000-01-01; +} diff --git a/tests/utests/schema_comparison/nbc/x yang-version/yang-version@2000-01-02.yang b/tests/utests/schema_comparison/nbc/x yang-version/yang-version@2000-01-02.yang new file mode 100644 index 000000000..70b2a1416 --- /dev/null +++ b/tests/utests/schema_comparison/nbc/x yang-version/yang-version@2000-01-02.yang @@ -0,0 +1,7 @@ +module yang-version { + yang-version 1.1; + namespace "urn:test:yang-version"; + prefix yvsn; + + revision 2000-01-02; +} diff --git a/tests/utests/schema_comparison/nbc/x yang-version/yang-version_cmp.json b/tests/utests/schema_comparison/nbc/x yang-version/yang-version_cmp.json new file mode 100644 index 000000000..1fd8364d1 --- /dev/null +++ b/tests/utests/schema_comparison/nbc/x yang-version/yang-version_cmp.json @@ -0,0 +1,34 @@ +{ + "ietf-yang-schema-comparison:schema-comparison": { + "schema": [ + { + "source": { + "module": "yang-version", + "revision": "2000-01-01" + }, + "target": { + "module": "yang-version", + "revision": "2000-01-02" + }, + "conformance": "non-backwards-compatible", + "module-comparison": [ + { + "changed": [ + { + "stmt": "yang-version", + "change": "modified", + "conformance": "non-backwards-compatible" + } + ], + "old": { + "yang-version": "1" + }, + "new": { + "yang-version": "1.1" + } + } + ] + } + ] + } +} diff --git a/tests/utests/schema_comparison/test_schema_comparison.c b/tests/utests/schema_comparison/test_schema_comparison.c index 008fa5a0f..5c2ba2a22 100644 --- a/tests/utests/schema_comparison/test_schema_comparison.c +++ b/tests/utests/schema_comparison/test_schema_comparison.c @@ -225,6 +225,7 @@ test_non_backwards_compatible(void **state) schema_comparison(st, "ext-inst"); schema_comparison(st, "presence"); schema_comparison(st, "union"); + schema_comparison(st, "yang-version"); } int