-
Notifications
You must be signed in to change notification settings - Fork 634
/
DSTestPlus.sol
149 lines (116 loc) · 4.68 KB
/
DSTestPlus.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {DSTest} from "ds-test/test.sol";
import {Hevm} from "./Hevm.sol";
/// @notice Extended testing framework for DappTools projects.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/test/utils/DSTestPlus.sol)
contract DSTestPlus is DSTest {
Hevm internal constant hevm = Hevm(HEVM_ADDRESS);
address internal constant DEAD_ADDRESS = 0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF;
string private checkpointLabel;
uint256 private checkpointGasLeft = 1; // Start the slot warm.
function startMeasuringGas(string memory label) internal virtual {
checkpointLabel = label;
checkpointGasLeft = gasleft();
}
function stopMeasuringGas() internal virtual {
uint256 checkpointGasLeft2 = gasleft();
// Subtract 100 to account for the warm SLOAD in startMeasuringGas.
uint256 gasDelta = checkpointGasLeft - checkpointGasLeft2 - 100;
emit log_named_uint(string(abi.encodePacked(checkpointLabel, " Gas")), gasDelta);
}
function fail(string memory err) internal virtual {
emit log_named_string("Error", err);
fail();
}
function assertFalse(bool data) internal virtual {
assertTrue(!data);
}
function assertUint128Eq(uint128 a, uint128 b) internal virtual {
assertEq(uint256(a), uint256(b));
}
function assertUint64Eq(uint64 a, uint64 b) internal virtual {
assertEq(uint256(a), uint256(b));
}
function assertUint96Eq(uint96 a, uint96 b) internal virtual {
assertEq(uint256(a), uint256(b));
}
function assertUint32Eq(uint32 a, uint32 b) internal virtual {
assertEq(uint256(a), uint256(b));
}
function assertBoolEq(bool a, bool b) internal virtual {
b ? assertTrue(a) : assertFalse(a);
}
function assertApproxEq(
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 assertRelApproxEq(
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 assertBytesEq(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 assertUintArrayEq(uint256[] memory a, uint256[] memory b) internal virtual {
require(a.length == b.length, "LENGTH_MISMATCH");
for (uint256 i = 0; i < a.length; i++) {
assertEq(a[i], b[i]);
}
}
function bound(
uint256 x,
uint256 min,
uint256 max
) internal returns (uint256 result) {
require(max >= min, "MAX_LESS_THAN_MIN");
uint256 size = max - min;
if (max != type(uint256).max) size++; // Make the max inclusive.
if (size == 0) return min; // Using max would be equivalent as well.
// Ensure max is inclusive in cases where x != 0 and max is at uint max.
if (max == type(uint256).max && x != 0) x--; // Accounted for later.
if (x < min) x += size * (((min - x) / size) + 1);
result = min + ((x - min) % size);
// Account for decrementing x to make max inclusive.
if (max == type(uint256).max && x != 0) result++;
emit log_named_uint("Bound Result", result);
}
function min3(
uint256 a,
uint256 b,
uint256 c
) internal pure returns (uint256) {
return a > b ? (b > c ? c : b) : (a > c ? c : a);
}
function min2(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? b : a;
}
}