rippled
Loading...
Searching...
No Matches
IOUAmount_test.cpp
1#include <xrpl/beast/unit_test.h>
2#include <xrpl/protocol/IOUAmount.h>
3
4namespace xrpl {
5
7{
8public:
9 void
11 {
12 testcase("zero");
13
14 IOUAmount const z(0, 0);
15
16 BEAST_EXPECT(z.mantissa() == 0);
17 BEAST_EXPECT(z.exponent() == -100);
18 BEAST_EXPECT(!z);
19 BEAST_EXPECT(z.signum() == 0);
20 BEAST_EXPECT(z == beast::zero);
21
22 BEAST_EXPECT((z + z) == z);
23 BEAST_EXPECT((z - z) == z);
24 BEAST_EXPECT(z == -z);
25
26 IOUAmount const zz(beast::zero);
27 BEAST_EXPECT(z == zz);
28
29 // https://github.com/XRPLF/rippled/issues/5170
30 IOUAmount const zzz{};
31 BEAST_EXPECT(zzz == beast::zero);
32 // BEAST_EXPECT(zzz == zz);
33 }
34
35 void
37 {
38 testcase("signum");
39
40 IOUAmount const neg(-1, 0);
41 BEAST_EXPECT(neg.signum() < 0);
42
43 IOUAmount const zer(0, 0);
44 BEAST_EXPECT(zer.signum() == 0);
45
46 IOUAmount const pos(1, 0);
47 BEAST_EXPECT(pos.signum() > 0);
48 }
49
50 void
52 {
53 testcase("beast::Zero Comparisons");
54
55 using beast::zero;
56
57 {
58 IOUAmount z(zero);
59 BEAST_EXPECT(z == zero);
60 BEAST_EXPECT(z >= zero);
61 BEAST_EXPECT(z <= zero);
62 unexpected(z != zero);
63 unexpected(z > zero);
64 unexpected(z < zero);
65 }
66
67 {
68 IOUAmount const neg(-2, 0);
69 BEAST_EXPECT(neg < zero);
70 BEAST_EXPECT(neg <= zero);
71 BEAST_EXPECT(neg != zero);
72 unexpected(neg == zero);
73 }
74
75 {
76 IOUAmount const pos(2, 0);
77 BEAST_EXPECT(pos > zero);
78 BEAST_EXPECT(pos >= zero);
79 BEAST_EXPECT(pos != zero);
80 unexpected(pos == zero);
81 }
82 }
83
84 void
86 {
87 testcase("IOU Comparisons");
88
89 IOUAmount const n(-2, 0);
90 IOUAmount const z(0, 0);
91 IOUAmount const p(2, 0);
92
93 BEAST_EXPECT(z == z);
94 BEAST_EXPECT(z >= z);
95 BEAST_EXPECT(z <= z);
96 BEAST_EXPECT(z == -z);
97 unexpected(z > z);
98 unexpected(z < z);
99 unexpected(z != z);
100 unexpected(z != -z);
101
102 BEAST_EXPECT(n < z);
103 BEAST_EXPECT(n <= z);
104 BEAST_EXPECT(n != z);
105 unexpected(n > z);
106 unexpected(n >= z);
107 unexpected(n == z);
108
109 BEAST_EXPECT(p > z);
110 BEAST_EXPECT(p >= z);
111 BEAST_EXPECT(p != z);
112 unexpected(p < z);
113 unexpected(p <= z);
114 unexpected(p == z);
115
116 BEAST_EXPECT(n < p);
117 BEAST_EXPECT(n <= p);
118 BEAST_EXPECT(n != p);
119 unexpected(n > p);
120 unexpected(n >= p);
121 unexpected(n == p);
122
123 BEAST_EXPECT(p > n);
124 BEAST_EXPECT(p >= n);
125 BEAST_EXPECT(p != n);
126 unexpected(p < n);
127 unexpected(p <= n);
128 unexpected(p == n);
129
130 BEAST_EXPECT(p > -p);
131 BEAST_EXPECT(p >= -p);
132 BEAST_EXPECT(p != -p);
133
134 BEAST_EXPECT(n < -n);
135 BEAST_EXPECT(n <= -n);
136 BEAST_EXPECT(n != -n);
137 }
138
139 void
141 {
142 testcase("IOU strings");
143
144 auto test = [this](IOUAmount const& n, std::string const& expected) {
145 auto const result = to_string(n);
147 ss << "to_string(" << result << "). Expected: " << expected;
148 BEAST_EXPECTS(result == expected, ss.str());
149 };
150
151 for (auto const mantissaSize : {MantissaRange::small, MantissaRange::large})
152 {
153 NumberMantissaScaleGuard mg(mantissaSize);
154
155 test(IOUAmount(-2, 0), "-2");
156 test(IOUAmount(0, 0), "0");
157 test(IOUAmount(2, 0), "2");
158 test(IOUAmount(25, -3), "0.025");
159 test(IOUAmount(-25, -3), "-0.025");
160 test(IOUAmount(25, 1), "250");
161 test(IOUAmount(-25, 1), "-250");
162 test(IOUAmount(2, 20), "2e20");
163 test(IOUAmount(-2, -20), "-2e-20");
164 }
165 }
166
167 void
169 {
170 testcase("mulRatio");
171
172 /* The range for the mantissa when normalized */
173 constexpr std::int64_t minMantissa = 1000000000000000ull;
174 constexpr std::int64_t maxMantissa = 9999999999999999ull;
175 // log(2,maxMantissa) ~ 53.15
176 /* The range for the exponent when normalized */
177 constexpr int minExponent = -96;
178 constexpr int maxExponent = 80;
179 constexpr auto maxUInt = std::numeric_limits<std::uint32_t>::max();
180
181 {
182 // multiply by a number that would overflow the mantissa, then
183 // divide by the same number, and check we didn't lose any value
184 IOUAmount bigMan(maxMantissa, 0);
185 BEAST_EXPECT(bigMan == mulRatio(bigMan, maxUInt, maxUInt, true));
186 // rounding mode shouldn't matter as the result is exact
187 BEAST_EXPECT(bigMan == mulRatio(bigMan, maxUInt, maxUInt, false));
188 }
189 {
190 // Similar test as above, but for negative values
191 IOUAmount bigMan(-maxMantissa, 0);
192 BEAST_EXPECT(bigMan == mulRatio(bigMan, maxUInt, maxUInt, true));
193 // rounding mode shouldn't matter as the result is exact
194 BEAST_EXPECT(bigMan == mulRatio(bigMan, maxUInt, maxUInt, false));
195 }
196
197 {
198 // small amounts
200 // Round up should give the smallest allowable number
201 BEAST_EXPECT(tiny == mulRatio(tiny, 1, maxUInt, true));
202 BEAST_EXPECT(tiny == mulRatio(tiny, maxUInt - 1, maxUInt, true));
203 // rounding down should be zero
204 BEAST_EXPECT(beast::zero == mulRatio(tiny, 1, maxUInt, false));
205 BEAST_EXPECT(beast::zero == mulRatio(tiny, maxUInt - 1, maxUInt, false));
206
207 // tiny negative numbers
209 // Round up should give zero
210 BEAST_EXPECT(beast::zero == mulRatio(tinyNeg, 1, maxUInt, true));
211 BEAST_EXPECT(beast::zero == mulRatio(tinyNeg, maxUInt - 1, maxUInt, true));
212 // rounding down should be tiny
213 BEAST_EXPECT(tinyNeg == mulRatio(tinyNeg, 1, maxUInt, false));
214 BEAST_EXPECT(tinyNeg == mulRatio(tinyNeg, maxUInt - 1, maxUInt, false));
215 }
216
217 { // rounding
218 {
219 IOUAmount one(1, 0);
220 auto const rup = mulRatio(one, maxUInt - 1, maxUInt, true);
221 auto const rdown = mulRatio(one, maxUInt - 1, maxUInt, false);
222 BEAST_EXPECT(rup.mantissa() - rdown.mantissa() == 1);
223 }
224 {
226 auto const rup = mulRatio(big, maxUInt - 1, maxUInt, true);
227 auto const rdown = mulRatio(big, maxUInt - 1, maxUInt, false);
228 BEAST_EXPECT(rup.mantissa() - rdown.mantissa() == 1);
229 }
230
231 {
232 IOUAmount negOne(-1, 0);
233 auto const rup = mulRatio(negOne, maxUInt - 1, maxUInt, true);
234 auto const rdown = mulRatio(negOne, maxUInt - 1, maxUInt, false);
235 BEAST_EXPECT(rup.mantissa() - rdown.mantissa() == 1);
236 }
237 }
238
239 {
240 // division by zero
241 IOUAmount one(1, 0);
242 except([&] { mulRatio(one, 1, 0, true); });
243 }
244
245 {
246 // overflow
248 except([&] { mulRatio(big, 2, 0, true); });
249 }
250 } // namespace xrpl
251
252 //--------------------------------------------------------------------------
253
254 void
255 run() override
256 {
257 testZero();
258 testSigNum();
261 testToString();
262 testMulRatio();
263 }
264};
265
266BEAST_DEFINE_TESTSUITE(IOUAmount, basics, xrpl);
267
268} // namespace xrpl
A testsuite class.
Definition suite.h:52
bool unexpected(Condition shouldBeFalse, String const &reason)
Definition suite.h:483
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:148
bool except(F &&f, String const &reason)
Definition suite.h:432
void run() override
Runs the suite.
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:26
mantissa_type mantissa() const noexcept
Definition IOUAmount.h:162
exponent_type exponent() const noexcept
Definition IOUAmount.h:156
int signum() const noexcept
Return the sign of the amount.
Definition IOUAmount.h:150
Sets the new scale and restores the old scale when it leaves scope.
Definition Number.h:801
T max(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
static std::int64_t constexpr minMantissa
Definition IOUAmount.cpp:48
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:598
IOUAmount mulRatio(IOUAmount const &amt, std::uint32_t num, std::uint32_t den, bool roundUp)
static std::int64_t constexpr maxMantissa
Definition IOUAmount.cpp:49
static int constexpr maxExponent
Definition IOUAmount.cpp:52
static int constexpr minExponent
Definition IOUAmount.cpp:51
T str(T... args)