union BUGFIX validating LYB values

The value needs tobe interpreted based on
the stored type in the value.
Reverts 9372871ed84c46d0f7e1811a3062f0e878bd3c0d
Fixes #1981
diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c
index 509be6c..a358e43 100644
--- a/src/plugins_types/union.c
+++ b/src/plugins_types/union.c
@@ -365,6 +365,7 @@
     LY_ERR ret = LY_SUCCESS;
     struct lysc_type_union *type_u = (struct lysc_type_union *)type;
     struct lyd_value_union *subvalue = storage->subvalue;
+    uint32_t type_idx;
 
     *err = NULL;
 
@@ -373,9 +374,16 @@
      * we have to perform union value storing again from scratch */
     subvalue->value.realtype->plugin->free(ctx, &subvalue->value);
 
-    /* use the first usable subtype to store the value */
-    ret = union_find_type(ctx, type_u->types, subvalue, 1, ctx_node, tree, NULL, NULL, err);
-    LY_CHECK_RET(ret);
+    if (subvalue->format == LY_VALUE_LYB) {
+        /* use the specific type to store the value */
+        lyb_parse_union(subvalue->original, 0, &type_idx, NULL, NULL);
+        ret = union_store_type(ctx, type_u->types[type_idx], subvalue, 1, ctx_node, tree, NULL, err);
+        LY_CHECK_RET(ret);
+    } else {
+        /* use the first usable subtype to store the value */
+        ret = union_find_type(ctx, type_u->types, subvalue, 1, ctx_node, tree, NULL, NULL, err);
+        LY_CHECK_RET(ret);
+    }
 
     /* success, update the canonical value, if any generated */
     lydict_remove(ctx, storage->_canonical);
diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c
index 9a0705a..3522795 100644
--- a/tests/utests/types/union.c
+++ b/tests/utests/types/union.c
@@ -124,12 +124,59 @@
     TEST_SUCCESS_LYB("lyb", "un1", "");
 }
 
+static void
+test_validation(void **state)
+{
+    const char *schema, *data;
+    struct lyd_node *tree;
+    char *out;
+
+    schema = MODULE_CREATE_YANG("val",
+            "leaf l1 {\n"
+            "  type union {\n"
+            "   type uint32 {\n"
+            "      range \"0..1048575\";\n"
+            "    }\n"
+            "    type enumeration {\n"
+            "      enum auto;\n"
+            "    }\n"
+            "  }\n"
+            "}\n"
+            "leaf int8 {type int8 {range 10..20;}}\n"
+            "leaf l2 {\n"
+            "  type union {\n"
+            "    type leafref {path /int8; require-instance true;}\n"
+            "    type string;\n"
+            "  }\n"
+            "}\n");
+    UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
+
+    /* parse from LYB */
+    data = "<l1 xmlns=\"urn:tests:val\">auto</l1><int8 xmlns=\"urn:tests:val\">15</int8><l2 xmlns=\"urn:tests:val\">15</l2>";
+    CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+    assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS));
+    lyd_free_all(tree);
+    CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+    free(out);
+
+    /* validate */
+    assert_int_equal(LY_SUCCESS, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT, NULL));
+
+    /* print and compare */
+    assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS));
+    assert_string_equal(out, data);
+
+    free(out);
+    lyd_free_all(tree);
+}
+
 int
 main(void)
 {
     const struct CMUnitTest tests[] = {
         UTEST(test_data_xml),
         UTEST(test_plugin_lyb),
+        UTEST(test_validation),
     };
 
     return cmocka_run_group_tests(tests, NULL, NULL);