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