SignedMath.t.sol 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.20;
  3. import {Test} from "forge-std/Test.sol";
  4. import {Math} from "../../../contracts/utils/math/Math.sol";
  5. import {SignedMath} from "../../../contracts/utils/math/SignedMath.sol";
  6. contract SignedMathTest is Test {
  7. function testSymbolicTernary(bool f, int256 a, int256 b) public {
  8. assertEq(SignedMath.ternary(f, a, b), f ? a : b);
  9. }
  10. // MIN & MAX
  11. function testSymbolicMinMax(int256 a, int256 b) public {
  12. assertEq(SignedMath.min(a, b), a < b ? a : b);
  13. assertEq(SignedMath.max(a, b), a > b ? a : b);
  14. }
  15. // MIN
  16. function testSymbolicMin(int256 a, int256 b) public {
  17. int256 result = SignedMath.min(a, b);
  18. assertLe(result, a);
  19. assertLe(result, b);
  20. assertTrue(result == a || result == b);
  21. }
  22. // MAX
  23. function testSymbolicMax(int256 a, int256 b) public {
  24. int256 result = SignedMath.max(a, b);
  25. assertGe(result, a);
  26. assertGe(result, b);
  27. assertTrue(result == a || result == b);
  28. }
  29. // AVERAGE
  30. // 1. simple test, not full int256 range
  31. function testAverage1(int256 a, int256 b) public {
  32. a = bound(a, type(int256).min / 2, type(int256).max / 2);
  33. b = bound(b, type(int256).min / 2, type(int256).max / 2);
  34. int256 result = SignedMath.average(a, b);
  35. assertEq(result, (a + b) / 2);
  36. }
  37. // 2. more complex test, full int256 range
  38. function testAverage2(int256 a, int256 b) public {
  39. (int256 result, int256 min, int256 max) = (
  40. SignedMath.average(a, b),
  41. SignedMath.min(a, b),
  42. SignedMath.max(a, b)
  43. );
  44. // average must be between `a` and `b`
  45. assertGe(result, min);
  46. assertLe(result, max);
  47. unchecked {
  48. // must be unchecked in order to support `a = type(int256).min, b = type(int256).max`
  49. uint256 deltaLower = uint256(result - min);
  50. uint256 deltaUpper = uint256(max - result);
  51. uint256 remainder = uint256((a & 1) ^ (b & 1));
  52. assertEq(remainder, Math.max(deltaLower, deltaUpper) - Math.min(deltaLower, deltaUpper));
  53. }
  54. }
  55. // ABS
  56. function testSymbolicAbs(int256 a) public {
  57. uint256 result = SignedMath.abs(a);
  58. unchecked {
  59. // must be unchecked in order to support `n = type(int256).min`
  60. assertEq(result, a < 0 ? uint256(-a) : uint256(a));
  61. }
  62. }
  63. }