rippled
Loading...
Searching...
No Matches
XRPAmount_test.cpp
1#include <xrpl/beast/unit_test.h>
2#include <xrpl/protocol/XRPAmount.h>
3
4namespace ripple {
5
7{
8public:
9 void
11 {
12 testcase("signum");
13
14 for (auto i : {-1, 0, 1})
15 {
16 XRPAmount const x(i);
17
18 if (i < 0)
19 BEAST_EXPECT(x.signum() < 0);
20 else if (i > 0)
21 BEAST_EXPECT(x.signum() > 0);
22 else
23 BEAST_EXPECT(x.signum() == 0);
24 }
25 }
26
27 void
29 {
30 testcase("beast::Zero Comparisons");
31
32 using beast::zero;
33
34 for (auto i : {-1, 0, 1})
35 {
36 XRPAmount const x(i);
37
38 BEAST_EXPECT((i == 0) == (x == zero));
39 BEAST_EXPECT((i != 0) == (x != zero));
40 BEAST_EXPECT((i < 0) == (x < zero));
41 BEAST_EXPECT((i > 0) == (x > zero));
42 BEAST_EXPECT((i <= 0) == (x <= zero));
43 BEAST_EXPECT((i >= 0) == (x >= zero));
44
45 BEAST_EXPECT((0 == i) == (zero == x));
46 BEAST_EXPECT((0 != i) == (zero != x));
47 BEAST_EXPECT((0 < i) == (zero < x));
48 BEAST_EXPECT((0 > i) == (zero > x));
49 BEAST_EXPECT((0 <= i) == (zero <= x));
50 BEAST_EXPECT((0 >= i) == (zero >= x));
51 }
52 }
53
54 void
56 {
57 testcase("XRP Comparisons");
58
59 for (auto i : {-1, 0, 1})
60 {
61 XRPAmount const x(i);
62
63 for (auto j : {-1, 0, 1})
64 {
65 XRPAmount const y(j);
66
67 BEAST_EXPECT((i == j) == (x == y));
68 BEAST_EXPECT((i != j) == (x != y));
69 BEAST_EXPECT((i < j) == (x < y));
70 BEAST_EXPECT((i > j) == (x > y));
71 BEAST_EXPECT((i <= j) == (x <= y));
72 BEAST_EXPECT((i >= j) == (x >= y));
73 }
74 }
75 }
76
77 void
79 {
80 testcase("Addition & Subtraction");
81
82 for (auto i : {-1, 0, 1})
83 {
84 XRPAmount const x(i);
85
86 for (auto j : {-1, 0, 1})
87 {
88 XRPAmount const y(j);
89
90 BEAST_EXPECT(XRPAmount(i + j) == (x + y));
91 BEAST_EXPECT(XRPAmount(i - j) == (x - y));
92
93 BEAST_EXPECT((x + y) == (y + x)); // addition is commutative
94 }
95 }
96 }
97
98 void
100 {
101 // Tautology
102 BEAST_EXPECT(DROPS_PER_XRP.decimalXRP() == 1);
103
104 XRPAmount test{1};
105 BEAST_EXPECT(test.decimalXRP() == 0.000001);
106
107 test = -test;
108 BEAST_EXPECT(test.decimalXRP() == -0.000001);
109
110 test = 100'000'000;
111 BEAST_EXPECT(test.decimalXRP() == 100);
112
113 test = -test;
114 BEAST_EXPECT(test.decimalXRP() == -100);
115 }
116
117 void
119 {
120 // Explicitly test every defined function for the XRPAmount class
121 // since some of them are templated, but not used anywhere else.
122 auto make = [&](auto x) -> XRPAmount { return XRPAmount{x}; };
123
124 XRPAmount defaulted;
125 (void)defaulted;
126 XRPAmount test{0};
127 BEAST_EXPECT(test.drops() == 0);
128
129 test = make(beast::zero);
130 BEAST_EXPECT(test.drops() == 0);
131
132 test = beast::zero;
133 BEAST_EXPECT(test.drops() == 0);
134
135 test = make(100);
136 BEAST_EXPECT(test.drops() == 100);
137
138 test = make(100u);
139 BEAST_EXPECT(test.drops() == 100);
140
141 XRPAmount const targetSame{200u};
142 test = make(targetSame);
143 BEAST_EXPECT(test.drops() == 200);
144 BEAST_EXPECT(test == targetSame);
145 BEAST_EXPECT(test < XRPAmount{1000});
146 BEAST_EXPECT(test > XRPAmount{100});
147
148 test = std::int64_t(200);
149 BEAST_EXPECT(test.drops() == 200);
150 test = std::uint32_t(300);
151 BEAST_EXPECT(test.drops() == 300);
152
153 test = targetSame;
154 BEAST_EXPECT(test.drops() == 200);
155 auto testOther = test.dropsAs<std::uint32_t>();
156 BEAST_EXPECT(testOther);
157 BEAST_EXPECT(*testOther == 200);
159 testOther = test.dropsAs<std::uint32_t>();
160 BEAST_EXPECT(!testOther);
161 test = -1;
162 testOther = test.dropsAs<std::uint32_t>();
163 BEAST_EXPECT(!testOther);
164
165 test = targetSame * 2;
166 BEAST_EXPECT(test.drops() == 400);
167 test = 3 * targetSame;
168 BEAST_EXPECT(test.drops() == 600);
169 test = 20;
170 BEAST_EXPECT(test.drops() == 20);
171
172 test += targetSame;
173 BEAST_EXPECT(test.drops() == 220);
174
175 test -= targetSame;
176 BEAST_EXPECT(test.drops() == 20);
177
178 test *= 5;
179 BEAST_EXPECT(test.drops() == 100);
180 test = 50;
181 BEAST_EXPECT(test.drops() == 50);
182 test -= 39;
183 BEAST_EXPECT(test.drops() == 11);
184
185 // legal with signed
186 test = -test;
187 BEAST_EXPECT(test.drops() == -11);
188 BEAST_EXPECT(test.signum() == -1);
189 BEAST_EXPECT(to_string(test) == "-11");
190
191 BEAST_EXPECT(test);
192 test = 0;
193 BEAST_EXPECT(!test);
194 BEAST_EXPECT(test.signum() == 0);
195 test = targetSame;
196 BEAST_EXPECT(test.signum() == 1);
197 BEAST_EXPECT(to_string(test) == "200");
198 }
199
200 void
202 {
203 testcase("mulRatio");
204
205 constexpr auto maxUInt32 = std::numeric_limits<std::uint32_t>::max();
206 constexpr auto maxXRP =
208 constexpr auto minXRP =
210
211 {
212 // multiply by a number that would overflow then divide by the same
213 // number, and check we didn't lose any value
214 XRPAmount big(maxXRP);
215 BEAST_EXPECT(big == mulRatio(big, maxUInt32, maxUInt32, true));
216 // rounding mode shouldn't matter as the result is exact
217 BEAST_EXPECT(big == mulRatio(big, maxUInt32, maxUInt32, false));
218
219 // multiply and divide by values that would overflow if done
220 // naively, and check that it gives the correct answer
221 big -= 0xf; // Subtract a little so it's divisable by 4
222 BEAST_EXPECT(
223 mulRatio(big, 3, 4, false).value() == (big.value() / 4) * 3);
224 BEAST_EXPECT(
225 mulRatio(big, 3, 4, true).value() == (big.value() / 4) * 3);
226 BEAST_EXPECT((big.value() * 3) / 4 != (big.value() / 4) * 3);
227 }
228
229 {
230 // Similar test as above, but for negative values
231 XRPAmount big(minXRP);
232 BEAST_EXPECT(big == mulRatio(big, maxUInt32, maxUInt32, true));
233 // rounding mode shouldn't matter as the result is exact
234 BEAST_EXPECT(big == mulRatio(big, maxUInt32, maxUInt32, false));
235
236 // multiply and divide by values that would overflow if done
237 // naively, and check that it gives the correct answer
238 BEAST_EXPECT(
239 mulRatio(big, 3, 4, false).value() == (big.value() / 4) * 3);
240 BEAST_EXPECT(
241 mulRatio(big, 3, 4, true).value() == (big.value() / 4) * 3);
242 BEAST_EXPECT((big.value() * 3) / 4 != (big.value() / 4) * 3);
243 }
244
245 {
246 // small amounts
247 XRPAmount tiny(1);
248 // Round up should give the smallest allowable number
249 BEAST_EXPECT(tiny == mulRatio(tiny, 1, maxUInt32, true));
250 // rounding down should be zero
251 BEAST_EXPECT(beast::zero == mulRatio(tiny, 1, maxUInt32, false));
252 BEAST_EXPECT(
253 beast::zero == mulRatio(tiny, maxUInt32 - 1, maxUInt32, false));
254
255 // tiny negative numbers
256 XRPAmount tinyNeg(-1);
257 // Round up should give zero
258 BEAST_EXPECT(beast::zero == mulRatio(tinyNeg, 1, maxUInt32, true));
259 BEAST_EXPECT(
260 beast::zero ==
261 mulRatio(tinyNeg, maxUInt32 - 1, maxUInt32, true));
262 // rounding down should be tiny
263 BEAST_EXPECT(
264 tinyNeg == mulRatio(tinyNeg, maxUInt32 - 1, maxUInt32, false));
265 }
266
267 { // rounding
268 {
269 XRPAmount one(1);
270 auto const rup = mulRatio(one, maxUInt32 - 1, maxUInt32, true);
271 auto const rdown =
272 mulRatio(one, maxUInt32 - 1, maxUInt32, false);
273 BEAST_EXPECT(rup.drops() - rdown.drops() == 1);
274 }
275
276 {
277 XRPAmount big(maxXRP);
278 auto const rup = mulRatio(big, maxUInt32 - 1, maxUInt32, true);
279 auto const rdown =
280 mulRatio(big, maxUInt32 - 1, maxUInt32, false);
281 BEAST_EXPECT(rup.drops() - rdown.drops() == 1);
282 }
283
284 {
285 XRPAmount negOne(-1);
286 auto const rup =
287 mulRatio(negOne, maxUInt32 - 1, maxUInt32, true);
288 auto const rdown =
289 mulRatio(negOne, maxUInt32 - 1, maxUInt32, false);
290 BEAST_EXPECT(rup.drops() - rdown.drops() == 1);
291 }
292 }
293
294 {
295 // division by zero
296 XRPAmount one(1);
297 except([&] { mulRatio(one, 1, 0, true); });
298 }
299
300 {
301 // overflow
302 XRPAmount big(maxXRP);
303 except([&] { mulRatio(big, 2, 1, true); });
304 }
305
306 {
307 // underflow
308 XRPAmount bigNegative(minXRP + 10);
309 BEAST_EXPECT(mulRatio(bigNegative, 2, 1, true) == minXRP);
310 }
311 } // namespace ripple
312
313 //--------------------------------------------------------------------------
314
315 void
316 run() override
317 {
318 testSigNum();
321 testAddSub();
322 testDecimal();
324 testMulRatio();
325 }
326};
327
328BEAST_DEFINE_TESTSUITE(XRPAmount, basics, ripple);
329
330} // namespace ripple
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:152
bool except(F &&f, String const &reason)
Definition suite.h:445
void run() override
Runs the suite.
constexpr value_type value() const
Returns the underlying value.
Definition XRPAmount.h:220
constexpr int signum() const noexcept
Return the sign of the amount.
Definition XRPAmount.h:151
constexpr double decimalXRP() const
Definition XRPAmount.h:243
T max(T... args)
T min(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
constexpr Number one
Definition Number.cpp:156
IOUAmount mulRatio(IOUAmount const &amt, std::uint32_t num, std::uint32_t den, bool roundUp)
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
constexpr XRPAmount DROPS_PER_XRP
Number of drops per 1 XRP.
Definition XRPAmount.h:240