diff BUGFIX created userord nodes

Userord item for the existing instances must
always be created.
Fixes sysrepo/sysrepo#2733
diff --git a/src/diff.c b/src/diff.c
index 5ab35cb..a283e2a 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -278,7 +278,7 @@
  * @param[in] first Node from the first tree, can be NULL (on create).
  * @param[in] second Node from the second tree, can be NULL (on delete).
  * @param[in] options Diff options.
- * @param[in,out] userord Sized array of userord items for keeping the current node order.
+ * @param[in] userord_item Userord item of @p first and/or @p second node.
  * @param[out] op Operation.
  * @param[out] orig_default Original default metadata.
  * @param[out] value Value metadata.
@@ -293,13 +293,12 @@
  */
 static LY_ERR
 lyd_diff_userord_attrs(const struct lyd_node *first, const struct lyd_node *second, uint16_t options,
-        struct lyd_diff_userord **userord, enum lyd_diff_op *op, const char **orig_default, char **value,
+        struct lyd_diff_userord *userord_item, enum lyd_diff_op *op, const char **orig_default, char **value,
         char **orig_value, char **key, char **orig_key, char **position, char **orig_position)
 {
     const struct lysc_node *schema;
     size_t buflen, bufused;
     uint32_t first_pos, second_pos;
-    struct lyd_diff_userord *userord_item;
 
     assert(first || second);
 
@@ -314,10 +313,6 @@
     schema = first ? first->schema : second->schema;
     assert(lysc_is_userordered(schema));
 
-    /* get userord entry */
-    userord_item = lyd_diff_userord_get(first, schema, userord);
-    LY_CHECK_RET(!userord_item, LY_EMEM);
-
     /* find user-ordered first position */
     if (first) {
         for (first_pos = 0; first_pos < LY_ARRAY_COUNT(userord_item->inst); ++first_pos) {
@@ -647,7 +642,7 @@
     LY_ERR ret = LY_SUCCESS;
     const struct lyd_node *iter_first, *iter_second;
     struct lyd_node *match_second, *match_first;
-    struct lyd_diff_userord *userord = NULL;
+    struct lyd_diff_userord *userord = NULL, *userord_item;
     struct lyd_dup_inst *dup_inst_first = NULL, *dup_inst_second = NULL;
     LY_ARRAY_COUNT_TYPE u;
     enum lyd_diff_op op;
@@ -671,15 +666,20 @@
                 &match_second), cleanup);
 
         if (lysc_is_userordered(iter_first->schema)) {
+            /* get (create) userord entry */
+            userord_item = lyd_diff_userord_get(iter_first, iter_first->schema, &userord);
+            LY_CHECK_ERR_GOTO(!userord_item, LOGMEM(LYD_CTX(iter_first)); ret = LY_EMEM, cleanup);
+
             /* we are handling only user-ordered node delete now */
             if (!match_second) {
                 /* get all the attributes */
-                LY_CHECK_GOTO(ret = lyd_diff_userord_attrs(iter_first, match_second, options, &userord, &op, &orig_default,
-                        &value, &orig_value, &key, &orig_key, &position, &orig_position), cleanup);
+                LY_CHECK_GOTO(ret = lyd_diff_userord_attrs(iter_first, match_second, options, userord_item, &op,
+                        &orig_default, &value, &orig_value, &key, &orig_key, &position, &orig_position), cleanup);
 
                 /* there must be changes, it is deleted */
                 assert(op == LYD_DIFF_OP_DELETE);
-                ret = lyd_diff_add(iter_first, op, orig_default, orig_value, key, value, position, orig_key, orig_position, diff);
+                ret = lyd_diff_add(iter_first, op, orig_default, orig_value, key, value, position, orig_key,
+                        orig_position, diff);
 
                 free(orig_value);
                 free(key);
@@ -744,8 +744,12 @@
                 &match_first), cleanup);
 
         if (lysc_is_userordered(iter_second->schema)) {
+            /* get userord entry */
+            userord_item = lyd_diff_userord_get(NULL, iter_second->schema, &userord);
+            LY_CHECK_ERR_GOTO(!userord_item, LOGMEM(LYD_CTX(iter_second)); ret = LY_EMEM, cleanup);
+
             /* get all the attributes */
-            ret = lyd_diff_userord_attrs(match_first, iter_second, options, &userord, &op, &orig_default,
+            ret = lyd_diff_userord_attrs(match_first, iter_second, options, userord_item, &op, &orig_default,
                     &value, &orig_value, &key, &orig_key, &position, &orig_position);
 
             /* add into diff if there are any changes */
diff --git a/tests/utests/data/test_diff.c b/tests/utests/data/test_diff.c
index 50954d7..b0d5104 100644
--- a/tests/utests/data/test_diff.c
+++ b/tests/utests/data/test_diff.c
@@ -18,47 +18,46 @@
 #include "libyang.h"
 
 #define CHECK_PARSE_LYD(INPUT, MODEL) \
-                CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, MODEL)
+        CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, MODEL)
 
 #define CHECK_LYD_STRING(IN_MODEL, TEXT) \
-                CHECK_LYD_STRING_PARAM(IN_MODEL, TEXT, LYD_XML, LYD_PRINT_WITHSIBLINGS)
+        CHECK_LYD_STRING_PARAM(IN_MODEL, TEXT, LYD_XML, LYD_PRINT_WITHSIBLINGS)
 
 #define CHECK_PARSE_LYD_DIFF(INPUT_1, INPUT_2, OUT_MODEL) \
-                assert_int_equal(LY_SUCCESS, lyd_diff_siblings(INPUT_1, INPUT_2, 0, &OUT_MODEL));\
-                assert_non_null(OUT_MODEL)
+        assert_int_equal(LY_SUCCESS, lyd_diff_siblings(INPUT_1, INPUT_2, 0, &OUT_MODEL));\
+        assert_non_null(OUT_MODEL)
 
-#define TEST_DIFF_3(XML_1, XML_2, XML_3, DIFF_1, DIFF_2, MERGE) \
-                { \
-    /*decladation*/\
-                    struct lyd_node *model_1;\
-                    struct lyd_node *model_2;\
-                    struct lyd_node *model_3;\
+#define TEST_DIFF_3(XML1, XML2, XML3, DIFF1, DIFF2, MERGE) \
+        { \
+            struct lyd_node *data1;\
+            struct lyd_node *data2;\
+            struct lyd_node *data3;\
     /*create*/\
-                    CHECK_PARSE_LYD(XML_1, model_1);\
-                    CHECK_PARSE_LYD(XML_2, model_2);\
-                    CHECK_PARSE_LYD(XML_3, model_3);\
+            CHECK_PARSE_LYD(XML1, data1);\
+            CHECK_PARSE_LYD(XML2, data2);\
+            CHECK_PARSE_LYD(XML3, data3);\
     /* diff1 */ \
-                    struct lyd_node *diff1;\
-                    CHECK_PARSE_LYD_DIFF(model_1, model_2, diff1); \
-                    CHECK_LYD_STRING(diff1, DIFF_1); \
-                    assert_int_equal(lyd_diff_apply_all(&model_1, diff1), LY_SUCCESS); \
-                    CHECK_LYD(model_1, model_2); \
+            struct lyd_node *diff1;\
+            CHECK_PARSE_LYD_DIFF(data1, data2, diff1); \
+            CHECK_LYD_STRING(diff1, DIFF1); \
+            assert_int_equal(lyd_diff_apply_all(&data1, diff1), LY_SUCCESS); \
+            CHECK_LYD(data1, data2); \
     /* diff2 */ \
-                    struct lyd_node *diff2;\
-                    CHECK_PARSE_LYD_DIFF(model_2, model_3, diff2); \
-                    CHECK_LYD_STRING(diff2, DIFF_2); \
-                    assert_int_equal(lyd_diff_apply_all(&model_2, diff2), LY_SUCCESS);\
-                    CHECK_LYD(model_2, model_3);\
+            struct lyd_node *diff2;\
+            CHECK_PARSE_LYD_DIFF(data2, data3, diff2); \
+            CHECK_LYD_STRING(diff2, DIFF2); \
+            assert_int_equal(lyd_diff_apply_all(&data2, diff2), LY_SUCCESS);\
+            CHECK_LYD(data2, data3);\
     /* merge */ \
-                    assert_int_equal(lyd_diff_merge_all(&diff1, diff2, 0), LY_SUCCESS);\
-                    CHECK_LYD_STRING(diff1, MERGE); \
-    /* CREAR ENV */ \
-                    lyd_free_all(model_1);\
-                    lyd_free_all(model_2);\
-                    lyd_free_all(model_3);\
-                    lyd_free_all(diff1);\
-                    lyd_free_all(diff2);\
-                }
+            assert_int_equal(lyd_diff_merge_all(&diff1, diff2, 0), LY_SUCCESS);\
+            CHECK_LYD_STRING(diff1, MERGE); \
+    /* cleanup */ \
+            lyd_free_all(data1);\
+            lyd_free_all(data2);\
+            lyd_free_all(data3);\
+            lyd_free_all(diff1);\
+            lyd_free_all(diff2);\
+        }
 
 const char *schema1 =
         "module defaults {\n"
@@ -862,6 +861,85 @@
 }
 
 static void
