rippled
FeeUnits_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2019 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 #include <ripple/basics/FeeUnits.h>
20 #include <ripple/beast/unit_test.h>
21 #include <ripple/protocol/SystemParameters.h>
22 #include <type_traits>
23 
24 namespace ripple {
25 namespace test {
26 
27 class feeunits_test : public beast::unit_test::suite
28 {
29 private:
30  void
32  {
33  using FeeLevel32 = FeeLevel<std::uint32_t>;
34 
35  {
36  XRPAmount x{100};
37  BEAST_EXPECT(x.drops() == 100);
38  BEAST_EXPECT(
39  (std::is_same_v<decltype(x)::unit_type, feeunit::dropTag>));
40  auto y = 4u * x;
41  BEAST_EXPECT(y.value() == 400);
42  BEAST_EXPECT(
43  (std::is_same_v<decltype(y)::unit_type, feeunit::dropTag>));
44 
45  auto z = 4 * y;
46  BEAST_EXPECT(z.value() == 1600);
47  BEAST_EXPECT(
48  (std::is_same_v<decltype(z)::unit_type, feeunit::dropTag>));
49 
50  FeeLevel32 f{10};
51  FeeLevel32 baseFee{100};
52 
53  auto drops = mulDiv(baseFee, x, f);
54 
55  BEAST_EXPECT(drops);
56  BEAST_EXPECT(drops.value() == 1000);
57  BEAST_EXPECT((std::is_same_v<
58  std::remove_reference_t<decltype(*drops)>::unit_type,
59  feeunit::dropTag>));
60 
61  BEAST_EXPECT((std::is_same_v<
62  std::remove_reference_t<decltype(*drops)>,
63  XRPAmount>));
64  }
65  {
66  XRPAmount x{100};
67  BEAST_EXPECT(x.value() == 100);
68  BEAST_EXPECT(
69  (std::is_same_v<decltype(x)::unit_type, feeunit::dropTag>));
70  auto y = 4u * x;
71  BEAST_EXPECT(y.value() == 400);
72  BEAST_EXPECT(
73  (std::is_same_v<decltype(y)::unit_type, feeunit::dropTag>));
74 
75  FeeLevel64 f{10};
76  FeeLevel64 baseFee{100};
77 
78  auto drops = mulDiv(baseFee, x, f);
79 
80  BEAST_EXPECT(drops);
81  BEAST_EXPECT(drops.value() == 1000);
82  BEAST_EXPECT((std::is_same_v<
83  std::remove_reference_t<decltype(*drops)>::unit_type,
84  feeunit::dropTag>));
85  BEAST_EXPECT((std::is_same_v<
86  std::remove_reference_t<decltype(*drops)>,
87  XRPAmount>));
88  }
89  {
90  FeeLevel64 x{1024};
91  BEAST_EXPECT(x.value() == 1024);
92  BEAST_EXPECT(
93  (std::is_same_v<decltype(x)::unit_type, feeunit::feelevelTag>));
94  std::uint64_t m = 4;
95  auto y = m * x;
96  BEAST_EXPECT(y.value() == 4096);
97  BEAST_EXPECT(
98  (std::is_same_v<decltype(y)::unit_type, feeunit::feelevelTag>));
99 
100  XRPAmount basefee{10};
101  FeeLevel64 referencefee{256};
102 
103  auto drops = mulDiv(x, basefee, referencefee);
104 
105  BEAST_EXPECT(drops);
106  BEAST_EXPECT(drops.value() == 40);
107  BEAST_EXPECT((std::is_same_v<
108  std::remove_reference_t<decltype(*drops)>::unit_type,
109  feeunit::dropTag>));
110  BEAST_EXPECT((std::is_same_v<
111  std::remove_reference_t<decltype(*drops)>,
112  XRPAmount>));
113  }
114  }
115 
116  void
118  {
119  // Json value functionality
120  using FeeLevel32 = FeeLevel<std::uint32_t>;
121 
122  {
124  auto y = x.jsonClipped();
125  BEAST_EXPECT(y.type() == Json::uintValue);
126  BEAST_EXPECT(y == Json::Value{x.fee()});
127  }
128 
129  {
131  auto y = x.jsonClipped();
132  BEAST_EXPECT(y.type() == Json::uintValue);
133  BEAST_EXPECT(y == Json::Value{x.fee()});
134  }
135 
136  {
138  auto y = x.jsonClipped();
139  BEAST_EXPECT(y.type() == Json::uintValue);
140  BEAST_EXPECT(
142  }
143 
144  {
146  auto y = x.jsonClipped();
147  BEAST_EXPECT(y.type() == Json::uintValue);
148  BEAST_EXPECT(y == Json::Value{0});
149  }
150 
151  {
153  auto y = x.jsonClipped();
154  BEAST_EXPECT(y.type() == Json::realValue);
155  BEAST_EXPECT(y == Json::Value{std::numeric_limits<double>::max()});
156  }
157 
158  {
160  auto y = x.jsonClipped();
161  BEAST_EXPECT(y.type() == Json::realValue);
162  BEAST_EXPECT(y == Json::Value{std::numeric_limits<double>::min()});
163  }
164 
165  {
167  auto y = x.jsonClipped();
168  BEAST_EXPECT(y.type() == Json::intValue);
169  BEAST_EXPECT(
171  }
172 
173  {
175  auto y = x.jsonClipped();
176  BEAST_EXPECT(y.type() == Json::intValue);
177  BEAST_EXPECT(
179  }
180  }
181 
182  void
184  {
185  // Explicitly test every defined function for the TaggedFee class
186  // since some of them are templated, but not used anywhere else.
187  using FeeLevel32 = FeeLevel<std::uint32_t>;
188 
189  {
190  auto make = [&](auto x) -> FeeLevel64 { return x; };
191  auto explicitmake = [&](auto x) -> FeeLevel64 {
192  return FeeLevel64{x};
193  };
194 
195  FeeLevel64 defaulted;
196  (void)defaulted;
197  FeeLevel64 test{0};
198  BEAST_EXPECT(test.fee() == 0);
199 
200  test = explicitmake(beast::zero);
201  BEAST_EXPECT(test.fee() == 0);
202 
203  test = beast::zero;
204  BEAST_EXPECT(test.fee() == 0);
205 
206  test = explicitmake(100u);
207  BEAST_EXPECT(test.fee() == 100);
208 
209  FeeLevel64 const targetSame{200u};
210  FeeLevel32 const targetOther{300u};
211  test = make(targetSame);
212  BEAST_EXPECT(test.fee() == 200);
213  BEAST_EXPECT(test == targetSame);
214  BEAST_EXPECT(test < FeeLevel64{1000});
215  BEAST_EXPECT(test > FeeLevel64{100});
216  test = make(targetOther);
217  BEAST_EXPECT(test.fee() == 300);
218  BEAST_EXPECT(test == targetOther);
219 
220  test = std::uint64_t(200);
221  BEAST_EXPECT(test.fee() == 200);
222  test = std::uint32_t(300);
223  BEAST_EXPECT(test.fee() == 300);
224 
225  test = targetSame;
226  BEAST_EXPECT(test.fee() == 200);
227  test = targetOther.fee();
228  BEAST_EXPECT(test.fee() == 300);
229  BEAST_EXPECT(test == targetOther);
230 
231  test = targetSame * 2;
232  BEAST_EXPECT(test.fee() == 400);
233  test = 3 * targetSame;
234  BEAST_EXPECT(test.fee() == 600);
235  test = targetSame / 10;
236  BEAST_EXPECT(test.fee() == 20);
237 
238  test += targetSame;
239  BEAST_EXPECT(test.fee() == 220);
240 
241  test -= targetSame;
242  BEAST_EXPECT(test.fee() == 20);
243 
244  test++;
245  BEAST_EXPECT(test.fee() == 21);
246  ++test;
247  BEAST_EXPECT(test.fee() == 22);
248  test--;
249  BEAST_EXPECT(test.fee() == 21);
250  --test;
251  BEAST_EXPECT(test.fee() == 20);
252 
253  test *= 5;
254  BEAST_EXPECT(test.fee() == 100);
255  test /= 2;
256  BEAST_EXPECT(test.fee() == 50);
257  test %= 13;
258  BEAST_EXPECT(test.fee() == 11);
259 
260  /*
261  // illegal with unsigned
262  test = -test;
263  BEAST_EXPECT(test.fee() == -11);
264  BEAST_EXPECT(test.signum() == -1);
265  BEAST_EXPECT(to_string(test) == "-11");
266  */
267 
268  BEAST_EXPECT(test);
269  test = 0;
270  BEAST_EXPECT(!test);
271  BEAST_EXPECT(test.signum() == 0);
272  test = targetSame;
273  BEAST_EXPECT(test.signum() == 1);
274  BEAST_EXPECT(to_string(test) == "200");
275  }
276  {
277  auto make = [&](auto x) -> FeeLevelDouble { return x; };
278  auto explicitmake = [&](auto x) -> FeeLevelDouble {
279  return FeeLevelDouble{x};
280  };
281 
282  FeeLevelDouble defaulted;
283  (void)defaulted;
284  FeeLevelDouble test{0};
285  BEAST_EXPECT(test.fee() == 0);
286 
287  test = explicitmake(beast::zero);
288  BEAST_EXPECT(test.fee() == 0);
289 
290  test = beast::zero;
291  BEAST_EXPECT(test.fee() == 0);
292 
293  test = explicitmake(100.0);
294  BEAST_EXPECT(test.fee() == 100);
295 
296  FeeLevelDouble const targetSame{200.0};
297  FeeLevel64 const targetOther{300};
298  test = make(targetSame);
299  BEAST_EXPECT(test.fee() == 200);
300  BEAST_EXPECT(test == targetSame);
301  BEAST_EXPECT(test < FeeLevelDouble{1000.0});
302  BEAST_EXPECT(test > FeeLevelDouble{100.0});
303  test = targetOther.fee();
304  BEAST_EXPECT(test.fee() == 300);
305  BEAST_EXPECT(test == targetOther);
306 
307  test = 200.0;
308  BEAST_EXPECT(test.fee() == 200);
309  test = std::uint64_t(300);
310  BEAST_EXPECT(test.fee() == 300);
311 
312  test = targetSame;
313  BEAST_EXPECT(test.fee() == 200);
314 
315  test = targetSame * 2;
316  BEAST_EXPECT(test.fee() == 400);
317  test = 3 * targetSame;
318  BEAST_EXPECT(test.fee() == 600);
319  test = targetSame / 10;
320  BEAST_EXPECT(test.fee() == 20);
321 
322  test += targetSame;
323  BEAST_EXPECT(test.fee() == 220);
324 
325  test -= targetSame;
326  BEAST_EXPECT(test.fee() == 20);
327 
328  test++;
329  BEAST_EXPECT(test.fee() == 21);
330  ++test;
331  BEAST_EXPECT(test.fee() == 22);
332  test--;
333  BEAST_EXPECT(test.fee() == 21);
334  --test;
335  BEAST_EXPECT(test.fee() == 20);
336 
337  test *= 5;
338  BEAST_EXPECT(test.fee() == 100);
339  test /= 2;
340  BEAST_EXPECT(test.fee() == 50);
341  /* illegal with floating
342  test %= 13;
343  BEAST_EXPECT(test.fee() == 11);
344  */
345 
346  // legal with signed
347  test = -test;
348  BEAST_EXPECT(test.fee() == -50);
349  BEAST_EXPECT(test.signum() == -1);
350  BEAST_EXPECT(to_string(test) == "-50.000000");
351 
352  BEAST_EXPECT(test);
353  test = 0;
354  BEAST_EXPECT(!test);
355  BEAST_EXPECT(test.signum() == 0);
356  test = targetSame;
357  BEAST_EXPECT(test.signum() == 1);
358  BEAST_EXPECT(to_string(test) == "200.000000");
359  }
360  }
361 
362 public:
363  void
364  run() override
365  {
366  BEAST_EXPECT(INITIAL_XRP.drops() == 100'000'000'000'000'000);
367  BEAST_EXPECT(INITIAL_XRP == XRPAmount{100'000'000'000'000'000});
368 
369  testTypes();
370  testJson();
371  testFunctions();
372  }
373 };
374 
375 BEAST_DEFINE_TESTSUITE(feeunits, ripple_basics, ripple);
376 
377 } // namespace test
378 } // namespace ripple
std::is_same_v
T is_same_v
ripple::mulDiv
std::optional< Dest > mulDiv(Source1 value, Dest mul, Source2 div)
Definition: FeeUnits.h:468
ripple::test::feeunits_test::testFunctions
void testFunctions()
Definition: FeeUnits_test.cpp:183
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::test::jtx::drops
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:241
ripple::XRPAmount::drops
constexpr value_type drops() const
Returns the number of drops.
Definition: XRPAmount.h:172
ripple::test::feeunits_test::testTypes
void testTypes()
Definition: FeeUnits_test.cpp:31
Json::realValue
@ realValue
double value
Definition: json_value.h:39
ripple::INITIAL_XRP
constexpr XRPAmount INITIAL_XRP
Configure the native currency.
Definition: SystemParameters.h:43
Json::uintValue
@ uintValue
unsigned integer value
Definition: json_value.h:38
std::uint64_t
ripple::feeunit::TaggedFee
Definition: FeeUnits.h:70
std::numeric_limits::min
T min(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::remove_reference_t
ripple::test::feeunits_test::testJson
void testJson()
Definition: FeeUnits_test.cpp:117
Json::intValue
@ intValue
signed integer value
Definition: json_value.h:37
ripple::test::feeunits_test::run
void run() override
Definition: FeeUnits_test.cpp:364
ripple::test::jtx::PrettyAmount::value
STAmount const & value() const
Definition: amount.h:124
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
std::numeric_limits::max
T max(T... args)
type_traits
ripple::test::feeunits_test
Definition: FeeUnits_test.cpp:27
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::XRPAmount
Definition: XRPAmount.h:46