union UPDATE get errors of all the types
Fixes #2071
diff --git a/src/plugins_types/union.c b/src/plugins_types/union.c
index a358e43..b03192e 100644
--- a/src/plugins_types/union.c
+++ b/src/plugins_types/union.c
@@ -172,6 +172,8 @@
const void *value = NULL;
size_t value_len = 0;
+ *err = NULL;
+
if (subvalue->format == LY_VALUE_LYB) {
lyb_parse_union(subvalue->original, subvalue->orig_len, NULL, &value, &value_len);
} else {
@@ -220,7 +222,10 @@
{
LY_ERR ret = LY_SUCCESS;
LY_ARRAY_COUNT_TYPE u;
+ struct ly_err_item **errs = NULL, *e;
uint32_t temp_lo = 0;
+ char *msg = NULL;
+ int msg_len = 0;
if (!types || !LY_ARRAY_COUNT(types)) {
return LY_EINVAL;
@@ -228,28 +233,52 @@
*err = NULL;
+ /* alloc errors */
+ errs = calloc(LY_ARRAY_COUNT(types), sizeof *errs);
+ LY_CHECK_RET(!errs, LY_EMEM);
+
/* turn logging temporarily off */
ly_temp_log_options(&temp_lo);
/* use the first usable subtype to store the value */
for (u = 0; u < LY_ARRAY_COUNT(types); ++u) {
- ret = union_store_type(ctx, types[u], subvalue, resolve, ctx_node, tree, unres, err);
+ ret = union_store_type(ctx, types[u], subvalue, resolve, ctx_node, tree, unres, &e);
if ((ret == LY_SUCCESS) || (ret == LY_EINCOMPLETE)) {
break;
}
- ly_err_free(*err);
- *err = NULL;
+ errs[u] = e;
}
if (u == LY_ARRAY_COUNT(types)) {
- ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "Invalid union value \"%.*s\" - no matching subtype found.",
+ /* create the full error */
+ msg_len = asprintf(&msg, "Invalid union value \"%.*s\" - no matching subtype found:\n",
(int)subvalue->orig_len, (char *)subvalue->original);
+ if (msg_len == -1) {
+ LY_CHECK_ERR_GOTO(!errs, ret = LY_EMEM, cleanup);
+ }
+ for (u = 0; u < LY_ARRAY_COUNT(types); ++u) {
+ if (!errs[u]) {
+ /* no error for some reason */
+ continue;
+ }
+
+ msg = ly_realloc(msg, msg_len + 4 + strlen(types[u]->plugin->id) + 2 + strlen(errs[u]->msg) + 2);
+ LY_CHECK_ERR_GOTO(!msg, ret = LY_EMEM, cleanup);
+ msg_len += sprintf(msg + msg_len, " %s: %s\n", types[u]->plugin->id, errs[u]->msg);
+ }
+
+ ret = ly_err_new(err, LY_EVALID, LYVE_DATA, NULL, NULL, "%s", msg);
} else if (type_idx) {
*type_idx = u;
}
- /* restore logging */
+cleanup:
+ for (u = 0; u < LY_ARRAY_COUNT(types); ++u) {
+ ly_err_free(errs[u]);
+ }
+ free(errs);
+ free(msg);
ly_temp_log_options(NULL);
return ret;
}
diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c
index c4c282c..2dbc511 100644
--- a/tests/utests/types/union.c
+++ b/tests/utests/types/union.c
@@ -104,7 +104,12 @@
/* invalid value */
TEST_ERROR_XML2("",
"defs", "", "un1", "123456789012345678901", LY_EVALID);
- CHECK_LOG_CTX("Invalid union value \"123456789012345678901\" - no matching subtype found.",
+ CHECK_LOG_CTX("Invalid union value \"123456789012345678901\" - no matching subtype found:\n"
+ " libyang 2 - leafref, version 1: Invalid type int8 value \"123456789012345678901\".\n"
+ " libyang 2 - leafref, version 1: Invalid type int64 value \"123456789012345678901\".\n"
+ " libyang 2 - identityref, version 1: Invalid identityref \"123456789012345678901\" value - identity not found in module \"defs\".\n"
+ " libyang 2 - instance-identifier, version 1: Invalid instance-identifier \"123456789012345678901\" value - syntax error.\n"
+ " libyang 2 - string, version 1: Unsatisfied length - string \"123456789012345678901\" length is not allowed.\n",
"Schema location \"/defs:un1\", line number 1.");
}