Files
regorus/tests/rvm/vm/suites/arithmetic_operations.yaml
Anand Krishnamoorthi a8a3a9809b feat!: Use num-bigint for large numbers (#500)
- Supply chain: Use the popular num-bigint crate for handling large integers
- Optimization: Handle f64, i64, u64 directly. These will be the most common instances of a number.

OPA number semantics isn't clear.
https://github.com/open-policy-agent/opa/issues/6281

As part of this change, we update the following failing tests:
- A local test that relies on what 15.3/3 evaluates to.
 With our current change, we round in a different direction than what OPA does, but consistent
 with Rust. We produce 5.1000000000000005 where as the OPA test expects 5.1.
 There is no clear definition in Rego of what the right answer is. Moreover, policies should not
 rely on exact floating point value comparison. Therefore this deviations is justified.
 The test is patched to pass.
- Another local vm test that exercised 1.1 + 2.2
- Another local vm test that exercises 5.5 - 2.2
- An OPA test that expects that a large integer number say 10e308 is printed in exponent notation.
 num-bigint does not print using scientific notation and instead prints all the digits.
 The benefit of preserving this compatibility is not clear. We skip this test.
- Doc tests that exercised handling floating point numbers with more than 15 (what f64 supports)
  digits of precision. There is no usecase for this scenario. The tests are updated to reflect
  the behavior.

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
2025-12-01 13:25:02 -06:00

169 lines
5.4 KiB
YAML

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# Arithmetic Operations Test Suite
# Tests mathematical operations: Add, Sub, Mul, Div
# These instructions perform basic arithmetic on numeric values
cases:
- note: arithmetic_add
description: Test Add instruction
example_rego: "10 + 5" # Addition expression
literals:
- 10
- 5
instructions:
- "Load { dest: 0, literal_idx: 0 }" # Load literal 10 into register 0
- "Load { dest: 1, literal_idx: 1 }" # Load literal 5 into register 1
- "Add { dest: 2, left: 0, right: 1 }" # Add register 0 + register 1, store in register 2
- "Return { value: 2 }" # Return result from register 2
want_result: 15
- note: arithmetic_sub
description: Test Sub instruction
example_rego: "10 - 3" # Subtraction expression
literals:
- 10
- 3
instructions:
- "Load { dest: 0, literal_idx: 0 }" # Load literal 10 into register 0
- "Load { dest: 1, literal_idx: 1 }" # Load literal 3 into register 1
- "Sub { dest: 2, left: 0, right: 1 }" # Subtract register 1 from register 0, store in register 2
- "Return { value: 2 }" # Return result from register 2
want_result: 7
- note: arithmetic_mul
description: Test Mul instruction
example_rego: "4 * 6" # Multiplication expression
literals:
- 4
- 6
instructions:
- "Load { dest: 0, literal_idx: 0 }" # Load literal 4 into register 0
- "Load { dest: 1, literal_idx: 1 }" # Load literal 6 into register 1
- "Mul { dest: 2, left: 0, right: 1 }" # Multiply register 0 * register 1, store in register 2
- "Return { value: 2 }" # Return result from register 2
want_result: 24
- note: arithmetic_div
description: Test Div instruction
example_rego: "15 / 3" # Division expression
literals:
- 15
- 3
instructions:
- "Load { dest: 0, literal_idx: 0 }" # Load literal 15 into register 0
- "Load { dest: 1, literal_idx: 1 }" # Load literal 3 into register 1
- "Div { dest: 2, left: 0, right: 1 }" # Divide register 0 / register 1, store in register 2
- "Return { value: 2 }" # Return result from register 2
want_result: 5
- note: arithmetic_div_by_zero
description: Test Div by zero - undefined normally, error in strict mode
example_rego: "10 / 0"
literals:
- 10
- 0
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Div { dest: 2, left: 0, right: 1 }"
- "Return { value: 2 }"
want_result: "#undefined"
want_error_strict: "Cannot divide"
- note: arithmetic_mod
description: Test Mod instruction
example_rego: "10 % 3"
literals:
- 10
- 3
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Mod { dest: 2, left: 0, right: 1 }"
- "Return { value: 2 }"
want_result: 1
- note: arithmetic_mod_by_zero
description: Test Mod by zero - undefined normally, error in strict mode
example_rego: "10 % 0"
literals:
- 10
- 0
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Mod { dest: 2, left: 0, right: 1 }"
- "Return { value: 2 }"
want_result: "#undefined"
want_error_strict: "Cannot modulo"
- note: arithmetic_mod_negative_operands
description: Test Mod with negative operands
example_rego: "-10 % 3"
literals:
- -10
- 3
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Mod { dest: 2, left: 0, right: 1 }"
- "Return { value: 2 }"
want_result: -1
- note: arithmetic_mod_on_float_error
description: Test Mod on float - should error
example_rego: "10.5 % 3"
literals:
- 10.5
- 3
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Mod { dest: 2, left: 0, right: 1 }"
- "Return { value: 2 }"
want_error: "modulo on floating-point number"
- note: arithmetic_chained_operations
description: Test chained arithmetic operations (a + b) * c
example_rego: "(5 + 3) * 2"
literals:
- 5
- 3
- 2
instructions:
- "Load { dest: 0, literal_idx: 0 }" # Load 5
- "Load { dest: 1, literal_idx: 1 }" # Load 3
- "Add { dest: 2, left: 0, right: 1 }" # 5 + 3 = 8
- "Load { dest: 3, literal_idx: 2 }" # Load 2
- "Mul { dest: 4, left: 2, right: 3 }" # 8 * 2 = 16
- "Return { value: 4 }"
want_result: 16
- note: arithmetic_float_precision
description: Test float arithmetic precision
example_rego: "0.1 + 0.2"
literals:
- 0.1
- 0.2
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Add { dest: 2, left: 0, right: 1 }"
- "Return { value: 2 }"
want_result: 0.30000000000000004
- note: arithmetic_large_numbers
description: Test arithmetic with large numbers
example_rego: "1000000 * 1000000"
literals:
- 1000000
- 1000000
instructions:
- "Load { dest: 0, literal_idx: 0 }"
- "Load { dest: 1, literal_idx: 1 }"
- "Mul { dest: 2, left: 0, right: 1 }"
- "Return { value: 2 }"
want_result: 1000000000000