From: Alan T. DeKok Date: Sat, 20 Nov 2021 14:46:00 +0000 (-0500) Subject: add tests for assignment operations X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=365e373e5ad9e65189c0d4b8e629d3530584ffa2;p=thirdparty%2Ffreeradius-server.git add tests for assignment operations --- diff --git a/src/bin/unit_test_attribute.c b/src/bin/unit_test_attribute.c index a7cf1b80db4..ad289edd0d1 100644 --- a/src/bin/unit_test_attribute.c +++ b/src/bin/unit_test_attribute.c @@ -1188,10 +1188,10 @@ static size_t command_calc(command_result_t *result, command_file_ctx_t *cc, fr_token_t op; char const *p, *value, *end; size_t slen; + bool assignment; a = talloc_zero(cc->tmp_ctx, fr_value_box_t); b = talloc_zero(cc->tmp_ctx, fr_value_box_t); - out = talloc_zero(cc->tmp_ctx, fr_value_box_t); p = in; end = in + inlen; @@ -1205,6 +1205,8 @@ static size_t command_calc(command_result_t *result, command_file_ctx_t *cc, op = fr_table_value_by_longest_prefix(&match_len, fr_tokens_table, p, end - p, T_INVALID); if (op != T_INVALID) { p += match_len; + assignment = fr_assignment_op[op]; + } else { op = token2op[(uint8_t) p[0]]; if (op == T_INVALID) { @@ -1212,6 +1214,8 @@ static size_t command_calc(command_result_t *result, command_file_ctx_t *cc, RETURN_PARSE_ERROR(0); } p++; + + assignment = false; } fr_skip_whitespace(p); @@ -1221,24 +1225,34 @@ static size_t command_calc(command_result_t *result, command_file_ctx_t *cc, p += match_len; fr_skip_whitespace(p); - /* - * If there's no output data type, then the code tries to - * figure one out automatically. - */ - if (!*p) { - type = FR_TYPE_NULL; + if (assignment) { + if (fr_value_calc_assignment_op(cc->tmp_ctx, a, op, b) < 0) { + RETURN_OK_WITH_ERROR(); + } + out = a; + } else { - if (strncmp(p, "->", 2) != 0) RETURN_PARSE_ERROR(0); - p += 2; - fr_skip_whitespace(p); + out = talloc_zero(cc->tmp_ctx, fr_value_box_t); - type = fr_table_value_by_longest_prefix(&match_len, fr_value_box_type_table, p, end - p, FR_TYPE_MAX); - if (type == FR_TYPE_MAX) RETURN_PARSE_ERROR(0); - fr_value_box_init(out, type, NULL, false); - } + /* + * If there's no output data type, then the code tries to + * figure one out automatically. + */ + if (!*p) { + type = FR_TYPE_NULL; + } else { + if (strncmp(p, "->", 2) != 0) RETURN_PARSE_ERROR(0); + p += 2; + fr_skip_whitespace(p); - if (fr_value_calc_binary_op(cc->tmp_ctx, out, type, a, op, b) < 0) { - RETURN_OK_WITH_ERROR(); + type = fr_table_value_by_longest_prefix(&match_len, fr_value_box_type_table, p, end - p, FR_TYPE_MAX); + if (type == FR_TYPE_MAX) RETURN_PARSE_ERROR(0); + fr_value_box_init(out, type, NULL, false); + } + + if (fr_value_calc_binary_op(cc->tmp_ctx, out, type, a, op, b) < 0) { + RETURN_OK_WITH_ERROR(); + } } slen = fr_value_box_print(&FR_SBUFF_OUT(data, COMMAND_OUTPUT_MAX), out, NULL); diff --git a/src/lib/util/calc.c b/src/lib/util/calc.c index 4188b7f36bb..7eefef766ee 100644 --- a/src/lib/util/calc.c +++ b/src/lib/util/calc.c @@ -1118,7 +1118,11 @@ int fr_value_calc_assignment_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t { int rcode = -1; - if (!fr_type_is_leaf(dst->type)) return -1; + if (!fr_type_is_leaf(dst->type)) { + fr_strerror_printf("Cannot perform any operations for destination type %s", + fr_table_str_by_value(fr_value_box_type_table, dst->type, "")); + return -1; + } if (!fr_assignment_op[op]) goto invalid; @@ -1130,15 +1134,21 @@ int fr_value_calc_assignment_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t rcode = 0; break; - case T_OP_ADD_EQ: - case T_OP_SUB_EQ: - case T_OP_PREPEND: /* * Just call the binary op function. It already * ensures that (a) the inputs are "const", and * (b) the output is over-written only as the * final step */ + case T_OP_ADD_EQ: + rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, T_ADD, src); + break; + + case T_OP_SUB_EQ: + rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, T_SUB, src); + break; + + case T_OP_PREPEND: rcode = fr_value_calc_binary_op(ctx, dst, dst->type, dst, op, src); break; @@ -1153,7 +1163,7 @@ int fr_value_calc_assignment_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_token_t fr_table_str_by_value(fr_value_box_type_table, dst->type, "")); } else if (rcode == ERR_INVALID) { - fr_strerror_printf("Invalid operator %s for destination type %s", + fr_strerror_printf("Invalid assignment operator %s for destination type %s", fr_tokens[op], fr_table_str_by_value(fr_value_box_type_table, dst->type, "")); } diff --git a/src/tests/unit/calc.txt b/src/tests/unit/calc.txt index 6df4af575ba..0efe2323ad8 100644 --- a/src/tests/unit/calc.txt +++ b/src/tests/unit/calc.txt @@ -80,5 +80,18 @@ match 3.500000 calc float32 1.0 * float32 2.5 -> float32 match 2.500000 +###################################################################### +# +# Assignment operations +# +calc uint8 1 := uint8 2 +match 2 + +calc uint8 1 += uint8 3 +match 4 + +calc string "2" += string "test" +match 2test + count -match 36 +match 42