]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add tests for assignment operations
authorAlan T. DeKok <aland@freeradius.org>
Sat, 20 Nov 2021 14:46:00 +0000 (09:46 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 20 Nov 2021 14:46:00 +0000 (09:46 -0500)
src/bin/unit_test_attribute.c
src/lib/util/calc.c
src/tests/unit/calc.txt

index a7cf1b80db449c441dd4fa390e810b64fd6e956f..ad289edd0d16c152c3d21a4d323b123a6ff1bfd8 100644 (file)
@@ -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);
index 4188b7f36bb22ff5d423202c1a264a5d19680777..7eefef766eea1c5ea60322d19c60d01e87fdb1b2 100644 (file)
@@ -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, "<INVALID>"));
+               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, "<INVALID>"));
 
        } 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, "<INVALID>"));
        }
index 6df4af575ba332b40e08cea8e662e6cb2b80bd12..0efe2323ad81d79b10a0b0de66fd2373dc54954c 100644 (file)
@@ -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