rippled
Quality_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/beast/unit_test.h>
21 #include <ripple/protocol/Quality.h>
22 #include <type_traits>
23 
24 namespace ripple {
25 
26 class Quality_test : public beast::unit_test::suite
27 {
28 public:
29  // Create a raw, non-integral amount from mantissa and exponent
30  STAmount static raw(std::uint64_t mantissa, int exponent)
31  {
32  return STAmount({Currency(3), AccountID(3)}, mantissa, exponent);
33  }
34 
35  template <class Integer>
36  static STAmount
38  Integer integer,
40  {
41  static_assert(std::is_integral<Integer>::value, "");
42  return STAmount(integer, false);
43  }
44 
45  template <class Integer>
46  static STAmount
48  Integer integer,
50  {
51  static_assert(std::is_integral<Integer>::value, "");
52  if (integer < 0)
53  return STAmount(-integer, true);
54  return STAmount(integer, false);
55  }
56 
57  template <class In, class Out>
58  static Amounts
59  amounts(In in, Out out)
60  {
61  return Amounts(amount(in), amount(out));
62  }
63 
64  template <class In1, class Out1, class Int, class In2, class Out2>
65  void
67  Quality const& q,
68  In1 in,
69  Out1 out,
70  Int limit,
71  In2 in_expected,
72  Out2 out_expected)
73  {
74  auto expect_result(amounts(in_expected, out_expected));
75  auto actual_result(q.ceil_in(amounts(in, out), amount(limit)));
76 
77  BEAST_EXPECT(actual_result == expect_result);
78  }
79 
80  template <class In1, class Out1, class Int, class In2, class Out2>
81  void
83  Quality const& q,
84  In1 in,
85  Out1 out,
86  Int limit,
87  In2 in_expected,
88  Out2 out_expected)
89  {
90  auto const expect_result(amounts(in_expected, out_expected));
91  auto const actual_result(q.ceil_out(amounts(in, out), amount(limit)));
92 
93  BEAST_EXPECT(actual_result == expect_result);
94  }
95 
96  void
98  {
99  testcase("ceil_in");
100 
101  {
102  // 1 in, 1 out:
103  Quality q(Amounts(amount(1), amount(1)));
104 
105  ceil_in(
106  q,
107  1,
108  1, // 1 in, 1 out
109  1, // limit: 1
110  1,
111  1); // 1 in, 1 out
112 
113  ceil_in(
114  q,
115  10,
116  10, // 10 in, 10 out
117  5, // limit: 5
118  5,
119  5); // 5 in, 5 out
120 
121  ceil_in(
122  q,
123  5,
124  5, // 5 in, 5 out
125  10, // limit: 10
126  5,
127  5); // 5 in, 5 out
128  }
129 
130  {
131  // 1 in, 2 out:
132  Quality q(Amounts(amount(1), amount(2)));
133 
134  ceil_in(
135  q,
136  40,
137  80, // 40 in, 80 out
138  40, // limit: 40
139  40,
140  80); // 40 in, 20 out
141 
142  ceil_in(
143  q,
144  40,
145  80, // 40 in, 80 out
146  20, // limit: 20
147  20,
148  40); // 20 in, 40 out
149 
150  ceil_in(
151  q,
152  40,
153  80, // 40 in, 80 out
154  60, // limit: 60
155  40,
156  80); // 40 in, 80 out
157  }
158 
159  {
160  // 2 in, 1 out:
161  Quality q(Amounts(amount(2), amount(1)));
162 
163  ceil_in(
164  q,
165  40,
166  20, // 40 in, 20 out
167  20, // limit: 20
168  20,
169  10); // 20 in, 10 out
170 
171  ceil_in(
172  q,
173  40,
174  20, // 40 in, 20 out
175  40, // limit: 40
176  40,
177  20); // 40 in, 20 out
178 
179  ceil_in(
180  q,
181  40,
182  20, // 40 in, 20 out
183  50, // limit: 40
184  40,
185  20); // 40 in, 20 out
186  }
187  }
188 
189  void
191  {
192  testcase("ceil_out");
193 
194  {
195  // 1 in, 1 out:
196  Quality q(Amounts(amount(1), amount(1)));
197 
198  ceil_out(
199  q,
200  1,
201  1, // 1 in, 1 out
202  1, // limit 1
203  1,
204  1); // 1 in, 1 out
205 
206  ceil_out(
207  q,
208  10,
209  10, // 10 in, 10 out
210  5, // limit 5
211  5,
212  5); // 5 in, 5 out
213 
214  ceil_out(
215  q,
216  10,
217  10, // 10 in, 10 out
218  20, // limit 20
219  10,
220  10); // 10 in, 10 out
221  }
222 
223  {
224  // 1 in, 2 out:
225  Quality q(Amounts(amount(1), amount(2)));
226 
227  ceil_out(
228  q,
229  40,
230  80, // 40 in, 80 out
231  40, // limit 40
232  20,
233  40); // 20 in, 40 out
234 
235  ceil_out(
236  q,
237  40,
238  80, // 40 in, 80 out
239  80, // limit 80
240  40,
241  80); // 40 in, 80 out
242 
243  ceil_out(
244  q,
245  40,
246  80, // 40 in, 80 out
247  100, // limit 100
248  40,
249  80); // 40 in, 80 out
250  }
251 
252  {
253  // 2 in, 1 out:
254  Quality q(Amounts(amount(2), amount(1)));
255 
256  ceil_out(
257  q,
258  40,
259  20, // 40 in, 20 out
260  20, // limit 20
261  40,
262  20); // 40 in, 20 out
263 
264  ceil_out(
265  q,
266  40,
267  20, // 40 in, 20 out
268  40, // limit 40
269  40,
270  20); // 40 in, 20 out
271 
272  ceil_out(
273  q,
274  40,
275  20, // 40 in, 20 out
276  10, // limit 10
277  20,
278  10); // 20 in, 10 out
279  }
280  }
281 
282  void
284  {
285  testcase("raw");
286 
287  {
288  Quality q(0x5d048191fb9130daull); // 126836389.7680090
289  Amounts const value(
290  amount(349469768), // 349.469768 XRP
291  raw(2755280000000000ull, -15)); // 2.75528
292  STAmount const limit(
293  raw(4131113916555555, -16)); // .4131113916555555
294  Amounts const result(q.ceil_out(value, limit));
295  BEAST_EXPECT(result.in != beast::zero);
296  }
297  }
298 
299  void
301  {
302  testcase("round");
303 
304  Quality q(0x59148191fb913522ull); // 57719.63525051682
305  BEAST_EXPECT(q.round(3).rate().getText() == "57800");
306  BEAST_EXPECT(q.round(4).rate().getText() == "57720");
307  BEAST_EXPECT(q.round(5).rate().getText() == "57720");
308  BEAST_EXPECT(q.round(6).rate().getText() == "57719.7");
309  BEAST_EXPECT(q.round(7).rate().getText() == "57719.64");
310  BEAST_EXPECT(q.round(8).rate().getText() == "57719.636");
311  BEAST_EXPECT(q.round(9).rate().getText() == "57719.6353");
312  BEAST_EXPECT(q.round(10).rate().getText() == "57719.63526");
313  BEAST_EXPECT(q.round(11).rate().getText() == "57719.635251");
314  BEAST_EXPECT(q.round(12).rate().getText() == "57719.6352506");
315  BEAST_EXPECT(q.round(13).rate().getText() == "57719.63525052");
316  BEAST_EXPECT(q.round(14).rate().getText() == "57719.635250517");
317  BEAST_EXPECT(q.round(15).rate().getText() == "57719.6352505169");
318  BEAST_EXPECT(q.round(16).rate().getText() == "57719.63525051682");
319  }
320 
321  void
323  {
324  testcase("comparisons");
325 
326  STAmount const amount1(noIssue(), 231);
327  STAmount const amount2(noIssue(), 462);
328  STAmount const amount3(noIssue(), 924);
329 
330  Quality const q11(Amounts(amount1, amount1));
331  Quality const q12(Amounts(amount1, amount2));
332  Quality const q13(Amounts(amount1, amount3));
333  Quality const q21(Amounts(amount2, amount1));
334  Quality const q31(Amounts(amount3, amount1));
335 
336  BEAST_EXPECT(q11 == q11);
337  BEAST_EXPECT(q11 < q12);
338  BEAST_EXPECT(q12 < q13);
339  BEAST_EXPECT(q31 < q21);
340  BEAST_EXPECT(q21 < q11);
341  BEAST_EXPECT(q11 >= q11);
342  BEAST_EXPECT(q12 >= q11);
343  BEAST_EXPECT(q13 >= q12);
344  BEAST_EXPECT(q21 >= q31);
345  BEAST_EXPECT(q11 >= q21);
346  BEAST_EXPECT(q12 > q11);
347  BEAST_EXPECT(q13 > q12);
348  BEAST_EXPECT(q21 > q31);
349  BEAST_EXPECT(q11 > q21);
350  BEAST_EXPECT(q11 <= q11);
351  BEAST_EXPECT(q11 <= q12);
352  BEAST_EXPECT(q12 <= q13);
353  BEAST_EXPECT(q31 <= q21);
354  BEAST_EXPECT(q21 <= q11);
355  BEAST_EXPECT(q31 != q21);
356  }
357 
358  void
360  {
361  testcase("composition");
362 
363  STAmount const amount1(noIssue(), 231);
364  STAmount const amount2(noIssue(), 462);
365  STAmount const amount3(noIssue(), 924);
366 
367  Quality const q11(Amounts(amount1, amount1));
368  Quality const q12(Amounts(amount1, amount2));
369  Quality const q13(Amounts(amount1, amount3));
370  Quality const q21(Amounts(amount2, amount1));
371  Quality const q31(Amounts(amount3, amount1));
372 
373  BEAST_EXPECT(composed_quality(q12, q21) == q11);
374 
375  Quality const q13_31(composed_quality(q13, q31));
376  Quality const q31_13(composed_quality(q31, q13));
377 
378  BEAST_EXPECT(q13_31 == q31_13);
379  BEAST_EXPECT(q13_31 == q11);
380  }
381 
382  void
384  {
385  testcase("operations");
386 
387  Quality const q11(
388  Amounts(STAmount(noIssue(), 731), STAmount(noIssue(), 731)));
389 
390  Quality qa(q11);
391  Quality qb(q11);
392 
393  BEAST_EXPECT(qa == qb);
394  BEAST_EXPECT(++qa != q11);
395  BEAST_EXPECT(qa != qb);
396  BEAST_EXPECT(--qb != q11);
397  BEAST_EXPECT(qa != qb);
398  BEAST_EXPECT(qb < qa);
399  BEAST_EXPECT(qb++ < qa);
400  BEAST_EXPECT(qb++ < qa);
401  BEAST_EXPECT(qb++ == qa);
402  BEAST_EXPECT(qa < qb);
403  }
404  void
405  run() override
406  {
409  test_operations();
410  test_ceil_in();
411  test_ceil_out();
412  test_raw();
413  test_round();
414  }
415 };
416 
418 
419 } // namespace ripple
ripple::Quality_test::raw
static STAmount raw(std::uint64_t mantissa, int exponent)
Definition: Quality_test.cpp:30
std::is_signed
ripple::Quality_test::test_ceil_out
void test_ceil_out()
Definition: Quality_test.cpp:190
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::composed_quality
Quality composed_quality(Quality const &lhs, Quality const &rhs)
Definition: Quality.cpp:101
ripple::Quality_test::test_ceil_in
void test_ceil_in()
Definition: Quality_test.cpp:97
ripple::Quality_test::test_round
void test_round()
Definition: Quality_test.cpp:300
ripple::QualityDirection::in
@ in
ripple::noIssue
Issue const & noIssue()
Returns an asset specifier that represents no account and currency.
Definition: Issue.h:103
ripple::QualityDirection::out
@ out
std::enable_if_t
ripple::STAmount
Definition: STAmount.h:45
ripple::Quality_test::amount
static STAmount amount(Integer integer, std::enable_if_t<!std::is_signed< Integer >::value > *=0)
Definition: Quality_test.cpp:47
std::uint64_t
ripple::Quality_test::test_comparisons
void test_comparisons()
Definition: Quality_test.cpp:322
std::is_integral
ripple::Quality_test::test_operations
void test_operations()
Definition: Quality_test.cpp:383
ripple::Quality_test::amount
static STAmount amount(Integer integer, std::enable_if_t< std::is_signed< Integer >::value > *=0)
Definition: Quality_test.cpp:37
ripple::Currency
base_uint< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
Definition: UintTypes.h:56
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
protocol
Definition: ValidatorList.h:38
ripple::Quality_test::test_raw
void test_raw()
Definition: Quality_test.cpp:283
ripple::Quality_test
Definition: Quality_test.cpp:26
ripple::Quality_test::ceil_out
void ceil_out(Quality const &q, In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected)
Definition: Quality_test.cpp:82
ripple::Quality_test::run
void run() override
Definition: Quality_test.cpp:405
ripple::Quality_test::amounts
static Amounts amounts(In in, Out out)
Definition: Quality_test.cpp:59
ripple::Quality_test::ceil_in
void ceil_in(Quality const &q, In1 in, Out1 out, Int limit, In2 in_expected, Out2 out_expected)
Definition: Quality_test.cpp:66
type_traits
ripple::AccountID
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:47
ripple::Quality_test::test_composition
void test_composition()
Definition: Quality_test.cpp:359