rippled
IOUAmount_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/IOUAmount.h>
21 #include <ripple/beast/unit_test.h>
22 
23 namespace ripple {
24 
25 class IOUAmount_test : public beast::unit_test::suite
26 {
27 public:
28  void testZero ()
29  {
30  testcase ("zero");
31 
32  IOUAmount const z (0, 0);
33 
34  BEAST_EXPECT(z.mantissa () == 0);
35  BEAST_EXPECT(z.exponent () == -100);
36  BEAST_EXPECT(!z);
37  BEAST_EXPECT(z.signum () == 0);
38  BEAST_EXPECT(z == beast::zero);
39 
40  BEAST_EXPECT((z + z) == z);
41  BEAST_EXPECT((z - z) == z);
42  BEAST_EXPECT(z == -z);
43 
44  IOUAmount const zz (beast::zero);
45  BEAST_EXPECT(z == zz);
46  }
47 
48  void testSigNum ()
49  {
50  testcase ("signum");
51 
52  IOUAmount const neg (-1, 0);
53  BEAST_EXPECT(neg.signum () < 0);
54 
55  IOUAmount const zer (0, 0);
56  BEAST_EXPECT(zer.signum () == 0);
57 
58  IOUAmount const pos (1, 0);
59  BEAST_EXPECT(pos.signum () > 0);
60  }
61 
62  void testBeastZero ()
63  {
64  testcase ("beast::Zero Comparisons");
65 
66  using beast::zero;
67 
68  {
69  IOUAmount z (zero);
70  BEAST_EXPECT(z == zero);
71  BEAST_EXPECT(z >= zero);
72  BEAST_EXPECT(z <= zero);
73  unexpected (z != zero);
74  unexpected (z > zero);
75  unexpected (z < zero);
76  }
77 
78  {
79  IOUAmount const neg (-2, 0);
80  BEAST_EXPECT(neg < zero);
81  BEAST_EXPECT(neg <= zero);
82  BEAST_EXPECT(neg != zero);
83  unexpected (neg == zero);
84  }
85 
86  {
87  IOUAmount const pos (2, 0);
88  BEAST_EXPECT(pos > zero);
89  BEAST_EXPECT(pos >= zero);
90  BEAST_EXPECT(pos != zero);
91  unexpected (pos == zero);
92  }
93  }
94 
96  {
97  testcase ("IOU Comparisons");
98 
99  IOUAmount const n (-2, 0);
100  IOUAmount const z (0, 0);
101  IOUAmount const p (2, 0);
102 
103  BEAST_EXPECT(z == z);
104  BEAST_EXPECT(z >= z);
105  BEAST_EXPECT(z <= z);
106  BEAST_EXPECT(z == -z);
107  unexpected (z > z);
108  unexpected (z < z);
109  unexpected (z != z);
110  unexpected (z != -z);
111 
112  BEAST_EXPECT(n < z);
113  BEAST_EXPECT(n <= z);
114  BEAST_EXPECT(n != z);
115  unexpected (n > z);
116  unexpected (n >= z);
117  unexpected (n == z);
118 
119  BEAST_EXPECT(p > z);
120  BEAST_EXPECT(p >= z);
121  BEAST_EXPECT(p != z);
122  unexpected (p < z);
123  unexpected (p <= z);
124  unexpected (p == z);
125 
126  BEAST_EXPECT(n < p);
127  BEAST_EXPECT(n <= p);
128  BEAST_EXPECT(n != p);
129  unexpected (n > p);
130  unexpected (n >= p);
131  unexpected (n == p);
132 
133  BEAST_EXPECT(p > n);
134  BEAST_EXPECT(p >= n);
135  BEAST_EXPECT(p != n);
136  unexpected (p < n);
137  unexpected (p <= n);
138  unexpected (p == n);
139 
140  BEAST_EXPECT(p > -p);
141  BEAST_EXPECT(p >= -p);
142  BEAST_EXPECT(p != -p);
143 
144  BEAST_EXPECT(n < -n);
145  BEAST_EXPECT(n <= -n);
146  BEAST_EXPECT(n != -n);
147  }
148 
150  {
151  testcase("IOU strings");
152 
153  BEAST_EXPECT(to_string(IOUAmount (-2, 0)) == "-2");
154  BEAST_EXPECT(to_string(IOUAmount (0, 0)) == "0");
155  BEAST_EXPECT(to_string(IOUAmount (2, 0)) == "2");
156  BEAST_EXPECT(to_string(IOUAmount (25, -3)) == "0.025");
157  BEAST_EXPECT(to_string(IOUAmount (-25, -3)) == "-0.025");
158  BEAST_EXPECT(to_string(IOUAmount (25, 1)) == "250");
159  BEAST_EXPECT(to_string(IOUAmount (-25, 1)) == "-250");
160  BEAST_EXPECT(to_string(IOUAmount (2, 20)) == "2000000000000000e5");
161  BEAST_EXPECT(to_string(IOUAmount (-2, -20)) == "-2000000000000000e-35");
162  }
163 
165  {
166  testcase ("mulRatio");
167 
168  /* The range for the mantissa when normalized */
169  constexpr std::int64_t minMantissa = 1000000000000000ull;
170  constexpr std::int64_t maxMantissa = 9999999999999999ull;
171  // log(2,maxMantissa) ~ 53.15
172  /* The range for the exponent when normalized */
173  constexpr int minExponent = -96;
174  constexpr int maxExponent = 80;
175  constexpr auto maxUInt = std::numeric_limits<std::uint32_t>::max ();
176 
177  {
178  // multiply by a number that would overflow the mantissa, then
179  // divide by the same number, and check we didn't lose any value
180  IOUAmount bigMan (maxMantissa, 0);
181  BEAST_EXPECT(bigMan == mulRatio (bigMan, maxUInt, maxUInt, true));
182  // rounding mode shouldn't matter as the result is exact
183  BEAST_EXPECT(bigMan == mulRatio (bigMan, maxUInt, maxUInt, false));
184  }
185  {
186  // Similar test as above, but for negative values
187  IOUAmount bigMan (-maxMantissa, 0);
188  BEAST_EXPECT(bigMan == mulRatio (bigMan, maxUInt, maxUInt, true));
189  // rounding mode shouldn't matter as the result is exact
190  BEAST_EXPECT(bigMan == mulRatio (bigMan, maxUInt, maxUInt, false));
191  }
192 
193  {
194  // small amounts
196  // Round up should give the smallest allowable number
197  BEAST_EXPECT(tiny == mulRatio (tiny, 1, maxUInt, true));
198  BEAST_EXPECT(tiny == mulRatio (tiny, maxUInt - 1, maxUInt, true));
199  // rounding down should be zero
200  BEAST_EXPECT(beast::zero == mulRatio (tiny, 1, maxUInt, false));
201  BEAST_EXPECT(beast::zero == mulRatio (tiny, maxUInt - 1, maxUInt, false));
202 
203  // tiny negative numbers
204  IOUAmount tinyNeg (-minMantissa, minExponent);
205  // Round up should give zero
206  BEAST_EXPECT(beast::zero == mulRatio (tinyNeg, 1, maxUInt, true));
207  BEAST_EXPECT(beast::zero == mulRatio (tinyNeg, maxUInt - 1, maxUInt, true));
208  // rounding down should be tiny
209  BEAST_EXPECT(tinyNeg == mulRatio (tinyNeg, 1, maxUInt, false));
210  BEAST_EXPECT(tinyNeg == mulRatio (tinyNeg, maxUInt - 1, maxUInt, false));
211  }
212 
213  {
214  // rounding
215  {
216  IOUAmount one (1, 0);
217  auto const rup = mulRatio (one, maxUInt - 1, maxUInt, true);
218  auto const rdown = mulRatio (one, maxUInt - 1, maxUInt, false);
219  BEAST_EXPECT(rup.mantissa () - rdown.mantissa () == 1);
220  }
221  {
223  auto const rup = mulRatio (big, maxUInt - 1, maxUInt, true);
224  auto const rdown = mulRatio (big, maxUInt - 1, maxUInt, false);
225  BEAST_EXPECT(rup.mantissa () - rdown.mantissa () == 1);
226  }
227 
228  {
229  IOUAmount negOne (-1, 0);
230  auto const rup = mulRatio (negOne, maxUInt - 1, maxUInt, true);
231  auto const rdown = mulRatio (negOne, maxUInt - 1, maxUInt, false);
232  BEAST_EXPECT(rup.mantissa () - rdown.mantissa () == 1);
233  }
234  }
235 
236  {
237  // division by zero
238  IOUAmount one (1, 0);
239  except ([&] {mulRatio (one, 1, 0, true);});
240  }
241 
242  {
243  // overflow
245  except ([&] {mulRatio (big, 2, 0, true);});
246  }
247  }
248 
249  //--------------------------------------------------------------------------
250 
251  void run () override
252  {
253  testZero ();
254  testSigNum ();
255  testBeastZero ();
256  testComparisons ();
257  testToString ();
258  testMulRatio ();
259  }
260 };
261 
262 BEAST_DEFINE_TESTSUITE(IOUAmount,protocol,ripple);
263 
264 } // ripple
ripple::mulRatio
IOUAmount mulRatio(IOUAmount const &amt, std::uint32_t num, std::uint32_t den, bool roundUp)
Definition: IOUAmount.cpp:248
ripple::IOUAmount::exponent
int exponent() const noexcept
Definition: IOUAmount.h:126
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::maxMantissa
static const std::int64_t maxMantissa
Definition: IOUAmount.cpp:32
ripple::IOUAmount_test::testZero
void testZero()
Definition: IOUAmount_test.cpp:28
ripple::IOUAmount
Floating point representation of amounts with high dynamic range.
Definition: IOUAmount.h:41
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::IOUAmount_test::testComparisons
void testComparisons()
Definition: IOUAmount_test.cpp:95
ripple::IOUAmount::signum
int signum() const noexcept
Return the sign of the amount.
Definition: IOUAmount.h:120
ripple::IOUAmount_test::run
void run() override
Definition: IOUAmount_test.cpp:251
ripple::maxExponent
static const int maxExponent
Definition: IOUAmount.cpp:35
ripple::IOUAmount_test::testMulRatio
void testMulRatio()
Definition: IOUAmount_test.cpp:164
std::int64_t
ripple::IOUAmount_test::testBeastZero
void testBeastZero()
Definition: IOUAmount_test.cpp:62
ripple::IOUAmount_test
Definition: IOUAmount_test.cpp:25
ripple::minMantissa
static const std::int64_t minMantissa
Definition: IOUAmount.cpp:31
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::IOUAmount::mantissa
std::int64_t mantissa() const noexcept
Definition: IOUAmount.h:132
ripple::IOUAmount_test::testToString
void testToString()
Definition: IOUAmount_test.cpp:149
ripple::minExponent
static const int minExponent
Definition: IOUAmount.cpp:34
std::numeric_limits::max
T max(T... args)
ripple::IOUAmount_test::testSigNum
void testSigNum()
Definition: IOUAmount_test.cpp:48