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

feat(test): assertApproxEq, assertNotEq, assertFalse #38

Merged
merged 19 commits into from
Apr 22, 2022
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e17d6f0
feat(test): assertApproxEq, assertNotEq, assertFalse
OliverNChalk Apr 18, 2022
1e3b6a2
refactor: yoink assertApproxEq from t11s
OliverNChalk Apr 20, 2022
fb089f0
feat(test): yoink assertRelApproxEq from t11s
OliverNChalk Apr 20, 2022
dfaa2d5
style(test): align multi-line log messages for character alignment
OliverNChalk Apr 20, 2022
7e73c21
fix(test): correct yoink/translation errors
OliverNChalk Apr 20, 2022
1a78d1b
feat(test): add more bool asserts, t11s assertFalse
OliverNChalk Apr 20, 2022
3e8d693
feat(test): add assertEq(bool, err)
OliverNChalk Apr 20, 2022
b61c6c4
feat(test): add assertEq(bytes, bytes)
OliverNChalk Apr 20, 2022
51ff84f
refactor(test): standardized approx eq assertion naming
OliverNChalk Apr 21, 2022
3e0ef00
refactor(test): drop assertNotEq as it's bad practice
OliverNChalk Apr 21, 2022
1f08a76
refactor(test): improve assertEq(bool,bool) error messaging
OliverNChalk Apr 21, 2022
f0e1ba9
fix(test): remove duplicate assertEq(bool,bool)
OliverNChalk Apr 21, 2022
03355c9
fix(test): use log instead of log_named_string
OliverNChalk Apr 21, 2022
2c23374
feat(test): add int256 impls for assertApproxEqRel
OliverNChalk Apr 21, 2022
924456a
style(test): re-order code and group overloads together
OliverNChalk Apr 21, 2022
99a36d8
style(test): use single STD-ASSERTIONS code region
OliverNChalk Apr 22, 2022
3c15901
style(test): declare assertFalse before assertEq
OliverNChalk Apr 22, 2022
113b11c
style(test): add STD-CHEATS code region
OliverNChalk Apr 22, 2022
b434995
style: add STD-ERRORS & STD-STORAGE delimters
OliverNChalk Apr 22, 2022
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
222 changes: 214 additions & 8 deletions src/Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ abstract contract Test is DSTest {
Vm public constant vm = Vm(HEVM_ADDRESS);
StdStorage internal stdstore;

/*//////////////////////////////////////////////////////////////////////////
STD-CHEATS
//////////////////////////////////////////////////////////////////////////*/

// Skip forward or rewind time by the specified number of seconds
function skip(uint256 time) public {
vm.warp(block.timestamp + time);
Expand Down Expand Up @@ -139,8 +143,207 @@ abstract contract Test is DSTest {
addr := create(0, add(bytecode, 0x20), mload(bytecode))
}
}

/*//////////////////////////////////////////////////////////////////////////
STD-ASSERTIONS
//////////////////////////////////////////////////////////////////////////*/

function assertFalse(bool data) internal virtual {
assertTrue(!data);
}

function assertFalse(bool data, string memory err) internal virtual {
assertTrue(!data, err);
}

function assertEq(bool a, bool b) internal {
if (a != b) {
emit log ("Error: a == b not satisfied [bool]");
emit log_named_string (" Expected", b ? "true" : "false");
emit log_named_string (" Actual", a ? "true" : "false");
fail();
}
}

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();
}
}

function assertEq(bytes memory a, bytes memory b) internal virtual {
if (keccak256(a) != keccak256(b)) {
emit log ("Error: a == b not satisfied [bytes]");
emit log_named_bytes(" Expected", b);
emit log_named_bytes(" Actual", a);
fail();
}
}

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

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

if (delta > maxDelta) {
emit log ("Error: a ~= b not satisfied [uint]");
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();
}
}

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

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();
}
}

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

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);
fail();
}
}

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

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();
}
}

function assertApproxEqRel(
uint256 a,
uint256 b,
uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%
) 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;

if (percentDelta > maxPercentDelta) {
emit log ("Error: a ~= b not satisfied [uint]");
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();
}
}

function assertApproxEqRel(
uint256 a,
uint256 b,
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
string memory err
) 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;

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();
}
}

function assertApproxEqRel(
int256 a,
int256 b,
int256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%
) 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;

if (percentDelta > maxPercentDelta) {
emit log ("Error: a ~= b not satisfied [uint]");
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();
}
}

function assertApproxEqRel(
int256 a,
int256 b,
int256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
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;

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();
}
}
}

/*//////////////////////////////////////////////////////////////////////////
STD-ERRORS
//////////////////////////////////////////////////////////////////////////*/

Copy link
Collaborator

Choose a reason for hiding this comment

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

We should add a header here before stdError "STD-ERRORS" to separate them from the assertions.

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, can resolve if happy

library stdError {
bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01);
Expand All @@ -159,19 +362,22 @@ library stdError {
struct StdStorage {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here "STD-STORAGE"

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, can resolve if happy

mapping (address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;
mapping (address => mapping(bytes4 => mapping(bytes32 => bool))) finds;

bytes32[] _keys;
bytes4 _sig;
uint256 _depth;
address _target;
bytes32 _set;
}

/*//////////////////////////////////////////////////////////////////////////
STD-STORAGE
//////////////////////////////////////////////////////////////////////////*/

library stdStorage {
event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint slot);
event WARNING_UninitedSlot(address who, uint slot);

Vm private constant vm_std_store = Vm(address(uint160(uint256(keccak256('hevm cheat code')))));

function sigs(
Expand All @@ -192,8 +398,8 @@ library stdStorage {
// if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);
function find(
StdStorage storage self
)
internal
)
internal
returns (uint256)
{
address who = self._target;
Expand All @@ -212,7 +418,7 @@ library stdStorage {
(, bytes memory rdat) = who.staticcall(cald);
fdat = bytesToBytes32(rdat, 32*field_depth);
}

(bytes32[] memory reads, ) = vm_std_store.accesses(address(who));
if (reads.length == 1) {
bytes32 curr = vm_std_store.load(who, reads[0]);
Expand All @@ -239,7 +445,7 @@ library stdStorage {
(success, rdat) = who.staticcall(cald);
fdat = bytesToBytes32(rdat, 32*field_depth);
}

if (success && fdat == bytes32(hex"1337")) {
// we found which of the slots is the actual one
emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));
Expand All @@ -259,7 +465,7 @@ library stdStorage {
delete self._target;
delete self._sig;
delete self._keys;
delete self._depth;
delete self._depth;

return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];
}
Expand Down Expand Up @@ -343,7 +549,7 @@ library stdStorage {
delete self._target;
delete self._sig;
delete self._keys;
delete self._depth;
delete self._depth;
}

function bytesToBytes32(bytes memory b, uint offset) public pure returns (bytes32) {
Expand Down