+test_userord_list2(void **state)
+{
+    (void) state;
+    const char *xml1 =
+            "<df xmlns=\"urn:libyang:tests:defaults\">\n"
+            "  <ul>\n"
+            "    <l1>d</l1>\n"
+            "    <l2>4</l2>\n"
+            "  </ul>\n"
+            "</df>\n";
+    const char *xml2 =
+            "<df xmlns=\"urn:libyang:tests:defaults\">\n"
+            "  <ul>\n"
+            "    <l1>c</l1>\n"
+            "    <l2>3</l2>\n"
+            "  </ul>\n"
+            "  <ul>\n"
+            "    <l1>d</l1>\n"
+            "    <l2>4</l2>\n"
+            "  </ul>\n"
+            "</df>\n";
+    const char *xml3 =
+            "<df xmlns=\"urn:libyang:tests:defaults\">\n"
+            "  <ul>\n"
+            "    <l1>a</l1>\n"
+            "    <l2>1</l2>\n"
+            "  </ul>\n"
+            "  <ul>\n"
+            "    <l1>b</l1>\n"
+            "    <l2>2</l2>\n"
+            "  </ul>\n"
+            "  <ul>\n"
+            "    <l1>c</l1>\n"
+            "    <l2>3</l2>\n"
+            "  </ul>\n"
+            "  <ul>\n"
+            "    <l1>d</l1>\n"
+            "    <l2>4</l2>\n"
+            "  </ul>\n"
+            "</df>\n";
+
+    const char *out_diff_1 =
+            "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+            "  <ul yang:operation=\"create\" yang:key=\"\">\n"
+            "    <l1>c</l1>\n"
+            "    <l2>3</l2>\n"
+            "  </ul>\n"
+            "</df>\n";
+    const char *out_diff_2 =
+            "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+            "  <ul yang:operation=\"create\" yang:key=\"\">\n"
+            "    <l1>a</l1>\n"
+            "    <l2>1</l2>\n"
+            "  </ul>\n"
+            "  <ul yang:operation=\"create\" yang:key=\"[l1='a']\">\n"
+            "    <l1>b</l1>\n"
+            "    <l2>2</l2>\n"
+            "  </ul>\n"
+            "</df>\n";
+    const char *out_merge =
+            "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+            "  <ul yang:operation=\"create\" yang:key=\"\">\n"
+            "    <l1>c</l1>\n"
+            "    <l2>3</l2>\n"
+            "  </ul>\n"
+            "  <ul yang:key=\"\" yang:operation=\"create\">\n"
+            "    <l1>a</l1>\n"
+            "    <l2>1</l2>\n"
+            "  </ul>\n"
+            "  <ul yang:key=\"[l1='a']\" yang:operation=\"create\">\n"
+            "    <l1>b</l1>\n"
+            "    <l2>2</l2>\n"
+            "  </ul>\n"
+            "</df>\n";
+
+    TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
+}
+
+static void
 test_keyless_list(void **state)
 {
     (void) state;
@@ -1133,6 +1211,7 @@
         UTEST(test_userord_llist2, setup),
         UTEST(test_userord_mix, setup),
         UTEST(test_userord_list, setup),
+        UTEST(test_userord_list2, setup),
         UTEST(test_keyless_list, setup),
         UTEST(test_state_llist, setup),
         UTEST(test_wd, setup),