Skip to content

Commit ef60310

Browse files
stewegmichalvasko
authored andcommitted
plugin types BUGFIX correct handling of union type
This bugfix corrects the behavior or union type plugin when used with LYPLG_TYPE_STORE_ONLY flag
1 parent deae604 commit ef60310

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

src/plugins_types/union.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -486,9 +486,6 @@ lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, c
486486
ret = lyb_fill_subvalue(ctx, type_u, value, value_size_bits, prefix_data, subvalue, &options, unres, err);
487487
LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
488488
} else {
489-
/* to correctly resolve the union type, we need to always validate the value */
490-
options &= ~LYPLG_TYPE_STORE_ONLY;
491-
492489
/* store value to subvalue */
493490
ret = union_subvalue_assignment(value, value_size_bits, &subvalue->original, &subvalue->orig_size_bits, &options);
494491
LY_CHECK_GOTO(ret, cleanup);
@@ -498,9 +495,16 @@ lyplg_type_store_union(const struct ly_ctx *ctx, const struct lysc_type *type, c
498495
&subvalue->format, &subvalue->prefix_data);
499496
LY_CHECK_GOTO(ret, cleanup);
500497

501-
/* use the first usable subtype to store the value */
502-
ret = union_find_type(ctx, type_u, subvalue, options, 0, NULL, NULL, NULL, NULL, unres, err);
503-
LY_CHECK_GOTO((ret != LY_SUCCESS) && (ret != LY_EINCOMPLETE), cleanup);
498+
/* use the first usable and valid subtype to store the value */
499+
ret = union_find_type(ctx, type_u, subvalue, options & ~LYPLG_TYPE_STORE_ONLY, 0, NULL, NULL, NULL, NULL, unres,
500+
err);
501+
if (ret && (ret != LY_EINCOMPLETE) && (options & LYPLG_TYPE_STORE_ONLY)) {
502+
/* we tried to find the actual type by validating the value but no type matched, so try to find any type */
503+
ly_err_free(*err);
504+
*err = NULL;
505+
ret = union_find_type(ctx, type_u, subvalue, options, 0, NULL, NULL, NULL, NULL, unres, err);
506+
}
507+
LY_CHECK_GOTO(ret && (ret != LY_EINCOMPLETE), cleanup);
504508
}
505509

506510
/* store canonical value, if any (use the specific type value) */

tests/utests/types/union.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,61 @@ test_validation(void **state)
301301
lyd_free_all(tree);
302302
}
303303

304+
static void
305+
test_validation_store_only(void **state)
306+
{
307+
const char *val_text = NULL;
308+
struct ly_err_item *err = NULL;
309+
struct lys_module *mod;
310+
struct lyd_value value = {0};
311+
struct lyplg_type *type = lysc_get_type_plugin(lyplg_type_plugin_find(NULL, "", NULL, ly_data_type2str[LY_TYPE_UNION]));
312+
struct lysc_type *lysc_type;
313+
const char *schema;
314+
315+
schema = MODULE_CREATE_YANG("base",
316+
"leaf l1 {\n"
317+
" type union {\n"
318+
" type string {\n"
319+
" pattern \"[A-Z]\";\n"
320+
" }\n"
321+
" type int8 {\n"
322+
" range 1..5;\n"
323+
" }\n"
324+
" }\n"
325+
"}\n");
326+
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
327+
lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
328+
329+
/* check proper type */
330+
assert_string_equal("ly2 union", type->id);
331+
332+
/* with LYPLG_TYPE_STORE_ONLY and correct validation */
333+
err = NULL;
334+
val_text = "1";
335+
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text) * 8,
336+
LYPLG_TYPE_STORE_ONLY, LY_VALUE_CANON, NULL, LYD_VALHINT_STRING | LYD_VALHINT_DECNUM, NULL, NULL, &value, NULL, &err));
337+
assert_int_equal(value.subvalue->value.realtype->basetype, LY_TYPE_INT8);
338+
type->free(UTEST_LYCTX, &value);
339+
ly_err_free(err);
340+
341+
/* with LYPLG_TYPE_STORE_ONLY and incorrect validation */
342+
err = NULL;
343+
val_text = "6";
344+
assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text) * 8,
345+
LYPLG_TYPE_STORE_ONLY, LY_VALUE_CANON, NULL, LYD_VALHINT_STRING | LYD_VALHINT_DECNUM, NULL, NULL, &value, NULL, &err));
346+
assert_int_equal(value.subvalue->value.realtype->basetype, LY_TYPE_STRING);
347+
type->free(UTEST_LYCTX, &value);
348+
ly_err_free(err);
349+
350+
/* without LYPLG_TYPE_STORE_ONLY and incorrect validation */
351+
err = NULL;
352+
val_text = "10";
353+
assert_int_equal(LY_EVALID, type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text) * 8,
354+
0, LY_VALUE_CANON, NULL, LYD_VALHINT_STRING | LYD_VALHINT_DECNUM, NULL, NULL, &value, NULL, &err));
355+
ly_err_free(err);
356+
UTEST_LOG_CTX_CLEAN;
357+
}
358+
304359
int
305360
main(void)
306361
{
@@ -310,6 +365,7 @@ main(void)
310365
UTEST(test_plugin_lyb),
311366
UTEST(test_plugin_sort),
312367
UTEST(test_validation),
368+
UTEST(test_validation_store_only),
313369
};
314370

315371
return cmocka_run_group_tests(tests, NULL, NULL);

0 commit comments

Comments
 (0)