Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(test): assertApproxEq{Rel,Abs} unit tests, improvements. & fixes #51

Merged
merged 15 commits into from
Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 67 additions & 45 deletions src/Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,11 @@ abstract contract Test is DSTest {
function assertEq(bool a, bool b, string memory err) internal {
if (a != b) {
emit log_named_string("Error", err);
emit log_named_string(" Expected", b ? "true" : "false");
emit log_named_string(" Actual", a ? "true" : "false");
fail();
assertEq(a, b);
}
}

function assertEq(bytes memory a, bytes memory b) internal virtual {
function assertEq(bytes memory a, bytes memory b) internal {
if (keccak256(a) != keccak256(b)) {
emit log ("Error: a == b not satisfied [bytes]");
emit log_named_bytes(" Expected", b);
Expand All @@ -186,12 +184,10 @@ abstract contract Test is DSTest {
}
}

function assertEq(bytes memory a, bytes memory b, string memory err) internal virtual {
function assertEq(bytes memory a, bytes memory b, string memory err) internal {
if (keccak256(a) != keccak256(b)) {
emit log_named_string ("Error", err);
emit log_named_bytes (" Expected", b);
emit log_named_bytes (" Actual", a);
fail();
assertEq(a, b);
}
}

Expand All @@ -200,7 +196,7 @@ abstract contract Test is DSTest {
uint256 b,
uint256 maxDelta
) internal virtual {
uint256 delta = a > b ? a - b : b - a;
uint256 delta = stdMath.delta(a, b);

if (delta > maxDelta) {
emit log ("Error: a ~= b not satisfied [uint]");
Expand All @@ -218,50 +214,42 @@ abstract contract Test is DSTest {
uint256 maxDelta,
string memory err
) internal virtual {
uint256 delta = a > b ? a - b : b - a;
uint256 delta = stdMath.delta(a, b);

if (delta > maxDelta) {
emit log_named_string ("Error", err);
emit log_named_uint (" Expected", b);
emit log_named_uint (" Actual", a);
emit log_named_uint (" Max Delta", maxDelta);
emit log_named_uint (" Delta", delta);
fail();
assertApproxEqAbs(a, b, maxDelta);
}
}

function assertApproxEqAbs(
int256 a,
int256 b,
int256 maxDelta
uint256 maxDelta
) internal virtual {
int256 delta = a > b ? a - b : b - a;
uint256 delta = stdMath.delta(a, b);

if (delta > maxDelta) {
emit log ("Error: a ~= b not satisfied [int]");
emit log_named_int (" Expected", b);
emit log_named_int (" Actual", a);
emit log_named_int (" Max Delta", maxDelta);
emit log_named_int (" Delta", delta);
emit log_named_uint (" Max Delta", maxDelta);
emit log_named_uint (" Delta", delta);
fail();
}
}

function assertApproxEqAbs(
int256 a,
int256 b,
int256 maxDelta,
uint256 maxDelta,
string memory err
) internal virtual {
int256 delta = a > b ? a - b : b - a;
uint256 delta = stdMath.delta(a, b);

if (delta > maxDelta) {
emit log_named_string ("Error", err);
emit log_named_int (" Expected", b);
emit log_named_int (" Actual", a);
emit log_named_int (" Max Delta", maxDelta);
emit log_named_int (" Delta", delta);
fail();
assertApproxEqAbs(a, b, maxDelta);
}
}

Expand All @@ -272,7 +260,7 @@ abstract contract Test is DSTest {
) internal virtual {
if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too.

uint256 percentDelta = ((a > b ? a - b : b - a) * 1e18) / b;
uint256 percentDelta = stdMath.percentDelta(a, b);

if (percentDelta > maxPercentDelta) {
emit log ("Error: a ~= b not satisfied [uint]");
Expand All @@ -292,54 +280,46 @@ abstract contract Test is DSTest {
) internal virtual {
if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too.

uint256 percentDelta = ((a > b ? a - b : b - a) * 1e18) / b;
uint256 percentDelta = stdMath.percentDelta(a, b);

if (percentDelta > maxPercentDelta) {
emit log_named_string ("Error", err);
emit log_named_uint (" Expected", b);
emit log_named_uint (" Actual", a);
emit log_named_decimal_uint (" Max % Delta", maxPercentDelta, 18);
emit log_named_decimal_uint (" % Delta", percentDelta, 18);
fail();
assertApproxEqRel(a, b, maxPercentDelta);
}
}

function assertApproxEqRel(
int256 a,
int256 b,
int256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%
uint256 maxPercentDelta
) internal virtual {
if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too.

int256 percentDelta = ((a > b ? a - b : b - a) * 1e18) / b;
uint256 percentDelta = stdMath.percentDelta(a, b);

if (percentDelta > maxPercentDelta) {
emit log ("Error: a ~= b not satisfied [uint]");
emit log ("Error: a ~= b not satisfied [int]");
emit log_named_int (" Expected", b);
emit log_named_int (" Actual", a);
emit log_named_decimal_int (" Max % Delta", maxPercentDelta, 18);
emit log_named_decimal_int (" % Delta", percentDelta, 18);
emit log_named_decimal_uint(" Max % Delta", maxPercentDelta, 18);
emit log_named_decimal_uint(" % Delta", percentDelta, 18);
fail();
}
}

function assertApproxEqRel(
int256 a,
int256 b,
int256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
uint256 maxPercentDelta,
string memory err
) internal virtual {
if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too.

int256 percentDelta = ((a > b ? a - b : b - a) * 1e18) / b;
uint256 percentDelta = stdMath.percentDelta(a, b);

if (percentDelta > maxPercentDelta) {
emit log_named_string ("Error", err);
emit log_named_int (" Expected", b);
emit log_named_int (" Actual", a);
emit log_named_decimal_int (" Max % Delta", maxPercentDelta, 18);
emit log_named_decimal_int (" % Delta", percentDelta, 18);
fail();
assertApproxEqRel(a, b, maxPercentDelta);
}
}
}
Expand Down Expand Up @@ -580,3 +560,45 @@ library stdStorage {
return result;
}
}

/*//////////////////////////////////////////////////////////////////////////
DELTA MATHS
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

STD-MATH

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

//////////////////////////////////////////////////////////////////////////*/

library stdMath {
function abs(int256 a) internal pure returns (uint256) {
unchecked {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just letting you guys know: #53

// must be unchecked in order to support `a = type(int256).min`
return uint256(a >= 0 ? a : -a);
}
}

function delta(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b
? a - b
: b - a;
}

function delta(int256 a, int256 b) internal pure returns (uint256) {
// a and b are of the same sign
if (a >= 0 && b >= 0 || a < 0 && b < 0) {
return delta(abs(a), abs(b));
}

// a and b are of opposite signs
return abs(a) + abs(b);
}

function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 absDelta = delta(a, b);

return absDelta * 1e18 / b;
}

function percentDelta(int256 a, int256 b) internal pure returns (uint256) {
uint256 absDelta = delta(a, b);
uint256 absB = abs(b);

return absDelta * 1e18 / absB;
}
}
Loading